수행기록퀘스트4

Quest4: 최종 결과물 완성 (RPI Pico W와 클라우드를 연동한 대시보드 시각화 프로젝트)
2022. 9. 12 (월) 18:18 최종수정 2022. 9. 22 (목) 20:38 칩헤드 조회 1169 좋아요 2 스크랩 2 댓글 4

> ※ Pico W 대신 Pico 보드를 사용하셔도 무방합니다. (별도 Wifi 모듈 사용 필요)
> ※ '모터 제어' 콘테스트 이벤트를 통해 Pico 또는 Pico W 를 받으신 분들은 50명에서 제외됩니다.

> 1. 그간 Pico W와 IoT 클라우드를 활용한 아이디어의 결과물 제작 과정과 소감을 자료와 영상으로 제출해 주세요.
> (*제작 과정은 따라하기가 가능할 정도로 구체적이어야 합니다.)
> 2. 제작에 사용된 회로와 소스코드를 압축 파일로 첨부하여 제출해 주세요. (zip 파일만 업로드 가능)

 

RPI Pico (w)와 클라우드를 연동한 대시보드 시각화 프로젝트

 

 

         - 목 차 - 

□ 1. 아이디어 소개 
□ 2. 아이디어 구현
□ 3. 하드웨어 구성 다이어그램
□ 4. 소프트웨어 구성 다이어그램
□ 5. 클라우드 환경설정 및 개발툴 셋업
□ 6. 클라우드 데이타를 대시보드로 시각화
□ 7. 참조 사이트
□ 8. 데모 동영상

 

 

□ 1. 아이디어 소개 

2021년 1월 라즈베리 파이 피코 (W)가 출시되었습니다. 피코는 리눅스 커널 기반의 개발보드가 아닌
라즈베리파이 자체 개발한 마이크로컨트롤러 칩 (RP2040)입니다. 이 RP2040 SoC 칩기반의
라즈베리파이 Pico (W)보드는 아주 작고 다재다능한 보드에 탑재돼 완전히 새로운 형태의
보드라고 볼수 있습니다.  RP2040 칩 스펙 정보는 다음과 같습니다. 

 

 
   □ Dual ARM Cortex-M0+ @ 133MHz
   □ 264kB on-chip SRAM in six independent banks
   □ Support for up to 16MB of off-chip Flash memory via dedicated QSPI bus
   □ DMA controller
   □ Fully-connected AHB crossbar
   □ Interpolator and integer divider peripherals
   □ On-chip programmable LDO to generate core voltage
   □ 2 on-chip PLLs to generate USB and core clocks
   □ 30 GPIO pins, 3 of which can be used as analogue inputs
   □ Peripherals
   □ 2 UARTs
   □ 2 SPI controllers
   □ 2 I2C controllers
   □ 16 PWM channels
   □ USB 1.1 controller and PHY, with host and device support
   □ 8 PIO state machines

 

이 RP2040은 264KB의 내장 RAM과 최대 16MB의 오프칩 플래시를 지원하는 듀얼 코어 Arm Cortex-M0+
프로세서를 갖추고 있으며, 다양한 GPIO(I2C, SPI, Programmable I/O)를 지원합니다. 그래서 기존의
아두이노나 마이크로컨트롤러 보드에 필적한다. 하지만 이 피코의 가장 큰 놀라움은 단 4달러의 가격입니다.

Raspberry Pi Pico 핀아웃 다이어그램

                                          라즈베리파이 피코 (W)의 GPIO  구조도 

 

이번 프로젝트에서 피코의 가격, 언어(C/C++, Python), Wifi모듈 등의 특성을 활용하려고 합니다. 
특히, 라즈베리파이 PICO W 보드는 매우 작은 사이즈와 초전력의 장점을 가지고 있습니다. 이에
이러한 초소형 보드를 이용하여 수집한 정보들을 클라우드에 보내고, 클라우드에 저장된 정보들을
이용하여 시각화된 대시보드를 제공하는 프로젝트를 진행하였습니다. 

                                             아이디어 전체 동작 구성도 

 


