콘테스트 프로젝트 진행 상황
각 Quest를 단계적으로 완성하는 프로젝트입니다.
Quest 1: 클라우드 동적 메시지 보드
2022.08.13
1. 아이디어 소개
광고나 공지사항 등을 전달하는 메시지 보드를 클라우드 환경을 사용하여 제작하려 합니다. 기존의 버스나 건물에 사용하는 메시지 보드는 리모컨 등을 사용하여 메시지를 설정하는데 이는 사용자가 자주 메시지 내용을 바꾸고 싶을 때는 매우 불편할 것이라 생각합니다. ‘클라우드 접속이 되는 인터넷 환경에서 사용자가 언제든 메시지 보드의 내용을 바꿀 수 있다면 매우 편리하지 않을까?’ 하는 아이디어에서 시작하게 되었습니다.
2. 전체 구조

- 사용자가 표시하고자 하는 메시지를 클라우드 서버에 입력
- 메시지 보드는 클라우스 서버에서 메시지를 추출하여 디스플레이
- 메시지 주변의 LED Light Strip으로 해당하는 메시지의 중요도 표시
3. 하드웨어 구성

4. 소프트웨어 구성

Quest 2: 클라우드 동적 메세지 보드 - 개발 환경 구성 (툴 설치 및 클라우드 환경 설정)
2022.08.28
1. 개발 툴 설치

MicroPython을 사용하기 위해서 Thonny를 설치하였습니다.

일반적인 설정으로 설치를 마무리하였습니다.

설치를 마무리하고 Pico W에 UF2 파일를 업로드하고 WiFi 연결 테스트 코드를 작성하여 테스트해 보았습니다.
2. AWS IoT 연결

AWS 계정을 생성하고 결제 정보 등을 등록하였습니다.

AWS IoT에 Security Key 및 Policy 등을 설정하였습니다.

my_pico_w 이름으로 장치를 등록하고 Certificate와 Key를 생성하여 Pico W에 다운로드 하였습니다.
Quest 3: 클라우드 연결 및 데이터 업로드
2022.09.11

설치를 마무리하고 Pico W에 UF2 파일를 업로드하고 WiFi 연결 테스트 코드를 작성하여 테스트해 보았습니다.
2. AWS IoT 연결

AWS 계정을 생성하고 결제 정보 등을 등록하였습니다.

AWS IoT에 Security Key 및 Policy 등을 설정하였습니다.

my_pico_w 이름으로 장치를 등록하고 Certificate와 Key를 생성하여 Pico W에 다운로드 하였습니다.
Quest 4: [Quest 4] 클라우드 동적 메시지 보드
2022.10.03
클라우드 동적 메시지 보드
1. 아이디어
광고나 공지사항 등을 전달하는 메시지 보드를 클라우드 환경을 적용한다면 기존의 버스나 건물에 사용하는 메시지 보드의 리모컨 등을 사용하여 메시지를 설정하는 불변함을 해소하고 사용자가 자주 메시지 내용을 변경하고자 하는 경우에도 인터넷 환경에 있는 장소라면 어디든지 상관없이 메시지 보드의 내용을 업데이트 할 수 있어서 유용하게 활용할 수 있을까? 하는 아이디어로 제작을 하게 되었습니다.
2. 전체 구조 
1. 사용자가 표시하고자 하는 메시지를 클라우드 서버에 Publish
2. 메시지 보드는 클라우스 서버에서 메시지를 Subscribe하여 디스플레이
3. 메시지 주변의 LED Light Strip으로 해당하는 메시지의 중요도 또는 그래픽적 효과 표시
3 하드웨어 구성

