Entrées analogiques

Ce que l'on va faire ici

Ici, nous allons voir comment utiliser les broches GPIO en entrée analogiques avec MicroPython sur la carte Pi Pico pour réaliser des mesures.

La carte Pico Pi dispose de 4 entrées analogiques 12 bits :

  • 3 sont câblées sur les broches de la carte (ADC0 (GP26), ADC1(GP27), ADC2(GP28))
  • 1 est câblée sur VSys/3 permettant un monitoring de batterie par exemple (ADC3 - GP29 interne)
  • 1 est câblée sur le capteur de température présent sur la carte (ADC4 - interne au RP2040)

Note

Le datasheet du RP2040 annonce une fréquence de mesure possible de 500 000 Kz ! En pratique avec Micropython, c'est du 1000 mesures / seconde environ.

Intérêt du 12 bits versus 10 bits ?

Une carte Arduino typiquement convertit en 10 bits, soit 1024 niveaux sur 5V. La précision est donc de ~4.8mV.

Avec la Pi pico, la précision est de 12 bits, soit 4095 niveaux mais cette fois sur 3.3V. la précision est donc de 0.8mV.

Entre les 2 on a donc un gain en précision de l'ordre de x6. Ceci concrètement va être intéressant avec certains capteurs, tels que les capteurs de courant par exemple, qui ont une sortie "étroite" entre par exemple 1V et 1.5V avec une résolution limitée à cette plage de tension. Avoir plus de précision permet de tirer pleinement parti du capteur analogique et mesure correctement de petites variations.

Liens utiles :

Infos techniques utiles

  • Les broches analogiques mesurent en 3.3V sur 12 bits (0-4095) soit une précision de 0,8mV !

Instructions Micropython utiles pour la Pi Pico

La classe ADC a une seule fonction :

  • read_u16() : lit la valeur de la broche analogique.

ATTENTION

La fonction read_u16() renvoie le résultat en valeur 16 bits : autrement dit, la valeur 4095 (valeur 12 bits) est transformée en 65535 (valeur 16 bits). Pour passer de l'un à l'autre, il faut diviser par 16, avec ajustement des unités selon :

value=((sensor.read_u16()+1)/16)-1

La valeur 4095 est alors bien obtenue.

A noter que la valeur correcte peut également être obtenue en faisant (plus facile à retenir) :

value=sensor.read_u16())*4095/65535

L'autre option est de traiter la valeur comme telle en 65535, mais comme la mesure se fait en 12 bits, autant l'avoir à la bonne "échelle". Noter que si on traite en base 16 bits, on n'aura pas de gain de précision : c'est juste une opération mathématique de Micropython qui donne la valeur 16 bits.

Note

La doc de la Pi Pico indique que la raison est une uniformisation avec les autres cartes Micropython, mais je n'ai pas souvenir que la Pyboard fournisse une valeur sur 16 bits, mais bien en 12 bits directement. Mais bref, passons, retenez bien que vous obtenez une valeur 16 bits qu'il faut basculer en 12 bits, ou à traiter en base 16 bits, comme vous voulez.

Exemple : Mesurer la sortie d'une résistance variable linéaire.

On pourra utiliser le montage suivant :

Le code pour lire la valeur analogique brute sur ADC0 est le suivant :

from machine import ADC, Timer

sensor=ADC(0)

timer=Timer()

def loop(timer):

    value=sensor.read_u16()*4095/65535 # conversion 16 vers 12 bits

    print("{:.2f}".format(value)) # affichage avec 2 decimales


timer.init(freq=1, callback=loop)

Lire la température du capteur "onboard"

La Pi Pico dispose d'un capteur de température "onboard", sur la carte, connecté sur ADC4 (qui n'est pas disponible sur une GPIO du coup).

Le datasheet du RP2040 indique que le capteur obéit aux paramètres suivants :

Vbe = 0.706V at 27 degrees C, with a slope of -1.721mV per degree. 
Therefore the temperature can be approximated as follows : 
T = 27 - (ADC_voltage - 0.706)/0.001721

Ainsi, pour monitorer la température du Pi, on fera :

from machine import ADC, Timer

sensor=ADC(4) # ADC4 est le capteur de température onboard

timer=Timer()

def loop(timer):

    #value=sensor.read_u16()*4095/65535
    #valueV=value*3.3/4095

    valueV=sensor.read_u16()*3.3/65535 # idem en 1 ligne

    temp=27-(valueV-0.706)/0.001721

    #print(temp)
    print("{:.2f}".format(temp)) # avec 2 décimales

timer.init(freq=1, callback=loop)

Note

La sensibilité du capteur semble être de 0.5°C environ, autrement dit a un caractère essentiellement indicatif, à comparer aux 0.06°C de précision d'un DS18B20 1-wire. J'ai en ce qui me concerne, de plus, un décalage de l'ordre de 2°C entre la température réelle et la carte Pico. Ajouter une correction de 2°C en l'occurrence.

Monitorer la tension sur la broche Vsys

La Pi Pico utilise la broche ADC3 (GP29 interne) pour mesure Vsys/3 : ceci est potentiellement très intéressant pour monitorer une alimentation sur batterie, possible entre 1.8V et 5.5V.

Ainsi, pour monitorer la tension de VSys, on fera :

from machine import ADC, Timer

sensor=ADC(3) # ADC3 est branché en interne sur VSys/3

timer=Timer()

def loop(timer):

    valueV=(sensor.read_u16()*3.3/65535)*3 # x3 car mesure VSys/3

    #print(temp)
    print("{:.2f}".format(valueV)) # avec 2 décimales

timer.init(freq=1, callback=loop)

La sortie non connectée donne par exemple :

1.20

1.20

1.20

Voir également