Raspberry Pi 筆記(20):MCP3008 讀取類比訊號測溫度與光度

兩三個星期前到台北光華商場電子材料行找 MCP3008 這顆 IC,竟然問了三家都沒有賣這個IC,還是上網去買才買到。為什麼要使用這個 IC 呢? 主要是因為Raspberry Pi沒有支援類比訊號輸入,例如要用Raspberry Pi去讀取溫度或光度偵測的類比訊號,是無法達成的。MCP 3008這個 IC的功能就是將類比訊號轉換成數位訊號(Analogue-to-digital converter, ADC),它有8通道 ,每個通道可依類比設備的輸入值傳回一個10位元的數值。MCP3008可使用SPI介面跟Raspberry Pi連接,以下就來看看如何運用MCP3008偵測溫度和光度。


[MCP3008]

MCP3008讀取ADC數值時,會傳回一個10-bit的數字,介於0到1023之間,可以根據輸入電壓與傳回值的電壓,計算出類比訊號的值,再根據類比設備的特性得到所需的資訊。可參考MCP3008 Datasheet 。

圖片來源:MCP3008 Datasheet

MCP3008 pinout description (接腳說明)
來源:MCP3008 Datasheet

Digital Ground (DGND):Digital ground 連接至內部數位電路
Analog inputs (CH0 - CH7):類比通路0 - 7
Chip Select/Shutdown (CS/SHDN):CS/SHDN pin當設定為低電壓時,被用來啟動設備間的通訊;設定為高電壓時,停止設備間的通訊進入等待狀態。CS/SHDN pin在通訊時必須設定為高電壓才能進行通訊。
Serial Data Output (DOUT):SPI串列通訊時資料輸出,資料會因為設備間通訊的時序變化而改變。
● Serial Data Input (DIN):SPI Port串列資料輸入,用來載入設定資料給通訊設備。
● Serial Clock (CLK):SPI clock pin被用來啟動通訊。
來源:MCP3008 Datasheet

[溫度感測元件LM35]

LM35是一個常見的溫度感測IC,根據技術文件說明LM35輸出電壓與攝氏溫標呈線性關係,0℃時輸出為零,每提高1℃輸出就增加10mV。由此特性,我們可以根據輸出電壓換算測得的溫度,例如:測得電壓0.24V時,表示當時溫度為24℃。可參考LM35 Datasheet 。

  來源:網路

[光敏電阻(Photocell)]

光敏電阻是一種特殊的電阻,簡稱光電阻,又名光導管。它的電阻和光線的強弱有直接關係。當有光線照射時,電阻內原本處於穩定狀態的電子受到激發,成為自由電子。所以光線越強,產生的自由電子也就越多,電阻就會越小。在光線越暗時,電阻值會越高。
  來源:網路

[材料]

• Raspberry Pi 主板 x1
• MCP3008 IC  x1
• LM35 IC x1
• 光敏電阻 x1
• 10K電阻 x1
• 連接線  x N條

[線路連接與電路圖]


  • MCP3008 CH0接光敏電阻,光敏電阻另一隻腳接地(GND)
  • MCP3008 CH0接10K電阻,10K電阻另一隻腳接3.3V
  • MCP3008 CH1接LM35中間接腳,LM35另外兩隻腳分別接3.3V及接地
  • MCP3008 pin16(VDD)及pin15(VREF)接3.3V,pin14(AGND)及pin9(DGND)接地
  • MCP3008 pin13(CLK)接Pi pin23(SCLK);pin12(DOUT)接Pi pin21(SPI0_MISO);pin11(DIN)接Pi pin19(SPI0_MISI);pin10(CS/SHDN)接Pi pin24(SPI0_CE0)


[2017/02/21] 更新上述接線,改為表格。


MCP3008
Pi
Pin 1 (CH0)

Pin 2 (CH1)

Pin 3 (CH2) 

Pin 9 (DGND)
Pin 6 (Ground)
Pin 10 (CS/SHDN)
Pin 24 SPI0_CE0 (GPIO8)
Pin 11 (DIN)
Pin 19 SPI0_MISI (GPIO10)
Pin 12 (DOUT)
Pin 21 SPI0_MISO (GPIO9)
Pin 13 (CLK)
Pin 23 SCLK (GPIO11)
Pin 14 (AGND)
Pin 6 (Ground)
Pin 15 (VREF)
Pin 1 (3.3V)
Pin 16 (VDD)
Pin 1 (3.3V)



[程式碼]

import spidev
import time
import os

# open(bus, device) : open(X,Y) will open /dev/spidev-X.Y
spi = spidev.SpiDev()
spi.open(0,0)

# Read SPI data from MCP3008, Channel must be an integer 0-7
def ReadADC(ch):
    if ((ch > 7) or (ch < 0)):
       return -1
    adc = spi.xfer2([1,(8+ch)<<4,0])
    data = ((adc[1]&3)<<8) + adc[2]
    return data

