행복한 하루
라즈베리파이 제로 프로젝트(14) – Pioneer600 모듈 (PCF8574 I/O expansion) 본문
라즈베리파이 제로 프로젝트(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 통신을 이용한다)
2) Block Diagram
3) 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은 버저와 연결되어 있습니다.
- 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에 불이 들어오는 원리입니다.
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. 동작 영상
감사합니다.
“쿠팡 파트너스 활동을 통해 일정액의 수수료를 받을 수 있음"
'RaspberryPi > Raspberry Pi Zero' 카테고리의 다른 글
라즈베리파이 제로 프로젝트(16) – Pioneer600 모듈 Real Time Clock (DS3231) (0) | 2021.03.13 |
---|---|
라즈베리파이 제로 프로젝트(15) – Pioneer600 모듈 (BMP280) (0) | 2021.03.07 |
라즈베리파이 제로 프로젝트(13) – Pioneer600 모듈 (키 버튼 입력받기) (0) | 2021.02.14 |
라즈베리파이 제로 프로젝트(12) – Pioneer600 모듈 (LED 제어 - PWM) (0) | 2021.02.13 |
라즈베리파이 제로 프로젝트(12) – Pioneer600 모듈 테스트 1편 - LED 제어 (0) | 2021.02.08 |