3.12. Odczyt sygnałów analogowych za pomocą ADC¶
Do tej pory kamera odczytywała sygnały cyfrowe – pin jest albo 0, albo 1, przełącznik jest otwarty lub zamknięty. Większość sygnałów pochodzących z rzeczywistych sensorów ma charakter analogowy: jest to ciągłe napięcie, które płynnie zmienia się w pewnym zakresie. Fotorezystor przechodzi przez wszystkie napięcia między szynami zasilania w miarę zmian jasności otoczenia. Wyjście sensora temperatury dryfuje o kilka miliwoltów, gdy pomieszczenie się nagrzewa. Wyjście mikrofonu rośnie i opada wraz z otaczającym go dźwiękiem.
Przetwornik analogowo-cyfrowy (ADC) jest pomostem między tymi światami. Próbkuje napięcie na pinie i zwraca liczbę całkowitą, którą Python może odczytać jak każdą inną wartość.
3.12.1. Kwantyzacja¶
Wartość cyfrowa nie może dokładnie odwzorować ciągłego napięcia. Zadaniem ADC jest kwantyzacja – przypisanie każdej próbki do najbliższego z ustalonego zbioru poziomów. N-bitowy ADC ma 2^N poziomów; przetwornik 12-bitowy ma ich 4096 rozłożonych w zakresie wejściowym.
Kwantyzacja: każda próbka sygnału analogowego (linia ciągła) jest zaokrąglana do jednego ze skończonego zbioru poziomów cyfrowych (schodkowa linia przerywana).¶
Napięcie pomiędzy dwoma sąsiednimi poziomami to rozdzielczość kroku (step size) ADC; cokolwiek mniejszego znika w zaokrągleniu. 12-bitowy ADC w zakresie 3,3 V ma krok wynoszący około 3.3 / 4096 ≈ 0.8 mV – na tyle drobny, że w oprogramowaniu większość sygnałów wygląda praktycznie na ciągłe.
3.12.2. Klasa machine.ADC¶
machine.ADC obejmuje jeden analogowy kanał wejściowy. Utwórz jej instancję z pinem, który chcesz odczytywać, a następnie wywołaj read_u16():
from machine import ADC
adc = ADC("P6")
value = adc.read_u16()
print(value)
read_u16() zawsze zwraca 16-bitową liczbę całkowitą bez znaku z zakresu od 0 do 65535. Natywna rozdzielczość ADC zależy od płytki (12 bitów na STM32, zależnie od portu w innych przypadkach); wynik jest wyrównany do lewej w obrębie 16 bitów, dzięki czemu szczegóły sprzętowe nie przenikają do Pythona – wartość 65535 oznacza pełną skalę niezależnie od układu.
Napięcie odniesienia – wejście odpowiadające pełnej skali – zależy od płytki. Sprawdź Płytki OpenMV, aby poznać wartość dla swojej kamery. Wszystko powyżej napięcia odniesienia jest odczytywane jako pełna skala (i może uszkodzić pin, jeśli przekroczy bezwzględne maksymalne napięcie wejściowe).
3.12.2.1. Przeliczanie zliczeń na napięcie¶
Odwzorowanie zliczeń na napięcie jest liniowe, przy czym zliczenia pełnej skali odpowiadają dokładnie Vref:
voltage = counts × Vref / 65535
W kodzie:
VREF = 3.3 # cam-dependent; see the quickref
counts = adc.read_u16()
voltage = counts * VREF / 65535
print(voltage, "V")
3.12.3. Dzielniki napięcia¶
Dwa rezystory połączone szeregowo między szyną napięcia a masą tworzą dzielnik napięcia. Węzeł między nimi przyjmuje napięcie wyznaczone przez stosunek obu rezystorów:
Dzielnik napięcia: R1 i R2 połączone szeregowo skalują Vin w dół do V_out.¶
V_out = Vin × R2 / (R1 + R2)
Równe rezystory dają połowę napięcia szyny; R2 znacznie mniejszy niż R1 umieszcza punkt odprowadzenia blisko masy; R2 znacznie większy umieszcza go blisko szyny.
Wzór zakłada, że nic innego nie pobiera zauważalnego prądu z V_out. Pin ADC ma wysoką impedancję (megaomy, nanoampery) i z łatwością spełnia to założenie, więc dzielnik zasilający ADC zachowuje się tak, jak przewiduje wzór.
3.12.4. Potencjometry¶
Potencjometr to pojedynczy fizyczny element, który stanowi dokładnie dzielnik napięcia, z przesuwnym ślizgaczem przemieszczającym punkt odprowadzenia między dwoma końcami. Obracanie pokrętła zmienia jednocześnie R1 i R2, utrzymując ich sumę (całkowitą rezystancję potencjometru) na stałym poziomie.
Potencjometr podłączony jako ręczne źródło napięcia dla ADC: 3,3 V na jednym końcu, masa na drugim, ślizgacz do pinu.¶
Potencjometr to kanoniczne urządzenie wejściowe do wypróbowania ADC. Podłącz jeden koniec do 3.3 V, drugi do masy, a ślizgacz do pinu obsługującego ADC; obracanie pokrętła przesuwa ślizgacz przez wszystkie napięcia między szynami.
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. Odczyt wyższych napięć za pomocą dzielnika¶
Napięcie powyżej Vref ustawi ADC na pełnej skali i może uszkodzić wejście, jeśli przekroczy bezwzględną wartość maksymalną. Aby odczytać wyższe źródło – baterię, wyjście sensora wykraczające poza Vref – przeskaluj je w dół za pomocą stałego dzielnika napięcia, zanim dotrze do pinu:
Skalowanie źródła wysokiego napięcia tak, aby pasowało do ADC: R1 i R2 tworzą stały dzielnik napięcia, którego punkt odprowadzenia zasila pin ADC.¶
Dobierz R1 i R2 tak, aby podzielone napięcie pozostawało w zakresie ADC przy najwyższym spodziewanym napięciu wejściowym:
V_adc = V_in × R2 / (R1 + R2)
Dla maksymalnego V_in = 12 V i napięcia odniesienia 3,3 V stosunek R2 / (R1 + R2) musi wynosić co najwyżej 3.3 / 12 ≈ 0.275. Częstym wyborem z niewielkim zapasem jest R1 = 33 kΩ, R2 = 10 kΩ. Stosunek wynosi 10 / 43 ≈ 0.233, więc V_adc osiąga maksymalnie około 12 × 0.233 ≈ 2.79 V – bezpiecznie poniżej Vref.
Aby odzyskać oryginalne V_in z odczytu ADC, odwróć wzór dzielnika:
V_in = V_adc × (R1 + R2) / R2
W kodzie:
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")
Kilka praktycznych uwag:
Dzielnik pobiera w sposób ciągły
V_in / (R1 + R2). PrzyR1 + R2 = 43 kΩiV_in = 12 Vto około 280 µA – zwykle pomijalne, ale jeśli źródło jest zasilane bateryjnie, rozważ większe rezystory (od 100 kΩ do 1 MΩ), aby ograniczyć pobór w stanie spoczynku.Tolerancja rezystorów (zwykle ±1 % lub ±5 %) bezpośrednio wpływa na dokładność pomiaru. Dwa rezystory ±5 % mogą dać odzyskanemu
V_inbłąd w najgorszym przypadku rzędu ±10 %.Impedancja źródłowa dzielnika łączy się z dowolną pojemnością pasożytniczą, dolnoprzepustowo filtrując wejście. W przypadku szybko zmieniających się sygnałów ma to znaczenie; w przypadku sprawdzania napięcia baterii nie ma.