행복한 하루

라즈베리파이 제로 프로젝트(14) – Pioneer600 모듈 (PCF8574 I/O expansion) 본문

RaspberryPi/Raspberry Pi Zero

라즈베리파이 제로 프로젝트(14) – Pioneer600 모듈 (PCF8574 I/O expansion)

변화의 물결 2021. 2. 19. 00:49

 

 

안녕하세요.

 

  네 번째 시간으로 사용하는 라즈베리파이 I/O 포트가 부족하면 어떡해야 할까요? 다른 라즈베리파이를 연결해서 통신해서 사용해야 할까요?  음… 그렇게도 사용하면 되지만, 가성비가 좋은 방법을 찾아야 할 것입니다. 그래서 나온 I/O expansion 칩이 있습니다. 회사들은 여러 곳 있지만, 모듈에 장착된 것을 이용해서 조이스틱, LED를 제어해 보겠습니다.

  

1. PCF8574 데이터 시트 확인

1) 2 GENERAL DESCRIPTION

  The PCF8574 is a silicon CMOS circuit. It provides general purpose remote I/O expansion for most microcontroller families via the two-line bidirectional bus (I2C-bus)

 ( CMOS 회로이고 일반적인 I/O 확장 칩이고 I2C 통신을 이용한다)

 

I2C 연결

2) Block Diagram

 Block Diagram

 3) Pin Description

Pin Description

 4) I2C Address

  - I2C 통신하기 위해서 주소를 확인해 보아야 합니다. 아래의 회로도를 보면 A2, A1, A0 핀을 GND에 연결해두었습니다. 즉, 0으로 설정하겠다는 의미가 됩니다. 고로 상위 비트는 2로 하드웨어 상 2로 고정한 상태이므로 현재 Pioneer600에 부착된 PCF8574의 주소는 0x20이라고 보시면 됩니다.

 

  

2. 회로도 확인

  - P0 ~ P3에 조이스틱이 연결되어 있고, P4에 LED2가 연결되어 있고, P5~P6는 L3, L4로 핀을 넣을 수 있도록 구멍을 내어놓았습니다. P7은 버저와 연결되어 있습니다.

 

PC8574 회로

 

- PCF8547을 제어하기 위해서 I2C로 통신하기 때문에 모듈과 라즈베리파이 제로 서로 SDA와 SCL로 연결해 줍니다.

 

라즈베리파이와 연결

 

   

3. 소스 확인

1) wiringPi (led.c)

  - 제공된 소스상에는 led.c 와 LED.c 가 제공되어 있습니다. LED.c는 pcf8574.h 파일을 사용해서 제공해주는 함수를 사용하고 있습니다. 그래서 일반 I2C 제어하는 방식의 led.c 파일을 간단하게 설명해드리겠습니다.

 

  - 우선 칩을 제어하기 위해서 파일 디스크립션(fd)을 가지고 와야 합니다. 어떤 장비인지 제어하고 싶은 지정하기 위해서 0x20이라는 주소를 인자로 넘겨줍니다. 그러면 제어를 할 수 있는 포인터를 리턴해줍니다.

 

fd = wiringPiI2CSetup(0x20);

 

  - 이제 칩의 포인터를 받았으니 포인터로 핀을 제어합니다. 여기서 0xEF라고 하는 것은 이진수로 보았을 때 1110 1111로 표현할 수 있고 8개의 핀을 이진수로 제어한다는 것입니다. 그래서 p7 ~ P0를 비트 단위로 제어한다고 생각하면 됩니다. LED는 P4이고 5번째 0으로 표시된 위치입니다. 그래서 나머지는 다 1로 해주고 0으로 해서 LED만 켜준다는 의미입니다.

 

  추가로 0인데 왜 LED가 On 이 되는가는 회로를 보면 D2가 +3.3V에 연결되어 L2 쪽에서 제어되도록 되어 있기 때문에 전압 차를 만들어 전류가 흘러가게 하려면 L2쪽에 0V로 만들면 전류가 흘러 LED에 불이 들어오는 원리입니다.

 

LED 회로

 

wiringPiI2CWrite(fd,0xEF);  //LED ON  

#include <wiringPi.h>
#include <wiringPiI2C.h>

int main (void)
{
    int fd;
        wiringPiSetup();
    fd = wiringPiI2CSetup(0x20);

    while (1)
    {
        wiringPiI2CWrite(fd,0xEF);  //LED ON
        delay(500);
        wiringPiI2CWrite(fd,0xFF);  //LED OFF
        delay(500);
    }
    return 0;
}

 

2) wiringPi (pcf8574.c)

 - led.c에서 중복되는 부분은 빼고 설명하겠습니다. 추가된 부분이 wiringPiI2CRead 입니다.

주소값(0x20)에 현재 상태를 읽어 오는 함수입니다.

 그리고  value = i2c_readByte() | 0xF0; 를 통해 조이스틱 키가 눌린 값의 가지고 옵니다. 어떻게 하위 4bit가 방향을 나타내는 비트로 눌리면 0으로 변경시키게 됩니다.

그래서 switch 구문에서 0xFE(1111 1110) 이 left를 0xFD(1111 1101) 이 up으로 구분할 수 있게 되는 것입니다.

 

- 버저와 LED On/Off는 1)의 LED 내용과 동일한 내용이라고 보시면 됩니다.

   

#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <stdio.h>

#define PCF8574_Address 0x20
#define beep_on  i2c_writeByte(0x7F & i2c_readByte())
#define beep_off i2c_writeByte(0x80 | i2c_readByte())
#define led_off  i2c_writeByte(0x10 | i2c_readByte())
#define led_on   i2c_writeByte(0xEF & i2c_readByte())

int fd;

void i2c_writeByte(char byte)
{
        wiringPiI2CWrite(fd,byte);
}
char i2c_readByte()
{
        return (char)wiringPiI2CRead(fd);
}

int main()
{
        char value;

        if (wiringPiSetup() < 0)return 1;
        fd = wiringPiI2CSetup(PCF8574_Address);
    printf("PCF8574 Test Program !!!\n");

    while(1)
    {
                i2c_writeByte(0x0F | i2c_readByte());
                value = i2c_readByte() | 0xF0;
                if(value != 0xFF)
                {
                        beep_on;
                        led_on;
                        switch(value)
                        {
                                case 0xFE:
                                        printf("left\n");break;
                                case 0xFD:
                                        printf("up\n"); break;
                                case 0xFB:
                                        printf("dowm\n");break;
                                case 0xF7:
                                        printf("right\n");break;
                                default :
                                        printf("unknow\n");
                        }
                        while(value != 0xFF)
                        {
                                i2c_writeByte(0x0F | i2c_readByte());
                                value = i2c_readByte() | 0xF0;
                                delay(10);
                        }
                        beep_off;
                        led_off;
                }
                delay(10);
        }
}

  

  python 소스도 분석하려고 했는데, wiringPi로 구조과 유사해서 패스하기로 하였습니다. ^^

 

 

  pi@raspberrypi:~/Pioneer600/PCF8574/wiringPi $ ./led

  Unable to open I2C device: No such file or directory 메시지가 나올 경우

 

  pi@raspberrypi:~/Pioneer600/PCF8574/wiringPi $ sudo raspi-config

  실행해서 i2c를 활성화해주시면 됩니다.

 

  3. Interface Options -> P5 I2C Enable/disable -> Yes

 

 4. 동작 영상

 

감사합니다.

 

PCF8574.pdf
0.13MB

 

 

“쿠팡 파트너스 활동을 통해 일정액의 수수료를 받을 수 있음"

Comments