Raspberry Pi Pico W로 시계 및 날씨 확인 제품을 만들어 보자. (4) ws2812 test 및 WIFI 시간 테스트

Raspberry Pi Pico W로 시계 및 날씨 확인 제품을 만들어 보자. (4)


이전 포스트 라즈베리파이 피코의 프로그래밍을 위해 thonny로 연결 후 led blink 까지 테스트 진행 했다. 이번엔 ws2812 LED Matrix 를 켜보고 시간 표기를 해주고, WIFI 로 시간 서버에서 시간을 받아와 보자.


1. ws2812 LED Matrix 연결

알리에서 구매한 

요녀석을 연결 해보자. 


후면에 5V , GND , DIN 이 있어. 그곳에 전원 라인(5V, GND) 를 따로 뽑아 주고, DIN과 GND 를 또 뽑아서 PICO 에 연결해 줬다.

내가 연결 해준곳은 GP22 번에 연결 해줬는데 바로 옆에 GND 가 있어서 그곳으로 연결했다.

wiring 은 이게 전부.. 참 간편하다. 일단 테스트용이니 5V 와 GND 를 파워 서플라이에 물려주고, 라즈베리 전원은 PC에서 USB 포트로 입력시켰다. 저렇게 전원이 다르면 GND에 전위차가 생겨 동작을 안할수 있으니, GND는 전원이 다르다면 절연 용이 아닌이상 묶어주는게 마음 편하다.

참고로 ws2812는 보통 PWM DMA를 사용해 주기를 이용해 한 비트의 펄스 길이를 만들어 주고 펄스 폭을 조정해 한 비트가 HIGH/LOW 인지 만들어 준다.

특정 LED 를 키기 위해 특정 데이터만 보내는것이 아니라, 내가 킬 LED 앞에 연결되 있는 모든 LED 데이터를 보내줘야 한다. 그래서 보통 LED 갯수만큼의 배열을 만들고 한개의 led만 킨다고 해도 모든 LED 데이터를 일괄로 보낸다.


2. MICRO PYTHON - neopixel module 사용.

micropython의 문서를 보면 neopixel module이 포함되어 있다. 간단히 import neopixel 이면 끝난다. 하드웨어 설정을 단 2줄로 끝낼수 있으니, 얼마나 편한가. 속도를 신경 쓰지 않는 프로젝트라면 간편하게 micropython 을 사용하자.

import neopixel
import time
from machine import UART,Pin,Timer,ADC,I2C,PWM

Pwm_Pin = Pin(22, Pin.OUT)
neo = neopixel.NeoPixel(Pwm_Pin, 256,bpp=3, timing=1)
count=0

def move():
    
    global neo    
    global count
    
    for i in range(256):
        neo[i] = (0,0,0)
    neo[count] = (10,0,0)
    count= count+1
    if count > 255:
        count=0
    neo.write()
    
def main():
    
    while True:
        move()
        time.sleep(0.02)

일단 출력할 핀 ( DIN에 연결한 GP22 ) 를 neopixel 에 쓸 핀으로 정한뒤, neopixel 클래스의 neopixel 함수를 사용 하면 되는데, 함수 원형은 

classneopixel.NeoPixel(pinn*bpp=3timing=1)

Construct an NeoPixel object. The parameters are:

  • pin is a machine.Pin instance.

  • n is the number of LEDs in the strip.

  • bpp is 3 for RGB LEDs, and 4 for RGBW LEDs.

  • timing is 0 for 400KHz, and 1 for 800kHz LEDs (most are 800kHz).

매개변수를 보면 사용할 pin , 그리고 led 갯수, RGB LED 인지 RGBW LED 인지, 그리고 timing 인데 ws2812는 800khz 를 쓴다.

나의 LED MATRIX는 16 x 16 = 256개 LED 이다. 그리고 RGB LED 이고

그래서 neo = neopixel.NeoPixel(Pwm_Pin, 256,bpp=3, timing=1) 이렇게 사용했다.

그리고 1번째 LED 부터 순차로 키면서 LED 가 어떻게 배열이 되있는지 알아볼려고 move 함수를 만들었다.

