수행기록퀘스트4

AWS IoT 클라우드를 사용한 LED 컨트롤러
2022. 10. 1 (토) 10:53 최종수정 2022. 11. 17 (목) 21:27 rudals 조회 1036 좋아요 1 스크랩 0 댓글 0

# Raspberry Pi Pico W 아이디어 & 개발계획서 작성

Raspberry Pi Pico W와 대표적인 클라우드 서비스인 아마존 웹 서비스(AWS)의 IOT_Core 서비스의 MQTT 프로토콜을 사용하여 LED 디바이스를 제어할 수 있는 시스템을 계획하였습니다.

 

이번 콘테스트는 Raspberry Pi Pico W를 사용하여 진행되었는데 보드관련 사양을 알아보았습니다.

□ Raspberry Pi Pico W 보드 사양

  - RP2040 microcontroller chip designed by Raspberry Pi in the United Kingdom

  - Dual-core ARM Cortex M0+ processor, flexible clock running up to 133 MHz

  - 264kB of SRAM, and 2MB of on-board Flash memory

  - On-board single-band 2.4GHz wireless interfaces (802.11n)

  - Castellated module allows soldering direct to carrier boards

  - USB 1.1 Host and Device support

  - Low-power sleep and dormant modes

  - Drag & drop programming using mass storage over USB

  - 26 multi-function GPIO pins

  - 2×SPI, 2×I2C, 2×UART, 3×12-bit ADC, 16×controllable PWM channels

  - Accurate clock and timer on-chip

  - Temperature sensor

  - Accelerated floating point libraries on-chip

  - 8×Programmable IO (PIO) state machines for custom peripheral support

 

Pico W 보드는 저렴한 가격에 여러 종류의 인터페이스가 제공되는데 특히나 무선 인터페이스가 제공되어 다양한 애플리케이션 작성 및 활용이 가능한 제품입니다.

 

□ 개발 툴

Pico W 개발 툴로 PICO C/C++ SDK을 사용했는데 MicroPython의 경우 조금 검색만 해 보더라도 많은 예제 및 게시글을 찾을 수 있을 뿐만 아니라 대부분의 기능들이 OS에 내장되어 있어 사용하기 쉬운 반면에 C/C++ SDK는 검색을 해도 관련 정보를 쉽게 찾을 수 없었고 관련 어플리케이션을 작성하려면 해당 기능들을 하나하나 구현해야 하는 번거로운 점이 있습니다. 아마도 이런 점들 때문에 몇몇 분들이 퀘스트 초창기에는 C/C++ SDK로 개발 계획을 세웠으나 지금은 모두 MicroPython나 Arduino로 전향하신 듯 보입니다.

 

□ AWS 클라우드

콘테스트 오픈 후에는 다른 클라우드 서비스를 사용할 수 있도록 변경되었지만, 콘테스트 오픈 전에는 Quest3 주제가 ‘AWS 클라우드 연결’이었던 적이 있었습니다.

제가 봤던 당시에는 AWS 클라우드만 있어서 관련정보를 찾아보다 보니 첫 클라우드 서비스로 AWS를 사용하게 되었습니다.

 

# 개발 과정

□ 하드웨어

WS2812 LED를 사용하여 8x8 매트릭스로 구성하여 아래와 같은 패널을 제작하였습니다.

 

 

□ 소프트웨어

아래 그림과 같이 총 4개의 파트로 나눠 구현해 보았습니다.

- Publisher는 윈도우10에서 Python을 사용하여 topic으로 메시지를 송신합니다.

- Broker는 웹상에서 AWS IoT Core Service로 설정되어 동작됩니다.

- Subscriber는 Raspberry Pi Pico W 보드에서 topic의 메시지를 수신합니다.

- LED는 WS2812를 8x8 매트릭스 구성으로 총 64개를 사용하여 수신된 MQTT 메시지를 디스플레이 합니다.

 

 

1. Publisher

Publisher의 구현은 https://aws.amazon.com/ko/premiumsupport/knowledge-center/iot-core-publish-mqtt-messages-python 내용을 참고하여 작성하였습니다. 전반적인 AWS IoT 환경 설정부터 예제까지 자세히 설명되어 있으니 참고하시면 좋을 것 같습니다. 제공되는 예제를 참고하여 Publisher를 아래와 같이 작성하였습니다.

import sys

from awscrt import io, mqtt, auth, http

from awsiot import mqtt_connection_builder

import time

from aws_secure_data import *

 

