Eclairage à led de vélo 3W+tracker (atmega, ESP32)

Cet idiot de charger la batterie du TTGO avec l'eclairage allumé et l’écran allumé et que le processeur tourne et consomme. Comment peut-on charger la batterie en deep sleep en appuyant sur un bouton et en utilisant le ligth sleep pour les delay ? En effet, en deep sleep, l’ecran OLED est éteint est le processeur ce met en veille, donc pour recharger la batterie c’est mieux

alors qu’en ligth sleep l’ecran reste allumé.

mais le timer reveille à chaque fois le processeur.

esp_sleep_enable_timer_wakeup(ms * 1000);

il faut bloquer le réveille timer

https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/system/sleep_modes.html#_CPPv418esp_sleep_source_t
voici l’instruction qui disable le timer
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);

De plus, si la tension batterie est inférieure à 3V, il faut mettre en deep. sleep le processeur et ne pas réveiller le processeur pour ne pas détruire la batterie lorsqu’elle se décharge à 100%
Voici le code qui utilise le wake up timer et le _ext0_wakeup

#include <TFT_eSPI.h>
#include <SPI.h>


TFT_eSPI tft = TFT_eSPI();  // Invoke library

   #define S1       0    //fonctionne à 0L     BP gauche
   #define S2      35// BP droite
   #define ADC_PIN 34
   
RTC_DATA_ATTR   bool flag=0;    //save data sleep
RTC_DATA_ATTR   int  wakeup_reason;
RTC_DATA_ATTR float tensionbatt;

   void espDelay(int ms)
{
    esp_sleep_enable_timer_wakeup(ms * 1000);
    esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
    esp_light_sleep_start();      // no sleep oled 
}

void setup() {  
pinMode(ADC_PIN, INPUT);
pinMode(S2, INPUT_PULLUP);
pinMode(14, OUTPUT);
digitalWrite(14,1);
  
    tft.init();
    tft.setRotation(0); //format portrait a l'endroit
    Serial.begin(115200);
      
     tft.fillScreen(TFT_BLACK);
    tft.setTextColor(TFT_WHITE,TFT_BLACK); 
  analogReadResolution(12);   //12 bits    
}

void loop() {

    if (flag==0) { 
  tft.setCursor(0, 0, 4);// (x,y,taille)
  tensionbatt=analogRead(ADC_PIN);          //34 interne, pont diviseur par 2 (100Kohm)
  tensionbatt=(tensionbatt*2*3.3)/(4095);
  tft.print(tensionbatt,2); 
    }

       if (!(digitalRead(S1)))  {if (flag==1) {flag=0;} else {flag=1;} 
                              
                                if (flag==1) { flag=0;
                                espDelay(500);;   //rebond bouton poussoir
                  //esp_sleep_enable_touchpad_wakeup();
                  esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);               
                  esp_sleep_enable_ext0_wakeup(GPIO_NUM_0,0);           
                  esp_deep_sleep_start();     //sleep le oled                                  
                                            }
                              }
                              
    if (tensionbatt<=3.7) {
  //  esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);   //inutile
    esp_deep_sleep_start();     //sleep le oled
    }                         
                            

//   wakeup_reason = esp_sleep_get_wakeup_cause();  //retourne le chiffre 2 pour le reveil avec  bouton
//   tft.setCursor(0, 40, 4);                       //retoune le chiffre 4 pour le le reveil timer
//   tft.print(wakeup_reason);
  
   espDelay(1000);
 }
4 Likes

Je me suis inspirée de tout ce qui a été dit pour faire un éclairage arriere, pas facile de faire une concaténation de tout ce qui a été dit car on si perd entre Arduino pro, nano et TTGO.

Quelle sera l’autonomie de fonctionnement de l’éclairage avec le TTGO ?

J’ai un TTGO donc j’ai fait l’eclairage proposé sans le tracker avec une batterie de 1200mA.h

