兩三個星期前到台北光華商場電子材料行找 MCP3008 這顆 IC,竟然問了三家都沒有賣這個IC,還是上網去買才買到。為什麼要使用這個 IC 呢? 主要是因為Raspberry Pi沒有支援類比訊號輸入,例如要用Raspberry Pi去讀取溫度或光度偵測的類比訊號,是無法達成的。MCP 3008這個 IC的功能就是將類比訊號轉換成數位訊號(Analogue-to-digital converter, ADC),它有8通道 ,每個通道可依類比設備的輸入值傳回一個10位元的數值。MCP3008可使用SPI介面跟Raspberry Pi連接,以下就來看看如何運用MCP3008偵測溫度和光度。
MCP3008讀取ADC數值時,會傳回一個10-bit的數字,介於0到1023之間,可以根據輸入電壓與傳回值的電壓,計算出類比訊號的值,再根據類比設備的特性得到所需的資訊。可參考MCP3008 Datasheet 。
MCP3008 pinout description (接腳說明)
● 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 IC x1
• LM35 IC x1
• 光敏電阻 x1
• 10K電阻 x1
• 連接線 x N條
[2017/02/21] 更新上述接線,改為表格。
● Raspberry Pi Spy : Analogue Sensors On The Raspberry Pi Using An 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
● 維基百科 : 光敏電阻
可以請你比較一下 Arduino 與 Raspberry Pi 兩個都玩過的感想嗎
回覆刪除我玩過Arduino一陣,看網路上說它對實時系統設計較優,看起來 Raspberry Pi CPU比較強,較適合多媒體的應用,想聽聽看真的兩個都玩過的人的意見。
BTW, 用Arduino Sketch 和 Python 開發難易度有很大差別嗎?
自問自答,Arduino是即時系統,適合用來控制電子零件立即反應,斷電復電完全不受影響,供電立即開始工作。RBPi是多工系統、基本上就在跑Linux,對熟悉Linux的人來說上手容易,但執行程式時沒那麼快,也需要開機時間。需要的耗電量也大不同,基本上RBPi很難只靠電池運作,對於想要轉接USB設備如BLE, WiFi等相當容易,要開發攝錄影相關功能的話只能選RBPi。
刪除Python的寫法也不難,只是要開機就執行需要寫些script讓程式自動執行。
不好意思~~ 想請問一下
回覆刪除我照著這篇的敘述做了一次,為何都讀去不到電壓值
code是上面附的,硬體也照接了,SPI介面也打開了
作者已經移除這則留言。
回覆刪除作者已經移除這則留言。
回覆刪除作者已經移除這則留言。
回覆刪除RBPi 2也可以做到很即時喔!請看https://www.youtube.com/watch?v=4vwFFmXGSRo還有用時序歸正程式方法,不管是8051/Android/Arduino/mbed/PIC/python/VB/VC#/...程式碼只需少許修改即可互通共用喔!
回覆刪除請問如果我想把顯示的值丟到SQL上該怎麼辦?
回覆刪除建議你使用 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
請問您開發的語言是用那一個呢? 是爬蟲嗎?
回覆刪除這篇文章的重點是講解如何在 RaspBerry Pi 透處理類比值轉數位處理
回覆刪除作者已經移除這則留言。
回覆刪除作者已經移除這則留言。
回覆刪除AD DA 模組或晶片有很多種, MCP3008 是其中一種, 您也可以使用 PCF8591
回覆刪除便宜也好用, 他使用 I2C 介面, 8 Bit 精度 (0 - 254) 但在一般應用上也
夠用了
謝謝說明, 有時間再來試看看PCF8591。
刪除張貼留言