def publish_message(topic, msg):

  event_loop_group = io.EventLoopGroup(1)

  host_resolver = io.DefaultHostResolver(event_loop_group)

  client_bootstrap = io.ClientBootstrap(event_loop_group, host_resolver)

  mqtt_connection = mqtt_connection_builder.mtls_from_path(

              endpoint=ENDPOINT,

              cert_filepath=PATH_TO_CERTIFICATE,

              pri_key_filepath=PATH_TO_PRIVATE_KEY,

              client_bootstrap=client_bootstrap,

              ca_filepath=PATH_TO_AMAZON_ROOT_CA_1,

              client_id=CLIENT_ID,

              clean_session=False,

              keep_alive_secs=6

              )

 

  print("Connecting to AWS IoT Server...")

  connect_future = mqtt_connection.connect()

  connect_future.result()

  print("Connected!")

  print('Begin Publish')

  mqtt_connection.publish(topic=topic, payload=msg, qos=mqtt.QoS.AT_LEAST_ONCE)

  print('Publish End')

  print("Disconnected!")

 

param = sys.argv[1]

if param == "demo1":

  publish_message('test/pub', "on");

elif param == "demo2":

publish_message('test/pub', "off");

elif param == "demo3":

publish_message('test/pub', b'0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF:0000FF')

 

2. Broker

Broker 관련 설정은 Quest3의 내용과 동일하니 관련 링크를 참고하시면 됩니다.

 

3. Subscriber

Subscriber는 Pico C/C++ SDK를 사용하여 구현했는데 먼저 Pico C/C++ SDK 개발환경 설정을 해야 합니다. 기본적이 C/C++ SDK 빌드 관련 내용은 Quest2 게시글의 내용과 동일하니 관련 링크를 참고하시면 됩니다. 우선 AWS를 사용하기 위해서는 mbedtls 라이브러리를 SDK에 추가해 줘야 하는데 아래와 같이 다운로드 받은 후 관련 설정을 해 주면 됩니다.

cd pico-sdk/lib

git clone git@github.com:Mbed-TLS/mbedtls.git -b mbedtls-2.28

cd ../..

vi pico-sdk/src/rp2-common/pico-common/pico_mbedtls/CMakeLists.txt

if (DEFINED ENV{PICO_MBEDTLS_PATH} AND (NOT PICO_MBEDTLS_PATH))

    set(PICO_MBEDTLS_PATH $ENV{PICO_MBEDTLS_PATH})

    message("Using PICO_MBEDTLS_PATH from environment ('${PICO_MBEDTLS_PATH}')")

endif()

 

set(MBEDTLS_TEST_PATH "library/aes.c")

if (NOT PICO_MBEDTLS_PATH)

    set(PICO_MBEDTLS_PATH ${PROJECT_SOURCE_DIR}/lib/mbedtls)

elseif (NOT EXISTS ${PICO_MBEDTLS_PATH}/${MBEDTLS_TEST_PATH})

    message(WARNING "PICO_MBEDTLS_PATH specified but content not present.")

endif()

 