Comme la dit darinacio, il faut filtrer numeriquement le courant car même avec un condensateur de 440uF, pour une PWM de 0.6, le courant moyen est de 0.3A avec une variation est de 0.1A

J’ai choisi une boucle de régulation de 1ms donc une fréquence d’échantillonnage de 1000Hz et affichage tous les 1s des données et un mode veuille light de 950ms.

sur la figure suite, on peut observer le courant filtré et non filtré

de plus, il y a des différences entre la commande car il y a une zone morte de l’ADC de l’ESP32

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/adc.html

tant que la tension image de courant n’est pas supérieur à 0.1V, ESP32 ne mesure rien.

heureusement, que l’on demande des courant 3 fois plus important.

Avant de faire la boucle fermée, il faut faire la commande en boucle ouverte qui permet de verifier le bon fonctionnement de la carte hacheur qui alimente la led et la mesure de courant.

voici le code de la boucle ouverte

//eclairage arriere clignotant TTGO+OLED+LED CREE
#include <TFT_eSPI.h>
#include <SPI.h>
//  #include <EEPROM.h>


TFT_eSPI tft = TFT_eSPI();  // Invoke library

   #define S1       0    //fonctionne à 0L     BP gauche
   #define S2      35// BP droite
   #define ADC_PIN 34
   
RTC_DATA_ATTR   bool flag=0,flagT;    //save data sleep
RTC_DATA_ATTR   int  wakeup_reason;
RTC_DATA_ATTR float tensionbatt,consigne, courant, erreur;
RTC_DATA_ATTR unsigned int  PWM, compteur1;
RTC_DATA_ATTR byte compteur,i ;

RTC_DATA_ATTR float entree,entree1,entree2,entree3, entree4,courantFiltre,sortieI,sortieI1,sortieI2, courant1,courant2 ;
RTC_DATA_ATTR float a1,a2,courantled ;

RTC_DATA_ATTR float denominateur=0,Gain=0;
float  fe=1000,fc=10;  //frequence de coupure desiréé   

const int ledPin32 = 32;
const int ledChannel = 1;


   void espDelay(int ms)  //****************
{
    esp_sleep_enable_timer_wakeup(ms * 1000);
    esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);  //
  //   esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_AUTO,ESP_PD_DOMAIN_CPU);  //coupe le oled
    esp_light_sleep_start();      // no sleep oled 
}


void setup() {  
pinMode(ADC_PIN, INPUT);
pinMode(2, INPUT);
pinMode(S2, INPUT_PULLUP);
pinMode(14, OUTPUT);
pinMode(26, OUTPUT);

digitalWrite(14,1);
  
    tft.init();
    tft.setRotation(0); //format portrait a l'endroit
    Serial.begin(115200);
      
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_WHITE,TFT_BLACK); 
  analogReadResolution(12);   //12 bits 
 
ledcSetup(ledChannel, 64000, 10);     //PWM 64kHz  10bits
ledcAttachPin(ledPin32, ledChannel);  //broche 32 PWM

   denominateur=(fe*fe+fe*fc*PI*sqrt(2)+fc*fc*PI*PI);
   a1=(fc*fc*PI*PI-fe*fe)*2/denominateur;
   a2=(fe*fe*fe*fe+(fc*fc*fc*fc*PI*PI*PI*PI))/(denominateur*denominateur)         ;                             //pow(base, exponent)
   Gain=(1+2+1)/(1+a1+a2);  
  tft.setCursor(0, 100, 4);
  tft.print(fe,0);tft.println("fe ");
  tft.print(fc,0);tft.println("fc ");
  tft.print("a1");tft.println(a1,3); 
  tft.print("a2");tft.println(a2,3); 
  tft.print("G");tft.print(Gain,0); 
}



