close
出品21ic論壇 tobot
網站:bbs.21ic.com

在物聯網時代,用得最多的是什麼?答案無疑是傳感器!

相信大家都入手過不少傳感器,DHT11作為一款比較常用的溫濕度傳感器,估計沒人會說「沒聽過」或者「不會用」吧?

最近我帶兒子玩樹莓派的時候,發現了一個問題,那就是網上使用樹莓派讀取DHT11的python代碼同質化太嚴重。而且說是給樹莓派使用的,但實際上,每段代碼只適合少許型號的樹莓派使用,例如下面這段代碼:


這段代碼在樹莓派3b上工作的不錯,但在樹莓派4b上就完全不能用了,讀出的結果為255(全1)。

對照Datasheet,我們很容易就能分析出原因。但這裡就不大段抄文了,簡單說一下原理,在讀取數據的時候,如果有一個較長時間的持續高電平,讀取此位為1,否則就是0,如下圖所示:


根據手冊來說:「0」的高電位持續時間是26~28us,「1」的高電位持續時間是70us。在上面的代碼中,是以循環是否超過8次作為該位0、1的區分,這是樹莓派3b中比較適合的數字了(相信也是反覆試驗出來的)。

但是,因為不同樹莓派的SoC主頻不同,顯然如果換一款樹莓派(比如樹莓派4b)這個數值肯定是需要根據實際修改的,將其循環次數k記錄下來:

[7, 8, 8, 25, 25, 8, 8, 9, 8, 8, 8, 9, 8, 8, 9, 8, 8, 8, 8, 26, 26, 8, 8, 9, 8, 8, 8, 8, 8, 8, 8, 9, 8, 8, 24, 24, 8, 8, 8, 8]

從數值上來看,7、8、9應該是0;24、25、26應該是1,那麼直接把剛才的代碼第25行改成if k<15:再嘗試。

根據傳感器的要求,每次讀取時間間隔超過1s,多次讀取,發現大多數時候讀取的結果都是正確的,但也有錯得比較離譜的情況,比如下面這種情況:


那麼,這是為什麼呢?

其實原因很簡單,樹莓派的SoC工作頻率並不固定,因此循環周期也是不同的。以樹莓派4b為例,它的頻率可以在600MHz~1500MHz間變化。


這樣一來,每次循環所用的時間肯定是有較大差異的。

如果不用循環,那麼直接讀取兩次時間差值是否可行呢?經過驗證,這是可以的,只要使用time.time.time_ns()函數就行。

不過,這裡有個小問題,那就是python的效率比較低,在樹莓派上,即使原始值是「0」(只有不到30us),經過兩次調用這個函數並且做差值運算以後,花費的時間依然超過了70us。

當然,這並不是什麼大問題,我們直接嘗試將兩次調用的時間相減(實測大概是50us),作為基礎數值加到30us中,因此將上述循環計數改成時間計數:


這樣在一定程度上,可以抵禦樹莓派主頻自動變化造成讀數錯誤的風險。

實測,依然有一定出錯概率,因此最合適的方案就是:多讀幾次,把校驗錯誤和明顯不符合常識的數值(比如濕度大於100)丟棄,這樣結果相對準確一些。

代碼很簡單,這裡就不獻醜了,僅提出一個思路,請大家自行展開嘗試。另外,如果有需要查看原圖和代碼的小夥伴,請點擊底部「閱讀原文」進行下載。

▍推薦閱讀:

突發!國內一晶圓廠發生爆炸事故
新的焊武帝誕生!這焊接技術,簡直逆天了
勵志!26歲腦癱小伙兒考過CCIE高級網絡工程師

21ic獨家「修煉寶典」|電子必看公眾號|電子「設計錦囊」

添加管理員微信


你和大牛工程師之間到底差了啥?
加入技術交流群,與高手面對面

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()