if (EXISTS ${PICO_MBEDTLS_PATH}/${MBEDTLS_TEST_PATH})

    message("mbedtls available at ${PICO_MBEDTLS_PATH}")

 

    set(src_crypto

        aes.c

        aesni.c

        arc4.c

        aria.c

        asn1parse.c

        asn1write.c

        base64.c

        bignum.c

        blowfish.c

        camellia.c

        ccm.c

        chacha20.c

        chachapoly.c

        cipher.c

        cipher_wrap.c

        constant_time.c

        cmac.c

        ctr_drbg.c

        des.c

        dhm.c

        ecdh.c

        ecdsa.c

        ecjpake.c

        ecp.c

        ecp_curves.c

        entropy.c

        entropy_poll.c

        error.c

        gcm.c

        havege.c

        hkdf.c

        hmac_drbg.c

        md.c

        md2.c

        md4.c

        md5.c

        memory_buffer_alloc.c

        mps_reader.c

        mps_trace.c

        nist_kw.c

        oid.c

        padlock.c

        pem.c

        pk.c

        pk_wrap.c

        pkcs12.c

        pkcs5.c

        pkparse.c

        pkwrite.c

        platform.c

        platform_util.c

        poly1305.c

        psa_crypto.c

        psa_crypto_aead.c

        psa_crypto_cipher.c

        psa_crypto_client.c

        psa_crypto_driver_wrappers.c

        psa_crypto_ecp.c

        psa_crypto_hash.c

        psa_crypto_mac.c

        psa_crypto_rsa.c

        psa_crypto_se.c

        psa_crypto_slot_management.c

        psa_crypto_storage.c

        psa_its_file.c

        ripemd160.c

        rsa.c

        rsa_internal.c

        sha1.c

        sha256.c

        sha512.c

        threading.c

        timing.c

        version.c

        version_features.c

        xtea.c

    )

    list(TRANSFORM src_crypto PREPEND ${PICO_MBEDTLS_PATH}/library/)

    add_library(pico_mbedtls_crypto INTERFACE)

    target_sources(pico_mbedtls_crypto INTERFACE ${src_crypto})

 

    set(src_x509

        certs.c

        pkcs11.c

        x509.c

        x509_create.c

        x509_crl.c

        x509_crt.c

        x509_csr.c

        x509write_crt.c

        x509write_csr.c

    )

    list(TRANSFORM src_x509 PREPEND ${PICO_MBEDTLS_PATH}/library/)

    add_library(pico_mbedtls_x509 INTERFACE)

    target_sources(pico_mbedtls_x509 INTERFACE ${src_x509})

 

    set(src_tls

        debug.c

        net_sockets.c

        ssl_cache.c

        ssl_ciphersuites.c

        ssl_cli.c

        ssl_cookie.c

        ssl_msg.c

        ssl_srv.c

        ssl_ticket.c

        ssl_tls.c

        ssl_tls13_keys.c

    )

    list(TRANSFORM src_tls PREPEND ${PICO_MBEDTLS_PATH}/library/)

    add_library(pico_mbedtls_tls INTERFACE)

    target_sources(pico_mbedtls_tls INTERFACE ${src_tls})

 

    add_library(pico_mbedtls INTERFACE)

    target_link_libraries(pico_mbedtls INTERFACE pico_mbedtls_crypto pico_mbedtls_x509 pico_mbedtls_tls)

    target_compile_definitions(pico_mbedtls INTERFACE MBEDTLS_CONFIG_FILE="mbedtls_config.h")

    target_include_directories(pico_mbedtls INTERFACE ${PICO_MBEDTLS_PATH}/include/ ${PICO_MBEDTLS_PATH}/library/)

 

    function(suppress_mbedtls_warnings)

        set_source_files_properties(

            ${PICO_MBEDTLS_PATH}/library/ecdsa.c

            ${PICO_MBEDTLS_PATH}/library/ecp.c

            ${PICO_MBEDTLS_PATH}/library/ecp_curves.c

            ${PICO_MBEDTLS_PATH}/library/pk_wrap.c

            ${PICO_MBEDTLS_PATH}/library/pkparse.c

            ${PICO_MBEDTLS_PATH}/library/x509_crt.c

            ${PICO_MBEDTLS_PATH}/library/ssl_cli.c

            PROPERTIES

            COMPILE_OPTIONS "-Wno-cast-qual"

        )

        set_source_files_properties(

            ${PICO_MBEDTLS_PATH}/library/psa_crypto_client.c

            ${PICO_MBEDTLS_PATH}/library/psa_crypto_driver_wrappers.c

            PROPERTIES

            COMPILE_OPTIONS "-Wno-redundant-decls"

        )

    endfunction()

 

endif()

 

 

다음은 mbedtls가 빌드되어지도록 아래 diff 파일을 참고하여 CMakeLists 파일을 수정합니다.

diff --git a/src/rp2_common/CMakeLists.txt b/src/rp2_common/CMakeLists.txt

index 0d0f9b9..ff8df7c 100644

--- a/src/rp2_common/CMakeLists.txt

+++ b/src/rp2_common/CMakeLists.txt

@@ -61,6 +61,7 @@ if (NOT PICO_BARE_METAL)

     pico_add_subdirectory(cyw43_driver)

     pico_add_subdirectory(pico_lwip)

     pico_add_subdirectory(pico_cyw43_arch)

+    pico_add_subdirectory(pico_mbedtls)

     pico_add_subdirectory(pico_stdlib)

그런 다음 첨부된 애플리케이션 파일을 pico-examples/pico_w 디렉터리에 넣은 후 빌드하면 aws_mqtt_sub 애플리케이션이 빌드됩니다.

 

4. LED

WS2812 LED를 구동 시키기 위해 https://github.com/ForsakenNGS/Pico_WS2812를 참고하여 작성하였습니다. Publisher로부터 받은 메시지로부터 LED출력용 데이터를 구한 후 디스플레이 됩니다.

 

# 데모영상

아래 유투브 영상을 참고하시기 바랍니다.

 

# 첨부파일

관련 소스코드를 ZIP파일로 첨부하였습니다.

첨부파일
picow_quest4_rudals.zip 다운로드

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