3.12. Lecture de signaux analogiques avec l’ADC¶
Jusqu’à présent, la caméra a lu des signaux numériques : une broche est soit à 0 soit à 1, un interrupteur est ouvert ou fermé. La plupart des signaux issus de capteurs du monde réel sont analogiques : une tension continue qui varie de façon progressive sur une certaine plage. Une photorésistance balaie toutes les tensions entre les rails à mesure que la luminosité ambiante change. La sortie d’un capteur de température dérive de quelques millivolts lorsqu’une pièce se réchauffe. La sortie d’un microphone monte et descend au gré du son environnant.
Un convertisseur analogique-numérique (ADC) fait le pont. Il échantillonne la tension présente sur une broche et renvoie un entier que Python peut lire comme n’importe quelle autre valeur.
3.12.1. Quantification¶
Une valeur numérique ne peut pas représenter exactement une tension continue. Le rôle de l’ADC est de quantifier : ramener chaque échantillon au niveau le plus proche parmi un ensemble fixe de niveaux. Un ADC à N bits possède 2^N niveaux ; un convertisseur 12 bits en compte 4096 répartis sur sa plage d’entrée.
Quantification : chaque échantillon du signal analogique (trait plein) est arrondi à l’un des niveaux numériques d’un ensemble fini (ligne en escalier en pointillés).¶
La tension entre deux niveaux adjacents est le pas de quantification de l’ADC ; tout ce qui est plus petit que cela disparaît dans l’arrondi. Un ADC 12 bits sur une plage de 3,3 V a un pas d’environ 3.3 / 4096 ≈ 0.8 mV : assez fin pour que la plupart des signaux paraissent quasiment continus du point de vue logiciel.
3.12.2. La classe machine.ADC¶
machine.ADC encapsule un canal d’entrée analogique. Construisez-la avec la broche que vous voulez lire, puis appelez read_u16() :
from machine import ADC
adc = ADC("P6")
value = adc.read_u16()
print(value)
read_u16() renvoie toujours un entier non signé sur 16 bits compris entre 0 et 65535. La résolution native de l’ADC varie selon la carte (12 bits sur STM32, spécifique au portage ailleurs) ; le résultat est aligné à gauche sur 16 bits, de sorte que ce détail matériel ne transparaît pas dans Python : une valeur de 65535 correspond à la pleine échelle quelle que soit la puce.
La tension de référence (l’entrée qui correspond à la pleine échelle) dépend de la carte. Consultez la Cartes OpenMV pour connaître la valeur sur votre caméra. Toute tension supérieure à la référence est lue comme la pleine échelle (et peut endommager la broche si elle dépasse la tension d’entrée maximale absolue).
3.12.2.1. Conversion des unités en tension¶
La correspondance entre les unités et la tension est linéaire, la valeur de pleine échelle correspondant exactement à Vref :
voltage = counts × Vref / 65535
En code :
VREF = 3.3 # cam-dependent; see the quickref
counts = adc.read_u16()
voltage = counts * VREF / 65535
print(voltage, "V")
3.12.3. Diviseurs de tension¶
Deux résistances en série entre un rail de tension et la masse forment un diviseur de tension. Le nœud situé entre elles se trouve à une tension déterminée par le rapport des deux résistances :
Un diviseur de tension : R1 et R2 en série abaissent Vin vers V_out.¶
V_out = Vin × R2 / (R1 + R2)
Des résistances égales donnent la moitié de la tension du rail ; R2 bien plus petite que R1 place le point de prélèvement près de la masse ; R2 bien plus grande le place près du rail.
La formule suppose que rien d’autre ne tire un courant appréciable de V_out. Une broche d’ADC est à haute impédance (mégohms, nanoampères) et satisfait facilement cette condition, si bien qu’un diviseur alimentant un ADC se comporte comme le prévoit la formule.
3.12.4. Potentiomètres¶
Un potentiomètre est un composant physique unique qui constitue exactement un diviseur de tension, doté d’un curseur coulissant qui déplace le point de prélèvement entre les deux extrémités. Tourner le bouton modifie R1 et R2 ensemble tout en maintenant constante leur somme (la résistance totale du potentiomètre).
Un potentiomètre câblé comme source de tension manuelle pour l’ADC : 3,3 V à une extrémité, la masse à l’autre, le curseur vers la broche.¶
Un potentiomètre est le dispositif d’entrée par excellence pour expérimenter l’ADC. Câblez une extrémité au 3.3 V, l’autre à la masse, et le curseur à une broche compatible ADC ; tourner le bouton fait balayer au curseur toutes les tensions entre les rails.
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. Lire des tensions plus élevées avec un diviseur¶
Une tension supérieure à Vref plaquera l’ADC à la pleine échelle et peut endommager l’entrée si elle dépasse la valeur maximale absolue. Pour lire une source plus élevée (une batterie, une sortie de capteur dont la plage dépasse Vref), abaissez-la avec un diviseur de tension fixe avant qu’elle n’atteigne la broche :
Mise à l’échelle d’une source haute tension pour qu’elle convienne à l’ADC : R1 et R2 forment un diviseur de tension fixe dont le point de prélèvement alimente la broche d’ADC.¶
Choisissez R1 et R2 de sorte que la tension divisée reste à l’intérieur de la plage de l’ADC à la tension d’entrée maximale que vous prévoyez :
V_adc = V_in × R2 / (R1 + R2)
Pour un maximum V_in = 12 V et une référence de 3,3 V, le rapport R2 / (R1 + R2) doit valoir au plus 3.3 / 12 ≈ 0.275. Un choix courant avec un peu de marge est R1 = 33 kΩ, R2 = 10 kΩ. Le rapport vaut 10 / 43 ≈ 0.233, donc V_adc plafonne à environ 12 × 0.233 ≈ 2.79 V : confortablement en dessous de Vref.
Pour retrouver le V_in d’origine à partir d’une lecture de l’ADC, inversez la formule du diviseur :
V_in = V_adc × (R1 + R2) / R2
En code :
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")
Quelques remarques pratiques :
Le diviseur consomme
V_in / (R1 + R2)en permanence. AvecR1 + R2 = 43 kΩetV_in = 12 V, cela représente environ 280 µA : généralement négligeable, mais si la source est alimentée par batterie, envisagez des résistances plus grandes (100 kΩ à 1 MΩ) pour réduire la consommation au repos.La tolérance des résistances (typiquement ±1 % ou ±5 %) se répercute directement sur la précision de la mesure. Deux résistances à ±5 % peuvent entacher le
V_inreconstitué d’une erreur d’environ ±10 % dans le pire des cas.L’impédance de source du diviseur se combine à toute capacité parasite pour filtrer l’entrée en passe-bas. Pour des signaux à variation rapide, cela compte ; pour une vérification de tension de batterie, non.