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 ajoitus 0- ja 1-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.

Kaksi päällekkäistä aaltomuotoa. Ylempi näyttää 0-bitin: a lyhyt korkea pulssi (high_0), jota seuraa pidempi matala jakso (low_0). Alempi näyttää 1-bitin: pidempi korkea pulssi (high_1), jota seuraa lyhyempi matala jakso (low_1).

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.