4. 소프트웨어 구성
.png)
5. 소스 코드
"""
Dynamic Message Board Source File
"""
import os
import sys
import _thread
import time
import machine
from machine import Pin, SPI, PWM
import micropython
from micropython import const
from dot_matrix_MAX7219 import DotMatrix_MAX7219_8x8
from led_WS2812B import LED_WS2812B
DM_INITIAL_BRIGHTNESS = const(0)
SSID = "xxxxxxxx"
PASSWORD = "xxxxxxxx"
# AWS IoT Endpoint
MQTT_BROKER_ENDPOINT = "xxxxxxxxx.iot.us-west-1.amazonaws.com"
FILE_KEY = "private.der"
FILE_CRT = "certificate.der"
_lock_print = _thread.allocate_lock()
_lock_time = _thread.allocate_lock()
_dm = DotMatrix_MAX7219_8x8(use_HW_SPI = True, SPI_select = 1, SPI_frequency_Hz = 64000000)
_led = LED_WS2812B(lock_time = _lock_time, gpio_DIN = 28, LED_count = 66)
_messageData = None # 메시지 데이터
_LED_Data = None # LED 데이터
# MQTT 메시지 수신
def callback_mqtt(topic, payload_UTF8, payload_Bytes):
global _messageData # 메시지 데이터
global _LED_Data # LED 데이터
data = json.loads(payload_UTF8)
_messageData = (data["message"], data["message_brightness"], data["message_speed"], data["message_timeout"])
_LED_Data = (data["LED"], (data["LED_color"]["red"], data["LED_color"]["green"], data["LED_color"]["blue"]), data["LED_speed"], data["LED_timeout"])
# 메시지 표시 업데이트
def update_MessageDisplay():
global _messageData # 메시지 데이터
if _messageData is not None:
(message, message_brightness, message_speed, message_timeout) = _messageData
_messageData = None
# 메시지 표시 초기화
_ms.time_ms = 0
_ms.period_ms = _pico.constrain(round(5 / max(float(message_speed), 0.1)), 5, 50) # 메시지 표시 주기 (범위: 5 ~ 50)
lines = message.split("\n")
_ms.messageList = [line for line in lines if line.strip() != ""] # 공백 라인 제거
if len(_ms.messageList) < 1: _ms.messageList = [""]
_ms.lineCount = len(_ms.messageList)
_ms.timeout = max(int(message_timeout) * 1000, 0) # 유지 시간 (단위: msec, 0인 경우 계속 유지)
_ms.line = -1
_ms.sequence = _ms.sequenceLength
_dm.set_Brightness(_pico.constrain(int(float(message_brightness) * 15), 0, 15)) # 밝기 설정 (범위: 0 ~ 15)
_ms.time_ms += 1
if _ms.time_ms >= _ms.period_ms:
_ms.time_ms = 0
MESSAGE_START_OFFSET = 25
MESSAGE_START_DELAY = 15
_ms.sequence += 1
if _ms.sequence >= _ms.sequenceLength:
_ms.line += 1
if _ms.line >= len(_ms.messageList): _ms.line = 0
_ms.sequence = 0
_ms.sequenceLength = len(_ms.messageList[_ms.line]) * 8 + 8 + MESSAGE_START_DELAY + MESSAGE_START_OFFSET
if _ms.timeout >= 0:
if _ms.sequence <= 8:
_dm.clear()
_dm.draw_Text(_ms.messageList[_ms.line], MESSAGE_START_OFFSET, 8 - _ms.sequence)
_dm.update()
elif _ms.sequence <= (8 + MESSAGE_START_DELAY):
pass
else:
_dm.clear()
_dm.draw_Text(_ms.messageList[_ms.line], MESSAGE_START_DELAY + MESSAGE_START_OFFSET + 8 -_ms.sequence, 0)
_dm.update()
# LED 표시 업데이트
def update_LED_Display():
global _LED_Data # LED 데이터
global _ld
if _LED_Data is not None:
(LED, LED_color, LED_speed, LED_timeout) = _LED_Data
_LED_Data = None
_ld.time_ms = 0
_ld.period_ms = _pico.constrain(round(5 / max(float(LED_speed), 0.1)), 5, 50) # LED 표시 주기 (범위: 5 ~ 50)
LED_timeout = None if int(LED_timeout) <= 0 else float(LED_timeout)
_led.start_PatternLoop(str(LED), fade_in_out = True, direction = True, color = tuple(LED_color), timeout = LED_timeout) # 패턴 루프 시작 (패턴: "BREATH" "COLOR_OVER_RAINBOW" "RAINBOW_CYCLE" "THEATER_CHASE_RAINBOW")
_ld.time_ms += 1
if _ld.time_ms >= _ld.period_ms:
_ld.time_ms = 0
_led.process_PatternLoop()
# main 함수
def main():
global _messageData # 메시지 데이터
global _LED_Data # LED 데이터
_pico.UART0_init(baudrate = 115200, gpio_tx = 0, gpio_rx = 1, rx_invert = True) # UART0 초기화
_pico.UART1_init(baudrate = 115200, gpio_tx = 8, gpio_rx = 9) # UART1 초기화
_led.clear(update = True)
_dm.set_Brightness(DM_INITIAL_BRIGHTNESS) # 밝기 설정 (범위: 0 ~ 15)
_dm.clear()
_dm.draw_Text("[ INITIALIZING ]", 0, 0, 1)
_dm.update()
# 네트워크 연결
print("Connnecting Network (SSID: " + SSID + ")", end = "")
wifi.connect(SSID, PASSWORD) # 네트워크 연결
_dm.clear()
_dm.draw_Text("[NETWORK ONLINE]", 0, 0, 1)
_dm.update()
# MQTT Broker 연결
if mqttClient.connect_To_AWS_MQTT_Broker(MQTT_BROKER_ENDPOINT, FILE_KEY, FILE_CRT): # MQTT Broker 연결 (AWS MQTT Broker)
if DEBUG: print(" → Success")
else:
if DEBUG: print(" → Failure [System Reset]")
machine.reset() # 시스템 리셋
# MQTT Subscribe
public_IP = _http_api.get_GeolocationData()[1]
topic = "dynamic message to Pico W"
mqttClient.subscribe(topic) # MQTT Subscribe (Topic: weather data 59.6.230.229)
_dm.clear()
while True:
mqttClient.process_CheckMessage() # MQTT 메시지 처리
update_LED_Display() # LED 표시 업데이트
sys.exit()
def thread_SubCore():
while True:
update_MessageDisplay()
_thread.exit()
if __name__ == "__main__":
main()
6. 회로도