void loop() {
//comande de la LED en boucle ouverte
       if (digitalRead(S1)==0)  {compteur++;PWM=PWM+20;espDelay(200);}
       if (digitalRead(S1)==1)  {compteur=0;}
       if (!(digitalRead(S2)))  {PWM=PWM-10;espDelay(200);}      //consigne=consigne-0.1;
if (PWM>=600) {PWM=600;} 
if (PWM<=0)  {PWM=0;}
       
       
 //si appuie du S1 plus de 15 secondes (15 fois la loop )alors mise en veuille pour recharge batterie           
     if (compteur>=15){
        esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);    //reveille par le RESET                 
        esp_deep_sleep_start();     //sleep le oled                                  
                      }
                          
//mise en veuille si batterie < à 3.2                             
  if (tensionbatt<=3.2) {
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_0,0); 
    esp_deep_sleep_start();     //sleep le oled
    }                         


  tensionbatt=analogRead(ADC_PIN);          //34 interne, pont diviseur par 2 (100Kohm)
  tensionbatt=(tensionbatt*2*3.63)/(4095);


 for (i=0; i <= 12; i++) {           //boucle de 1ms pour faire la regulation  1000Hz
   if ( digitalRead(26)== 1 ) {digitalWrite(26,LOW);}  else {digitalWrite(26,HIGH);}
                   
entree=analogRead(2);        //resistance shunt de 1ohm
entree1=analogRead(2);               
entree2=analogRead(2);
entree3=analogRead(2);
entree4=analogRead(2);

courant2= courant1;
courant1= courant;
sortieI2=sortieI1;      //sortie(n-2)
sortieI1=sortieI;       //sortie(n-1)
courant=(entree4+entree3+entree2+entree1+entree)/4;   //filtre moyenneur
courant=(entree*3.65)/(4096);   //mesure un courant max de 14.6A  

sortieI=(courant+courant1*2+courant2-sortieI1*a1-sortieI2*a2) ;      //filtre passe pas recursif ordre 2
courantFiltre=(sortieI/Gain);
 Serial.print(courant,3);Serial.print(";");Serial.println(courantFiltre);     

if (PWM>=0)   {courantled=(courantFiltre*1024)/PWM; }       //mesure dans la souce du transitor canal N
if (PWM==0)   {courantled=0; } 
/*
erreur=consigne-courantled;
Integral= Integral+erreur*10;       //Integral= Integral+erreur*ki;
      if (Integral>=1023) Integral=1023;
      if (Integral<=0) {Integral=0;}
      PWM=Integral;
*/      

  ledcWrite(ledChannel,PWM);                            
  delay (1);
  }  //end for

//affichage tous les 950ms
  tft.setCursor(0, 0, 4);// (x,y,taille)  //durée 4ms
  tft.print(tensionbatt,2); 
  tft.println("=V");
  tft.print(courantled,3); 
  tft.println("=I");
  tft.setCursor(0, 60, 4);
  tft.print(PWM);
  tft.println("=PWM    "); 

  ledcWrite(ledChannel,0);  //mettre à 0 la PWM                                 
  espDelay(950);    //PWM ne fonctionne plus et interruption fonctionne    oled fonctionne

   
 }//end loop

voici la consommation, en mode clignotement

Sachant que l’eclairage doit avoir une indice de protection IP65, à la place de faire une commande de la consigne de courant ou de la PWM par les boutons poussoirs du TTGO, il serait plus pertinent de faire un boitier en imprimante 3D sans trous avec collage et de faire la commande en blutooth du changement de consigne.

Donc je me suis inspirée de ces boitiers

Le chargement de la batterie avec l’USBC se fera évidement coté led (extérieur).

L’éclairage sera tenu par un gros élastique.

L’USB sera caché par un un bouchon USB

2 Likes

Quel sera le temps de réponse de la régulation avec le filtrage du courant et le calcul de l’intégration qui se fait seulement pendant 50ms puisque le micro est en mode veille pendant 950ms ?

Pour un courant de consigne de 0.3A et un coefficient intégral ki=10 tous les 1ms, on peut observer que l’on a un léger dépassement. Le temps de réponse est assez long d’environ de 5s.

