3.17. Bitfolyamok és impulzusmérés¶
Egyes eszközöknek pontosan időzített impulzusmintákra van szükségük, nem pedig állandó frekvenciájú PWM-jelre. Egy WS2812 RGB LED minden bitet egy meghatározott szélességű impulzusként kódol; egy HC-SR04 ultrahangos távolságmérő egy visszhang-impulzussal válaszol, amelynek szélessége az oda-vissza repülési idő; egy IR-távirányító egy fejlécet küld, amelyet az adatbitek be-ki kapcsolási sorozatként követnek.
A machine modul két függvényt kínál erre a fajta időzítéspontos GPIO-ra:
A
bitstream()egy impulzussorozatot küld, külön időzítéssel a0és az1bitekhez.A
time_pulse_us()mikroszekundumban méri egy beérkező impulzus szélességét.
3.17.1. Bitfolyam küldése¶
A machine.bitstream() egy lábat, egy kódolást, egy időzítési specifikációt és a küldendő bájtokat veszi át. A leggyakoribb kódolás (0) a magas-alacsony impulzusszélesség-moduláció: minden bit egy bizonyos szélességű magas impulzus, amelyet egy másik szélességű alacsony impulzus követ, ahol a 0 és az 1 bitek eltérő időzítésűek.
A magas-alacsony impulzusszélesség-kódolás: egy 0 és egy 1 is egy magas fázisból áll, amelyet egy alacsony fázis követ, eltérő szélességekkel.¶
A kanonikus példa a WS2812 (NeoPixel) RGB LED, amely 800 kHz-en várja a biteket, a következő időzítésekkel:
0: 400 ns magas, majd 850 ns alacsony.1: 800 ns magas, majd 450 ns alacsony.
from machine import Pin, bitstream
pin = Pin("P7", Pin.OUT)
# (high_0, low_0, high_1, low_1) in nanoseconds
timing = (400, 850, 800, 450)
# one LED: GRB order, three bytes per LED (red shown here)
bitstream(pin, 0, timing, b"\x00\xff\x00")
Az MCU a kért szélességekre bit-bangeli az impulzusokat; az ehhez elég gyors kamerákon az időzítés néhány tíz nanoszekundumon belüli pontosságú.
Figyelem
A bitstream() a teljes átvitel idejére letiltja az összes megszakítást, hogy pontosan kézben tarthassa az impulzusidőzítést. A hívás időtartama lineárisan skálázódik a bájtok számával – WS2812 időzítésnél (bájtonként körülbelül 10 µs) 100 bájt küldése a CPU-t körülbelül 1 ms-ra szünetelteti, 1000 bájt 10 ms-ra, 10000 bájt pedig teljes 100 ms-ra. Bármi, ami hívásonként néhány száz bájton túlmegy, észrevehető lefagyásokat kockáztat – bontsd a hosszú frissítéseket kisebb darabokra, úgy hogy a hívás minden darab között visszatérjen, hogy a szkript többi része futhasson.
Megjegyzés
Kifejezetten WS2812 / NeoPixel szalagok meghajtásához a neopixel modul a bitstream() függvényt egy magasabb szintű felületbe csomagolja, amely kezeli a színsorrend átrendezését és a tömeges szalagfrissítéseket. Akkor nyúlj közvetlenül a bitstream() függvényhez, amikor a protokoll nem WS2812, de még mindig egy magas-alacsony PDM alakba illeszkedik.
3.17.2. Beérkező impulzus mérése¶
A machine.time_pulse_us() egy lábon egyetlen impulzus szélességét méri. Megvárja, amíg a vonal eléri a megadott szintet (az impulzus kezdetét), majd megméri, mennyi ideig marad a vonal azon a szinten (az impulzus vége), és visszaadja az időtartamot mikroszekundumban.
A klasszikus felhasználás egy HC-SR04 ultrahangos távolságérzékelő. A kamera egy 10 µs-os trigger-impulzust küld, majd megvárja, amíg a visszhang-láb visszaad egy impulzust, amelynek szélessége a hang oda-vissza ideje:
import time
from machine import Pin, time_pulse_us
trigger = Pin("P7", Pin.OUT, value=0)
echo = Pin("P8", Pin.IN)
while True:
trigger.value(1)
time.sleep_us(10)
trigger.value(0)
width = time_pulse_us(echo, 1, timeout_us=30_000)
if width > 0:
# sound at ~343 m/s; round trip / 2 / 343 = distance (m)
distance_cm = (width * 343) / 2 / 10_000
print(distance_cm, "cm")
time.sleep_ms(100)
A harmadik argumentum a mikroszekundumban megadott időkorlát, amely külön-külön vonatkozik az „impulzus kezdetére várás” és az „impulzus végére várás” szakaszra. Időtúllépéskor a függvény egy negatív értéket ad vissza, amely azonosítja, melyik szakasz hiúsult meg: -2, ha az impulzus soha nem indult el, -1, ha elindult, de soha nem ért véget az ablakon belül.
Az időkorlát mindkét fele számít a valós érzékelőknél. Egy HC-SR04-nek egy-két ezredmásodpercbe telhet, mire elindítja a visszhangját, és maga a visszhang távoli tárgyaknál több tíz ezredmásodperc hosszú is lehet. A timeout_us méretezése a szükséges maximális tartományhoz korlátok között tartja a mérést.