Thermocouple이나 가변저항 등으로 읽은 전압(V) 값은 연속적인, 아날로그 신호입니다. 하지만 라즈베리파이의 GPIO핀 만으로 아날로그 신호를 읽는 것은 어려울 수 있습니다. 그러므로 PCF8591와 같은 AD/DA 컨버터 모듈을 이용해서 아날로그 신호를 라즈베리파이가 인식할 수 있는 신호로 바꿔주어야 합니다.
라즈베리파이 구매시, 스타터 키트와 같은 패키지 상품을 구매하면 AD/DA 컨버터 모듈을 끼워줍니다. 이 글에서는 제가 라즈베리파이를 구매했을때 같이 온 PCF8591 AD / DA 컨버터 모듈 사용방법을 써 볼려고 합니다.
처음에 쓰면서 기판도 태워먹고, 납땜질도 하는 등 삽질 하면서 알아낸 팁들도 추가하겠습니다. 다 읽어보시면 얻어가는게 많으실 겁니다.
PCF8591은 아날로그 신호를 디지털 신호로 바꿔주는 역할을 합니다. 분해능(Resolution)은 8-bit로, 어떤 아날로그 신호를 0~255 사이의 값으로 변환시켜 줍니다.
인터넷에서 구매가능한 PCF8591 모델이 2개 정도 있습니다. 아래 사진에서 보듯이 두 모델이 외형적으로 다릅니다.

좌측 하단은 Sunfounder사의 PCF8591 모듈이고, 상단은 TZT사, 우측하단은 YL-40 입니다.
AD / DA 컨버터 PCF8591 모듈 [TS0199]
4개의 입력, 1개의 출력 채널 / I2C 통신 / A0,A1,A2는 하드웨어 주소를 프로그래밍하는데 사용되며 추가 하드웨어 없이 8개 장치를 I2C 버스에 연결할 수 있음 / 작동 전압: DC 2.5-6V
www.devicemart.co.kr
상단(TZT), 우측하단(YL-40): https://www.devicemart.co.kr/goods/view?no=12537448
AD/DA 컨버터 PCF8591 모듈 [RBP-022]
PCF8951칩 기반의 AD/DA 컨버터 모듈 / 작동 전압 범위 : 2.5V-6V / I2C 버스를 통한 직렬 입출력 / PCB 크기 : 3.6cm * 2.3cm
www.devicemart.co.kr
(후원은 개뿔 여기 디바이스마트에서산 첫번째 모듈은 가변저항이 망가진채로 와가지고 다른거에서 가변저항떼고 납땜질로 붙이다가 손 하얗게 다 익었음 ㅠ)
TZT/YL-40 의 모듈과 Sunfounder사의 모듈 둘다 똑같은 기능을 수행하지만, 전자의 PCF8591에는 기판에 부품이 더 많이 붙어있습니다. 각각 어떤 역할을 하는지 설명해드리겠습니다.
PCF8591의 인풋/아웃풋 으로는 AIN0~3, 그리고 AOUT 이 있습니다. 각각 아날로그 인풋 0,1,2,3 그리고 아날로그 아웃풋(1) 이렇게 이해하시면 됩니다.

위 사진은 TZT/YL-40 제품 설명도입니다. 사진 상단 J4, J5, J6에 검은색 플라스틱으로 씌어져 있는게 "점퍼캡" 이라고 불리는 부품입니다. 아래사진처럼 이렇게 끼웠다 뗏다 할 수 있습니다.

위 같은 경우에는 점퍼캡을 J6만 연결시켜 놨다고 할 수 있겠네요. 이 점퍼캡의 역할은, 기판에 내장되어있는 광다이오드, 써미스터, 그리고 가변저항을 '사용할지 안할지' 물리적으로 선택할 수 있도록 해줍니다.
- 점퍼캡을 J4 에다가 연결하면, AIN0의 값을 읽을 때 기판에 있는 Photodiode의 전압 값을 읽습니다.
- 점퍼캡을 J5에다 연결하면, AIN1의 값을 읽을 때 기판에 있는 Thermisistor의 전압 값을 읽습니다.
- 점퍼캡을 J6에다가 연결하면, AIN3의 값을 읽을 때 기판에 있는 가변저항(10kohm pot)의 값을 읽습니다.
AIN2는 raw input입니다. AIN2의 값을 읽고 싶을때는, 점퍼선을 AIN2와 회로 어딘가에 연결하여 그 지점의 값을 읽을 수 있습니다.
**** 주의!!!! ****
PCF8591 프로그램이 돌아가고 있는 상태에서는 절대 점퍼캡을 연결하거나 제거하여서는 안됩니다. 첫번째 사진 상단의 모듈이 제가 그렇게 했다가 기판에 저항이 터져서 (프로그램 실행중 J6 연결 -> 기판 뒷면의 R9 저항 터짐) 고장이 났습니다. 그래서 부품용으로 쓰고 있습니다.
PCF8591을 사용하기 앞서, 라즈베리파이 설정에서 I2C사용설정을 해주셔야하고 (다른분이 쓰신 글 링크 걸어놓겠습니다.)
라즈베리파이 I2C 사용방법
라즈베리 I2C 기능에는 치명적일 수 있는 문제가 있습니다!! 해당 글 최하단 참고. I2C 기능이 필요하...
blog.naver.com
I2C 통신 주소를 알아내야합니다. bash에 다음과 같이 입력하시면:
i2cdetect -y 1

