Contrôleur multifonctionnel élaboré autour du ESP32 DEVKIT V1 DOIT (2 de 4)

Le programme

Nous sommes rendus à l’étape de l’implantation du programme.

Avant même de fixer le ESP32 DEVKIT V1 DOIT sur la carte vous pouvez transférer le programme sur le module en le reliant à l’ordinateur par la prise USB du module. Cela valide son bon fonctionnement et il sera préconfiguré, compatible à l’environnement pour lequel vous souhaitez l’installer.

Le programme présenté a deux fonctionnalités :

  • Faire clignoter, aux secondes, la DEL bleue.
  •  Afficher, par l’entremise du port série, les données sur le voltage d’alimentation relier à la borne D35 (GPIO35). Ces informations seront accessibles sur le terminal série de l’IDE ARDUINO. Activation : menu «Outils» -> «Moniteur série».

Sur le schéma d’assignation des broches, le GPIO35 correspond à l’entrée du convertisseur Analogique/Digital #1 canal #7 -> ADC1CH7

La DEL bleue

Sur la plaquette, une DEL bleue est reliée sur le circuit de la broche GPIO33. Elle suit son état : HAUT-> allumée; BAS->éteinte.

La constante de type entière DelBleue correspond au numéro de GPIO connecté avec la DEL.
     const int DelBleue = 33;

Définition du GPIO33 en sortie
    pinMode(DelBleue, OUTPUT);

Allumer la DEL
    digitalWrite(DelBleue, HIGH); 

Éteindre la DEL
   digitalWrite(DelBleue, LOW);

La mesure du voltage d’entrée

Le module ESP32 DEVKIT V1 possède 16 entrées reliées à des convertisseurs analogique à numérique (CAN) ou ADC en anglais (Analog to Digital Converter).

Voir la vidéo de NTS sur YouTube

Le GPIO35 est attribué pour la mesure du voltage d’alimentation d’entrée. Il correspond à la variable ADC1_CHANNEL_7 du pilote adc.h que nous incluons dans le programme. 
    #include <driver/adc.h>

Définition de la résolution du convertisseur 

Avec une résolution de 12 bits, le signal analogique est évalué selon 4096 niveaux possibles (2 exposant 12), de 0 à 4095. Comparativement, pour une résolution de 10 bits (comme dans les cartes ARDUINO) le signal est évalué selon 1024 niveaux, 0 à 1023. Dans le ESP32 la résolution est définie comme la largeur de bits «WIDTH_BIT».
   adc1_config_width(ADC_WIDTH_BIT_12);

Définition de l’atténuation

Sans atténuation, le signal d’entrée au niveau du GPIO doit se situer entre 0 et 1,1 volt (atténuation de 0DB).  Si un voltage d’entrée supérieur est à mesurer, un atténuateur programmable dans le ESP32 peut être activé. Les choix possibles sont : 0 dB; 2,5 dB; 6 dB; 11 dB 

Lorsque VDD_A est 3,3V (comme dans le ESP32 DEVKIT V1 DOIT) les limites sont:

  • Atténuation: 0dB (ADC_ATTEN_DB_0) tension à pleine échelle de 1,1
  • Atténuation: 2,5dB (ADC_ATTEN_DB_2_5) tension à pleine échelle de 1,5V
  • Atténuation: 6dB (ADC_ATTEN_DB_6) tension à pleine échelle de 2,2V
  • Atténuation: 11dB (ADC_ATTEN_DB_11) tension à pleine échelle de 3,9V

Remarque : Avec une atténuation de 11 dB, la tension maximale est limitée par VDD_A et non par la tension à pleine échelle. Donc 3,3V pour notre application.

Remarque : La tension à pleine échelle est la tension correspondante à une lecture maximale. En fonction de la largeur en bits configurée par ADC1, la valeur retournée par l’ADC est la suivante: 4095 pour 12 bits, 2047 pour 11 bits, 1023 pour 10 bits, 511 pour 9 bits.

Un autre fait important est que la linéarité du convertisseur sur l’ensemble de son échelle diffère selon le choix de l’atténuation. Vous trouverez ici de bonnes explications sur la précision des mesures du ESP32.