Mais, il y a bien convergence du courant led vers le courant de consigne.

Le choix de ki a été fait pour que la PWM s’incrémente pour une erreur de 0.1A alors la PWM (10 bits) s’incrémentera de 1=Ki*erreur.

On peut observer qu’il ne faut pas grand choses d’incrément de PWM pour modifier le courant led, car la résistance du montage est faible.

Avec un oscilloscope, on pourrait observer la zone morte du courant led mesuré par ESP32 au démarrage car le courant en réalité croit plus rapidement.

voici le code en boucle fermée

//eclairage arriere clignotant TTGO+OLED+LED CREE+batterie1.2A.h
#include <TFT_eSPI.h>
#include <SPI.h>
#include "BluetoothSerial.h"
BluetoothSerial SerialBT;


TFT_eSPI tft = TFT_eSPI();  // Invoke library

   #define S1       0  //fonctionne à 0L     BP gauche
   #define S2      35  // BP droite
   #define ADC_PIN 34
   
RTC_DATA_ATTR bool flag=0,flagT;    //save data sleep
RTC_DATA_ATTR int  wakeup_reason;
RTC_DATA_ATTR float tensionbatt,consigne, courant, erreur;
RTC_DATA_ATTR float timeduration, pourcentage;
RTC_DATA_ATTR unsigned int  PWM, compteur1;
RTC_DATA_ATTR byte compteur,i ;

RTC_DATA_ATTR float entree,entree1,entree2,entree3, entree4,courantFiltre,sortieI,sortieI1,sortieI2, courant1,courant2 ;
RTC_DATA_ATTR float courantled,Integral;

//fe=1000,fc=10;  //frequence de coupure desiréé  
RTC_DATA_ATTR const float a1=-1.911197, a2=0.914976, Gain=1059;
 

const int ledPin32 = 32;
const int ledChannel = 1;


   void espDelay(int ms)  //****************
{
    esp_sleep_enable_timer_wakeup(ms * 1000);
    esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);  //
  //   esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_AUTO,ESP_PD_DOMAIN_CPU);  //coupe le oled
    esp_light_sleep_start();      // no sleep oled 
}


void setup() {  
pinMode(ADC_PIN, INPUT);
pinMode(2, INPUT);
pinMode(S2, INPUT_PULLUP);
pinMode(14, OUTPUT);
pinMode(26, OUTPUT);

digitalWrite(14,1);
  
    tft.init();
    tft.setRotation(0); //format portrait a l'endroit
    Serial.begin(115200);
//    SerialBT.begin("ESP32test"); //Bluetooth device name  
  
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_WHITE,TFT_BLACK); 
  analogReadResolution(12);   //12 bits 
 
ledcSetup(ledChannel, 64000, 10);     //PWM 64kHz  10bits
ledcAttachPin(ledPin32, ledChannel);  //broche 32 PWM
 
}



void loop() {
  
    
//comande de la LED en boucle ouverte
       if (digitalRead(S1)==0)  {compteur++;consigne=consigne+0.1;Integral=500;espDelay(200);}
       if (digitalRead(S1)==1)  {compteur=0;}
       if (!(digitalRead(S2)))  {consigne=consigne-0.1;espDelay(200);}      //consigne=consigne-0.1;
//if (PWM>=600) {PWM=600;} 
//if (PWM<=0)  {PWM=0;}
if (consigne>=1) {consigne=1;} 
     
       
 //si appuie du S1 plus de 15 secondes (15 fois la loop )alors mise en veuille pour recharge batterie           
     if (compteur>=15){
        esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);    //reveille par le RESET                 
        esp_deep_sleep_start();     //sleep le oled                                  
                      }
                          
