3.17. Bittivirrat ja pulssin mittaus¶
Jotkin laitteet tarvitsevat tarkasti ajastettuja pulssikuvioita vakiotaajuisen PWM-signaalin sijaan. WS2812 RGB -LED koodaa jokaisen bitin tietyn levyisenä pulssina; HC-SR04-ultraäänietäisyysmittari vastaa kaikupulssilla, jonka leveys on edestakaisen matkan lentoaika; IR-kaukosäädin lähettää otsikon, jota seuraavat databitit päällä-pois-sekvensseinä.
machine-moduulissa on kaksi funktiota tämänkaltaista ajoitustarkkaa GPIO:ta varten:
bitstream()lähettää pulssijonon, jolla on erillinen ajoitus0- ja1-biteille.time_pulse_us()mittaa saapuvan pulssin leveyden mikrosekunteina.
3.17.1. Bittivirran lähettäminen¶
machine.bitstream() ottaa nastan, koodauksen, ajoitusmäärittelyn ja lähetettävät tavut. Yleisin koodaus (0) on korkea-matala -pulssinkestomodulaatio: jokainen bitti on yhden levyinen korkea pulssi, jota seuraa toisen levyinen matala pulssi, ja 0- ja 1-biteillä on erilliset ajoitukset.
Korkea-matala-pulssinkestokoodaus: 0 ja 1 kumpikin koostuvat korkeasta vaiheesta, jota seuraa matala vaihe, erillisillä leveyksillä.¶
Kaanoninen esimerkki on WS2812 (NeoPixel) RGB -LED, joka odottaa bittejä 800 kHz:n taajuudella näillä ajoituksilla:
0: 400 ns korkealla, sitten 850 ns matalalla.1: 800 ns korkealla, sitten 450 ns matalalla.
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")
MCU bittipaukuttaa pulssit pyydetyillä leveyksillä; siihen riittävän nopeissa kameroissa ajoitus on tarkka kymmenien nanosekuntien sisällä.
Varoitus
bitstream() poistaa kaikki keskeytykset käytöstä koko lähetyksen ajaksi, jotta se voi pitää tarkan hallinnan pulssiajoituksesta. Kutsun kesto kasvaa lineaarisesti tavujen määrän mukaan – WS2812-ajoituksella (noin 10 µs tavua kohti) 100 tavun lähettäminen pysäyttää suorittimen noin 1 ms:n ajaksi, 1000 tavua 10 ms:n ja 10000 tavua täydet 100 ms. Mikä tahansa muutaman sadan tavun yli kutsua kohti riskeeraa havaittavia jumiutumisia – pilko pitkät päivitykset pienempiin paloihin niin, että kutsu palaa kunkin palan välissä, jotta loput skriptistä voivat suorittua.
Muista
Erityisesti WS2812 / NeoPixel -nauhojen ajamiseen neopixel-moduuli kietoo bitstream()-funktion korkeamman tason rajapintaan, joka hoitaa värijärjestyksen sekoittamisen ja koko nauhan joukkopäivitykset. Tartu suoraan bitstream()-funktioon, kun protokolla ei ole WS2812 mutta sopii silti korkea-matala-PDM-muotoon.
3.17.2. Saapuvan pulssin mittaaminen¶
machine.time_pulse_us() mittaa yksittäisen pulssin leveyden nastassa. Se odottaa, että linja saavuttaa määritetyn tason (pulssin alku), mittaa sitten, kuinka kauan linja pysyy tällä tasolla (pulssin loppu), ja palauttaa keston mikrosekunteina.
Klassinen käyttö on HC-SR04-ultraäänietäisyyssensori. Kamera lähettää 10 µs:n liipaisupulssin, sitten odottaa, että kaikunasta palauttaa pulssin, jonka leveys on äänen edestakainen aika:
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)
Kolmas argumentti on aikakatkaisu mikrosekunteina, sovellettuna erikseen ”odota pulssin alkamista”- ja ”odota pulssin loppumista” -vaiheisiin. Aikakatkaisussa funktio palauttaa negatiivisen arvon, joka kertoo mikä vaihe epäonnistui: -2 jos pulssi ei koskaan alkanut, -1 jos se alkoi mutta ei koskaan loppunut ikkunan sisällä.
Aikakatkaisun molemmat puolikkaat ovat tärkeitä todellisille sensoreille. HC-SR04:llä voi kestää yhdestä kahteen millisekuntia aloittaa kaikunsa, ja itse kaiku voi olla kymmeniä millisekunteja pitkä kaukana oleville kohteille. timeout_us-arvon mitoittaminen tarvittavalle enimmäisetäisyydelle pitää mittauksen rajattuna.