7. 시연 동영상
8. 제작 소감
우선 적용된 Raspberry Pi Pico W를 사용하면서 느낀 장점은 파이썬 언어를 사용하여 보다 친숙하게 개발이 가능하였던 것과 2개의 스레드를 사용할 수 있어서 작업 프로세스를 적절히 분할하여 사용할 수 있고 서로 간섭없이 처리가 이루어져서 속도에 큰 장점이 있다는 것입니다. 특히 Pico W에는 와이파이 기능이 탑재되어 매우 저렴한 가격으로 인터넷을 활용하는 어플리케이션이 제작 가능한 것이 큰 경쟁력이라고 생각합니다. 또한 이번 프로젝트에는 사용하지 않았지만 일반적인 MCU와는 달리 기본적으로 파일시스템이 적용되어 저장 공간에 파일을 생성, 입출력이 가능하다는 것이 타 MCU와 구별되는 장점이라고 생각되었습니다. 느꼈던 가장 큰 단점으로는 실시간 디버깅이 지원되지 않기 때문에 print 함수 만을 사용하여 프로그램의 작동과 오류를 검출하는 것이 시간이 오래 걸리고 불편했다는 점입니다. 이번 프로젝트를 통해서 파이썬 언어를 펌웨어 개발에 활용하는데 많은 기법을 익힐 수 있었으며 다중 스레드에서 효과적으로 하드웨어를 제어하고 처리 속도를 향상시키는데 좋은 경험과 공부가 되었습니다. 앞으로도 이러한 MAKE 콘테스트 행사가 더 활발해진다면 공부하는 학생들과 현업의 엔지니어들에게 동기부여가 되어 기술발전에 도움이 될 것이라고 생각합니다.
프로젝트 갤러리
프로젝트 제작 과정과 최종 결과물을 담은 이미지 갤러리입니다.












![[Quest 4] 클라우드 동적 메시지 보드](https://cdn.e4ds.com/make/images/3h8ptuu6tu7ctj5jemrc.png)
![[Quest 4] 클라우드 동적 메시지 보드](https://cdn.e4ds.com/images/ck/skkz58hqm2j479b2thqo.png)
![[Quest 4] 클라우드 동적 메시지 보드](https://cdn.e4ds.com/images/ck/tpo7wylqphcq8l0ra9wo.png)
![[Quest 4] 클라우드 동적 메시지 보드](https://cdn.e4ds.com/images/ck/sjqciy5er5uksq5novnr(1).png)
프로젝트 자료실
프로젝트를 재현하거나 학습하는데 필요한 모든 자료를 제공합니다.
등록된 자료가 없습니다.
프로젝트 소개
아직 등록된 프로젝트 소개가 없습니다.
코드 & 회로도
등록된 코드/회로 자료가 없습니다.
댓글 0개
아직 댓글이 없습니다. 첫 댓글을 남겨보세요!