//mise en veuille si batterie < à 3.2                             
/*   if (tensionbatt<=3.2) {
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_0,0); 
    esp_deep_sleep_start();     //sleep le oled
    }                         
*/

  tensionbatt=analogRead(ADC_PIN);          //34 interne, pont diviseur par 2 (100Kohm)
  tensionbatt=(tensionbatt*2*3.63)/(4095);


 for (i=0; i <= 12; i++) {           //boucle de 1ms pour faire la regulation  1000Hz
   if ( digitalRead(26)== 1 ) {digitalWrite(26,LOW);}  else {digitalWrite(26,HIGH);}
                   
entree=analogRead(2);        //resistance shunt de 1ohm
entree1=analogRead(2);               
entree2=analogRead(2);
entree3=analogRead(2);
entree4=analogRead(2);

courant2= courant1;
courant1= courant;
sortieI2=sortieI1;      //sortie(n-2)
sortieI1=sortieI;       //sortie(n-1)
courant=(entree4+entree3+entree2+entree1+entree)/4;   //filtre moyenneur
courant=(entree*3.65)/(4096);   //mesure un courant max de 14.6A  

sortieI=(courant+courant1*2+courant2-sortieI1*a1-sortieI2*a2) ;      //filtre passe pas recursif ordre 2
courantFiltre=(sortieI/Gain);


if (PWM>=0)   {courantled=(courantFiltre*1024)/PWM; }       //mesure dans la souce du transitor canal N
if (PWM==0)   {courantled=0; } 

erreur=consigne-courantled;
Integral= Integral+erreur*10;       //Integral= Integral+erreur*ki;
      if (Integral>=700) Integral=700;
      if (Integral<=0) {Integral=0;}
      PWM=Integral;
      
if (consigne<=0.09)  {consigne=0;PWM=0;}        

  ledcWrite(ledChannel,PWM);                            
  delay (1);
  }  //end for

//affichage tous les 950ms
  pourcentage= map(tensionbatt*10, 30, 42, 0, 100);
  timeduration=(pourcentage*1.2)/((0.02+consigne*0.05)*100);    //0.05*consigne correpond au rapport cyclique 50ms/(950ms+50ms)
  tft.setCursor(0, 0, 4);// (x,y,taille)  //durée 4ms
  tft.print(pourcentage);tft.println("=%"); 
  tft.print(timeduration,1);tft.println("=hour");
  tft.print(consigne,2);tft.println("=Cons");
  tft.print(courantled,3);tft.println("=I   ");
  tft.print(PWM);tft.println("=PWM    "); 

Serial.print(courantled,3);Serial.print(";");Serial.print(consigne,1);Serial.print(";");Serial.println(PWM); 


  ledcWrite(ledChannel,0);  //mettre à 0 la PWM                                 
  espDelay(950);    //PWM ne fonctionne plus et interruption fonctionne    oled fonctionne

   
 }//end loop
5 Likes

Est-ce que on peut utiliser le Bluetooth avec une interruption light sleep ?

Vu la grosse consommation de la carte en mode normal (entre 160 et 260mA), dans le dernier code j’ai utilisé une interruption light sleep pour résoudre le problème mais il désactivait le Bluetooth. Donc en cherchant j’ai trouvé seulement une solution : l’utilisation d’un oscillateur externe de 32.768kHz. Mais l’implémentation d’un oscillateur externe signifie une affectation à la vitesse d’envoi (avant à 240Mhz), dans ce cas c’est mieux utiliser une carte Nano Arduino qui ne consomme pas trop (en comparaison avec le TTGO).
Donc, si on met de côté l’idée de diminuer la consommation le Bluetooth fonction bien avec le code :

//eclairage arriere clignotant TTGO+OLED+LED CREE+batterie1.2A.h
#include <TFT_eSPI.h>
#include <SPI.h>
#include "BluetoothSerial.h"
BluetoothSerial SerialBT;


TFT_eSPI tft = TFT_eSPI();  // Invoke library

   #define S1       0  //fonctionne à 0L     BP gauche
   #define S2      35  // BP droite
   #define ADC_PIN 34
   
