3.12. Analogisignaalin lukeminen ADC:llä#
Tähän asti kamera on lukenut digitaalisia signaaleja – nasta on joko 0 tai 1, kytkin on auki tai kiinni. Useimmat reaalimaailman sensoreilta tulevat signaalit ovat analogisia: jatkuva jännite, joka vaihtelee tasaisesti jollakin alueella. Valovastus käy läpi jokaisen jännitteen kiskojen välillä ympäristön kirkkauden muuttuessa. Lämpötila-anturin lähtö ajautuu muutaman millivoltin huoneen lämmetessä. Mikrofonin lähtö nousee ja laskee ympärillä olevan äänen mukaan.
Analogia-digitaalimuunnin (ADC) on silta näiden välillä. Se näytteistää nastan jännitteen ja palauttaa kokonaisluvun, jonka Python voi lukea kuten minkä tahansa muunkin arvon.
3.12.1. Kvantisointi#
Digitaalinen arvo ei voi esittää jatkuvaa jännitettä tarkasti. ADC:n tehtävä on kvantisoida – pyöristää jokainen näyte lähimpään kiinteästä joukosta tasoja. N-bittisessä ADC:ssä on 2^N tasoa; 12-bittisessä muuntimessa niitä on 4096 jaettuna sen tuloalueelle.
Kvantisointi: jokainen analogiasignaalin näyte (yhtenäinen viiva) pyöristetään yhteen äärellisestä joukosta digitaalisia tasoja (porrastettu katkoviiva).#
Kahden vierekkäisen tason välinen jännite on ADC:n askelkoko; mikä tahansa sitä pienempi häviää pyöristykseen. 12-bittisellä ADC:llä 3,3 V:n alueella askelkoko on noin 3.3 / 4096 ≈ 0.8 mV – riittävän hieno, jotta useimmat signaalit näyttävät ohjelmistossa käytännössä jatkuvilta.
3.12.2. machine.ADC-luokka#
machine.ADC kapseloi yhden analogisen tulokanavan. Luo se nastalla, jonka haluat lukea, ja kutsu sitten read_u16():
from machine import ADC
adc = ADC("P6")
value = adc.read_u16()
print(value)
read_u16() palauttaa aina etumerkittömän 16-bittisen kokonaisluvun väliltä 0 ja 65535. ADC:n natiivi resoluutio vaihtelee kortin mukaan (12-bittinen STM32:ssa, muualla porttikohtainen); tulos kohdistetaan vasemmalle 16 bittiin, joten laitteistoyksityiskohta ei vuoda Pythoniin – arvo 65535 on täysi asteikko sirusta riippumatta.
Referenssijännite – tulo, joka vastaa täyttä asteikkoa – riippuu kortista. Tarkista arvo kamerallesi kohdasta OpenMV-kortit. Mikä tahansa referenssin yläpuolella oleva luetaan täydeksi asteikoksi (ja voi vaurioittaa nastaa, jos se ylittää absoluuttisen maksimitulojännitteen).
3.12.2.1. Lukemien muuntaminen jännitteeksi#
Kuvaus lukemista jännitteeksi on lineaarinen, ja täyden asteikon lukemat kuvautuvat tarkalleen arvoon Vref:
voltage = counts × Vref / 65535
Koodissa:
VREF = 3.3 # cam-dependent; see the quickref
counts = adc.read_u16()
voltage = counts * VREF / 65535
print(voltage, "V")
3.12.3. Jännitteenjakajat#
Kaksi vastusta sarjassa jännitekiskon ja maan välillä muodostavat jännitteenjakajan. Niiden välinen solmu asettuu jännitteeseen, jonka kahden vastuksen suhde määrää:
Jännitteenjakaja: R1 ja R2 sarjassa skaalaavat Vin-arvon alas arvoksi V_out.#
V_out = Vin × R2 / (R1 + R2)
Yhtä suuret vastukset antavat puolet kiskon jännitteestä; kun R2 on paljon pienempi kuin R1, haaroituskohta on lähellä maata; kun R2 on paljon suurempi, se on lähellä kiskoa.
Kaava olettaa, ettei mikään muu ota merkittävää virtaa kohdasta V_out. ADC-nasta on korkeaimpedanssinen (megaohmeja, nanoampeereja) ja täyttää tämän helposti, joten ADC:tä syöttävä jakaja käyttäytyy kaavan ennustamalla tavalla.
3.12.4. Potentiometrit#
Potentiometri on yksittäinen fyysinen komponentti, joka on juuri jännitteenjakaja, jossa liukuva liukukosketin siirtää haaroituskohtaa kahden pään välillä. Nuppia kääntämällä muutetaan R1- ja R2-arvoja yhdessä pitäen niiden summa (potentiometrin kokonaisresistanssi) vakiona.
Potentiometri kytkettynä manuaaliseksi jännitelähteeksi ADC:lle: 3,3 V toisessa päässä, maa toisessa, liukukosketin nastaan.#
Potentiometri on perinteinen syöttölaite ADC:n kokeilemiseen. Kytke toinen pää kohtaan 3.3 V, toinen maahan ja liukukosketin ADC-kelpoiseen nastaan; nuppia kääntämällä liukukosketin pyyhkii läpi jokaisen jännitteen kiskojen välillä.
import time
from machine import ADC
pot = ADC("P6")
VREF = 3.3
while True:
counts = pot.read_u16()
voltage = counts * VREF / 65535
print(voltage, "V")
time.sleep_ms(100)
3.12.5. Korkeampien jännitteiden lukeminen jakajalla#
Vref-arvon yläpuolella oleva jännite kiinnittää ADC:n täyteen asteikkoon ja voi vaurioittaa tuloa, jos se ylittää absoluuttisen maksimiarvon. Korkeamman lähteen lukemiseksi – akku, sensorin lähtö, joka ulottuu Vref-arvon yli – skaalaa se alas kiinteällä jännitteenjakajalla ennen kuin se saavuttaa nastan:
Korkeajännitelähteen skaalaaminen ADC:lle sopivaksi: R1 ja R2 muodostavat kiinteän jännitteenjakajan, jonka haaroituskohta syöttää ADC-nastaa.#
Valitse R1 ja R2 niin, että jaettu jännite pysyy ADC:n alueen sisällä suurimmalla odottamallasi tulojännitteellä:
V_adc = V_in × R2 / (R1 + R2)
Suurimmalle arvolle V_in = 12 V ja 3,3 V:n referenssille suhteen R2 / (R1 + R2) on oltava enintään 3.3 / 12 ≈ 0.275. Yleinen valinta hieman pelivaralla on R1 = 33 kΩ, R2 = 10 kΩ. Suhde on 10 / 43 ≈ 0.233, joten V_adc saavuttaa enimmillään noin 12 × 0.233 ≈ 2.79 V – turvallisesti Vref-arvon alapuolella.
Alkuperäisen V_in-arvon palauttamiseksi ADC-lukemasta käännä jakajan kaava:
V_in = V_adc × (R1 + R2) / R2
Koodissa:
from machine import ADC
R1 = 33_000
R2 = 10_000
VREF = 3.3
adc = ADC("P6")
counts = adc.read_u16()
v_adc = counts * VREF / 65535
v_in = v_adc * (R1 + R2) / R2
print(v_in, "V")
Muutamia käytännön huomioita:
Jakaja ottaa jatkuvasti
V_in / (R1 + R2). ArvoillaR1 + R2 = 43 kΩjaV_in = 12 Vse on noin 280 µA – yleensä mitätön, mutta jos lähde on akkukäyttöinen, harkitse suurempia vastuksia (100 kΩ:sta 1 MΩ:iin) lepovirran vähentämiseksi.Vastuksen toleranssi (tyypillisesti ±1 % tai ±5 %) vaikuttaa suoraan mittaustarkkuuteen. Kaksi ±5 %:n vastusta voivat aiheuttaa palautetulle
V_in-arvolle pahimmillaan noin ±10 %:n virheen.Jakajan lähdeimpedanssi yhdistyy hajakapasitanssin kanssa muodostaen tulolle alipäästösuodattimen. Nopeasti muuttuville signaaleille tällä on merkitystä; akun jännitteen tarkistukselle ei.