Utilisation des entrées analogiques du Pico

Dans cet exemple, le but est de d'utiliser les entrées analogiques du Pico pour mesurer des tensions d'alimentation.


L'exemple utilisé ici est conforme au paragraphe Alimentation du Pico - Alimentations sur batteries. Par rapport au schéma de branchement des batteries et de l'alimentaiton du Pico donné dans cette rubrique, nous souhaitons mesurer la tension des batteries aux bornes IN+ et IN- du régulateur de tension, et, la tension 5VDC de sortie du régulateur entre les bornes OUT+ et OUT-.


Pour que nos mesures soient raisonnablement fiables, il va falloir apporter des modifications matérielles pour améliorer la référence de tension du convertisseur ADC du Pico, et pour adapter les niveaux de tension à ce qui sera acceptable par notre Pico.

Référence de tension ADC

Pour mesurer des tensions, un convertisseur ADC a besoin d'une référence de tension stable. Sur le Pico, cette référence de tension est la tension de 3,3 VDC que le Pico élabore à partir de son alimentation en 5VDC, que celle-ci soit issue de la prise USB ou de la broche VSYS. La documentation du Pico est assez claire à ce sujet : Cette référence de tension n'est pas idéale et peut être relativement instable. Il est donc conseillé d'adjoindre une référence de tension externe. Cette référence de tension externe étant relié à la broche ADC_VREF. La référence de tension définie également le niveau de tension maximale que le convertisseur ADC pourra mesurer. En général on utilise des références de tension inférieures à la tension d'alimentation de 3,3 VDC (Cela permet notamment de réduire le bruit de fond 50 Hz de l'alimentation). Les références de tension les plus répandues fournissent une tension de 2,048V. On adjoint donc à notre Pico une référence de tesnion de 2,048V. Il en existe un grand nombre disponible sur la marché. Elles sont, en général, basées sur le chip LM4040. En voici un exemple : ADA 2200


Le schéma ci-dessous détaille le cablage de cette référence de tension sur le Pico :



Pont diviseur

La référence de tension utilisée impose que les tensions en entrées du convertisseur ADC soient toutes inférieures à 2.048V. Hors nous souhaitons mesurer des tensions de l'ordre de 12V et de 5V. Il est donc nécessaire de réduire ces tensions par de simples ponts diviseurs non chargés composés de 2 résistances. Le choix de la valeur des résistances, au dela de diviser une tension, est crucial. Si nous utilisons des résistances de faibles valeurs, nous allons consommer beaucoup de courant et vider nos batteries relativement vite. A contrario, plus nos résistances auront des valeurs élevées, moins bonne sera la précision de la mesure. En effet, plus la résistance est élevée, moins bonne est sa précision. Cela dit, nous ne cherchons pas une mesure "idéale", 5 à 10% de précision sur nos mesures suffisent. Pour le pont diviseur de la tension de batteries d'environ 12V nous utiliserons des résistances de 10 KOhms et 100 KOhms, soit une division par 0,0909 (10 /110) . Pour le pont diviseur de la tension 5V, nous utiliserons des résistances de 22 KOhms et 100 KOhms, soit une division par 0,1803 (22 /122).


Le schéma de cablage est donc le suivant :



Linéarisation en tension des acquisitions sur le convertisseur

Le convertisseur étant un 12 bits de résolution, soit 4096 pas, la référence de tension étant de 2,048V, cela implique que la résolution en tension du convertisseur est de 2.048 / 4096, soit 0.0005 V.


En appliquant les valeurs de division des ponts diviseurs de nos tensions, nous devons multiplier la valeur lue sur le convertisseur par :


 - Pour la mesure de la tension de batteries : Inverse de 0,0909, soit 11,0011.

 - Pour la mesure de la tension d'alimentation : Inverse de 0,1803, soit 5,5463.

Code source

Ci dessous les fichiers "CmakeLists.txt" et "adc.cpp" d'un projet du même nom : "adc" :

CMakeLists.txt

# CMake version we need
cmake_minimum_required(VERSION 3.13)

# Define C anc CXX standards
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

# Pull in Raspberry Pi Pico SDK (must be before project)
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)

if (PICO_SDK_VERSION_STRING VERSION_LESS "1.4.0")
  message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.4.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}")
endif()

# Declare the project name and languages
project(adc C CXX ASM)

# Initialise the Raspberry Pi Pico SDK
pico_sdk_init()

# Add executable. Default name is the project name
add_executable(adc adc.cpp)

# Add some info to the executable (For picotool....)
pico_set_program_name(adc "adc")
pico_set_program_version(adc "0.1")

# Where do stdio functions send their stuff
pico_enable_stdio_uart(adc 1)
pico_enable_stdio_usb(adc 0)

# Add the standard include files to the build
target_include_directories(adc PRIVATE
  ${CMAKE_CURRENT_LIST_DIR}
  ${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts (Pico W) or any other standard includes, if required
)

# create map/bin/hex/uf2 file etc.
pico_add_extra_outputs(adc)

# Add any user requested libraries
target_link_libraries(adc
  pico_stdlib
  hardware_gpio
  hardware_adc
)

adc.cpp

#include ‹stdio.h›
#include "hardware/gpio.h"
#include "hardware/adc.h"

// Voies GPIO
static const uint ADC_SUPPLY12_PIN = 27; // GP27 : Entrée ADC1 --> Power supply 11,1 V
static const uint ADC_SUPPLY5_PIN = 28; // GP28 : Entrée ADC2 --> Power supply 5 V
// Voies ADC
static const uint ADC_SUPPLY12 = 1; // ADC1 : PowerSupply 12V
static const uint ADC_SUPPLY5 = 2; // ADC2 : PowerSupply 5V

// Référence de tension
static const float ADC_VREF = 2.048f;

// Multipliers
static float SUPPLY12_MULTIPLIER = 11.0011f;
static float SUPPLY5_MULTIPLIER = 5.5463f;

uint16_t ReadADC(uint Channel)
{
  adc_select_input(Channel);
  sleep_ms(5);
  return adc_read();
}

float ToVoltage(uint16_t Raw, float Multiplier)
{
  return Raw * (ADC_VREF / 4096) * Multiplier;
}

float Get12VPowerSupply()
{
  return ToVoltage(ReadADC(ADC_SUPPLY12), SUPPLY12_MULTIPLIER);
}

float Get5VPowerSupply()
{
  return ToVoltage(ReadADC(ADC_SUPPLY5), SUPPLY5_MULTIPLIER);
}

int main()
{
  stdio_init_all();

  // Initialisation ADDC et voies
  adc_init();
  adc_gpio_init(ADC_SUPPLY12_PIN);
  adc_gpio_init(ADC_SUPPLY5_PIN);

  // On mesure toutes les 10 secondes
  while(true)
  {
    sleep_ms(10000);

    // Mesure 12V
    float f12V = Get12VPowerSupply();

    // Mesure 5V
    float f5V = Get5VPowerSupply();

    // Ecriture sur la console
    printf("Mesure 12 VDC : %.2f - Mesure 5 VDC : %.2f\n", f12V, f5V);
  }
return 0;
}