# Convert data to voltage level
def ReadVolts(data,deci):
    volts = (data * 3.3) / float(1023)
    volts = round(volts,deci)
    return volts

# Calculate temperature from LM35 data
def ConvertTemp(data,deci):
    temp = data * 100
    temp = round(temp,deci)
    return temp

# Define sensor channels
light_ch = 0
temp_ch  = 1

# Define delay between readings
delay = 3

while True:

  # Read the light sensor data
  light_data = ReadADC(light_ch)
  light_volts = ReadVolts(light_data,2)

  # Read the temperature sensor data
  light_data = ReadADC(light_ch)
  light_volts = ReadVolts(light_data,2)

  # Read the temperature sensor data
  temp_data = ReadADC(temp_ch)
  temp_volts = ReadVolts(temp_data,4)
  temp       = ConvertTemp(temp_volts,2)

  # Print out results
  print "Temp  : ",temp_data, " (",temp_volts ,"V) -->",temp,"~C    Light : ",light_data," (",light_volts,"V)"

  # Delay seconds
  time.sleep(delay)

*註:data = ((adc[1]&3)<<8) + adc[2] 其中<< 因造成網頁編碼錯誤,改用全型小於符號,如需複製程式使用請改為半型

[程式解說]

程式中有一行spi.xfer2,他會送出3 Bytes 給Device,第一個位元是1,相當於二進位的00000001,″8+ch″表示Device的頻道位置,變成"00001000",″<<4″往左移 4個位元(bits),變成 ″10000000",最後一個字元是0,亦即 "00000000"。而程式中 "spi.xfer2([1,(8+channel)<<4,0])"會送出 " 00000001 10000000 00000000" 給接收設備,設備回應三個Bytes回來,而傳回值會放在最右邊10個Bits位置,該值介於0跟1023之間。我們可根據這個數字,判斷光度、溫度等類比的訊號。

[執行結果]


[參考資料]

Raspberry Pi Cookbook
Raspberry Pi Spy : Analogue Sensors On The Raspberry Pi Using An MCP3008
● 維基百科 : 光敏電阻

15 留言

  1. 可以請你比較一下 Arduino 與 Raspberry Pi 兩個都玩過的感想嗎
    我玩過Arduino一陣,看網路上說它對實時系統設計較優,看起來 Raspberry Pi CPU比較強,較適合多媒體的應用,想聽聽看真的兩個都玩過的人的意見。

    BTW, 用Arduino Sketch 和 Python 開發難易度有很大差別嗎?

    回覆刪除
    回覆
    1. 自問自答,Arduino是即時系統,適合用來控制電子零件立即反應,斷電復電完全不受影響,供電立即開始工作。RBPi是多工系統、基本上就在跑Linux,對熟悉Linux的人來說上手容易,但執行程式時沒那麼快,也需要開機時間。需要的耗電量也大不同,基本上RBPi很難只靠電池運作,對於想要轉接USB設備如BLE, WiFi等相當容易,要開發攝錄影相關功能的話只能選RBPi。
      Python的寫法也不難,只是要開機就執行需要寫些script讓程式自動執行。

      刪除
  2. 不好意思~~ 想請問一下

    我照著這篇的敘述做了一次,為何都讀去不到電壓值

    code是上面附的,硬體也照接了,SPI介面也打開了

    回覆刪除
  3. 作者已經移除這則留言。

    回覆刪除
  4. 作者已經移除這則留言。

    回覆刪除
  5. 作者已經移除這則留言。

    回覆刪除
  6. RBPi 2也可以做到很即時喔!請看https://www.youtube.com/watch?v=4vwFFmXGSRo還有用時序歸正程式方法,不管是8051/Android/Arduino/mbed/PIC/python/VB/VC#/...程式碼只需少許修改即可互通共用喔!

    回覆刪除
  7. 請問如果我想把顯示的值丟到SQL上該怎麼辦?

    回覆刪除
    回覆
    1. 建議你使用 Pythone + MSSQL API 解決您的需求

      https://docs.microsoft.com/zh-tw/sql/connect/python/pymssql/step-1-configure-development-environment-for-pymssql-python-development?view=sql-server-2017

      刪除
  8. 請問您開發的語言是用那一個呢? 是爬蟲嗎?

    回覆刪除
  9. 這篇文章的重點是講解如何在 RaspBerry Pi 透處理類比值轉數位處理

    回覆刪除
  10. 作者已經移除這則留言。

    回覆刪除
  11. 作者已經移除這則留言。

    回覆刪除
  12. AD DA 模組或晶片有很多種, MCP3008 是其中一種, 您也可以使用 PCF8591
    便宜也好用, 他使用 I2C 介面, 8 Bit 精度 (0 - 254) 但在一般應用上也
    夠用了

    回覆刪除
    回覆
    1. 謝謝說明, 有時間再來試看看PCF8591。

      刪除

張貼留言

較新的 較舊