---
title: MicroPython 與有採樣間距需求的感測器
image: https://i.imgur.com/f2cjXwk.png
disqus: paoyung
---
# MicroPython 與有採樣間距需求的感測器
###### tags: `MicroPython` `ESP32`
> [color=#58f][name=Paoyung][time=Jun 06, 2022] [:snake: ℳ𝒾𝒸𝓇ℴ𝒫𝓎𝓉𝒽ℴ𝓃 隨手記](/@PaoyungChang/mpy_trifiles)
前言
---
在 MicroPython 的創作中,常常要用上多種感測或顯示元件,以標準的撰寫風格會以 while 讓任務輪詢,當遇上有採樣間距的元件則以 sleep 稍做停等,但一旦遇上多種感測元件却有著不同停等間隔時,就很容易造成干擾或卡頓。若每個被調用元件的模組都能做好時間的管理,令人困擾的問題或許就能得以改善。在此以坊間經常使用的 DHT11 溫濕度傳感器配搭 ESP32 做為例子。
Timer
---
MicroPython 在 ESP32 上有 4 組 Timer 可用,模式有 ONE_SHOT 和 PERIODIC,相當於 Javascript 中的 setTimeout 和 setInterval。相關文件可參閱官方說明。而在下方的範例中,要做時間管理就必須佔用一組,預設是 Timer3,也可視情況自行指定。
> [color=green][Quick reference for the ESP32](https://docs.micropython.org/en/latest/esp32/quickref.html#timers)
數據與異常
---
- DHT11 的官方文件說其採樣週期間隔不得低於 1 秒,網路上的教學則建議為 2 秒,以下的範例仍依官方建議,**可視個人需求再行修改**。

- 而在某些元件或應用時,數據容易產生跳動,但正常情況下溫濕度是不會在幾秒內產生明顯變化,所以通常會用上一點小技巧做去抖均化,不過 DHT11 的精度不高,比較看不出其差別,因此暫不納入考量,待日後有機會再行展示。
> [color=green][DHT11 datasheet](https://cdn-shop.adafruit.com/datasheets/DHT11-chinese.pdf)
穿外套
---
MicroPython 的 dht 模組如前所述,採樣週期過短時會發出異常,造成程式執行的中斷,若希望能有一個可自行管理時間,不管何時呼叫它都不要阻斷和中斷的程式模組,就必須擴充模組的功能。擴充的方式有很多,正規做法是用 class 的繼承再加上 funtion 的覆寫來達成,在此不打算這麼做,而只是要幫原來的模組穿個外套:coat:,將原來的 dht 包在裡面,利用 timer 在安全的時間才做動作,僅此而已。其用法必須和原來的 dht 一致,才能讓已套用它的程式碼做最小幅的修改,即能改善異常的問題。
程式
---
[dht11.py](https://gist.githubusercontent.com/paoyung/664cc0367fe310fe7edac1b687d32c03/raw/17881cc3f2b47ea7b650f44ae05d8e5d97a9ab5a/dht11.py)
{%gist paoyung/664cc0367fe310fe7edac1b687d32c03%}
將上述的程式存為 [dht11.py]() 並上傳至 ESP32。用法就和原來的相同,僅做小幅的改變即可。
範例1
---
```python=
from machine import Pin
from dht11 import DHT11
from time import sleep
def demo():
# 未指定 Timer,預設使用 Timer3
d11 = DHT11(Pin(13))
led = Pin(2, Pin.OUT)
while 1:
led.value(not led.value())
d11.measure()
print('T:', d11.temperature())
print('H:', d11.humidity())
print('---------')
sleep(0.5)
```
範例2
---
```python=
from machine import Pin, Timer
from dht11 import DHT11
from time import sleep
def demo_interval():
# 指定使用 Timer0
tim0 = Timer(0)
d11 = DHT11(Pin(13), tim0)
led = Pin(2, Pin.OUT)
def callback(t):
d11.measure()
print('T:', d11.temperature())
print('H:', d11.humidity())
print('---------')
tim2 = Timer(2)
tim2.init(period=1200, mode=Timer.PERIODIC, callback=callback)
while 1:
led.value(not led.value())
sleep(0.5)
```
使用建議
---
範例 1 因在 measure 後執行了 sleep,而 measure 執行會佔用一小段時間,因此會增加實際 sleep 的時間,相對於較為要求精確的 case 會建議使用範例 2 的做法。
:sunglasses:
{%hackmd /@PaoyungChang/intro_v0702 %}