Voir la vidéo de G6EJD sur YouTube

Donc, en raison des caractéristiques de l’ADC, les résultats les plus précis sont obtenus dans les plages de tension approximatives suivantes:

  • 0dB d’atténuation (ADC_ATTEN_DB_0) entre 100 et 950mV (0,10 et 0,95 V)
  • 2.5dB d’atténuation (ADC_ATTEN_DB_2_5) entre 100 et 1250mV (0,10 et 1,25 V)
  • 6dB d’atténuation (ADC_ATTEN_DB_6) entre 150 et 1750mV (0,15 et 1,75 V)
  • 11dB d’atténuation (ADC_ATTEN_DB_11) entre 150 et 2450mV (0,15 et 2,5 V)

Le montage du déclencheur est prévu pour une tension d’alimentation entre 3.3 et 12,6 volts. Pour m’assurer de travailler dans la plage linéaire de la courbe, j’ai choisi l’atténuation de 11 dB.  Le voltage maximum que je peux présenté à l’entrée est 2,45 V. Donc, avec le diviseur de tension conçu (100K ohms – 22 Kohms), je reste en dessous de 2,45 V ( 2,27V calculé pour 12,6V d’alimentation «Vb = 12,6*((22/(100+22))»). Pour 3V, j’aurais 0,6V au GPIO, je reste dans la zone de linéarité du convertisseur.

Commande du réglage de l’atténuation
   adc1_config_channel_atten(ADC1_CHANNEL_7,ADC_ATTEN_DB_11)

Lecture de la valeur numérique à la sortie du convertisseur ADC
    adc1_get_raw(ADC1_CHANNEL_7) ou analogRead(35) est équivalent

La lecture du canal 7 est transférée dans la variable de type entière «digitalValueVoltAlimCtrl». La donnée est un nombre entre 0 et 4095 selon le voltage à l’entrée du convertisseur et de la valeur de l’atténuation configurée.
  int digitalValueVoltAlimCtrl = analogRead(35);

Conversion de la valeur lue en son équivalent en voltage 

La valeur entre 0 et 4095 est convertie en son équivalent en voltage

Pour ce faire, on applique simplement la règle de trois; on multiplie la valeur lue par la tension pleine échelle et on divise par la valeur numérique maximum selon la résolution. La tension pleine échelle est fonction de l’atténuation. La résolution est fonction du «WIDTH_BIT». Comme la valeur résultante comporte des décimales, elle sera enregistrée dans une variable de type «virgule-flottante». Si la valeur lue est 2047, que l’atténuation est de 11 dB et que la résolution est 12 bits, 4096 niveaux => 2047*3.9/4095 =1,95. Le voltage à l’entrée GPIO est 1,95V  la moitié de 3,9V. 

    float vpeDvValmx_0DB       = 1.1/4095;
    float vpeDvValmx_2_5DB   = 1.5/4095;
    float vpeDvValmx_6DB       = 2.2/4095;
    float vpeDvValmx_11DB    = 3.9/4095; 

 
   float VoltAlimCtrlReduit = digitalValueVoltAlimCtrl *  vpeDvValmx_11DB

Calcul de précision

Si l’atténuation est 11dB et que la résolution est de 12 bits nous avons avantage à employer la méthode par équation polynomiale proposée par G6EJD (David Bird) dans son vidéo. La précision du calcul sera à 1% près.

float reading = analogRead(35);

float VoltAlimCtrlReduitTrtPolyn = -0.000000000000016 * pow(reading,4) + 0.000000000118171 * pow(reading,3)- 0.000000301211691 * pow(reading,2)+ 0.001109019271794 * reading + 0.034143524634089;

Le voltage d’alimentation

Nous cherchons la valeur du voltage d’alimentation qui passe à travers le diviseur de tension avant d’arriver sur le GPIO. Le voltage lu est une valeur réduite du voltage d’alimentation. Nous devons multiplier le voltage lu par l’inverse du facteur de réduction. 

Selon les formules pour le diviseur de tension 
    Vb = Vs * Rb/(Ra+Rb)
    Vs = Vb * ((Ra+Rb)/Rb)
    Valimentation = Voltage lu * ((100000+22000)/22000)

    VoltMesure = VoltAlimCtrlReduit* 122/22;

Calibration de la lecture en fonction du jeu de résistances du diviseur de tension

Comme le jeu de résistances n’est pas précisément 100K et 22K, il y a 5% de tolérance, il faut multiplier le voltage calculé par un facteur de correction. Je mets à 1 au départ comme facteur de correction. Des mesures prises à la source, aux bornes du terminal bleu, avec un voltmètre préciseront le facteur réel. Lors de la calibration, j’emploie une source d’alimentation stable ayant une tension autour de 8 volts. Une pile Lipo 2S va très bien pour la calibration.

     float calibrationDiviseurTSN = 1;
     float calibrationDiviseurTsnTrtPolyn = 1;

     calibrationDiviseurTSN = Voltage réel au voltmètre/VoltMesure;

     float calibrationDiviseurTSN = 7.99/8.70;
     float calibrationDiviseurTsnTrtPolyn = 7.99/8.07;

     VoltMesure = VoltMesure * calibrationDiviseurTSN
     VoltMesure = VoltMesure * 
calibrationDiviseurTSNTrtPolyn;

Le deuxième calcul sera plus proche de la valeur réelle du voltage.

Référence 1 pour la conversion Analog/Digital

Référence 2 pour la conversion Analog/Digital

Téléchargement :

https://github.com/rcepmorel/Declencheur-Appareil_Photo_00

Declencheur-Appareil_Photo_00.ino

/*DÉCLENCHEUR D'APPAREIL PHOTO ET DE FLASHS
* 
* Auteur : Richard Morel
*     2018-11-09
* 
* Modification
*     2018-11-17
*     - Mesure du voltage d'entrée
*     - Ajout du clignotement de la DEL Bleu
*       Relié sur la broche D33
*     
*/

const int DelBleue = 33; // DEL bleue reliée au GPIO33

// Références pour la conversion Analog/Digital
// https://espressif-docs.readthedocs-hosted.com/projects/esp-idf/en/v2.1.1/api-reference/peripherals/adc.html
// https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/adc.html
#include <driver/adc.h>   
//ADC1_CHANNEL_7 D35 35

  // La tension pleine échelle par défaut du CAD (ADC) est 1,1 V
  // Pour lire des tensions plus élevées (jusqu’à la tension maximale de la broche, généralement 3,3 V), 
  // vous devez régler une atténuation du signal> 0 dB pour le canal du CAD quand VDD_A est 3.3V:
  // Une atténuation de 0 dB (ADC_ATTEN_0db) donne une tension à pleine échelle de 1,1 V
  // Une atténuation de 2,5 dB (ADC_ATTEN_2_5db) donne une tension à pleine échelle de 1,5 V
  // Une atténuation de 6 dB (ADC_ATTEN_6db) donne une tension à pleine échelle de 2,2 V
  // Une atténuation de 11 dB (ADC_ATTEN_11db) donne une tension à pleine échelle de 3,9 V (voir la remarque ci-dessous)
  // La tension à pleine échelle est la tension correspondant à une lecture maximale
  // Remarque : à 11 dB d'atténuation, la tension maximale est limitée par VDD_A, et non par la tension à pleine échelle.
  // En fonction de la largeur de bit configurée par ADC, cette valeur est: 4095 pour 12 bits, 2047 pour 11 bits, 1023 pour 10 bits, 511 pour 9 bits
  // 

  //En raison des caractéristiques du CAD, les résultats les plus précis sont obtenus dans les plages de tension approximatives suivantes:
  // - 0dB    d'atténuation (ADC_ATTEN_DB_0) entre 100 and 950mV
  // - 2.5dB  d'atténuation (ADC_ATTEN_DB_2_5) entre 100 and 1250mV
  // - 6dB    d'atténuation (ADC_ATTEN_DB_6) entre 150 to 1750mV
  // - 11dB   d'atténuation (ADC_ATTEN_DB_11) entre 150 to 2450mV
  // - Pour une précision maximale, utilisez les API d’étalonnage ADC et mesurez les tensions dans les plages recommandées.
 
float VoltMesure = 0;
float vpeDvValmx_0DB = 1.1/4095; // 12 bits de résolution
float vvpeDvValmx_2_5DB = 1.5/4095;
float vpeDvValmx_6DB = 2.0/4095;
float vpeDvValmx_11DB = 3.9/4095;

float calibrationDiviseurTSN = 7.99/8.70;      // valeur réelle diviser par VoltMesure lorsque calibrationDiviseurTSN égal à 1
float calibrationDiviseurTsnTrtPolyn = 7.99/8.07; // valeur réelle diviser par VoltMesure lorsque calibrationDiviseurTsn égal à 1


// ----------------------------------------------------------------------------- 
// SETUP   SETUP   SETUP   SETUP   SETUP   SETUP   SETUP   SETUP   SETUP
// ----------------------------------------------------------------------------- 
void setup() {
  Serial.begin(9600);
  
  pinMode(DelBleue, OUTPUT);
  
  // ***** Configuration pour faire des mesures sur D35 (voltage de la source d'alimentation) ******
  adc1_config_width(ADC_WIDTH_BIT_12); // Définie la résolution (0 à 4095)
  

  adc1_config_channel_atten(ADC1_CHANNEL_7,ADC_ATTEN_DB_11); //Le voltage maximum au GPIO est de 3.3V

  Serial.println("PRÊT");
}

// ----------------------------------------------------------------------------- 
// LOOP     LOOP     LOOP     LOOP     LOOP     LOOP     LOOP     LOOP     LOOP 
// ----------------------------------------------------------------------------- 
void loop() {

  // Méthode de la règle de trois
  int DigitalValueVoltAlimCtrl = analogRead(35);
  float VoltAlimCtrlReduit = DigitalValueVoltAlimCtrl * vpeDvValmx_11DB;
  VoltMesure = VoltAlimCtrlReduit*122/22; // Diviseur de tension 100K, 22K
  VoltMesure = VoltMesure*calibrationDiviseurTSN; // correction dû aux valeurs imprécises du diviseur de tension

  Serial.print(DigitalValueVoltAlimCtrl);Serial.print(" DigitalValueVoltAlimCtrl ");Serial.print(VoltAlimCtrlReduit);Serial.print(" VoltAlimCtrlReduit  ");
  Serial.print(VoltMesure);Serial.println(" VoltMesure"); 

  // Méthode de G6EJD  (applicable si l'atténuation est 11dB et la résolution est 12 bits)
  float reading = analogRead(35);
  float VoltAlimCtrlReduitTrtPolyn = -0.000000000000016 * pow(reading,4) + 0.000000000118171 * pow(reading,3)- 0.000000301211691 * pow(reading,2)+ 0.001109019271794 * reading + 0.034143524634089;
  float VoltMesureTrtPolyn = VoltAlimCtrlReduitTrtPolyn*122/22; // Diviseur de tension 100K, 22K
  VoltMesureTrtPolyn = VoltMesureTrtPolyn*calibrationDiviseurTsnTrtPolyn; // correction dû aux valeurs imprécises du diviseur de tension
  
  Serial.print(reading);Serial.print(" DigitalValueVoltAlimCtrl ");Serial.print(VoltAlimCtrlReduitTrtPolyn);Serial.print(" VoltAlimCtrlReduit  ");
  Serial.print(VoltMesureTrtPolyn);Serial.println(" VoltMesure"); 
  Serial.println(" "); 

  digitalWrite(DelBleue, HIGH);   // Allume le DEL (voltage HAUT)
  delay(1000);                    // Attend X millisecondes
  digitalWrite(DelBleue, LOW);    // Éteint le DEL (voltage BAS)
  delay(1000);                    // Attend X millisecondes
  
}

<- Contrôleur multifonctionnel élaboré autour du ESP32 DEVKIT V1 DOIT (1 de 4)        Contrôleur multifonctionnel élaboré autour du ESP32 DEVKIT V1 DOIT (3 de 4) ->