MicroPython
ESP32
PaoyungJun 06, 2022
ℳ𝒾𝒸𝓇ℴ𝒫𝓎𝓉𝒽ℴ𝓃 隨手記Image Not Showing Possible ReasonsLearn More →
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
在 MicroPython 的創作中,常常要用上多種感測或顯示元件,以標準的撰寫風格會以 while 讓任務輪詢,當遇上有採樣間距的元件則以 sleep 稍做停等,但一旦遇上多種感測元件却有著不同停等間隔時,就很容易造成干擾或卡頓。若每個被調用元件的模組都能做好時間的管理,令人困擾的問題或許就能得以改善。在此以坊間經常使用的 DHT11 溫濕度傳感器配搭 ESP32 做為例子。
MicroPython 在 ESP32 上有 4 組 Timer 可用,模式有 ONE_SHOT 和 PERIODIC,相當於 Javascript 中的 setTimeout 和 setInterval。相關文件可參閱官方說明。而在下方的範例中,要做時間管理就必須佔用一組,預設是 Timer3,也可視情況自行指定。
MicroPython 的 dht 模組如前所述,採樣週期過短時會發出異常,造成程式執行的中斷,若希望能有一個可自行管理時間,不管何時呼叫它都不要阻斷和中斷的程式模組,就必須擴充模組的功能。擴充的方式有很多,正規做法是用 class 的繼承再加上 funtion 的覆寫來達成,在此不打算這麼做,而只是要幫原來的模組穿個外套
dht11.py
# name: dht11.py, version: 0.1.0, author: paoyung.chang@gmail.com
# Copyright (c) 2022 Paoyung Chang. See the file LICENSE for copying permission.
# License link: https://gist.github.com/paoyung/7e465ad984a6cf24024508831ec54516
from machine import Pin, Timer
from time import sleep, ticks_ms, ticks_diff
import dht
class DHT11:
def __init__(self, pin, timer=Timer(3)):
self.dht11 = dht.DHT11(pin)
self.timer = timer
self.last_ticks = 0
self.t = 0
self.h = 0
def measure(self):
now = ticks_ms()
# 間隔要超過1秒以上才不會異常
if ticks_diff(now, self.last_ticks) > 1200:
self.last_ticks = now
try:
self.dht11.measure()
except:
return
else:
self.timer.init(period=1100, mode=Timer.ONE_SHOT, callback=self.read_data)
else:
# 間隔太短,略過
pass
def read_data(self, t):
self.t = self.dht11.temperature()
self.h = self.dht11.humidity()
def temperature(self):
return self.t
def humidity(self):
return self.h
將上述的程式存為 dht11.py 並上傳至 ESP32。用法就和原來的相同,僅做小幅的改變即可。
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)
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 的做法。