RTC_DATA_ATTR bool flag=0,flagT;    //save data sleep
RTC_DATA_ATTR int  wakeup_reason;
RTC_DATA_ATTR float tensionbatt,consigne, courant, erreur;
RTC_DATA_ATTR float timeduration, pourcentage;
RTC_DATA_ATTR unsigned int  PWM, compteur1;
RTC_DATA_ATTR byte compteur,i ;

RTC_DATA_ATTR float entree,entree1,entree2,entree3, entree4,courantFiltre,sortieI,sortieI1,sortieI2, courant1,courant2 ;
RTC_DATA_ATTR float courantled,Integral;

//fe=1000,fc=10;  //frequence de coupure desiréé  
RTC_DATA_ATTR const float a1=-1.911197, a2=0.914976, Gain=1059;
 

const int ledPin32 = 32;
const int ledChannel = 1;

void setup() {  
pinMode(ADC_PIN, INPUT);
pinMode(2, INPUT);
pinMode(S2, INPUT_PULLUP);
pinMode(14, OUTPUT);
pinMode(26, OUTPUT);

digitalWrite(14,1);
  
    tft.init();
    tft.setRotation(0); //format portrait a l'endroit
    Serial.begin(115200);
    SerialBT.begin("ESP32test"); //Bluetooth device name  
  
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_WHITE,TFT_BLACK); 
  analogReadResolution(12);   //12 bits 
 
ledcSetup(ledChannel, 64000, 10);     //PWM 64kHz  10bits
ledcAttachPin(ledPin32, ledChannel);  //broche 32 PWM
 
}


void loop() {
    //SerialBT.begin("ESP32test"); //Bluetooth device name
    SerialBT.print("*L");SerialBT.println("Test eclairage"); 
//comande de la LED en boucle ouverte
       if (digitalRead(S1)==0)  {compteur++;consigne=consigne+0.1;Integral=500;delay(200);}
       if (digitalRead(S1)==1)  {compteur=0;}
       if (!(digitalRead(S2)))  {consigne=consigne-0.1;delay(200);}      //consigne=consigne-0.1;
//if (PWM>=600) {PWM=600;} 
//if (PWM<=0)  {PWM=0;}
if (consigne>=1) {consigne=1;} 
     
       
 //si appuie du S1 plus de 5 secondes (15 fois la loop )alors mise en veuille pour recharge batterie           
     if (compteur>=5){
        esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);    //reveille par le RESET                 
        esp_deep_sleep_start();     //sleep le oled                                  
                      }
                          
//mise en veuille si batterie < à 3.2                             
/*   if (tensionbatt<=3.2) {
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_0,0); 
    esp_deep_sleep_start();     //sleep le oled
    }                         
*/

  tensionbatt=analogRead(ADC_PIN);          //34 interne, pont diviseur par 2 (100Kohm)
  tensionbatt=(tensionbatt*2*3.63)/(4095);


 for (i=0; i <= 50; i++) {           //boucle de 1ms pour faire la regulation  1000Hz
   if ( digitalRead(26)== 1 ) {digitalWrite(26,LOW);}  else {digitalWrite(26,HIGH);}
                   
   entree=analogRead(2);        //resistance shunt de 1ohm
   entree1=analogRead(2);               
   entree2=analogRead(2);
   entree3=analogRead(2);
   entree4=analogRead(2);

   courant2= courant1;
   courant1= courant;
   sortieI2=sortieI1;      //sortie(n-2)
   sortieI1=sortieI;       //sortie(n-1)
   courant=(entree4+entree3+entree2+entree1+entree)/4;   //filtre moyenneur
   courant=(entree*3.65)/(4096);   //mesure un courant max de 14.6A  

   sortieI=(courant+courant1*2+courant2-sortieI1*a1-sortieI2*a2) ;      //filtre passe pas recursif ordre 2
   courantFiltre=(sortieI/Gain);


   if (PWM>=0)   {courantled=(courantFiltre*1024)/PWM; }       //mesure dans la souce du transitor canal N
   if (PWM==0)   {courantled=0; } 

   erreur=consigne-courantled;
   Integral= Integral+erreur*10;       //Integral= Integral+erreur*ki;
      if (Integral>=700) Integral=700;
      if (Integral<=0) {Integral=0;}
      PWM=Integral;
      
   if (consigne<=0.09)  {consigne=0;PWM=0;}        

   ledcWrite(ledChannel,PWM);                            
   delay (1);
  }  //end for

