一、前言
單總線也叫做一線總線(one-write),它只有1根信號線,既傳輸時鐘又傳輸數(shù)據(jù),而且數(shù)據(jù)傳輸是雙向的,通過一問一答的形式實現(xiàn)兩個設(shè)備之間的數(shù)據(jù)交互。具體的原理我就不細說了,感興趣的同學可以自己去查閱相關(guān)的資料,今天我以DS18B20為例,講一下樹莓派的單總線的使用方法。
二、硬件連接
DS18B20引腳定義如下,根據(jù)引腳定義連接到樹莓派上,我這里用的是一個擴展板,直接把傳感器接上即可。
引腳 | 名稱 | 說明 |
---|---|---|
1 | GND | 供電電源負極 |
2 | DQ | 數(shù)據(jù)輸入輸出引腳(和MCU任意一個IO口相連,注意:這里需要有上拉電阻) |
3 | VCC | 供電電源正極 |
注意:如果你的傳感器是插件封裝的,一定要分清楚正負,不然會燒壞的。判斷方法(僅供參考):平的一面對著自己,左邊的是GND,右邊的是VCC,中間的是信號線。接上之后可以迅速上電然后斷電,摸一下傳感器,如果迅速發(fā)熱并且非常燙說明接反了。
三、使能1-write接口
方法1:通過配置命令
sudo raspi-config // 打開配置
sudo reboot // 重啟,如果之前沒有使能,配置完之后要重啟才能生效
方法2:在可視化界面的設(shè)置里面修改
注意:如果設(shè)備啟動的時候是沒有使能1-Write接口的,使能之后需要重啟才能生效。
四、通訊測試
sudo modprobe w1-gpio
sudo modprobe w1-therm
cd /sys/bus/w1/devices
ls // 查詢傳感器的ID,如果什么都沒有,可能是前面沒有使能1-Write,或者使能了但是沒有重啟,也可能是硬件連接有問題
cd 28-xxxxxxx // 28-xxxxxxx:18b20的ID,每個傳感器的id都是不同的,根據(jù)自己的輸入,如果查詢的ID里面不是28開頭而是00開頭的,那應(yīng)該不是ds18b20
cat w1_slave
五、編寫代碼并運行
1、方式1
基于w1thermsensor庫驅(qū)動DS18B20,w1thermsensor庫集成了多款傳感器的驅(qū)動(DS18S20、DS1822、DS18B20、DS28EA00、DS1825/MAX31850K)。
w1thermsensor Github 鏈接:https://github.com/timofurrer/w1thermsensor
示例代碼:
from w1thermsensor import W1ThermSensor
sensor = W1ThermSensor(W1ThermSensor.THERM_SENSOR_DS18B20, "00000cb51493") #00000cb51493:是ds18b20的id,根據(jù)自己的id輸入(注意不要把“28-”也復制進來)
temp = sensor.get_temperature()
print(temp)
注:該代碼基于w1thermsensor庫驅(qū)動,使用w1thermsensor庫之前先要安裝這個庫,命令如下:
sudo apt-get install python3-pip // python3 pip安裝管理器依賴包
sudo apt-get install python3-w1thermsensor // w1thermsensor庫
查詢要讀取的ds18b20的id。
可以通過第四步的通訊測試查,也可以用下面的命令查。
cd /etc
ls /sys/bus/w1/devices
示例代碼1運行結(jié)果:
2、方式2
這個方法其實就是基于第四點的通訊測試,把手動輸入的命令寫在腳本上運行。
示例代碼:
#!/usr/bin/python
# -*- coding:utf-8 -*-
import os
import glob
import time
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'
def read_rom():
name_file=device_folder+'/name'
f = open(name_file,'r')
return f.readline()
def read_temp_raw():
f = open(device_file, 'r')
lines = f.readlines()
f.close()
return lines
def read_temp():
lines = read_temp_raw()
while lines[0].strip()[-3:] != 'YES':
time.sleep(0.2)
lines = read_temp_raw()
equals_pos = lines[1].find('t=')
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
temp_c = float(temp_string) / 1000.0
temp_f = temp_c * 9.0 / 5.0 + 32.0
return temp_c, temp_f
print(' rom: '+ read_rom())
while True:
print(' C=%3.3f F=%3.3f'% read_temp())
time.sleep(1)
示例代碼運行結(jié)果:
六、結(jié)束語
DS18B20是一款很簡單的單總線傳感器,我覺得以此為例去學習和了解單總線是一個非常好的選擇。
關(guān)于樹莓派和單片機的一些個人見解:
樹莓派快速入門系列教程,剛剛進入基礎(chǔ)編程的教學,為了避免大家進入思維的誤區(qū),在這里我想說說我對樹莓派的一些看法。樹莓派是一個微型的電腦,在運算能力方面是比單片機要強的,在編程上樹莓派更偏向應(yīng)用層的開發(fā),也可以理解為電腦軟件的開發(fā)。而單片機的話更多的是做底層外設(shè)驅(qū)動的開發(fā),應(yīng)用層主要也是以控制為主,不會說用單片機去做一個非常復雜的數(shù)據(jù)運算或者處理大量的數(shù)據(jù)。
所以,樹莓派的編程其實是有一點點脫離硬件的,就是我們可以不管底層的硬件是怎么實現(xiàn)數(shù)據(jù)采集和傳輸?shù)?,直接調(diào)用庫函數(shù),把數(shù)據(jù)拿到就行了,當然,有時間和精力的話是可以去研究一下硬件的原理和底層的實現(xiàn)。而單片機的開發(fā)很多時候會遇到一些沒用過的芯片,我們就需要根據(jù)芯片的數(shù)據(jù)手冊去開發(fā)一個驅(qū)動程序,然后再做應(yīng)用層的開發(fā),當然了,單片機也是可以跑操作系統(tǒng)的,比如FreeRTos、RT-thread等,跑操作系統(tǒng)的話和樹莓派的編程就有些類似了,但畢竟跑系統(tǒng)的單片機還是少數(shù)。
總結(jié)起來就是一句話:樹莓派編程能用庫的就用庫,底層怎么實現(xiàn)的不用管,我們是做大事的,不要花太多的時間在一些小事情上面。純粹是個人的看法,勿噴,如果你有不同的見解,歡迎在評論區(qū)留言,謝謝?。?!
好了,這一講的內(nèi)容就這么多了,如果對你有幫助,可以給個收藏,如果想了解更多樹莓派的知識可以關(guān)注我,后續(xù)我會繼續(xù)更新更多的教程。
樹莓派入門系列教程:樹莓派從零開始快速入門系列匯總