요래 뜹니다. 이 주소, 0x48 이 I2C 통신장치의 주소이고, 나중에 쓰일 예정이므로 꼭 기억해주시길 바랍니다.
(대부분의 이런 기기들은 고정주소값을 가지고 있는 것 같습니다.)
이제 실제 사용 코드와 예시를 보여드리겠습니다.
예시 1. PCF8591에 내장된 가변저항의 값을 읽어, AOUT으로 값 내보내기
예시 2. PCF8591의 AIN0(점퍼캡 x) 에 가변저항을 연결하여 값을 읽고, AOUT으로 값 내보내기
예시 1. PCF8591에 내장된 가변저항의 값을 읽어, AOUT으로 값 내보내기
예시를 보여드리겠습니다. 이 예시는 PCF8591의 J6에 점퍼캡을 결합하여 AIN3의 값 (J6가 연결되어 있으므로, 기판의 가변저항 값)을 읽어, 이 값을 AOUT으로 보내 LED 밝기를 조절하는 프로그램입니다.
PCF8591 과 Rpi의 연결은:
PCF8591
|
Raspberry Pi GPIO
|
VCC
|
3V3
|
GND
|
GND
|
SDA
|
SDA(GPIO2)
|
SCL
|
SCL(GPIO3)
|
PCF8591의 AOUT을 LED와 저항에 연결하여 줍니다.

코드:
import smbus
import time
# bash에 $ i2cdetect -y 1 하여 나온 i2c 주소가 0x48
address = 0x48
cmd = 0x40
bus = smbus.SMBus(1)
def analogRead(channel):
bus.write_byte(address, cmd+channel)
value = bus.read_byte(address)
return value
def analogWrite(value):
bus.write_byte_data(address, cmd, value)
def GreenLEDComp(input):
output = input*(231-131)/255 + 131
# AOUT에 연결되어있는 녹색 LED가 V값 131부터 231 사이에서만 반응하기에, 0~255 값을 131~231 사이에 선형적으로 배정
return round(output) # bus.write_byte_data(arg1, arg2, arg3)에서 arg3가 정수값만을 받음. 그러므로 round().
#드라이버 코드
while True:
AIN3 = analogRead(3)
print("AIN3 = ", AIN3)
analogWrite(GreenLEDComp(AIN3))
time.sleep(0.1)
코드설명:
import smbus
# ~~~
address = 0x48
cmd = 0x40
bus = smbus.SMBus(1)
I2C통신을 위한 smbus 라이브러리를 이용하여, bus라는 객체를 생성해줍니다.
def analogRead(channel):
bus.write_byte(address, cmd+channel)
value = bus.read_byte(address)
return value
# ~~~
AIN3 = analogRead(3)
아날로그 값을 읽어주는 함수입니다. 설명을 드리자면:
AIN0 의 주소: 0x40 (cmd(0x40) + 0)
AIN1 의 주소: 0x41 (cmd + 1)
AIN2 의 주소: 0x42 (cmd + 2)
AIN3 의 주소: 0x43 (cmd + 3)
이기 때문에, analogRead(3)은 AIN3의 값을 읽어줍니다.
def analogWrite(value):
bus.write_byte_data(address, cmd, value)
원하는 값을 AOUT으로 보내주는 함수입니다.
드라이버코드는:
1. AIN3 값을 읽어서
2. 프롬프트에 값을 표시해주고
3. AOUT으로 값을 보내주고
4. 이 과정을 0.1초마다 반복하라
입니다.
실행영상:
예시 2. PCF8591의 AIN1(점퍼캡 x) 에 가변저항을 연결하여 값을 읽고, AOUT으로 값 내보내기
PCF8591 연결:
모든 점퍼캡을 제거 (J5포함 제거)하고, AIN1과 가변저항(10k)을 점퍼선으로 연결

코드:
import smbus
import time
# I2C bus adress
address = 0x48;
cmd = 0x40;
bus = smbus.SMBus(1);
def analogRead(chn):
bus.write_byte(address, chn + cmd)
value = bus.read_byte(address)
return value
def analogWrite(value):
bus.write_byte_data(address, cmd, value)
while True:
value = analogRead(1)
print("AIN1 = ", value)
analogWrite(value)
time.sleep(0.1)
Sunfounder사의 PCF8591도 동일한 코드와 방법으로 실행 가능합니다.
(Sunfounder 제품은 가변저항과 점퍼캡이 AIN0과 연결되어있습니다)
From: https://blog.naver.com/reddishradish01/223504679341
[Raspberry Pi / PCF8591] PCF8591을 이용한 아날로그-디지털 입출력 신호 변환 (파이선)
Thermocouple이나 가변저항 등으로 읽은 전압(V) 값은 연속적인, 아날로그 신호입니다. 하지만 라즈베리...
blog.naver.com
같은 블로그 주인장입니다. 구글 노출시킬려고 복붙작업 중