//affichage tous les 950ms
  pourcentage= map(tensionbatt*10, 30, 42, 0, 100);
  timeduration=(pourcentage*1.2)/((0.02+consigne*0.05)*100);    //0.05*consigne correpond au rapport cyclique 50ms/(950ms+50ms)
  tft.setCursor(0, 0, 4);// (x,y,taille)  //durée 4ms
  tft.print(pourcentage);tft.println("=%"); 
  tft.print(timeduration,1);tft.println("=hour");
  tft.print(consigne,2);tft.println("=Cons");
  tft.print(courantled,3);tft.println("=I   ");
  tft.print(PWM);tft.println("=PWM    "); 

  Serial.print(courantled,3);Serial.print(";");Serial.print(consigne,1);Serial.print(";");Serial.println(PWM); 


  ledcWrite(ledChannel,0);  //mettre à 0 la PWM                                 
  delay(950);    //PWM ne fonctionne plus et interruption fonctionne    oled fonctionne
   
 }//end loop

Avec l’application “Bluetooth Electronics” j’ai mettre un place un afficheur et de boutons pour tester la communication avec le ESP32. En utilisant cet interface et le code j’ai obtenu les résultats :

1 Like

........................................A continuer.........................................

En reprenant le post de darinacio daté le 16 Février, nous avons constaté une erreur dans les calculs des équations. Il faut se souvenir que nous voulons utiliser une régulation du courant pour avoir Iled = Ic. Ici vous pouvez trouver sa nouvelle équation :

Est-ce que c’est possible d’utiliser un autre type de correcteur ?

Oui, si on utilise un correcteur PI c’est possible de déplacer de point de départ pour n’a pas avoir un changement trop significatif au moment de la régulation. Je me suis inspiré du correcteur précèdent pour avoir le correcteur PI analogique suivant :

Le développement de sa fonction de transfert :

Ce qui nous donne :

1 Like

Réalisation de l'éclairage

Suite à l'étude expliqué dans le dernier post j'ai rédigé le programme pour la carte Arduino Pro Mini :

#include <SoftwareSerial.h>
#include <TimerOne.h>
#include <avr/wdt.h>       //chien de garde
#include <avr/power.h>   //mise en veille
#include <avr/sleep.h>
#include "LowPower.h"     //https://github.com/rocketscream/Low-Power


// Configuration des variables

unsigned int temps; //temps de la routine d'interruption
byte  temps1=0,mode=0,PWM=0, PWM1;   
float I=0,erreur=0,kp=1,ki=7.5,Ic=1,Integral=200, aff=0;
float I1=0,erreur1=0, Ic1=0.1,Integral1=200, aff1=0;
int compt;

// the setup function runs once when you press reset or power the board
void setup() {
 
   pinMode(5, OUTPUT);      //PWM
   pinMode(6, OUTPUT);      //PWM

   Serial.begin(9600);      //Initialisation de la communication serial

   TCCR0B = (TCCR0B & 0b11111000) | 0x01;         //pin 5 et 6  64khz    http://playground.arduino.cc/Main/TimerPWMCheatsheet
                                            
   analogReference(INTERNAL);
   analogWrite(5,255);
  
}

/*****************Fonction pour économiser la consommation***************************/
void sleepNow(void)
{
    //LowPower.powerDown(SLEEP_60MS, ADC_OFF, BOD_OFF);
    set_sleep_mode(SLEEP_MODE_IDLE);
    //set_sleep_mode(SLEEP_MODE_ADC);
    //set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_enable();
    power_adc_disable();
    power_spi_disable();
    // power_timer0_disable();
    power_timer2_disable();
    power_twi_disable();  

}


