天天看點

MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)

MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)

0. [外話] 後期基于nodemuc做開發學習與測試

之前用的青蛙創客的europa開發闆,接口封裝得太好,以緻于想自由接線的時候很是頭大。從淘寶上又買了塊nodemcu開發闆,不到十塊錢,用起來不心疼,真的是買不了吃虧買不了上當。

MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)

兩塊闆一主一從,後面有需要主從通訊什麼的,也可以實驗了。nodemcu刷micropython固件方法跟前面提到刷europa是一樣的,不過這麼會兒功夫,官方固件已經更新到 1.16了。 哎,咱這學習進度又拉下了。。。

強調一下 nodemcu闆子上的管腳字元标注跟實際GPIO管腳号是有差別的,需要按網上提供的接線圖做對照使用。

MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)

比如要使用GPIO0控制或讀取信号時,不能接到闆子上标注D0的針腳處,需要按對照圖接到D3(GPIO 00)上。這個一定要注意。

1. 擷取DHT11資料

1.1. 接線

手上有N年時買Arduino開發闆時送的DHT11子產品。DHT11子產品有4根針腳,有3根是有用的,見圖示。

MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)

我們把資料腳接入到D5(GPIO 14),旁邊就有正負極腳,走線整齊。

1.2. 讀取資料

micropython标準庫已經對DHT驅動進行了封裝,咱們直接用就可以了

import dht
import machine

d = dht.DHT11(machine.Pin(14))
d.measure()  # 先調用測量函數
d.temperature()  # 然後可以查濕度
d.humidity()  # 和濕度了
           
MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)

廣東的天氣吓死人,房間裡面都32度。空調開起來~~

DHT11精度隻到整數,這就不要談什麼誤差了吧,真的是僅限學習使用了。

2. 擷取AHT10資料

2.1. AHT10子產品說明

買nodemcu時,順手也買了個AHT10子產品,這個子產品精度要高于DHT11,網上找了下讀取資料的資料。

在廠商奧松官網産品頁,赫然看到該子產品已停産。流年不利,且行且珍惜吧。不過産品說明書還是能下載下傳。

産品手冊前面啰裡吧嗦的那些就先不管了,直接在第8頁看到有對使用方法和解析資料的說明。幹脆也貼下圖吧

MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)

“傳感器讀取流程”的意思來看,子產品接線并上電後,需要先從主機給它發送初始化指令,然後就跟DHT11的measure一樣測量一下,就可以讀取溫濕度資料了。中間要注意的就是傳回的資料可能因為傳感器狀态忙而無效。

咱們學習時候就先不管狀态的事兒了,按正常流程手動指令去執行,晶片怎麼地都忙完了。

2.2. 接線

AHT10購買時介紹中說的資料走的I2C總線,官方手冊前面也提到這一點了。I2C總線需要4條線來連接配接,子產品背後也标注了。nodemcu上需要用正負極加兩個GPIO接口來與之對應。我這裡的接線方式為(AHT10 – nodemcu) vin – 3v, GND – G, SCL – GPIO 05 (D1), SDA – GPIO 04 (D2)

如圖:

MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)

另外還要注意一點,AHT10手冊上有說VIN輸入的電壓範圍是1.8V到3.6V之間,是以咱們接線時隻能接到3.3V針腳上,不要接到5V了,燒穿就沒得玩了。

2.3. micropython讀取資料

引入基礎庫,并定義I2C總結協定使用的引腳

from machine import Pin, I2C
i2c = I2C(scl=Pin(5), sda=Pin(4), freq=100000)
           

官方手冊裡面寫了AHT10子產品的從機位址是0x38,如果不放心,可以自己掃找描去拿位址:

掃描到的位址是56(十進制),跟官方寫的0x38(十六進制)是一緻的。

線已經接好了,咱們就直接先初始化裝置,然後就可以測量了

i2c.writeto(addr, b'\xE1\x08\x00')  # 初始化
i2c.writeto(addr, b'\xAC\x33\x00')  # 測量
           

測量完按手冊說的,要先查狀态再決定要不要讀取結果,這裡先直接讀結果到中間變量,友善後面計算

讀取到6個位元組的資料,其中第1個位元組是狀态位,後面5個位元組分兩半存儲了濕度和溫度資料

MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)
rst0 = data[1]<<12 | data[2]<<4 | data[3]>>4
rst1 = (data[3]&0x0f)<<16 | data[4]<<8 | data[5]
           

這裡涉及到位運算和位移的操作,目的是把紅框和綠框兩個數拆分開。

基本方法是把高位數向左移位後,與後面的低位數按位或運算,就得到各自的二進制完整數值。綠框最高位因為隻有一半,是以先跟0x0F做與運算,把該位元組的前4位置為0而保留後4位的原始值。

另外手冊第9頁有轉換資料的公式,按圖索骥

from math import pow

# 濕度轉換公式
humidity = rst0 / pow(2, 20) * 100
# 溫度轉換公式
temperature = rst1 * 200 / pow(2, 20) - 50
           

REPL實測效果:

MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)

開了空調果然不一樣,溫度下來不說,濕度變低就沒那麼躁了。

2.4. AHT10三方驅動庫

淘寶購買AHT10子產品時,産品介紹頁資料中有C++版本的驅動庫檔案。(前面按位操作取值也是參考該庫來着)

網上搜尋到有大神已經對mpy版本進行封裝和開源了,見 Gitee庫AHT10

MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)MicroPython-On-ESP8266——擷取溫濕度傳感器資料(DHT11 / AHT10)

有了這個庫其實直接拿來用就好了,省去翻看官方手冊的時間了。相見恨晚呐~~

2.5. 自用驅動庫

上面大神庫加入了溫度取攝氏度還是華氏度模式,也跟官方驅動一樣實作了露/霜點的計算,這些咱用不到,就按DHT11的模式做個近似的封裝。

按官方手機的說明來看,加入了狀态位的判斷,空閑時取到的溫濕度才有效

import utime

class AHT10:
    def __init__(self, i2c, address=0x38):
        if i2c is None:
            raise ValueError('I2C object required.')
        self.i2c = i2c
        self.address = address
        self.i2c.writeto(self.address, b'\xE1\x08\x00')  # 初始化子產品
        self._h, self._t = 0, 0  # 濕度,溫度

    def status(self, data=None):
        '檢查忙閑狀态'
        if not data:
            self.i2c.writeto(self.address, b'\x71')
            data = self.i2c.readfrom(self.address, 1)
        return data & 0x40  # 最高位為1是忙(測量中)

    def measure(self):
        '測量'
        self._h, self._t = 0, 0
        for _ in range(3): # 最多重試3次
            self.i2c.writeto(self.address, b'\xAC\x33\x00')
            utime.sleep_ms(100)  # 子產品需要80ms以上的測量時間
            raw = self.i2c.readfrom(self.address, 6)
            if self.status(raw[0]):
                utime.sleep_ms(20)  # 忙就稍等再測
            else:
                data_h = raw[1] << 12 | raw[2] << 4 | raw[3] >> 4
                data_t = (raw[3] & 0x0F) << 16 | raw[4] << 8 | raw[5]
                self._h, self._t = data_h * 100 / 1048576, ((200 * data_t) / 1048576) - 50
                break

    def humidity(self):
        '傳回測量到的濕度 %RH'
        return self._h

    def temperature(self):
        '傳回測量到的溫度 C'
        return self._t

    def reset(self):
        '軟複位'
        self.i2c.writeto(self.address, b'\xBA')
        utime.sleep_ms(20)

           

繼續閱讀