□ 2. 아이디어 구현

내장 WiFi 모듈, 외장 WiFi 모듈, 거리 센서등으로 IoT향 Pico W 보드를 동작 가능범위를 확장할 것입니다.

그리고, Pico보드에 내장에 Pico W WiFi를 로더밸런서으로써 동작 시킨 다음에, Heartbeat 구조로

클라우드 네트웍 송신이 가능한 외장 wifi 장치들을 (=별도의 WiFi장치들) 구성하는 시스템을 구성후에

중소규모의 스마트 팩토리 환경에서 하나의 네트웍 장치가 고장이 나더라도, 수진됩 센서 데이타들을 항상

신뢰할수 있고 안정적으로 클라우드에 리포트할수 있는 인프라 스터력쳐가 운영 가능한지 도전 해보려고 합니다. 


본 개인 프로젝트에서 라즈베리 피코 (W) 소형보드에서 수집한 센서 데이터들을 Azure Cloud를 무료 호스팅하는
HiveMQ Cloud에 MQTT 프로토콜을 이용하여 추가적인 비용 부담 없이 리포트 보내려고 합니다.

HiveMQ를 이용하려는 이유 중의 하나는 HiveMQ Cloud를 사용하면 최대 100개의 장치를 무료로 연결할 수 있고,

이 서비스를 통해 유료로 사용해야 하는 Azure 또는 AWS를 덤으로  무료 사용이 가능한, 이른바 일석이조 이어서입니다. 

                                   HiveMQTT CLoud의 무료 계정 서비스 예시

 

이것은 종종 실험적인 과제를 수행하려고 할때 우리가 메시징을 실험할 수 있는 좋은 방법중의 하나입니다. 

이것을 Java, Raspberry Pi 및 엣지 디바이스 들과 결합하면 서로 다른 응용 프로그램과 장치 간에
데이터를 교환하는 것이 매우 편리하고 쉬워집니다.  또한 메세징 시스템을 통해  HiveMQ Cloud내의 Azure Cloud에
무료로 저장이 가능합니다. 다만 무료이기 때문에 수집된 데이타의 보관은 3일까지만 가능하며, 유료 결제시에는
장시간 클라우드에 데이타를 보관이 가능합니다.  최종적으로 Java를 활용하여  수집된 데이타를 기반으로 하여
대시보드로 시각화하도록 하겠습니다. 

 

2.1. MQTT 브로커에 연결

CircuitPython 장치를 원하는 MQTT 브로커에 연결할 수 있습니다.  MQTT 브로커는 일반적으로
상업용 호스팅(유료), 무료 호스팅, 자체 호스팅의 세 가지 범주로 분류됩니다.

아래는 파이썬 언어를 이용하여 MQTT 브로커에 연결하는 예시를 보여주고 있습니다. 

# Specify MQTt topic name
mqtt_topic = "e4ds-quest04-chiphead/topic"

def connect(mqtt_client, userdata, flags, rc):
    # This function will be called when the mqtt_client is connected
    # successfully to the broker.
    print("Connected to MQTT Broker!")
    print("Flags: {0}\n RC: {1}".format(flags, rc))


def disconnect(mqtt_client, userdata, rc):
    # This method is called when the mqtt_client disconnects
    # from the broker.
    print("Disconnected from MQTT Broker!")


def subscribe(mqtt_client, userdata, topic, granted_qos):
    # This method is called when the mqtt_client subscribes to a new feed.
    print("Subscribed to {0} with QOS level {1}".format(topic, granted_qos))


def unsubscribe(mqtt_client, userdata, topic, pid):
    # This method is called when the mqtt_client unsubscribes from a feed.
    print("Unsubscribed from {0} with PID {1}".format(topic, pid))


def publish(mqtt_client, userdata, topic, pid):
    # This method is called when the mqtt_client publishes data to a feed.
    print("Published to {0} with PID {1}".format(topic, pid))


def message(client, topic, message):
    # Method called when a client's subscribed feed has a new value.
    print("New message on topic {0}: {1}".format(topic, message))