move 함수 내에선 아까 만든 neo 오브젝트가 배열 처럼 사용 되어, 함수 초반엔 neo led 를 (0,0,0)으로 초기화 값은 (R,G,B)이고 각각 unsigned char (uint8_t) 크기로 0부터 255까지 지정 할수 있다, 0 이면 off , 숫자가 올라갈수록 led 의 세기가 밝아진다.

count 를 적용해서 한번에 한개의 led 씩 순차로 키고, main 문의 while 에서 0.02초 단위로 move 함수를 적용 했다.


일단 방향과 led 배열은 



이런식으로 라인이 이어져 있어서 내가 원하는 배열로 맞추기 위해선 배열 군대 군대 값의 순서를 변경해 줘야 한다. 

1   2   3   4   5

6   7   8   9  10

11 12 13 14 15

이런식의 배열을 원했는데...... LED 배치와 아트웍 라인을 최소화 하기 위해 어쩔수 없이 저렇게 만들어 진듯 하다. ㅠㅠ


3. WIFI 및 시간 설정

자 그럼 시간 표시를 해볼까. 시간 표시는 대충 레이아웃을 잡았을때 


이렇게 표시를 해줄까 한다. 윗부분은 날씨를 보여줘야 하니. 넘어가고.

시간은 time 모듈을 이용해서 time.localtime() 이면 현재 시스템 시간을 불러 올수 있다. 하지만 배터리가 없어 rtc 적용이 불가하여, 전원을 제거후 다시 연결하면 시스템 초기 시간을 불러 오게 된다. 그래서 이부분을 개선하기 위해 wifi 를 이용해 인터넷 연결후 , http 메서드를 사용하여 worldtime api 에서 서울 시간을 불러와 보자.

일단 wifi 연결은 역시 micropython 의 network 모듈을 사용하면 쉽게 연결이 가능하다.

추가된 내용은 

import time
import network
import urequests

ssid = "xxxxxx"
passwd = "xxxxxxxxx"

def connect():
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    wlan.connect(ssid,passwd)    
    while wlan.isconnected() != True:
        time.sleep(1)
    print("wifi connected")
    time.sleep(1)
    
    for i in range(10):
        
        try:
            r = urequests.get("http://worldtimeapi.org/api/timezone/Asia/Seoul")
            time_buf = r.json().get("datetime") 
            rtc = machine.RTC()    
            rtc.datetime((int(time_buf[:4]),int(time_buf[5:7]),int(time_buf[8:10]),0,int(time_buf[11:13]),int(time_buf[14:16]),int(time_buf[17:19]),0))
            print("get time")
            r.close()
            break
        except Exception as e:
            print(e)
            
        time.sleep(1)

def main():
    
    connect()  
    


이렇게 connect 함수를 추가했고. http 메서드를 사용하기 위해 urequests 모듈도 추가했다.

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(ssid,passwd)

3줄이면 wifi 연결은 된다.  ssid 및 passwd 는 내가 사용하는 wifi의 이름과 비번을 넣으면 되고, 그후 연결 확인을 하는 구문을 추가했다.

그다음 urequests.get(url) 구문을 보내면 응답이 오는데, 그걸 r 변수에 넣고 json 형식이라 내가 필요한 부분 "datetime"만 가져와서 time_buf 에 넣었다.

그다음 machine 모듈중 rtc 기능에 datetime 함수를 사용하여 시간을 형식에 맞게 넣어줬다, 그중 weekday 와 subseconds 는 찾아오기 구찮아서 그냥 0으로 넣었다.

테스트 도중 간간히 http error 가 발생해 for 문을 이용해 몇번 더 확인 하고 확인 되면 break 로 빠져나가게 했다.

그렇게 불러온 시간은 시스템에 저장 되고, time.locatime() 으로 시간을 불러 올수 있다.


시간을 LED 로 표시하는건 다음 회차때 올려야 겠다.

다음엔 숫자를 표시하는 class 를 새로 만들어 불러와 써야겠다. 

4탄 끝.

댓글

이 블로그의 인기 게시물

T-PICOC3(MICROPYTHON)으로 WIFI 를 연결해보자. (1)

Raspberry Pi pico W 로 시계 및 날씨 확인 제품을 만들어 보자. (1) 구상 단계