3.12. Läsa analoga värden med ADC:n¶
Hittills har kameran läst digitala signaler – ett stift är antingen 0 eller 1, en strömbrytare är öppen eller sluten. De flesta signaler som kommer från verkliga sensorer är analoga: en kontinuerlig spänning som varierar jämnt över ett visst intervall. En fotoresistor sveper genom varje spänning mellan matningsskenorna när omgivningens ljusstyrka ändras. Utsignalen från en temperatursensor driver några millivolt när ett rum värms upp. Utsignalen från en mikrofon stiger och faller med ljudet runt omkring den.
En analog-till-digital-omvandlare (ADC) är bryggan. Den samplar spänningen på ett stift och returnerar ett heltal som Python kan läsa som vilket annat värde som helst.
3.12.1. Kvantisering¶
Ett digitalt värde kan inte representera en kontinuerlig spänning exakt. ADC:ns uppgift är att kvantisera – snäppa varje sampel till den närmaste av en fast uppsättning nivåer. En N-bitars ADC har 2^N nivåer; en 12-bitars omvandlare har 4096 av dem utspridda över sitt inspänningsintervall.
Kvantisering: varje sampel av den analoga signalen (heldragen) avrundas till en av en ändlig uppsättning digitala nivåer (stegvis streckad linje).¶
Spänningen mellan två intilliggande nivåer är ADC:ns stegstorlek; allt mindre än så försvinner i avrundningen. En 12-bitars ADC över ett intervall på 3,3 V har en stegstorlek på ungefär 3.3 / 4096 ≈ 0.8 mV – tillräckligt fint för att de flesta signaler ska se i praktiken kontinuerliga ut i mjukvaran.
3.12.2. Klassen machine.ADC¶
machine.ADC omsluter en analog ingångskanal. Konstruera den med det stift du vill läsa, och anropa sedan read_u16():
from machine import ADC
adc = ADC("P6")
value = adc.read_u16()
print(value)
read_u16() returnerar alltid ett 16-bitars heltal utan tecken mellan 0 och 65535. ADC:ns nativa upplösning varierar mellan kort (12-bitars på STM32, port-specifik i övrigt); resultatet vänsterjusteras in i 16 bitar så att hårdvarudetaljen inte läcker in i Python – ett värde på 65535 motsvarar fullt utslag oavsett chip.
Referensspänningen – ingången som motsvarar fullt utslag – beror på kortet. Kontrollera OpenMV-kort för värdet på din kamera. Allt över referensen läses som fullt utslag (och kan skada stiftet om det överskrider den absoluta maximala inspänningen).
3.12.2.1. Omvandla räknarvärden till spänning¶
Mappningen från räknarvärden till spänning är linjär, där räknarvärdet vid fullt utslag mappas exakt till Vref:
voltage = counts × Vref / 65535
I kod:
VREF = 3.3 # cam-dependent; see the quickref
counts = adc.read_u16()
voltage = counts * VREF / 65535
print(voltage, "V")
3.12.3. Spänningsdelare¶
Två resistorer i serie mellan en spänningsskena och jord bildar en spänningsdelare. Noden mellan dem ligger på en spänning som bestäms av förhållandet mellan de två resistorerna:
En spänningsdelare: R1 och R2 i serie skalar ner Vin till V_out.¶
V_out = Vin × R2 / (R1 + R2)
Lika stora resistorer ger halva skenans spänning; R2 mycket mindre än R1 placerar uttaget nära jord; R2 mycket större placerar det nära skenan.
Formeln förutsätter att inget annat drar nämnvärd ström från V_out. Ett ADC-stift är högimpediant (megohm, nanoampere) och uppfyller detta enkelt, så en delare som matar en ADC beter sig som formeln förutsäger.
3.12.4. Potentiometrar¶
En potentiometer är en enda fysisk komponent som är precis en spänningsdelare, med en glidande släpkontakt som flyttar uttaget mellan de två ändarna. Att vrida på ratten ändrar R1 och R2 tillsammans samtidigt som deras summa (potentiometerns totala resistans) hålls konstant.
En potentiometer kopplad som en manuell spänningskälla för ADC:n: 3,3 V i ena änden, jord i den andra, släpkontakten till stiftet.¶
En potentiometer är standardingångsenheten för att prova ADC:n. Koppla ena änden till 3.3 V, den andra till jord och släpkontakten till ett ADC-kapabelt stift; att vrida på ratten sveper släpkontakten genom varje spänning mellan skenorna.
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. Läsa högre spänningar med en delare¶
En spänning över Vref låser ADC:n vid fullt utslag och kan skada ingången om den överskrider det absoluta maxvärdet. För att läsa en högre källa – ett batteri, en sensorutsignal som sträcker sig bortom Vref – skala ner den med en fast spänningsdelare innan den når stiftet:
Skala en högspänningskälla för att passa ADC:n: R1 och R2 bildar en fast spänningsdelare vars uttag matar ADC-stiftet.¶
Välj R1 och R2 så att den delade spänningen håller sig inom ADC:ns intervall vid den högsta inspänning du förväntar dig:
V_adc = V_in × R2 / (R1 + R2)
För en maximal V_in = 12 V och en referens på 3,3 V måste förhållandet R2 / (R1 + R2) vara högst 3.3 / 12 ≈ 0.275. Ett vanligt val med lite marginal är R1 = 33 kΩ, R2 = 10 kΩ. Förhållandet är 10 / 43 ≈ 0.233, så V_adc toppar vid ungefär 12 × 0.233 ≈ 2.79 V – säkert under Vref.
För att återskapa den ursprungliga V_in från en ADC-avläsning, invertera delarformeln:
V_in = V_adc × (R1 + R2) / R2
I kod:
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ågra praktiska anmärkningar:
Delaren drar kontinuerligt
V_in / (R1 + R2). MedR1 + R2 = 43 kΩochV_in = 12 Vär det ungefär 280 µA – vanligtvis försumbart, men om källan är batteridriven bör du överväga större resistorer (100 kΩ till 1 MΩ) för att minska viloströmmen.Resistorernas tolerans (vanligtvis ±1 % eller ±5 %) går direkt in i mätnoggrannheten. Två ±5 %-resistorer kan ge den återskapade
V_inett värsta-fall-fel på ungefär ±10 %.Delarens källimpedans kombineras med eventuell strökapacitans och lågpassfiltrerar ingången. För snabbt föränderliga signaler spelar det roll; för en kontroll av batterispänning gör det det inte.