# Create a socket pool
pool = socketpool.SocketPool(wifi.radio)

# Set up a MiniMQTT Client
mqtt_client = MQTT.MQTT(
    broker=secrets["broker"],
    port=secrets["port"],
    username=secrets["aio_username"],
    password=secrets["aio_key"],
    socket_pool=pool,
    ssl_context=ssl.create_default_context(),
)

# Connect callback handlers to mqtt_client
mqtt_client.on_connect = connect
mqtt_client.on_disconnect = disconnect
mqtt_client.on_subscribe = subscribe
mqtt_client.on_unsubscribe = unsubscribe
mqtt_client.on_publish = publish
mqtt_client.on_message = message

print("Attempting to connect to %s" % mqtt_client.broker)
mqtt_client.connect()

print("Subscribing to %s" % mqtt_topic)
mqtt_client.subscribe(mqtt_topic)

print("Publishing to %s" % mqtt_topic)
mqtt_client.publish(mqtt_topic, "Hello Broker!")

print("Unsubscribing from %s" % mqtt_topic)
mqtt_client.unsubscribe(mqtt_topic)

print("Disconnecting from %s" % mqtt_client.broker)
mqtt_client.disconnect()

 

2.2. Raspberry Pi Pico 개발환경 및 연동 작업 

RP2040은 M4(SAMD51)의 클럭 속도와 M0(SAMD21)에 해당하는 2개의 코어를 갖춘 강력한 칩입니다. 
M0 칩이기 때문에 아쉽게도 부동 소수점 단위 또는 DSP 하드웨어 지원이 없습니다.  따라서 무거운
부동 소수점 연산으로 작업을 수행하는 경우 소프트웨어에서 수행되므로 M4만큼 빠르지 않습니다. 
그러나, 다른 많은 계산 작업의 경우 M4에 가까운 속도를 얻을 수 있습니다.

MicroPython (또는 CircuitPython)에서 PIO 제어 명령을 생성하여 주변 장치를 스크립팅하고 런타임에
로드할 수 있습니다. 각각 4개의 상태 머신이 있는 2개의 PIO 주변 장치가 있습니다.

RP2040에는 많은 온보드 RAM(264KB)이 있지만 FLASH 메모리는 내장되어 있지 않습니다.
대신 외부 QSPI 플래시 칩이 제공합니다. 이 보드에는 실행 중인 프로그램과 MicroPython
(또는 CircuitPython)에서 사용하는 파일 저장소 간에 공유되는 2MB가 있습니다. C/C++를 사용하면
전체 플래시 메모리를 얻게 되며, Python을 사용하면 소스코드, 파일, 이미지, 글꼴 등을 위해 약 1MB가 남게 됩니다.

 

 


□ 3. 하드웨어 구성 다이어그램

본 섹션은 Raspberry Pico W 개발환경을 준비하는 것부터  관련 하드웨어 구성 요소를 연결하기 위한 내용을 설명합니다.

내장 와이파이는 HeartBeat용도로 동작시키고, 외장의 ESP32 WiFi를 이용하여 Circuitpython과 연동후에,

무료 Hive MQTT를 이용하여 Azure IoT Cloud를 무료로 쓰보겠습니다.

 

                           회로도의 기본 설계 구상 레이아웃

 

           라즈베리파이 피코 (W) , 빵보드, 케이블 선 등의 기본 부품들의 구성 내역

 

Adafruit AirLift (ESP32 WiFi Co-Processor Breakout 보드)

 

 


□ 4. 소프트웨어 구성 다이어그램

라즈베리파이 피코 (W)보드에서 내장 Wifi는 HeartBeat Pulse용도로 셋업을하고 ESP32 WiFi를 추가 연결하기 위하여 

CircuitPython 패키지를 플래시하고 라이브러리를 추가한후 관련 소프트웨어 코드를 업로드해야 합니다.


