라즈베리파이의 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
