Search

파이썬으로 하는 피지컬 컴퓨팅 실습(라즈베리파이 피코 W)

생성일
2025/08/15 19:12
태그
안녕하세요! 두부쌤 입니다~
이번 시간에는 파이썬을 통한 피지컬 컴퓨팅 수업에 대해 간단하게 소개해 드리려고 합니다.
마이크로컨트롤러 보드는 라즈베리파이 피코 W를 활용했습니다.
(라즈베리파이 외에도 괜찮은 교구가 많이 있으니 학교 사정에 맞게 구입하시면 될 것 같습니다 ^^)

■ 피지컬 컴퓨팅 시뮬레이션

WOKWI는 회원가입 없이 온라인으로 간단하게 시뮬레이션을 진행할 수 있는 사이트입니다.
시뮬레이션을 통해 하드웨어 부품 배치와 배선을 확인하고 프로그래밍을 미리 해볼 수 있습니다.
※ 실제 프로그래밍은 Thonny에서 진행합니다.
1.
라즈베리파이 시뮬레이션의 진행은 ‘Pi Pico’를 선택해서 할 수 있습니다.
2.
스타터 템플릿은 원하는 언어를 선택하면 되지만, 저는 ‘Micropython’을 선택하여 진행하겠습니다.
3.
파이썬 코드를 작성하여 시뮬레이션을 해 볼 수 있는 페이지가 나타납니다.
3.
피코의 내장 LED를 깜빡이는 코드를 작성하여 시뮬레이션을 진행해 보겠습니다.
다음은 피코의 내장 LED를 깜빡이게 하는 코드입니다.
from machine import Pin import time # GP25 = Pico 보드에 있는 내장 LED 핀 led = Pin("LED", Pin.OUT) while True: led.toggle() # 현재 상태 반전 (켜기/끄기) time.sleep(0.5) # 0.5초 대기
Python
복사
4.
코드를 작성하고 시뮬레이션 영역에서 ‘start the simulation’ 버튼을 눌러 프로그램을 동작해 보면 LED 가 깜박이는 것을 확인해 볼 수 있습니다.
다음으로 다양한 키트를 추가하는 방법에 대해 알아보겠습니다~
1.
시뮬레이션 영역에서 ‘Add a new part’버튼을 누르면 다양한 키트를 추가할 수 있습니다.
2.
여기에서는 LCD 16x2(I2C)를 추가해서 배선을 확인해보겠습니다.
3.
추가한 LCD의 GND핀을 마우스로 클릭해 보면 Pico에 연결해야하는 부분이 하얀색으로 표시됩니다. 오른쪽과 같이 연결할 위치를 클릭하면 전선이 연결되는것을 확인할 수 있습니다.
4.
나머지 핀인 VCC, SDA, SCL도 모두 연결해보겠습니다.
5. 이제 아래 코드를 왼쪽 코드 입력창에 입력하고 실행해보겠습니다.
(LCD 제어는 코드가 조금 복잡합니다. 전체적인 코드 설명보다는 중요한 부분에 대한 설명과 실행에 초점을 맞추면 좋을 것 같습니다.)
1.
main.py
from machine import I2C, Pin import utime # --- I2C LCD 제어 클래스 --- class I2cLcd: MASK_RS = 0x01 MASK_RW = 0x02 MASK_E = 0x04 SHIFT_BACKLIGHT = 3 LCD_BACKLIGHT = 1 << SHIFT_BACKLIGHT LCD_NOBACKLIGHT = 0x00 def __init__(self, i2c, i2c_addr, num_lines, num_columns): self.i2c = i2c self.i2c_addr = i2c_addr self.num_lines = num_lines self.num_columns = num_columns self.backlight = self.LCD_BACKLIGHT self._init_lcd() def _init_lcd(self): utime.sleep_ms(50) self._write_init_nibble(0x03) utime.sleep_ms(5) self._write_init_nibble(0x03) utime.sleep_ms(5) self._write_init_nibble(0x03) utime.sleep_ms(2) self._write_init_nibble(0x02) # 4비트 모드 self._command(0x28) # 4비트, 2라인, 5x8 폰트 self._command(0x08) # 디스플레이 OFF self._command(0x01) # 화면 지우기 utime.sleep_ms(2) self._command(0x06) # 엔트리 모드 self._command(0x0C) # 디스플레이 ON def clear(self): self._command(0x01) utime.sleep_ms(2) def move_to(self, col, row): row_offsets = [0x00, 0x40, 0x14, 0x54] self._command(0x80 | (col + row_offsets[row])) def putstr(self, string): for ch in string: self._write(ord(ch), self.MASK_RS) def _command(self, cmd): self._write(cmd, 0) def _write(self, data, mode): high = data & 0xF0 low = (data << 4) & 0xF0 self._write_byte(high | mode) self._write_byte(low | mode) def _write_byte(self, byte): self.i2c.writeto(self.i2c_addr, bytes([byte | self.backlight])) self._toggle(byte) def _toggle(self, byte): self.i2c.writeto(self.i2c_addr, bytes([byte | self.MASK_E])) utime.sleep_us(500) self.i2c.writeto(self.i2c_addr, bytes([byte & ~self.MASK_E])) utime.sleep_us(500) def _write_init_nibble(self, nibble): self._write_byte((nibble << 4) & 0xF0) # I2C1 버스 사용: SDA=GP2, SCL=GP3 (diagram.json과 일치) i2c = I2C(1, sda=Pin(2), scl=Pin(3), freq=100000) # (선택) 주소 스캔해서 확인 print("scan:", [hex(x) for x in i2c.scan()]) lcd = I2cLcd(i2c, 0x27, 2, 16) lcd.clear() lcd.putstr("Hello World!") lcd.move_to(0, 1) lcd.putstr("Hi, Gilbut!") while True: utime.sleep(1)
Python
복사
2.
diagram.json
{ "version": 1, "author": "Anonymous maker", "editor": "wokwi", "parts": [ { "type": "wokwi-pi-pico", "id": "pico", "top": 112.05, "left": -54, "attrs": { "env": "micropython-20241129-v1.24.1" } }, { "type": "wokwi-lcd1602", "id": "lcd1", "top": -70.4, "left": 53.6, "attrs": { "pins": "i2c" } } ], "connections": [ [ "lcd1:GND", "pico:GND.1", "black", [ "h0" ] ], [ "lcd1:VCC", "pico:3V3", "red", [ "h0" ] ], [ "lcd1:SDA", "pico:GP2", "green", [ "h0" ] ], // GP2 로 변경 [ "lcd1:SCL", "pico:GP3", "green", [ "h0" ] ] ], "dependencies": {} }
JSON
복사
6.
코드를 모두 작성하였으면 ‘start the simulation’ 버튼을 눌러 동작을 확인해 봅니다.
이렇게 정상적으로 출력되는 것을 확인할 수 있습니다!
이처럼 WOKWI를 통해 온라인으로 간단하게 시뮬레이션을 진행할 수 있습니다.
실제 피지컬 컴퓨팅 수업에서는 교사의 교구 실습을 모든 학생이 직접 보기 힘들기에, 이러한 시뮬레이션을 활용하면 수업 내용을 보다 명확하게 전달할 수 있습니다.
또한 학생들이 사이트에서 직접 시뮬레이션을 해보고 즉각적으로 결과를 확인할 수 있기에 학습 효율을 높이는 데에도 유용합니다!

Thonny를 통한 피지컬 컴퓨팅

이제 Thonny를 통해 직접 프로그래밍을 진행해보도록 하겠습니다~
먼저 아래 사이트에서 Thonny를 다운받아 설치합니다.
다음으로 아래 사이트에서 라즈베리파이 피코 W의 펌웨어를 다운받습니다.
(펌웨어는 보드마다 다릅니다. 저는 라즈베리파이 피코 W를 활용했습니다.)
라즈베리파이 피코의 경우 피코에 있는 BOOTSEL 버튼을 누른 채 USB로 연결하면 드라이브처럼 인식이 돼 펌웨어를 올릴 수 있는 상태가 됩니다. 이후 드라이브 폴더를 열고 그곳에 다운 받은 펌웨어를 붙여넣으면 됩니다. 그다음 USB 연결을 해제한 후 BOOTSEL 버튼을 누르지 않고 다시 USB를 연결합니다.
이제 Thonny를 실행한 후, [실행] - [인터프리터 선택]을 클릭합니다.
옵션에서 [인터프러티] - [MicroPython (Raspberry Pi Pico)]를 선택합니다. [포트]는 USB가 연결된 장치로 선택하면 됩니다.
확인을 누르고 Thonny의 오른쪽 하단이 MicroPython으로 잘 설정되어있는지 확인합니다.
이제 시뮬레이션에서 실행했던 다음 코드를 입력하고 잘 연결되었는지 확인해보겠습니다.
from machine import Pin import time # GP25 = Pico 보드에 있는 내장 LED 핀 led = Pin("LED", Pin.OUT) while True: led.toggle() # 현재 상태 반전 (켜기/끄기) time.sleep(0.5) # 0.5초 대기
Python
복사
실행을 누르고 이 컴퓨터를 선택합니다.
LED가 잘 깜빡이는 걸 확인할 수 있습니다~
다음으로 시뮬레이션에서 진행했던 LCD에 글자 출력하기를 해보겠습니다.
시뮬레이션으로 했던 것처럼 케이블을 연결한 후, 다음 코드를 실행합니다.
from machine import I2C, Pin import utime class I2cLcd: MASK_RS = 0x01 MASK_RW = 0x02 MASK_E = 0x04 SHIFT_BACKLIGHT = 3 LCD_BACKLIGHT = 1 << SHIFT_BACKLIGHT LCD_NOBACKLIGHT = 0x00 def __init__(self, i2c, i2c_addr, num_lines, num_columns): self.i2c = i2c self.i2c_addr = i2c_addr self.num_lines = num_lines self.num_columns = num_columns self.backlight = self.LCD_BACKLIGHT self._init_lcd() def _init_lcd(self): utime.sleep_ms(50) self._write_init_nibble(0x03); utime.sleep_ms(5) self._write_init_nibble(0x03); utime.sleep_ms(5) self._write_init_nibble(0x03); utime.sleep_ms(2) self._write_init_nibble(0x02) # 4-bit self._command(0x28) # 4-bit, 2-line, 5x8 self._command(0x08) # display off self._command(0x01) # clear utime.sleep_ms(2) self._command(0x06) # entry mode self._command(0x0C) # display on, cursor off def clear(self): self._command(0x01); utime.sleep_ms(2) def move_to(self, col, row): row_offsets = [0x00, 0x40, 0x14, 0x54] self._command(0x80 | (col + row_offsets[row])) def putstr(self, string): for ch in string: self._write(ord(ch), self.MASK_RS) def _command(self, cmd): self._write(cmd, 0) def _write(self, data, mode): high = data & 0xF0 low = (data << 4) & 0xF0 self._write_byte(high | mode) self._write_byte(low | mode) def _write_byte(self, byte): # 백라이트 유지 self.i2c.writeto(self.i2c_addr, bytes([byte | self.backlight])) # 토글에도 백라이트/RS 등 기존 비트 유지 self._toggle(byte | self.backlight) def _toggle(self, byte): self.i2c.writeto(self.i2c_addr, bytes([byte | self.MASK_E])) utime.sleep_us(500) self.i2c.writeto(self.i2c_addr, bytes([byte & ~self.MASK_E])) utime.sleep_us(500) def _write_init_nibble(self, nibble): self._write_byte((nibble << 4) & 0xF0) # I2C0 (SDA=GP0, SCL=GP1) i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=100000) print("scan:", [hex(x) for x in i2c.scan()]) lcd = I2cLcd(i2c, 0x27, 2, 16) lcd.clear() lcd.putstr("Hello World!") lcd.move_to(0, 1) lcd.putstr("Hi, Gilbut!") while True: utime.sleep(1)
Python
복사
정상적으로 잘 출력되고 있습니다~
이처럼 라즈베리파이 피코와 Thonny 그리고 WOKWI 시뮬레이션을 함께 활용하면 하드웨어 실습과 프로그래밍을 한 번에 경험할 수 있는 통합적인 수업 구성이 가능합니다.
저희 학생들 역시 시뮬레이션을 통해 사전 이해를 높이고 실제 보드 실습에서 코드를 실행하며 시뮬레이션에 대한 즉각적인 피드백을 받음으로써 높은 몰입도와 흥미를 가지고 재미있게 수업에 참여했습니다! 물론 파이썬 코드 부분이 많이 어렵지만… 다양한 보조 자료를 통해 코드에 대한 부담감을 많이 줄이려고 했습니다.
(모듈에 대한 실습 후 간단한 프로젝트 활동을 진행할 수 있습니다. 이 부분은 기회가 된다면 다음에 소개하도록 하겠습니다~)
이번 뉴스레터가 선생님들의 피지컬 컴퓨팅 수업 구상에 작은 보탬이 되었길 바랍니다!
다음 달에 뵙겠습니다~
감사합니다!