수행기록퀘스트4
# 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 다운로드
로그인 후
참가 상태를 확인할 수 있습니다.