제일먼저 라즈베리파이 피코 (W)의 소프트웨어 구성 요소의 사용을 단순화하기 위해 https://circuitpython.org/libraries 에서
아래의 구성요소를 사용하면 삽질 작업을 많이 줄일수 있습니다.  관련된 파일들만을 다운로드하고 PC에서 압축을 풀고,
다음 목록의 디렉토리 또는 파일을 "CIRCUITPY" 드라이브의 "libs" 디렉토리에 복사하여 동작 시키도록 합니다. 

  • 1. adafruit_bus_device
  • 2. adafruit_esp32_spi
  • 3. adafruit_hcsr04
  • 4. adafruit_io
  • 5. adafruit_minimqtt
  • 6. adafruit_requests

 

 


□ 5. 클라우드 환경설정 및 개발툴 셋업

아래는 이 프로젝트의 전체 코드를 요약하고 있습니다. 코드 내에 주석을 추가하여 전체 단계를  설명하였습니다. 

$ vi code.py
import time
import board
import busio
import adafruit_hcsr04
import adafruit_requests as requests
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
import adafruit_minimqtt.adafruit_minimqtt as MQTT

from digitalio import DigitalInOut
from adafruit_esp32spi import adafruit_esp32spi

# Load the WiFi and HiveMQ Cloud credentials (e.g., secrets.py)
try:
    from secrets import secrets
except ImportError:
    print("Error, secrets could not be read")
    raise

# MQTT Topic to publish data from Pico to HiveMQ Cloud
topic_name = "/img/blog/distance"

# Initialize the Pico pins, WiFi module and distance sensor
esp32_cs = DigitalInOut(board.GP13)
esp32_ready = DigitalInOut(board.GP14)
esp32_reset = DigitalInOut(board.GP15)
spi = busio.SPI(board.GP10, board.GP11, board.GP12)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
hcsr04 = adafruit_hcsr04.HCSR04(trigger_pin=board.GP17, echo_pin=board.GP16)

# Handle HTTP requests
requests.set_socket(socket, esp)

# Check ESP32 status
print("Checking ESP32")
if esp.status == adafruit_esp32spi.WL_IDLE_STATUS:
    print("\tESP32 found and in idle mode")
print("\tFirmware version: ", esp.firmware_version)
print("\tMAC address: ", [hex(i) for i in esp.MAC_address])

# List the detected WiFi networks
print("Discovered WiFi networks:")
for ap in esp.scan_networks():
    print("\t", (str(ap["ssid"], "utf-8")), "\t\tRSSI: ", ap["rssi"])

# Connect to the configured WiFi network
print("Connecting to WiFi: ", secrets["ssid"])
while not esp.is_connected:
    try:
        esp.connect_AP(secrets["ssid"], secrets["password"])
    except RuntimeError as e:
        print("\tCould not connect to WiFi: ", e)
        continue
print("\tConnected to ", str(esp.ssid, "utf-8"), "\t\tRSSI:", esp.rssi)
print("\tIP address of this board: ", esp.pretty_ip(esp.ip_address))
print("\tPing google.com: " + str(esp.ping("google.com")) + "ms")

# Configure MQTT to use the ESP32 interface
MQTT.set_socket(socket, esp)

# Configure MQTT client (uses secure connection by default)
mqtt_client = MQTT.MQTT(
    broker=secrets["broker"],
    port=secrets["port"],
    username=secrets["MQTT_USER_NAME"],
    password=secrets["MQTt_KEY_VALUE"]
)

# Define callback methods and assign them to the MQTT events
def connected(client, userdata, flags, rc):
    print("\tConnected to MQTT broker: ", client.broker)

def disconnected(client, userdata, rc):
    print("\tDisconnected from MQTT broker!")

def publish(mqtt_client, userdata, topic, pid):
    print("\tPublished a message to: ", topic)

mqtt_client.on_connect = connected
mqtt_client.on_disconnect = disconnected
mqtt_client.on_publish = publish

# Connect to the MQTT broker
print("Connecting to MQTT broker...")
try:
    mqtt_client.connect()
    print("\tSucceeded")
except Exception as e:
    print("\tMQTT connect failed: ", e)

