이 블로그는 임베디드 컴퓨터를 이용한 장치(시스템) 개발과 원격제어에 필요한 지식을 공유 하기 위한 블로그 입니다.
실제 개발과 프로그램 예를 위하여 Microchip 사의 ATmega128를 사용한 보드와 Arduino Mega 보드(ATmega2560), Raspberry Pi Pico, Raspberry Pi, WiFi 모듈을 사용 합니다.

python-i2c

Raspberry Pi Pico I2C - MicroPython
Raspberry Pi Pico I2C(Inter-Integrated Circuit) 통신 - MicroPython


  • Pi Pico I2C 통신
    • I2C object(class I2C)
      • I2C는 2개의 Bus line을 사용하여 장치 간 통신을 한다. SCL(클럭)과 SDA(데이터) 2개의 통신 선을 사용한다.

        참고자료: ATmega128 I2C 통신

      • I2C object 생성자(Constructors): class machine.I2C(id=- 1, *, scl, sda, freq=400000)
        • id: I2C 장치의 식별자 이다. id 가 -1(기본값)인 경우 I2C는 소프트웨어로 구현된다. 이 경우 SCL 및 SDA에 핀을 활당하여야 한다. id에 허용되는 다른 값은 특정 보드에 따라 다르며 scl 및 sda 지정은 경우에 따라 필수 또는 허용되지 않을 수 있다. Pi Pico 모듈을 사용하는 경우에는 I2C 번호(Software I2C인 경우 생략할 수 있음)와 scl와 sda 핀을 지정하여야 한다.
        • scl: SCL 선의 Pin 객체이다.
        • sda: SDA 선의 Pin 객체이다.
        • freq: SCL clock rate
      • 일반적인 Method
        • I2C.init(scl, sda, *, freq=400000): I2C 버스를 초기화한다.
        • I2C.deinit(): I2C bus를 Turn off 한다.
        • I2C.scan(): 0x08과 0x77(포함) 사이의 모든 I2C 주소를 스캔하고 응답하는 주소 목록을 반환한다. 장치는 주소(write bit 포함)가 버스로 전송된 후 SDA 라인을 로우로 하면 응답한다.
      • I2C 기본 동작
        • start(): 버스에 START 조건을 생성한다.(SCL이 높은 동안 SDA가 낮음으로 전환됨).
        • stop(): 버스에 STOP 조건을 생성한다.(SCL이 높은 동안 SDA가 높음으로 전환됨).
        • readinto(buf, nack=True): 버스에서 테이터(Byte)를 읽어 buf에 저장한다. 읽은 바이트 수는 buf의 길이 이다. ACK는 마지막 바이트를 수신 한 후에 버스로 전송된다. 마지막 바이트가 수신 된 후, nack가 참이면 NACK가 전송되고 그렇지 않으면 ACK가 전송된다.(이 경우 슬레이브는 연속되는 호출에서 더 많은 바이트를 읽을 것이라고 가정한다).
        • I2C.write(buf): buf에서 버스에 테이터(Byte)를 Write 한다. 각 테이터(Byte)를 Write한 다음 ACK가 수신되었는지 확인하고 NACK가 수신되면 나머지 테이터(Byte) 전송을 중지한다. 이 함수는 수신 된 ACK 수를 반환한다.
      • 표준 Bus 동작
        • 다음 Method는 슬레이브 장치를 대상으로 하는 표준 I2C 읽기 및 쓰기 Method 이다.

        • I2C.readfrom(addr, nbytes, stop=True): addr로 지정된 슬레이브에서 n 바이트를 읽는다. stop이 참이면 전송이 끝날 때 STOP 조건이 생성된다. 읽은 데이터가있는 바이트 열 객체를 반환한다.
        • I2C.readfrom_into(addr, buf, stop=True): addr에 의해 지정된 슬레이브에서 테이터(Byte)를 읽어 buf에 저장한다. 읽은 바이트 수는 buf의 길이 이다. stop이 참이면 전송이 끝날 때 STOP 조건이 생성한다. 이 메서드는 None을 반환한다.
        • I2C.writeto(addr, buf, stop=True): buf에 저장된 테이터(Byte)를 addr로 지정된 슬레이브에 write 한다. Bus에 데이터(Byte)를 write한 다음 NACK가 수신되면 나머지 테이터는 전송되지 않는다. stop이 True이면 전송이 끝날 때 STOP 조건이 생성된다. 이 함수는 수신 된 ACK 수를 반환한다.
        • I2C.writevto(addr, vector, stop=True): 벡터에 포함 된 테이터(Byte)를 addr로 지정된 슬레이브에 write 한다. 벡터는 Tuple 또는 Object 목록이어야 한다. addr가 한 번 전송 된 다음 벡터 내의 각 객체로 부터 테이터(Byte)가 순차적으로 Write 된다. 벡터의 객체는 길이가 0 바이트 일 수 있으며이 경우 데이터는 출력되지 않는다. 벡터의 객체 중 하나에서 테이터(Byte)를 쓴 다음 NACK가 수신되면 나머지 테이터(Byte)와 나머지 객체는 전송되지 않는다. stop이 참이면 NACK가 수신 되더라도 전송이 끝날 때 STOP 조건이 생성된다. 이 함수는 수신 된 ACK 수를 반환한다.
      • Memory 동작
        • 일부 I2C 장치는 읽고 쓸 수있는 메모리 장치(or 레지스터 세트)역할을 한다. 이 경우 Slave address와 Memory address가 필요하다. 다음 Method는 이러한 장치와 통신하기 위한 기능이다.

        • I2C.readfrom_mem(addr, memaddr, nbytes, *, addrsize=8)
          • addr로 지정한 슬레이브의 메모리 주소(memaddr)에서 시작하여 n 바이트를 읽는다. 인수 addrsize는 주소 크기를 비트 단위로 지정한다. 읽은 데이터가 저장된 바이트 열 객체를 반환한다.
        • I2C.readfrom_mem_into(addr, memaddr, buf, *, addrsize=8)
          • addr로 지정한 슬레이브의 메모리 주소(memaddr)에서 데이터(Byte)를 읽어 buf에 저장한다. 읽은 바이트 수는 buf의 길이 이다. 인수 addrsize는 주소 크기를 비트 단위로 지정한다(ESP8266에서 이 인수는 인식되지 않으며 주소 크기는 항상 8 비트이다). 이 메서드는 None을 반환한다.
        • I2C.writeto_mem(addr, memaddr, buf, *, addrsize=8)
          • addr로 지정한 슬레이브의 메모리 주소(memaddr)에 buf에 저장된 데이터(Byte)를 순차적으로 Write 한다. 인수 addrsize는 주소 크기를 비트 단위로 지정한다(ESP8266에서 이 인수는 인식되지 않으며 주소 크기는 항상 8 비트이다). 이 메서드는 None을 반환한다.

    • I2C 통신을 이용한 측정 과 제어 시스템 구성 예
    • I2C 통신을 이용한 측정 과 제어 시스템 구성도

      주: I2C Pull-Up 저항은 Pi Pico 모듈에 내장되어 있기 때문에 이 구성도에는 생략되었음.


    • 프로그램 예: DS1621을 사용한 온도 측정
      • 윗 I2C 통신을 이용한 측정 과 제어 시스템 구성 예에서 Pi Pico 개발보드를 Master로 디지털 온도 센서(DS1621)를 Slave device로 사용 한다. 이 예에서는 이해를 쉽게하기 위하여 온도측정에 필요한 최소한의 기능만 구현한다. 확장된 기능은 DS1621 Library를 사용하는 예를 참고 바람.

      • DS1621을 사용한 온도 측정 프로그램 예: python_i2c_ds1621_basic.py
      • 실험을 위한 준비
        • Pi Pico 개발보드와 온도 센서(DS1621)의 I2C 통신선 연결
          • Pi Pico 개발보드 SDA(GP20) <-> DS1621 SDA(Pin1) : 2-wire serial 통신을 위한 Data input/output pin.
          • Pi Pico 개발보드 SCL(GP21) <-> DS1621 SCL(Pin2) : 2-wire serial 통신을 위한 Clock input/output pin.
          • Pi Pico 개발보드 Pin 36 3.3V <-> DS1621 VDD(Pin8) : VDD pin.
          • Pi Pico 개발보드 Pin 38 GND <-> DS1621 GND(Pin4) : Ground pin.
        • 온도센서 번호(번지) 설정 하기
          • DS1621의 Pin7(A0), Pin6(A1), Pin5(A2)를 사용하여 온도 센서의 번호(번지)를 설정 한다.
          • 온도 센서의 번호(번지)를 설정 예
          • 0번(이 예에서는 0번 장치를 0x48 번지로 설정 하였다.): A0 <- GND, A1 <- GND, A2 <- GND

      • 실험 방법
        • 위 프로그램(python_i2c_ds1621_basic.py)을 Download 하여 저장한다.
        • Thonny IDE를 실행하고 Thonny IDE의 사용 환경(Thonny 실행에 사용할 장치와 COM Port 선택)이 바르게 되어 있는지 확인한다.
        • Thonny IDE의 Python shell 창에 prompt( >>> )가 출력되었는 확인한다.
        • Thonny IDE의 "파일 -> 열기"를 실행하여 python_i2c_ds1621_basic.py 파일을 Open 한다.
        • 실험
          • "실행 -> 현재 스크립트 실행"을 실행하거나 Toolbar의 "실행" Icon을 클릭하면 스크립트가 개발보드에 전송되고 프로그램이 실행된다.
          • 프로그램이 실행되면 750mSec 주기로 온도가 측정되어 콘솔창에 출력된다. DS1621 칩 위애 손을 대고 있으면 체온에 의하여 변동된 온도(보통 상승)가 출력된다.

    • 프로그램 예: DS1621을 사용한 온도 측정(DS1621 Library 사용)
    • 이 예에서는 DS1621 기능을 대부분 사용하기 위하여 DS1621 Library를 사용한다.

      • DS1621 Library를 사용한 프로그램 예
      • 실험을 위한 준비는 위 "DS1621을 사용한 온도 측정"을 참고 할 것.
      • 실험 방법
        • "python_i2c_ds1621_lib_main.py" 프로그램 파일을 Download하여 저장한다.
        • "DS1621.py" Library 파일을 Download하여 저장한다.
        • Thonny IDE를 실행하고 Thonny IDE의 사용 환경(Thonny 실행에 사용할 장치와 COM Port 선택)이 바르게 되어 있는지 확인한다.
        • Thonny IDE의 Python shell 창에 prompt( >>> )가 출력되었는 확인한다.
        • Thonny IDE의 "파일 -> 열기"를 실행하여 DS1621.py 파일을 Open 한다.
        • Thonny IDE의 "...(으)로 저장" 기능을 사용하여 DS1621.py 파일을 "MicroPython 장치"에 저장(Upload)한다.
        • Thonny IDE의 "파일 -> 열기"를 실행하여 python_i2c_ds1621_lib_main.py 파일을 Open 한다.
        • 실험
          • "실행 -> 현재 스크립트 실행"을 실행하거나 Toolbar의 "실행" Icon을 클릭하면 스크립트가 개발보드에 전송되고 프로그램이 실행된다.
          • 프로그램이 실행되면 750mSec 주기로 온도가 측정되어 콘솔창에 출력된다. DS1621 칩 위애 손을 대고 있으면 체온에 의하여 변동된 온도(보통 상승)가 출력된다.

          주: 프로그램 개발이 완료되면 python_i2c_ds1621_lib_main.py을 main.py로 Rename하여 Pi Pico에 Upload 하면 Pi Pico에 전원이 인가되는 즉시 자동으로 실행할 수 있다.


    • 프로그램 예: Master(Pi Pico) - Slave(ATmega128) I2C 통신 예
    • 이 예는 Master와 Slave(Pi Pico 개발보드를 Master로 ATmega128 보드를 Slave로 사용) 사이에 Data 통신을 하는 예 이다.

      • 프로그램 예
        • ATmega128 보드 프로그램(c 언어): cho_avr_i2c_slave_basic.zip
        • Pi Pico 개발보드 프로그램(MicroPython 언어): pico-i2c-avr-sw-basic.py

      • 실험을 위한 준비
        • Pi Pico 개발보드와 ATmega128 보드의 I2C 통신선 연결
          • Pi Pico 개발보드 SDA(GP20) <-> ATmega128 보드 SDA(PD1) : 2-wire serial 통신을 위한 Data input/output pin.
          • Pi Pico 개발보드 SCL(GP21) <-> ATmega128 보드 SCL(PD0) : 2-wire serial 통신을 위한 Clock input/output pin.
          • Pi Pico 개발보드 GND <-> ATmega128 보드 GND : Ground pin.
          • 전원 연결: Pi Pico 개발보드는 3.3V, ATmega128 보드는 5V를 사용하는 경우가 많기 때문에 주의가 필요함. 이 경우는 각각 전원을 연결하고 GND 선만 공통으로 연결한다.
          • Pin22에 Push button switch를 설치한다.
          • 참고자료: Switch Interfacing

      • 실험 방법
        • "pico-i2c-avr-sw-basic.py" 프로그램 파일을 Download하여 저장한다.
        • cho_avr_i2c_slave_basic.zip 파일을 Download 하여 압축을 풀고 여기에 포함된 cho_avr_i2c_slave_basic.hex을 ATmega128 보드에 설치한다.
        • ATmega128 보드의 UART0를 PC에 연결(USB - UART 변환 모듈 사용)하고 프로그램을 실행한다. PC에서 터미널 프로그램을 실행(ATmega128 보드의 COM 포트 번호 확인이 필요함. Baud rate: 19200)하고 ATmega128 보드의 Reset 버튼을 누르면 "I2C testing." 메세지가 출력된다.
        • Thonny IDE를 실행하고 Thonny IDE의 사용 환경(Thonny 실행에 사용할 장치와 COM Port 선택)이 바르게 되어 있는지 확인한다.
        • Thonny IDE의 Python shell 창에 prompt( >>> )가 출력되었는 확인한다.
        • Thonny IDE의 "파일 -> 열기"를 실행하여 pico-i2c-avr-sw-basic.py 파일을 Open 한다.
        • 실험
          • "실행 -> 현재 스크립트 실행"을 실행하거나 Toolbar의 "실행" Icon을 클릭하면 스크립트가 개발보드에 전송되고 프로그램이 실행된다.
          • 프로그램이 실행되면 Thonny IDE의 Python shell 창에 "Command: Push button switch(Pin22)" 메세지가 출력 된다.
          • Push button switch(Pin22) 버튼을 누르면 문자 'Y'가 ATmega128 보드에 전송되어 ATmega128 보드 터미널 창에 출력되고,
          • ATmega128 보드에서 Pi Pico 개발보드로 "AVR i2c testing" 메세지가 자동으로 전송된다.
          • 그 결과 Thonny IDE의 Python shell의 Console 창에 "AVR i2c testing" 메세지가 출력된다.

    • 프로그램 예: I2C 통신(Master(Pi Pico) - Slave(ATmega128))을 이용한 LED 제어
    • 이 예는 Pi Pico 개발보드(Master)에서 I2C 통신을 이용하여 ATmega128 보드(Slave)의 LED를 제어하는 예 이다.

      • I2C 통신을 이용하여 ATmega128 보드(Slave)의 LED를 제어하는 프로그램 예: pico-i2c-avr-keypad-led.zip
        • I2C 통신을 이용하여 ATmega128 보드(Slave)의 LED를 제어하는 프로그램은 아래와 같이 3개의 프로그램으로 구성된다.

        • ATmega128 보드 LED를 제어하는 프로그램(c 언어): cho_avr_i2c_slave_led.zip
        • Pi Pico 개발보드 프로그램(Keyoad 제어를 위한 library 프로그램): keypadSoft.py
        • Pi Pico 개발보드 프로그램(LED 제어를 위한 프로그램): pico-i2c-avr-keypad-led.py

      • 실험을 위한 준비는 위 "Master(Pi Pico) - Slave(ATmega128) I2C 통신 예"를 참고 바람.
      • 실험 방법
        • "pico-i2c-avr-keypad-led.zip"을 다운로드하여 압축을 해제 한다.
        • ATmega128 보드의 LED를 제어하는 cho_avr_i2c_slave_led.hex(위치: cho_avr_i2c_slave_led\cho_avr_i2c_slave_led\Debug)을 ATmega128 보드에 설치한다.
        • ATmega128 보드의 UART0를 PC에 연결(USB - UART 변환 모듈 사용)하고 프로그램을 실행한다. PC에서 터미널 프로그램을 실행(ATmega128 보드의 COM 포트 번호 확인이 필요함. Baud rate: 19200)하고 ATmega128 보드의 Reset 버튼을 누르면 "I2C LED control" 메세지가 출력된다.
        • Thonny IDE를 실행하고 Thonny IDE의 사용 환경(Thonny 실행에 사용할 장치와 COM Port 선택)이 바르게 되어 있는지 확인한다.
        • Thonny IDE의 Python shell 창에 prompt( >>> )가 출력되었는 확인한다.
        • Thonny IDE의 "파일 -> 열기"를 실행하여 keypadSoft.py 파일을 Open 한다.
        • Thonny IDE의 "...(으)로 저장" 기능을 사용하여 keypadSoft.py 파일을 "MicroPython 장치"에 저장(Upload)한다.
        • Thonny IDE에서 "파일 -> 열기... -> 이 컴퓨터"를 실행하여 pico-i2c-avr-keypad-led.py를 Open 한다.
        • 실험
          • "실행 -> 현재 스크립트 실행"을 실행하거나 Toolbar의 "실행" Icon을 클릭하면 스크립트가 개발보드에 전송되고 프로그램이 실행된다.
          • 프로그램이 실행되면 ESPlorer 콘솔창에 "Command: Left:1, Right:3, Blinking:2, Set LED:*, Get LED:#" 메세지가 출력 된다.
          • Keypad에서 LED 제어 명령(예: Keypad에서 1을 입력하면 ATmega128 보드의 LED Array가 좌측으로 순차적으로 점멸한다.)을 입력하면 입력한 명령이 ATmega128 보드에 전송되어 실행된다.

          주: 이 실험을 위하여는 ATmega128 보드의 PORTF에 LED Array가 연결되어 있어야 함.

          참고자료: Bit 정보를 보기 위한 8 Bits LED Bar 만들기

          주: 프로그램 개발이 완료되면 pico-i2c-avr-keypad-led.py을 main.py로 Rename하여 Pi Pico에 Upload 하면 Pi Pico에 전원이 인가되는 즉시 자동으로 실행할 수 있다.

    • I2C 통신을 사용한 LCD 모듈 제어
      • 장치 제어에 사용하는 Microcontroller는 I/O Port의 수가 제한되어 있기 때문에 LCD 모듈 제어(보통 8 Bits 가 필요)와 같이 많은 I/O Ports를 필요로 하는 장치의 제어를 위하여 I2C 통신을 사용한 I/O Port 확장(8 Bits) 모듈을 사용 한다. 이 예는 I2C 통신을 사용한 I/O Port 확장(8 Bits) 모듈을 이용하여 LCD 모듈을 제어하는 기술에 대하여 설명 한다.

      • I2C 통신을 사용한 LCD 모듈
        • I2C 통신을 사용한 I/O Port 확장(8 Bits) 모듈
          • SCL, SDA Pin은 I2C 통신에 사용 된다.
          • P0 - P7은 8 Bit Input/Output Port로 I/O Port 확장에 사용 한다.
          • A0 - A2는 Address를 설정하기 위하여 사용 한다.

        I2C 통신을 이용한 I/O Port 확장 Chip(PCF8574)의 Block diagram


        • I2C 통신을 사용한 LCD 모듈
          • I2C - LCD Module은 I2C - I/O Expander(PCF8574)와 LCD의 Contrast를 조정하는 회로(가변저항 포함), Backlight Control 회로로 구성 되어 LCD 모듈을 제어 한다.
          • I2C - LCD Module은 Microcontroller로 부터 I2C 통신을 이용하여 Data를 수신하고, 이 Data를 이용하여 LCD Module을 제어 한다.
          • I2C - LCD Module과 LCD Module은 함께 조립되어 판매 하기 때문에 이용자는 Microcontroller(AVR)과 I2C - LCD Module 사이의 4선(SCL, SDA, VCC, GND) 만 연결하면 된다.

          I2C 통신을 사용한 LCD 제어 시스템 구성도


          I2C - LCD Module 과 LCD Module(1602)을 통합한 제품 예

      • I2C - LCD Library를 사용한 프로그램 예: i2c-lcd.zip
        • 이 예는 I2C - LCD Library를 사용하여 PCF8574를 통해 연결된(I2C) HD44780 문자 LCD를 제어한다.

        • I2C - LCD Library를 사용하는 메인 프로그램: I2cLcd-main.py

        • PCF8574를 통해 연결된(I2C) HD44780 문자 LCD를 제어하는 Class Library: I2cLcd.py

        • HD44780와 호환되는 Character LCD와 통신하기 위한 API(Application Programming Interface) Class Library: LcdApi.py

      • 실험을 위한 준비
        • Pi Pico 개발보드 SDA(GP20) <-> LCD 모듈의 SDA : 2-wire serial 통신을 위한 Data input/output pin.
        • Pi Pico 개발보드 SCL(GP21) <-> LCD 모듈의 SCL : 2-wire serial 통신을 위한 Clock input/output pin.
        • Pi Pico 개발보드 GND <-> LCD 모듈의 GND : Ground pin.
        • 전원 연결: Pi Pico 개발보드의 5V pin과 LCD 모듈의 5V pin. LCD 모듈이 3.3V를 사용하는 경우에는 Pi Pico 개발보드의 3.3V 출력 pin과 연결하여야 한다.
      • 실험 방법
        • i2c-lcd.zip(I2cLcd-main.py, I2cLcd.py, LcdApi.py)를 파일을 Download하여 압축을 해제한다.
        • Thonny IDE를 실행하고 Thonny IDE의 사용 환경(Thonny 실행에 사용할 장치와 COM Port 선택)이 바르게 되어 있는지 확인한다.
        • Thonny IDE의 Python shell 창에 prompt( >>> )가 출력되었는 확인한다.
        • Thonny IDE의 "파일 -> 열기"를 실행하여 I2cLcd.py 파일을 Open 한다.
        • Thonny IDE의 "...(으)로 저장" 기능을 사용하여 I2cLcd.py 파일을 "MicroPython 장치"에 저장(Upload)한다.
        • Thonny IDE의 "파일 -> 열기"를 실행하여 LcdApi.py 파일을 Open 한다.
        • Thonny IDE의 "...(으)로 저장" 기능을 사용하여 LcdApi.py 파일을 "MicroPython 장치"에 저장(Upload)한다.
        • Thonny IDE에서 "파일 -> 열기... -> 이 컴퓨터"를 실행하여 I2cLcd-main.py를 Open 한다.
        • 자신이 사용하는 LCD 모듈의 Slave 주소를 확인하여 설정(I2C_ADDR 값을 변경)한다. 보통 PCF8574를 사용한 경우에는 0x27 번지이고, PCF8574A를 사용한 경우에는 0x3f 번지이다.
        • 실험
          • "실행 -> 현재 스크립트 실행"을 실행하거나 Toolbar의 "실행" Icon을 클릭하면 스크립트가 개발보드에 전송되고 프로그램이 실행된다.
          • 프로그램이 실행되면 첫 줄에 "Hello LCD", 둘째 줄에 "하트와 I2C LCD"가 출력된다.

          주: 프로그램 개발이 완료되면 I2cLcd-main.py을 main.py로 Rename하여 Pi Pico에 Upload 하면 Pi Pico에 전원이 인가되는 즉시 자동으로 실행할 수 있다.


  • Pi Pico I2C 관련 페이지 보기