3.12. Čtení analogového signálu pomocí ADC

Doposud kamera četla digitální signály – pin je buď 0 nebo 1, spínač je rozepnutý nebo sepnutý. Většina signálů přicházejících ze senzorů reálného světa je však analogová: spojité napětí, které se plynule mění v určitém rozsahu. Fotorezistor prochází všemi napětími mezi napájecími úrovněmi podle toho, jak se mění okolní jas. Výstup teplotního senzoru se posune o několik milivoltů, jak se místnost ohřívá. Výstup mikrofonu stoupá a klesá podle zvuku v okolí.

Analogově-digitální převodník (ADC) je mostem mezi nimi. Vzorkuje napětí na pinu a vrací celé číslo, které Python může číst jako jakoukoli jinou hodnotu.

3.12.1. Kvantizace

Digitální hodnota nemůže přesně reprezentovat spojité napětí. Úkolem ADC je kvantizovat – přiřadit každý vzorek nejbližší z pevné sady úrovní. N-bitový ADC má 2^N úrovní; 12bitový převodník jich má 4096 rozprostřených přes svůj vstupní rozsah.

Plynulá analogová křivka vykreslená v závislosti na čase, překrytá schodovitou digitální aproximací. Čárkované vodorovné čáry označují kvantizační úrovně; schodovitá křivka se přichytává k té úrovni, která je v každém bodě vzorkování nejblíže analogovému signálu.

Kvantizace: každý vzorek analogového signálu (plná čára) je zaokrouhlen na jednu z konečné sady digitálních úrovní (schodovitá čárkovaná čára).

Napětí mezi dvěma sousedními úrovněmi je velikost kroku ADC; cokoli menšího se ztratí v zaokrouhlení. 12bitový ADC v rozsahu 3,3 V má velikost kroku přibližně 3.3 / 4096 0.8 mV – dostatečně jemnou na to, aby většina signálů v softwaru vypadala prakticky spojitě.

3.12.2. Třída machine.ADC

machine.ADC obaluje jeden analogový vstupní kanál. Zkonstruujte ji s pinem, který chcete číst, a poté zavolejte read_u16():

from machine import ADC

adc = ADC("P6")
value = adc.read_u16()
print(value)

read_u16() vždy vrací 16bitové celé číslo bez znaménka mezi 0 a 65535. Nativní rozlišení ADC se liší podle desky (12bitové na STM32, jinde závisí na portu); výsledek je zarovnán doleva do 16 bitů, takže hardwarové detaily neprosakují do Pythonu – hodnota 65535 znamená plný rozsah bez ohledu na čip.

Referenční napětí – vstup, který odpovídá plnému rozsahu – závisí na desce. Hodnotu pro vaši kameru najdete v Desky OpenMV. Cokoli nad referencí se čte jako plný rozsah (a může poškodit pin, pokud překročí absolutní maximální vstupní napětí).

3.12.2.1. Převod hodnot na napětí

Mapování z hodnot na napětí je lineární, přičemž hodnoty plného rozsahu se mapují přesně na Vref:

voltage = counts × Vref / 65535

V kódu:

VREF = 3.3  # cam-dependent; see the quickref
counts = adc.read_u16()
voltage = counts * VREF / 65535
print(voltage, "V")

3.12.3. Napěťové děliče

Dva rezistory v sérii mezi napájecí úrovní a zemí tvoří napěťový dělič. Uzel mezi nimi má napětí dané poměrem obou rezistorů:

Napěťový dělič. Vin nahoře se připojuje přes R1 k uzlu odbočenému jako V_out, který se pak připojuje přes R2 k zemi.

Napěťový dělič: R1 a R2 v sérii zmenšují Vin na V_out.

V_out = Vin × R2 / (R1 + R2)

Stejné rezistory dají polovinu napájecího napětí; R2 mnohem menší než R1 posune odbočku blízko zemi; R2 mnohem větší ji posune blízko napájecí úrovni.

Vzorec předpokládá, že z V_out neodebírá znatelný proud nic dalšího. Pin ADC má vysokou impedanci (megaohmy, nanoampéry) a tuto podmínku snadno splňuje, takže dělič napájející ADC se chová tak, jak vzorec předpovídá.

3.12.4. Potenciometry

Potenciometr je jediná fyzická součástka, která je přesně napěťovým děličem, s posuvným jezdcem, který pohybuje odbočkou mezi dvěma konci. Otáčení knoflíku mění R1 a R2 současně, přičemž jejich součet (celkový odpor potenciometru) zůstává konstantní.

Potenciometr zapojený mezi 3,3 V a zem. Jezdec je odbočen na pin ADC.

Potenciometr zapojený jako ruční zdroj napětí pro ADC: 3,3 V na jednom konci, zem na druhém, jezdec na pin.

Potenciometr je typickým vstupním zařízením pro vyzkoušení ADC. Zapojte jeden konec na 3.3 V, druhý na zem a jezdec na pin podporující ADC; otáčení knoflíku posouvá jezdec přes všechna napětí mezi napájecími úrovněmi.

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. Čtení vyšších napětí pomocí děliče

Napětí nad Vref přitlačí ADC na plný rozsah a může poškodit vstup, pokud překročí absolutní maximální hodnotu. Chcete-li číst vyšší zdroj – baterii, výstup senzoru přesahující Vref – zmenšete jej pevným napěťovým děličem dříve, než dosáhne pinu:

Napěťový dělič zmenšující vysoké V_in na pin ADC. R1 vede z V_in dolů k uzlu, který je odbočen vodorovně na pin ADC; R2 pokračuje z uzlu dolů k zemi.

Zmenšení vysokonapěťového zdroje tak, aby vyhovoval ADC: R1 a R2 tvoří pevný napěťový dělič, jehož odbočka napájí pin ADC.

Zvolte R1 a R2 tak, aby dělené napětí zůstalo v rozsahu ADC při nejvyšším vstupním napětí, které očekáváte:

V_adc = V_in × R2 / (R1 + R2)

Pro maximální V_in = 12 V a referenci 3,3 V musí být poměr R2 / (R1 + R2) nejvýše 3.3 / 12 0.275. Běžnou volbou s malou rezervou je R1 = 33 , R2 = 10 . Poměr je 10 / 43 0.233, takže V_adc dosahuje maxima asi 12 × 0.233 2.79 V – bezpečně pod Vref.

Chcete-li z hodnoty ADC získat zpět původní V_in, invertujte vzorec děliče:

V_in = V_adc × (R1 + R2) / R2

V kódu:

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")

Několik praktických poznámek:

  • Dělič nepřetržitě odebírá V_in / (R1 + R2). Při R1 + R2 = 43 a V_in = 12 V je to asi 280 µA – obvykle zanedbatelné, ale pokud je zdroj napájen z baterie, zvažte větší rezistory (100 kΩ až 1 MΩ) pro snížení klidového odběru.

  • Tolerance rezistorů (typicky ±1 % nebo ±5 %) se přímo promítá do přesnosti měření. Dva rezistory ±5 % mohou dát získanému V_in chybu v nejhorším případě zhruba ±10 %.

  • Zdrojová impedance děliče se kombinuje s případnou parazitní kapacitou a vytváří dolnopropustný filtr vstupu. U rychle se měnících signálů na tom záleží; u kontroly napětí baterie nikoli.