# Continuously measure the distance and send the value to HiveMQ
print("Starting the distance measurement")
killed = False
while not killed:
    # Measure a distance
    distance = 0
    try:
        distance = hcsr04.distance
    except Exception as e:
        print("Distance measurement failure\n", e)

    # Send to HiveMQ Cloud
    try:
        json = "{\"value\": " + str(distance) + "}"
        print("\tMessage for queue: " + json)
        mqtt_client.publish(topic_name, json)
    except Exception as e:
        print("\tMQTT publish Failed, retrying\n", e)
        killed = True
        continue

    # Sleep a second
    time.sleep(1)

 

아래는 Python IDE 편집기 (Thonney 또는 Mu)에 출력되는 결과입니다. 

 

 

 


□ 6. 클라우드 데이타를 대시보드로 시각화

이 섹션은  클라우드에 수집한 센서 데이타들을 사람들이 쉽게 이해할수 있도록 시각화를 하기 위하여
대시보드를 제작하는 방법을 설명합니다. JavaFX를 이용하면, 약간의 코드 수정만으로 라즈베리파이
Pico 보드의  메시지의 데이터를 JavaFX 애플리케이션에 추가할 수 있습니다. 
수정해야 할 파일은 DashboardView.java 파일입니다.  제일 먼저 다음과 같이 새 변수를 추가합니다. 

 

그리고나서 생성자 내에서 기존 타일과 유사한 타일을 초기화합니다. 그 다음 라즈베리 피코보드로부터
수집된 거리 측정 데이타를 publish하는 주제에 대한 subscription을 아래와 같이정의합니다.

수신된 데이터를 구문 분석하고 타일을 업데이트하려면 마지막 단계로  다음과 같은 내용들이 추가되어야 합니다. 

 

이제 모든 작업이 완료되었습니다. 우리는 JavaFX를 이용하여 다음과 같이 하나의 대시보드에서 Pico 보드의 데이터를 
보기 쉽고 가독성이 빠르게 시각화를 할수 있습니다. 

 

                            수집된 센서 데이타들의 시각화  (대시보드) 스크린샷

 


□ 7. 참조 사이트:

     □ https://www.hivemq.com/blog/how-to-get-started-with-mqtt/
     □ https://www.raspberrypi.com/products/raspberry-pi-pico/
     □ https://thonny.org/
     □ https://codewith.mu/
     □ https://circuitpython.org/board/raspberry_pi_pico/
     □ https://openjfx.io/
     □ https://github.com/HanSolo/tilesfx
     □ https://io.adafruit.com/

 

 


□ 8. 데모 동영상: https://youtu.be/xzI6o6hxF6M

         

 

 

이상. 

첨부파일
quest04-source-chiphead-20220912.zip 다운로드
피스전기
2022.09.17 19:36
pico W WiFi 만으로 클라우드 연결이 가능했다면 더 좋은 어플리케이션 사례가 되었을 것 같은데요. 궁금해지는 것은 별도의 WiFi를 사용하지 않고 구현은 어려웠던 건가요?
칩헤드
2022.09.18 11:58
좋은 질문이십니다. 그럴리가요? 전혀요, :) 우리가 이전 Quest3에서 이미 학습한바와 같이, 내장된 Pico W WiFi장치로 클라우드 송신이 쉽게 가능하구요. 이 개인 플젝트는, 내장 pico W WiFi를 로더밸런서으로써 동작 시키고, heartbeat 구조로 클라우드 네트웍 송신이 가능한 외장 wifi 장치들을 (=별도의 WiFi장치들) 구성하는 테스트 베드를 도전해보고 싶은것이 배경입니다.
j
2022.09.13 11:57
우와 pico w는 아니지만 이렇게도 구현이 가능하군요..
칩헤드
2022.09.18 11:49
넵, 내장 Wifi는 HeartBeat 를 수행토록 하고, 외장 ESP32 Wifi는 CircuitPython으로 클라우드 연결 해보니, 충분히 중소기업들도 신뢰가능한 상업적 IoT 장치의 실현이 가능하겠다는 확신을 가질수 있었습니다.

로그인 후
참가 상태를 확인할 수 있습니다.