라즈베리파이의 GPIO에는 아날로그 신호를 처리하는 것이 없다. 그래서 아날로그 신호를 내보내는 대부분의 센서를 처리하기 위해서는 ADC(analog-to-digital converter)가 필요하다. ADC 중에는 MCP3008와 MCP3208 등이 있다. 라즈베리파이와 ADC 간의 통신은 SPI를 이용한다.
MCP3008, MCP3004, MCP3208, MCP3204
다음 웹페이지에는 MCP3008, MCP3004, MCP3208, MCP3204 에 대한 데이터시트에 가까운 정보를 제공하고 있다.
Raspberry PI – Adding analogue inputs using MCP3008, MCP3004, MCP3208, MCP3204
그리고 여기는 spidev 라이브러리를 이용하였다. ADC에서 읽은 값이 해상도가 10비트이면 0~1023, 12비트이면 0~4095라는 것을 알 수 있다.
spidev 라이브러리를 이용하여 https://kalten.tistory.com/46 처럼, 통신 여부를 검토하였더니 잘 작동하지 않아서 RPi.GPIO 라이브러리를 이용하였다.
MCP3008에서 센서의 신호처리(SPI통신)
다음은 신호처리를 위해 작성한 파이썬 코드이다. RPi.GPIO 라이브러리를 이용하였다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) # MCP3008 칩으로부터 SPI 신호를 읽는다. 8개 센서를 둘 수 있다.(adcnum은 0번부터 7번까지) def readadc(adcnum, clockpin, mosipin, misopin, cspin): if ((adcnum > 7) or (adcnum < 0)): return -1 GPIO.output(cspin, True) # CS핀을 high로 만든다. GPIO.output(clockpin, False) # clock핀을 low로 만든다. GPIO.output(cspin, False) # CS핀을 low로 만든다. commandout = adcnum commandout |= 0x18 # start bit + single-ended bit commandout <<= 3 # we only need to send 5 bits here for i in range(5): if (commandout & 0x80): GPIO.output(mosipin, True) else: GPIO.output(mosipin, False) commandout <<= 1 GPIO.output(clockpin, True) GPIO.output(clockpin, False) adcout = 0 # MCP3008은 10비트의 해상도를 갖고 있다. # MCP3008에서 총 12비트을 읽는다. (=one empty bit, one null bit and 10 ADC bits) for i in range(12): GPIO.output(clockpin, True) GPIO.output(clockpin, False) adcout <<= 1 if (GPIO.input(misopin)): adcout |= 0x1 GPIO.output(cspin, True) adcout >>= 1 # first bit is 'null' so drop it return adcout # adcout는 0부터 1023까지 값을 갖는다. #end of def |
MCP3208에서 센서의 신호처리
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) # MCP3208 칩으로부터 SPI 신호를 읽는다. 8개 센서를 둘 수 있다.(adcnum은 0번부터 7번까지) def readadc(adcnum, clockpin, mosipin, misopin, cspin): if ((adcnum > 7) or (adcnum < 0)): return -1 GPIO.output(cspin, True) # CS핀을 high로 만든다. GPIO.output(clockpin, False) # clock핀을 low로 만든다. 시작한다. GPIO.output(cspin, False) # CS핀을 low로 만든다. commandout = adcnum commandout |= 0x18 # start bit + single-ended bit commandout <<= 3 # we only need to send 5 bits here for i in range(5): if (commandout & 0x80): GPIO.output(mosipin, True) else: GPIO.output(mosipin, False) commandout <<= 1 GPIO.output(clockpin, True) GPIO.output(clockpin, False) adcout = 0 # MCP3208은 12비트의 해상도를 갖고 있다. # MCP3208에서 총 14비트을 읽는다. (=one empty bit, one null bit and 12 ADC bits) for i in range(14): GPIO.output(clockpin, True) GPIO.output(clockpin, False) adcout <<= 1 if (GPIO.input(misopin)): adcout |= 0x1 GPIO.output(cspin, True) adcout <<= 1 # first bit is 'null' so drop it return adcout # adcout는 0부터 4095까지 값을 갖는다. #end of def |
SPI at Rasberry Pi GPIO Pinout
SPI통신을 위한 라즈베리 파이의 GPIO 핀 배치는 다음과 같다.
SPI – Serial Peripheral Interface at Raspberry Pi
참고문헌
https://github.com/RaresPlescan/daisypi/blob/master/sense/mcp3208/adc_3.py