void loop (){
    // Lecture de la tension*2=courant car ll y a une resistence de mesure de 0.5ohm
   for (int i=0; i<=250; i++){
      /************************Régulation LED principal***************************************/
      I=analogRead(A1);
      I=I*0.0005371;            //0.5*1.1/1024
      erreur=Ic-I;

      Serial.println(I);

      //Correcteur PI; PWM=ki*Erreur/P + kp*Erreur
      Integral= Integral+(erreur*ki)+(erreur*kp); 

      if (Integral>=255) Integral=255;
      if (Integral<=0) {Integral=0;}
      
      PWM=255-Integral;// PWM inversé car le transistor est un Canal P

      
      
      aff = (Integral*100)/255;     //convertion en porcentage pour l'affichage

      analogWrite(6,PWM);    //commande de la LED de puissance
      
      /*******************Affichage pour les tests *******************************************/
//      Serial.print("Er= ");Serial.print(erreur,1);
//      Serial.print(" I= ");Serial.print(I);
//      Serial.print(" PWM= ");Serial.print(aff,0); Serial.println("%");

      /*************************************Regulation 3 LED**********************************/
      I1=analogRead(A3);
      I1=I1*0.0005371;            
      erreur1=Ic1-I1;

      //Correcteur PI; PWM=ki*Erreur/P + kp*Erreur
      Integral1= Integral1+(erreur1*ki)+(erreur1*kp);

      if (Integral1>=255) Integral1=255;
      if (Integral1<=0) {Integral1=10;}
      
      PWM1=255-Integral1;// Rapport cyclique inversé car le transistor est un Canal P


      
      aff1 = (Integral1*100)/255;     //convertion en porcentage pour l'affichage

      analogWrite(5,PWM1);      //commande des 3 LEDs
    
      /*************************Affichage pour les tests ************************************/
      //Serial.print("Er1= ");Serial.print(erreur1,1);
      //Serial.print(" I1= ");Serial.print(I1);
      //Serial.print(" PWM1= ");Serial.print(aff1,0);Serial.println("%");

      delay(1);  
   }

     analogWrite(5,255);    
     analogWrite(6,255);
     sleepNow();           //Mode sleep pour économiser la consommation
     delay(1000);
      
      // Le program va fonctionner de nouveau à partir d'ici
      sleep_disable(); // First thing to do is disable sleep. 
      power_all_enable();     // Re-enable the peripherals. 

     //analogWrite(5,PWM);    
     //analogWrite(6,PWM1); 

      if (Serial.available()){
         int val = Serial.read();
         if (val == 'd') {    //commande qui depend de l'application (Bluetooth Electronics)
            mode++;                  //incrementation des modes 
            if (mode>3) mode=1; 

               switch (mode) {
                  case 1: Ic=1; Ic1=0.1; Integral=240; Integral1=240;
                          Serial.println("mode1");
                          break;   
                  case 2: Ic=0.5; Ic1=0.05; Integral=127; Integral1=127;
                          Serial.println("mode2");
                          break;
                  case 3: Ic=0.25; Ic1=0.025; Integral=50; Integral1=50;
                          Serial.println("mode3");
                          break;
               }
            }
          /*****************affichage pour l'utilisateur******************/
           if (val == 'a'){
                Serial.print("*L"); Serial.print("Er=");Serial.print(erreur,1);Serial.println("*");
                Serial.print("*L"); Serial.print("I=");Serial.print(I);Serial.println("*");
                Serial.print("*L"); Serial.print("PWM=");Serial.print(aff,0);Serial.print("%");Serial.println("*");
                
           }    
      }      
}

Avec la maquette :

J'ai obtenu les résultats (mesure avec l'oscilloscope) :

TEK0037

Où on peut voir les signaux aux bornes de l'éclairage et ainsi qu'à la sortie du condensateur.