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

Communication avec Arduino:

Le MPU6050 utilise le protocole de communication I²C dont la connexion est réalisée par l'intermédiaire de deux lignes : • SDA (Serial Data Line) : ligne de données bidirectionnelle • SCL (Serial Clock Line) : ligne d'horloge de synchronisation bidirectionnelle Dans le monde Arduino, il existe une librairie dédiée à ce protocole : Wire. En lisant la doc de la librairie Wire Arduino, on voit que sur un Arduino NANO ce sont les entrées analogiques A4 et A5 qui correspondent respectivement à SDA et SCL. On câble donc tout cela ensemble. Le MPU a besoin d'être alimenté en 3.3V, on relie donc la broche Vcc à la broche 3.3V de l'Arduino et le GND au GND de l'Arduino. Ce qui nous donne au final ce câblage :

|500x262

Configuration :

Sensibilité de l’accéléromètre :

Le registre ACCEL_CONFIG permet de configurer la plage de fonctionnement de l'accéléromètre.

Une plage de ±2g est suffisante pour l'étude, ce qui nous amène à utiliser le facteur AFS_SEL = 0

https://servimg.com/view/19537397/6 Structure du registre ACCEL_CONFIG

La paramètre AFS_SEL est codé sur les bits 3 & 4. La valeur 0 en binaire s'écrit alors 0 aussi. Les bits 0, 1 et 2 sont réservés, on les laisse donc à 0. Les bits 5, 6, 7 servent à effectuer un auto-test des axes X Y Z respectivement. Cela ne nous intéresse pas, on les laisse donc à 0.

Plus loin dans la datasheet, on arrive sur la page du registre Power Management. Ce registre nous permet de choisir la source d'horloge que le MPU va utiliser au travers du paramètre CLKSEL.

https://servimg.com/view/19537397/7

Nous allons utiliser ici son horloge interne de 8MHz, soit CLKSEL = 0.

|500x44

Structure du registre PWR_MGMT_1

Là encore, on voit que ce registre est codé sur 8 bits. CLKSEL est codé sur les bits 0, 1 & 2. La valeur 0 en binaire s'ecrit alors 000 Le bit 3 TEMP_DIS (temparture disabled) sert à désactiver la lecture de la température lorsqu'il est à 1. On va garder cette information, on laisse donc ce bit à 0. On laisse le reste à 0, ce qui nous donne au final 00000000 en binaire, soit 0x00 (hex). Enfin, l'adresse du registre est 0x6B en hexadécimal. Ce qui nous donne le code Arduino suivant :

Wire.beginTransmission(MPU);        // Start communication with MPU6050 // MPU=0x68
Wire.write(0x6B);                  // Talk to the register 6B
Wire.write(0x00);                  // Make reset - place a 0 into the 6B register

Filtre passe bas :

Le registre, de nom CONFIG, va nous servir à configurer la fréquence de coupure du filtre passe-bas de l'accéléromètre au travers du paramètre DLPF_CFG.

Digital Low Pass Filter

On va partir sur une fréquendce d'environ ~43Hz, ce qui nous amène à DLPF_CFG = 3. On laisse les autres bits à 0, ce qui nous amène à en binaire, soit 0x03 en hexadécimal. Enfin, l'adresse du registre est 0x1A en hexadécimal. Ce qui nous amène au code Arduino suivant :

Wire.write(0x1A);             // Request the CONFIG register
Wire.write(0x03);             // Apply the desired configuration to the register : DLPF about 43Hz

Fréquence d’horloge :

Plus loin dans la datasheet, on arrive sur la page du registre Power Management. Ce registre nous permet de choisir la source d'horloge que le MPU va utiliser au travers du paramètre CLKSEL. https://servimg.com/view/19537397/10 Nous allons utiliser ici son horloge interne de 8MHz, soit CLKSEL=0

|500x44

Structure du registre PWR_MGMT_1 Là encore, on voit que ce registre est codé sur 8 bits. CLKSEL est codé sur les bits 0, 1 & 2. La valeur 0 en binaire s'ecrit alors 000. Le bit 3 TEMP_DIS (temparture disabled) sert à désactiver la lecture de la température lorsqu'il est à 1. On va garder cette information, on laisse donc ce bit à 0. On laisse le reste à 0, ce qui nous donne au final 00000000 en binaire, soit 0x00 (hex). Enfin, l'adresse du registre est 0x6B en hexadécimal. Ce qui nous donne le code Arduino suivant :

Wire.beginTransmission(MPU_ADDRESS); // Start communication with MPU
Wire.write(0x6B);                    // Request the PWR_MGMT_1 register
Wire.write(0x00);                    // Apply the desired configuration to the register
Wire.endTransmission();              // End the transmission

LECTURE DES DONNEES BRUTES DU MPU6050 :

Maintenant que le MPU6050 est câblé et configuré, il ne reste plus qu'à lire les données brutes du capteur.

On constate dans la table des registres que les registres 59 à 64 stockent les valeurs de sorties de l'accéléromètre .

|500x209

On va donc simplement parcourir le contenu de ces 6 registres, en commençant à l'adresse 0x3B :

Wire.beginTransmission(MPU_ADDRESS);// Start communicating with the MPU-6050
Wire.write(0x3B);                   // Send the requested starting register
Wire.endTransmission(false);             // End the transmission
Wire.requestFrom(MPU_ADDRESS,6);   // Request 14 bytes from the MPU-6050

Mesure de l’accélération :

Un accéléromètre mesure l'accélération subite et l'exprime en g. 1g représente l'accélération de pesanteur sur Terre, soit environ 9,8m.s−29 et des bananes. L'accéléromètre au repos mesure donc une accélération de 1g.

Script intégral en C sur l’IDE Arduino :

#include // include la bibliothèque Wire.h

#define MPU_ADDRESS 0x68  // I2C address of the MPU-6050

#define X  0        // X axis
#define Y  1        // Y axis
#define Z  2        // Z axis
float acc_total_vector;

int acc_raw[3] = {0,0,0};

/**
* Configure la plage de fonctionnement de l'accéléromètre :
*  - accéléromètre: +/-2g

*
* @return void
*/
void setup() {
analogReference(EXTERNAL);
Serial.begin(19200);
Wire.begin();  
// Configure power management
Wire.beginTransmission(MPU_ADDRESS); // Start communication with MPU
Wire.write(0x6B);                    // Request the PWR_MGMT_1 register
Wire.write(0x00);                    // Apply the desired configuration to the register
Wire.endTransmission();              // End the transmission

// Configure the acceleromter's sensitivity
Wire.beginTransmission(MPU_ADDRESS); // Start communication with MPU
Wire.write(0x1C);                    // Request the ACCEL_CONFIG register
Wire.write(0x00);                    // Apply the desired configuration to the register : ±8g
Wire.endTransmission();              // End the transmission

// Configure low pass filter
Wire.beginTransmission(MPU_ADDRESS); // Start communication with MPU
Wire.write(0x1A);                    // Request the CONFIG register
Wire.write(0x00);                    // Set Digital Low Pass Filter about ~43Hz
Wire.endTransmission();              // End the transmission

Wire.endTransmission(true);        //end the transmission
}

void loop() {
Wire.beginTransmission(MPU_ADDRESS);// Start communicating with the MPU-6050
Wire.write(0x3B);                   // Send the requested starting register
Wire.endTransmission(false);             // End the transmission
Wire.requestFrom(MPU_ADDRESS,6);   // Request 14 bytes from the MPU-6050

// Wait until all the bytes are received
while(Wire.available() < 6);

acc_raw[X]  = (Wire.read() << 8 | Wire.read())/ 16384.0; // Add the low and high byte to the acc_raw[X] variable
acc_raw[Y]  = (Wire.read() << 8 | Wire.read())/ 16384.0; // Add the low and high byte to the acc_raw[Y] variable
acc_raw[Z]  = (Wire.read() << 8 | Wire.read())/ 16384.0; // Add the low and high byte to the acc_raw[Z] variable

acc_total_vector = sqrt(pow(acc_raw[X], 2) + pow(acc_raw[Y], 2) + pow(acc_raw[Z], 2));

Serial.print(acc_raw[X]);
Serial.print("/");
Serial.print(acc_raw[Y]);
Serial.print("/");
Serial.print(acc_raw[Z]);
Serial.print("/");
Serial.println(acc_total_vector);
delay(10);

}

Résultats moniteur Arduino:

1g suivant +X :

1g suivant -Y :

1g suivant +Z:

Conclusion:

Quant aux différents filtres, j’ai utilisé le filtre passe-bas numérique intégré dans le MPU6050 avec une bande passante d’environ 45Hz, quand j’essaie de bouger le capteur pour voir les réponses suivant plusieurs axes, les réponses sont quasi-stables dans le moniteur série d’IDE Arduino, le fait d’implanter des équations récurrentes de différents types de filtre (pass_bas pass_haut passe bande …), c’est facile, mais je n’y vois pas l’intérêt, car tous les résultats qu’on trouve sur le moniteur série Arduino, sont soit 1g suivant X soit 1g suivant Y soit 1g suivant Z.

Allumer un feu stop après un freinage ou un arrêt normal du vélo, est tout à fait possible avec un accéléromètre détectant la décélération, toutefois cela nécessite une étude comparatives de plusieurs accéléromètres analogiques et numériques, sans oublier les autres solutions technologiques pour répondre à cette problématique, comme par exemple un compteur de vitesse (Tr/min)

Pourquoi ne pas avoir utilisé une bibliothèque dédiée pour le MPU 6050 ?????? Mais en général, avec ces bibliothèques, la configuration est difficile…. donc c’est vraiment bien, ce que vous avez fait.

Est-ce que vous avez fait des essais du capteur MPU6050 dans une voiture et vérifier les dynamiques de l’accélération avec une application smartphone ???????

si tu mets

[url=https://servimg.com/view/19537397/16][img]https://i.servimg.com/u/f38/19/53/73/97/z10.png[/img][/url]

on verra l'image |173x500

Bref, les compteurs de vélos (odomètre capteur magnet KY03) qui mesurent la vitesse grâce à un compte tour de la roue pourrait aussi mesurer la décélération et activé un STOPT arrière. Mais quelle pourrait être la précision de cette méthode ? Faut-il mettre plusieurs aimants sur la roue ? Faut-il filtrer la valeur de la décélération ?

De plus, il existe des éclairages arrière vélos qui donnent la direction (clignotant droit et gauche) sans fil, mais sur un vélo, il n’y qu’à tendre la main à droite ou à gauche donc c’est inutile. Mais pour un velomobile (vélo caréné), cela est intéressant http://velorizontal.1fr1.net/t17956-velomobile-electric-leiba-x-stream-iut-aisne |500x375 Voici un bel article avec 2 arduinos et une communication bluetooth https://create.arduino.cc/projecthub/simonwongwong/bluetooth-enabled-bicycle-turn-signal-2f4f5d Mais les matrices de leds ne permettent pas d’être vu de jour (pas assez de lumen)

L’article suivant utilise une télécommande 4 boutons https://github.com/sdebby/Arduino_bike_blink Donc une télécommande et un récepteur, voici en voici l’électronique http://www.wzmicro.com/rf.htm Cela ne coute rien, mais il faudra mettre le compteur de vélo sur l’Arduino arrière pour avoir un feu stop |500x260

Donc, un compteur vélo avec Bluetooth va être réalisé et commander l’éclairage arrière comme on peut l’observer sur la figure suivante. Le compteur avec son afficher a permis de vérifier le bon fonctionnement de la programmation et s’il fallait filtrer la mesure de la décélération Il faudra prendre des Arduino Pro et pas nano pour leurs faibles consommations sur la batterie. Mais pour vérifier la programmation le nano a été utilisé. |500x305 L’indication droite et gauche est évidemment clignotante ainsi que le stop et lors de la décélération. Mais on aurait pu mettre une 4éme led, pour un feu stop mais cela n’a pas été fait. Le bouton poussoir stop est inutile, puisque la décélération est mesurée et active automatiquement l’éclairage arrière.

Le compteur vélo a 4 aimants sur la roue pour augmenter la précision des mesures de la vitesse dans les basses vitesses. Avec l’utilisation de la mesure en milliseonde à chaque quart de roue L’erreur de la vitesse est déterminée par l’équation suivante avec 4 aimants DeltaVitesse=(2010*3.6/4)/(Timer+1)( Timer) pour Timer=25ms=>2.78km/h pour vitesse 72km/h La précision correspond à l’équation suivante Précision=1/(Timer+1) donc à 72km/h précisons de 3.8% et à 18km/h 1%

Etant donné que l’accélération est déterminée aussi pour chaque quart de roue tournée, l’erreur de l’accélération correspondra aux équations suivantes DeltaAccelera=(277)/(Timer+1)( Timer) pour Timer=25ms=>0.42m/s^2 pour vitesse 72km/h DeltaAccelera=(277)/(Timer+1)( Timer) pour Timer=100ms=>0.027m/s^2 pour vitesse 18km/h

Pour ne pas avoir de décélération intempestive, le calcul de la décélération se fera seulement si l’erreur de mesure de la vitesse est plus faible que sa variation. Etant donné que la propriété de la routine d’interruption extérieure n’est pas si facile à imposer par rapport à routine d’interruption timer sur Atmel, il n’y aura pas d’interruption timer.

Voici le code

#include 
#include 
//#include 


#define led13     13       //    
#define BPLeft    12       // 
#define Night     11       // 
#define BPRight   10       //
#define BPStop     9       //


LiquidCrystal lcd(8, 3, 4, 5, 6, 7);   // LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
// Configuration des variables

 float Time=0; 
 float  TO=0; 
 float  temps=0; 
 float  Time1=0;               
            float kph=0;
            float kph1=0;
            float distance=0;

            float deceler=0;
            float erreur=0;
            bool stop=0;
            bool flagnight=0;
            bool attendre=0;
            
            byte   buffer1=0; 
            String readString;

// the setup function runs once when you press reset or power the board
void setup() {

pinMode(led13, OUTPUT);   //led carte arduino
pinMode (BPLeft, INPUT_PULLUP);
pinMode (Night, INPUT_PULLUP);
pinMode (BPRight, INPUT_PULLUP);
pinMode (BPStop, INPUT_PULLUP);

 lcd.begin(16, 2);                   //modifier pour un afficheur 20x4
 Serial.begin(9600);     //57600
 //SoftwareSerial mySerial(0, 1);   // RX, TX mais il n'y a pas trop le choix sur la nano


//  Timer1.initialize(10000);           // initialize timer1, and set a 0,1 second period =>  100 000  pour 0.01s  10 000
//  Timer1.attachInterrupt(Routinetimer1);   // attaches le sous programme  Routinetimer1 as a timer overflow interrupt

  TCCR2B = (TCCR2B & 0b11111000) | 0x01;         //pin 3  32khz    

attachInterrupt(0, interrup2, RISING);   // il vaut mieux utiliser  KY003 tout ou rien   RISING, FALLING, CHANGE
TO = millis();                                   
}//fin setup

void interrup2() // la fonction appelée par l'interruption externe n°0
{//digitalWrite(led13,HIGH);
Time=(millis()-TO);  //mesure du temps     //micros()    millis()
TO=millis();

distance=(distance+(2.01/4));     //perimetre/4 aimants
kph1=kph;                            
if (Time>=500) {kph=0;deceler=0; } 
          else {kph=((2.010*1000*3.6)/(Time*4));   //kph=perimetre/time  avec 4 aimants   //
                erreur=(kph/(Time-2));                                                                             
                if ( (kph<(kph1-erreur)))  {deceler=(((kph-kph1)*277)/Time);} else {deceler=0;}   
                }              // en m/s^2  277=1000milliseconde/3.6      
if (deceler<-40) {deceler=-40; }
if (deceler>40) {deceler=40; }
//  digitalWrite(led13,LOW);   de la routine interr exterieur durée 0.7ms 
}



// Interruptions  tous les 100ms fait par le timer1***********************************

//void Routinetimer1()  {
//  temps++;  
//}//fin routineinterruption


///////////////////////////////////////////// Boucle correspondant à la fonction main 
void loop() {  
Time1=(millis()-TO);
if (Time1>=500) {kph=0;deceler=0;}   //remise à 0, lorsqu'il n'y a plus d'interruption
attendre=0;

  lcd.setCursor(0,0);  // (X,Y)                               
  lcd.print(kph,1);
  lcd.print("kph    "); 
  lcd.setCursor(9,0);  // (X,Y)                                
  lcd.print(distance/1000,2);
  lcd.print("km  ");

    lcd.setCursor(0,1);  // (X,Y)                            
    lcd.print(deceler,1);
    lcd.print("m/s"); 
    lcd.print((char)94);
    lcd.print("2 "); 

    if  (deceler<(-2)) {stop=1;lcd.setCursor(10,1);lcd.print("STOP");Serial.print(2); }  
    if  (deceler>0)    {stop=0,lcd.setCursor(10,1);lcd.print("    "); }
    if  (digitalRead(BPStop)==0) {stop=1;lcd.setCursor(10,1);lcd.print("STOP");Serial.print(2); }  
    if (digitalRead(BPLeft)==0)     {Serial.print(1); } 
    if (digitalRead(BPRight)==0 )   {Serial.print(3); } 
    if (digitalRead(BPRight)==0 && digitalRead(BPStop)==0   )    {distance=0;}   //remise à zero du compteur
    if  (digitalRead(BPStop)==0) {stop=1;lcd.setCursor(10,1);lcd.print("STOP");Serial.print(2); }
 if ((digitalRead(Night)==0) && (flagnight==0) && attendre==0 )      {flagnight=1;Serial.print(0);attendre=1; }   //eteindre la lumiere
 if ((digitalRead(Night)==0) && (flagnight==1) && attendre==0)      {flagnight=0;Serial.print(4);attendre=1;}   //allume lumiere
 if (flagnight==1)  {lcd.setCursor(15,0);lcd.print("N"); }      //lumiere
 if (flagnight==0)  {lcd.setCursor(15,0);lcd.print(" "); } 

/*Serial.print(Time,0);
Serial.print(";");
Serial.print(kph,1);
Serial.print(";");
Serial.print(deceler,1);
Serial.println(";");  */
delay(100);             
   
} // fin loop

la suite du post precedent

Voici le résultat de la mesure de la vitesse et la deceleration avec excel, du programme precedent |500x389

Pas envie de mettre 2 fils d’alimentation et 1 fil de communication entre le compteur et l’éclairage arrière entre le compteur et la partie éclairage arrière. Donc une commination série Bluetooth HC06 a été choisie. Il sera possible d’indiquer sur le compteur rétroéclairer, l’état de la batterie arrière.

Le code de la récepteur et qui gère le clignotement

#include 
#include 
//#include 


#define led12     12       // 
#define led11     11       // 
#define led10     10       // 

            byte  temps12=0;
            byte  temps11=0; 
            byte  temps10=0;
            byte c=0;
            bool flag12=0;
            bool flag11=0;
            bool flag10=0;
            bool flagnight=0;
            


void setup() {
pinMode(led12, OUTPUT);   //lumiere gauche, direction
pinMode(led11, OUTPUT);   //lumiere centrale, stop et eclairage
pinMode(led10, OUTPUT);   //lumiere gauche, direction


Serial.begin(9600);     
 //SoftwareSerial Serial(0, 1);   // RX, TX mais il n'y a pas trop le choix sur la nano

 Timer1.initialize(400000);           // initialize timer1, and set a 0,1 second period =>  100 000  pour 0.01s  10 000
 Timer1.attachInterrupt(Routinetimer1);   // attaches le sous programme  Routinetimer1 as a timer overflow interrupt
                            
}//fin setup




// Interruptions  tous les 400ms fait par le timer1***********************************
void Routinetimer1()  {
  temps12++;
  temps11++;
  temps10++;
if (temps12<15 && flag12==1)  {if ( digitalRead(12)== 1 ) {digitalWrite(12,LOW);}  else {digitalWrite(12,HIGH);}}  //clignotement pendant 15=6s/0.4s  gauche
if (temps12>15 && flag12==1)  {flag12=0;digitalWrite(led12,LOW);} 

if (temps10<15 && flag10==1)  {if ( digitalRead(10)== 1 ) {digitalWrite(10,LOW);}  else {digitalWrite(10,HIGH);}}  //clignotement pendant 15=6s/0.4s droite
if (temps10>15 && flag10==1)  {flag10=0;digitalWrite(led10,LOW);} 

if (temps11<15 && flag11==1)  {if ( digitalRead(11)== 1 ) {digitalWrite(11,LOW);}  else {digitalWrite(11,HIGH);}}  //clignotement pendant 15=6s/0.4s stop
if (temps11>15 && flag11==1)  {flag11=0; 
                               if (flagnight==1) {digitalWrite(11,HIGH);}
                               if (flagnight==0) {digitalWrite(11,LOW);}
                              } 
}//fin routineinterruption



///////////////////////////////////////////// Boucle correspondant à la fonction main 
void loop() {  

while (Serial.available()) { c=Serial.read();//Serial.print(c,DEC);  
if (c==48)        {digitalWrite(led11,LOW);flagnight=0;}       //0 arret en continu
if (c==49)        {digitalWrite(led12,HIGH);digitalWrite(led10,LOW);flag12=1;flag10=0;temps12=0;}        //1  direction gauche +5s
if (c==50)        {digitalWrite(led11,HIGH);flag11=1;temps11=0;}                                         //2  feu stop
if (c==51)        {digitalWrite(led10,HIGH);digitalWrite(led12,LOW);flag10=1;flag12=0;temps10=0;}        //3  direction droite +5s
if (c==52)        {digitalWrite(led11,HIGH);flagnight=1;}                                                //4  allumage en continu
                            }

} // fin loop

A la place de faire de nombreux essais, sur le vélo pour vérifier le programme de la mesure vitesse et de la décélération, un Arduino génère les impulsions de l’aimant. |500x208

Voici le code du générateur de front qui fait varier la vitesse pour verifier le bon fonctionnement du programme

#include 
#include 
#include 
#include 



#define led12     12       // 



LiquidCrystal lcd(9, 3, 4, 5, 6, 7);   // LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
// Configuration des variables



unsigned    int   temps=0; 
unsigned    int tempsmono=0;
            float  tempsperiode=0;
            float   tempsdecelerat;
            float  tempsdec=0;
            float  a=0;
            float  b=0;
            float deceleration;
            bool flag;
            

// the setup function runs once when you press reset or power the board
void setup() {


pinMode(led12, OUTPUT);   //

 Serial.begin(9600);     //57600

  Timer1.initialize(1000);           // initialize timer1, and set a 0,1 second period =>  100 000  pour 0.01s  10 000
  Timer1.attachInterrupt(Routinetimer1);   // attaches le sous programme  Routinetimer1 as a timer overflow interrupt

  TCCR2B = (TCCR2B & 0b11111000) | 0x01;         //pin 3  32khz    


  a=0.144;                 //((400-40)/tdecel);   400  correspond à 4.5km/h , 40 à 45km/h utilsation 4 aimants    (4.5-45)/(2.5s*3.6)=4.5m/s^2
  b=40;                    //coefficient de le deceleration
    Serial.print(a,3);
    Serial.print(";");
    Serial.println(b,3) ;                               
}//fin setup



// Interruptions  tous les 1ms fait par le timer1***********************************
void Routinetimer1()  {
temps++;
tempsperiode++;
tempsmono++;

//*
if (tempsperiode<50)  {deceleration=2000;}     //creation profil acceleration et decele
if (tempsperiode>=50 &&  tempsperiode<2500)  {deceleration=-0.2*(tempsperiode-50)+400;        
                                              if (deceleration<40) {deceleration=40;}
                                              }    //acceleration
if (tempsperiode>=2500 &&  tempsperiode<3500)  {deceleration=40;}                                               
if (tempsperiode>=3500 &&  tempsperiode<6000)  {deceleration=a*(tempsperiode-3500)+b;}      //deceleration  

if (tempsperiode>=6000 && tempsperiode<7000 )  {deceleration=1000;}
if (tempsperiode>=7000)  {tempsperiode=0;} 
//*/
               
//Serial.print(tempsperiode,0) ; 
//Serial.print(";"); 
//Serial.println(deceleration,0) ;     
//deceleration=40;           //4 aimants,  400=>4.5km/h   40=>45km/h    valeur fixe de vitesse
   
if (temps>=deceleration  && flag==0) {digitalWrite(led12,HIGH);tempsmono=0;flag=1;temps=0; }  //monostable=10ms
if (flag==1 && tempsmono>=4)        {digitalWrite(led12,LOW);flag=0;} 




}//fin routineinterruption


///////////////////////////////////////////// Boucle correspondant à la fonction main 
void loop() {  



} // fin loop

Avec la batterie, du compteur, on pourrait faire aussi un éclairage blanc vers l’avant Mais, cela sera une autre histoire….

Voici le programme du capteur accéléromètre MPU6050 mais avec un ESP32+OLED et un filtre passe bas du troisième ordre, pour un éclairage automatique arrière de vélo. |500x252 La méthode de test et des explications sont téléchargeables sur ce lien https://www.fichier-pdf.fr/2020/09/17/esp32-mpu6050-arduino-filtre-passe-bas-1hz/

#include "Arduino.h"
#include "heltec.h"
#include "Wire.h"
//#include "BluetoothSerial.h"    //https://randomnerdtutorials.com/esp32-bluetooth-classic-arduino-ide/
                                  //


#define MPU_ADDRESS 0x68  // I2C address of the MPU-6050
int Te=100000  ; //periode d'echantillonnage micro seconde  =>0.1s

int16_t accX=0;
int16_t accY=0;
int16_t accZ=0;

 float accX_0=0;
 float accY_0=0;
 float accZ_0=0;

float accY_1 = 0;  // recurence n-1
float accY_2 = 0;  // recurence n-2
float accY_3 = 0;  // recurence n-3
float YaFout=0;
float YaF =0;
float YaF1 =0;
float YaF2 =0;
float YaF3 =0;

float  Y[127];     //12.7s



byte var=1;
byte i=0;   //incrementation for te curve
bool flagmesure=1;
bool flagenvoie=1;
bool flagstop=0;
bool flagfrein=0;
bool flagrear=0;
bool flaglight=0;
int16_t temps=0;
int16_t tensionbatt;




hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
uint32_t cp0_regs[18];

//******************************************************************
void IRAM_ATTR onTimer() {      //IRAM et DRAM   routine d'interruption toutes les TE 0.1s 
//digitalWrite(33,HIGH); 
 portENTER_CRITICAL_ISR(&timerMux);

xthal_set_cpenable(1);  xthal_save_cp0(cp0_regs);   // // Save FPU registers
if ( digitalRead(25)== 1 ) {digitalWrite(25,LOW);}  else {digitalWrite(25,HIGH);}    //led sur la carte heltec

flagmesure=1;
     
  xthal_restore_cp0(cp0_regs);  xthal_set_cpenable(0);  // and turn it back off
  portEXIT_CRITICAL_ISR(&timerMux);
  
//  digitalWrite(33,LOW);
}//fin routine interrupt







//*********************************
void setup(){
pinMode(0, INPUT_PULLUP);   //bouton prg carte heltec ESP32
pinMode(25, OUTPUT);   //led
//pinMode(13, OUTPUT);   //mesure temps instruction oscilloscope
pinMode(21, OUTPUT);   // lecture batterie lithium

 Serial.begin(115200);

 Wire.begin(4,15,400000);       //Wire.begin(I2C_SDA, I2C_SCL);       0x3C oled   et MPU6050  broche 4 et 15

  Heltec.begin(true /*DisplayEnable Enable*/, false /*LoRa Disable*/, true /*Serial Enable*/);
  Heltec.display->flipScreenVertically();
  Heltec.display->setFont(ArialMT_Plain_24);           //10, 16, 24
  Heltec.display->setTextAlignment(TEXT_ALIGN_LEFT);


Wire.beginTransmission(MPU_ADDRESS);
 Wire.write(0x6B);  // PWR_MGMT_1 register
 Wire.write(0x00);     // set to zero (wakes up the MPU-6050)
 Wire.endTransmission();              // End the transmission

// Configure the acceleromter's sensitivity
Wire.beginTransmission(MPU_ADDRESS); // Start communication with MPU
Wire.write(0x1C);                    // Request the ACCEL_CONFIG register
Wire.write(0x00);                     // Apply the desired configuration to the register : ±2g=±20ms^-2     1g=16384
//Wire.write(0b00010000);             // Apply the desired configuration to the register : ±8g=±20ms^-2  1g=4096
Wire.endTransmission();              // End the transmission

// Configure low pass filter
Wire.beginTransmission(MPU_ADDRESS); // Start communication with MPU
Wire.write(0x1A);                    // Request the CONFIG register
//Wire.write(0x00);                    // Set Digital Low Pass Filter about ~260Hz   DLPF_CFG
Wire.write(0x06);                    // Set Digital Low Pass Filter about ~5Hz   DLPF_CFG
Wire.endTransmission();              // End the transmission

Wire.endTransmission(true);        //end the transmission

  timer = timerBegin(0, 80, true);
  timerAttachInterrupt(timer, &onTimer, true);
  timerAlarmWrite(timer, Te, true);      
  timerAlarmEnable(timer);

}


//************************
void loop(){

//if ( digitalRead(13)== 1 ) {digitalWrite(13,LOW);}  else {digitalWrite(13,HIGH);}     //teste du temps de la boucle
if (digitalRead(0)==0)   {var++;delay(1500); }    //utilisation du bouton prg de la carte ESP32 heltec
if (var>=5)   {var=1;flagenvoie=1; }              //4 valeurs pour afficher les valeurs numeriques ou courbes ou pause ou envoie des données
if ( touchRead(13)<30 )   {flagfrein=1;} else {flagfrein=0;}    //touchRead(13)



if ((flagmesure==1 && (var==1 | var==2)))   {    //mesure tous les 0.1ms
  temps++;
Wire.beginTransmission(MPU_ADDRESS);
Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);           // End the transmission
Wire.requestFrom(MPU_ADDRESS,6);   // Request 16 bytes from the MPU-6050

// Wait until all the bytes are received
while(Wire.available() < 6);

accX  = (Wire.read() << 8 | Wire.read()); // reading registers: 0x3B et 0x3C     MSB et LSB
accY  = (Wire.read() << 8 | Wire.read()); // reading registers: 0x3D 
accZ  = (Wire.read() << 8 | Wire.read()); // reading registers: 0x3F 

accX_0=accX/1638.0;   //en m/s^2  pour initilisation à 2*gravitation
accY_0=accY/1638.0;
accZ_0=accZ/1638.0;

accY_3=accY_2;
accY_2=accY_1;  //recurence n-2
accY_1=accY_0;  //recurence n-1

YaF3=YaF2;
YaF2=YaF1;
YaF1=YaF;         //filtre numerique passe bas 3éme orde Frequence de coupure=1Hz
YaF=accY_0+3*accY_1+3*accY_2+3*accY_3+0.278059*YaF3-1.18289*YaF2+1.76*YaF1;   //filtre numerique passe bas  Frequence de coupure=1Hz
YaFout=YaF/66;        //55 en theorie

i++;
if (i>=127) {i=0;}
//Y[i]=accY_0;    //sans filtre
Y[i]=YaFout;      //avec filtre    

if (YaFout>=2)  {flagstop=1;temps=0;}     //declenchement lumiere peandant 5seconde clignotant
if (YaFout<=-1) {flagstop=0;flagrear=0;temps=0;flaglight=0;}   //si acceleration arret lumiere arriere
if (flagstop==1 && temps<=50) {flagrear=1;}
if (temps>50) {flagrear=0;flaglight=0;}   
if (flagrear==1) {       if (flaglight== 1) {flaglight=0;}  else {flaglight=1;}     }  
                      

flagmesure=0;
 }  //fin if flagmesure




switch (var) {
  case 1:        //affichage value
//mesure de la charge de la batterie lithium 18650
digitalWrite(21,LOW);                    //active le pont diviseur
tensionbatt=analogRead(37);              //avec pont diviseur 100K et 220k  4.2V=>1.3125  donc 1630 decimale
tensionbatt=(tensionbatt/39+4);      //(volt*10) 12 bits 4096    0.35V chute de tension dans le transitor     3.3*3.2/409.6=1/39
tensionbatt = map(tensionbatt, 30, 42, 0, 100);    //map(value, fromLow, fromHigh, toLow, toHigh)   % de la charge
                                                   //2.9V=>-8%   3V=>0%    4.2V=100%    

//affichage  acceleration Y et  poucentage de la charge de la batterie
Heltec.display->clear();       //affichage numerique acceleration si appuie sur PRG
//Heltec.display->drawString(0, 0, "IUT GEII Soissons"); 
//Heltec.display->drawString(0, 11, "X "+String(accX_0,1)+"   ");
Heltec.display->drawString(0, 0, "Y "+String(accY_0,1)+"  ");          //acceleration filtré à 5HZ par le MPU6050
Heltec.display->drawString(83,0, String(tensionbatt)+"%");           //en poucentage de la charge
Heltec.display->drawString(0, 25,"Yf"+String(YaFout,1)+"   ");
Heltec.display->drawString(83, 25,String(flagfrein));
Heltec.display->drawString(100, 25,String(flaglight));
Heltec.display->display(); 
 break;  //case 1

case 2:       //affichage curve 
 Heltec.display->clear(); 
 Heltec.display->drawHorizontalLine(0,32,127);  //(x,y,length)      //trace les axes
 for (byte im = 0; im <= 127; im++) {    // affichage de la courbe
 Heltec.display->setPixel(im,(32-Y[im]*3));   //mettre la courbe au millieu et augmenter l'echelle de 3
 Heltec.display->display();  }
 break;  //case 2

case 3:       //mode pause

break;  //case 3



case 4:       //send data monitor 
if (flagenvoie>=1) {
 for (byte im = 0; im <= 127; im++) {    // affichage de la courbe
 Serial.print( Y[im]);Serial.println(";"); }
 Serial.println("stop");
flagenvoie=0;     }
break;  //case 4


 }//end switch 


 }//end loop

Le programme complet avec l’odomètre arrive, mais le programme sera moins lisible, donc on préfère le décomposer en plusieurs programmes.

Voici le programme du compteur de velo avec un capteur a effet hall et un aimant avec un ESP32+OLED qui gere plus facilement la commande du feu arriére que le capteur d’acceleration.
Les explications sont ici
https://www.fichier-pdf.fr/2020/10/02/esp32-odometre-alarme-capacimetrertc-heure/
le MPU6050 a été gardé pour realiser une alarme.
Il reste plus qu’à faire un tracker avec un GPS et l’envoie d’une notification……
Mais aussi realiser un boitier mécanique étanche, car pour l’instant ce n’est pas terrible


on va s’inpirer du boitier suivant

esp32_odometre_mpu6050_V3.ino (13.1 KB)

J’ai essayé votre programme sur un ESP32 TTGO avec un oled couleur d'aliexpress Mais j’ai un souci car je n’arrive pas à afficher quelques choses sur le oled pourtant j’ai bien télécharge les bibliothèques comme expliqué ici, ainsi que d’inclure les chemins ou sont les bibliothèques et le driver. cela compile bien https://github.com/Xinyuan-LilyGO/TTGO-T-Display https://www.instructables.com/Select-Color-Display-for-ESP32/

La variable i s’incrémente bien sur le moniteur série donc l’ESP32 fonctionne Pourriez-vous m’eclairer, SVP, car je suis dans le brouillard

Je mets le minimum du programme pour faire fonctionner le oled ici

#include 
#include 
//#include "WiFi.h"
#include 
//#include 
#include "esp_adc_cal.h"

#include 
//#include 
//#include  


//#include  
//#include 


//#define ST7789_DRIVER
//#define ILI9341_DRIVER

//#define CGRAM_OFFSET      // Library will add offsets required


//#define TFT_MOSI            19    //SDA
//#define TFT_SCLK            18    //SCL
//#define TFT_CS              5     //CS
//#define TFT_DC              16    //RS
//#define TFT_RST             23    //reset

//#define TFT_BL          4  // Display backlight control pin

#define TFT_BACKLIGHT_ON HIGH  // HIGH or LOW light OLED or not



//#define TFT_WIDTH  135
//#define TFT_HEIGHT 240
TFT_eSPI tft = TFT_eSPI (TFT_WIDTH, TFT_HEIGHT);  // édité



/*
#define LOAD_GLCD
#define LOAD_FONT2
#define LOAD_FONT4
#define LOAD_FONT6
#define LOAD_FONT7
#define LOAD_FONT8
#define LOAD_GFXFF

#define SMOOTH_FONT
*/


//#define SPI_FREQUENCY  27000000
//#define SPI_FREQUENCY    40000000   // Maximum for ILI9341


//#define SPI_READ_FREQUENCY  6000000 // 6 MHz is the maximum SPI read speed for the ST7789V

char buff[512];
int vref = 1100;
int i;

#define ADC_PIN 34

void setup()
{
  
Serial.begin(115200);

pinMode(2, OUTPUT);   //led
//pinMode(34, INPUT);   //led

tft.init();
tft.setRotation(1);
tft.fillScreen(TFT_BLACK);
tft.setTextSize(2);
tft.setTextColor(TFT_WHITE);
tft.setCursor(0, 0);
tft.setTextDatum(MC_DATUM);


if (TFT_BL > 0) { // TFT_BL has been set in the TFT_eSPI library in the User Setup file TTGO_T_Display.h
         pinMode(TFT_BL, OUTPUT); // Set backlight pin to output mode
         digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); // Turn backlight on. TFT_BACKLIGHT_ON has been set in the TFT_eSPI library in the User Setup file TTGO_T_Display.h
    }
    

tft.setTextSize(1);
uint16_t v = analogRead(ADC_PIN);
float battery_voltage = ((float)v / 4095.0) * 2.0 * 3.3 * (vref / 1000.0);
String voltage = "Voltage :" + String(battery_voltage) + "V";
Serial.println(voltage);
tft.fillScreen(TFT_BLACK);
tft.setTextDatum(MC_DATUM);
tft.drawString(voltage, tft.width() / 2, tft.height() / 2 );
delay(1000);
tft.drawString("Press again to wake up", tft.width() / 2, tft.height() / 2 );
delay(1000);

     tft.fillRect(0,0,240,135, TFT_BLUE); // erase the screen display
     tft.setTextSize(3);   // (num colonne , num ligne)
     tft.setCursor(0, 35); // (x colonne , y ligne) - F6CZV
     tft.print("VFO"); // F6CZV
delay(1000);

}




void loop()
{
  i++;
  if ( digitalRead(2)== 1 ) {digitalWrite(2,LOW);}  else {digitalWrite(2,HIGH);}
  Serial.println(i);
//tft.setRotation(0);

tft.fillScreen(TFT_RED);
delay(1000);
tft.fillScreen(TFT_BLUE);
//espDelay(1000);
delay(1000);
tft.fillScreen(TFT_GREEN);
delay(1000);
}

il y a une instrumentation de velo sur ce forum ici, j’ai envoyé un mail mais sans reponse http://cyclurba.fr/forum/570020/dn-codage-protocole-sn-rie-bbs0x.html?from=571&discussionID=18542&messageID=638753&rubriqueID=102&pageprec

Ca peut venir du fait que le constructeur

TFT_eSPI tft = TFT_eSPI(135, 240); // Invoke custom library

est avant les define des pins du SPI.

J'utilise ce même module TTGO et ça fonctionne bien. Il faut sélectionner

#define ILI9341_DRIVER

dans le fichier User_Setup.h de la bibliothèque TFT_eSPI. Les autres lignes doivent commentées :

// Only define one driver, the other ones must be commented out
#define ILI9341_DRIVER
//#define ST7735_DRIVER      // Define additional parameters below for this display
//#define ILI9163_DRIVER     // Define additional parameters below for this display
//#define S6D02A1_DRIVER
//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI
//#define HX8357D_DRIVER
//#define ILI9481_DRIVER
//#define ILI9486_DRIVER
//#define ILI9488_DRIVER     // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high)
//#define ST7789_DRIVER      // Full configuration option, define additional parameters below for this display
//#define ST7789_2_DRIVER    // Minimal configuration option, define additional parameters below for this display
//#define R61581_DRIVER
//#define RM68140_DRIVER
//#define ST7796_DRIVER
//#define SSD1963_480_DRIVER    // Untested
//#define SSD1963_800_DRIVER    // Untested
//#define SSD1963_800ALT_DRIVER // Untested
1 Like

A partir d’un d’éclairage arrière chinois à 5€, un Arduino pro mini a été programmé pour optimiser les performances de l’éclairage de la LED en mode flash et d’optimiser l’autonomie. En effet, un capteur de luminosité permet de faire d’augmenter l’éclairage de la led lorsque la luminosité extérieure est importante pour être bien vu de jour, mais aussi par temps de brouillard. C’est éclairage est devenu le plus performant de ce qui existe sur la marché. https://www.fub.fr/tests-eclairages Mais, il est possible de paramétrer l’éclairage par Bluetooth comme on peut le voir sur la photo suivante |500x375 En PDF, la méthodologie et le programme pour optimiser l’éclairage et les choix effectués ainsi que le programme….. https://www.fichier-pdf.fr/2021/01/31/rear-light-bike-3w-arduino-nano-bluetooth-mpu6050-v1/

D’autres prototypes devraient voir le jour avec amélioration et la minimisation du volume de l’électronique et du boitier.

1 Like

Suite au PDF précèdent,

Pour minimiser le câblage et éviter le problème du téléchargement d’un nouveau sketch de devoir déconnecter le HC06 à cause qu’il transmet tout le temps

J’ai voulu remplacé le HC06 par le BLE NAN0
Mais, je suis très déçu du BLE keywish qui ne se gère pas du tout comme un HC06
le manuel est tres bien fait
[keywish-nano-plus/Ble-Nano operation manual V.1.6.pdf at master · keywish/keywish-nano-plus · GitHub](http://“https://github.com/keywish/keywish-nano-plus/blob/master/BLE-Nano/Ble-Nano operation manual V.1.6.pdf”)

Par contre, il faut utiliser leurs applications
BLETestToosV1.0.apk

Mais qui est en mandarin, j’arrive quand même à commander l’éclairage et lire les valeurs du bluetooth….mais plus possible d’utiliser l’application bluetoothelectronics
https://www.keuwl.com/apps/bluetoothelectronics/
J’ai essayé de modifier le paramétrage avec la commande AT, le BLE NANO mais sans succès
j’ai envoyé un mail au support keywish, sans reponse depuis 1 semaine

La consommation moyenne du BLE nano est de 6mA avec un envoie 33 caracteres tous les 0.1s

On a modifié le programme de test du courant pour voir une commande continu et de modifier la periode lors de test de nouvelle LED

exemple, on a rajouté 3 led de petite puissance pour etre vu sur le coté
L’éclairage sur le côté ne demande pas d’être vu à 150m, sachant que lorsque l’on a un éclairage de de 10Watt à l’avant son flux est visible de côté ainsi que la réflexion de l’éclairage sur le sol
Pour être vu de coté à 6m avec 0.7 lux sur une largeur de 2m, il faut un angle d’environ de 6°
Avec 1 lumen ou 14 candela comme le démontre les équations suivantes

Par conséquent, de petite leds faibles puissance (50mA). seront suffisantes de diametre 5mm.
(3 led seront utilisé, 2 sur le coté et une pour l’arriere).

2 solutions pour faire la commande des 3 leds (3*50mA).

  • soit utiliser une résistance de limitation de courant qui aura des pertes mais sera une commande très fiable.
  • soit utiliser un hacheur qui minimisera les pertes mais si la régulation de courant n’est pas correcte alors il y a un risque de destruction des led et du transistor de commande. Pour ce courant pas la peine de prendre un transistor super-dimensionné avec un boitier TO251 mais un petit boitier SOT23 suffira
    L’inductance sera aussi bien plus petite devant supporte seulement un courant 150mA.

exemple de choix de led __*C503B-RAS *__6° 50mA 15 candela.
en mode eclairement continu, on peut mesurer les lux à 50cm sur un mur

Toujours à 50cm l’éclairage en fonction du courant est bien correct autour de 50mA avec un coefficient de performance de 3200lux/A
Puis, au-delà de 0.1A, les performances de l’éclairage se dégradent fortement.

Voici la commande des 3 led avec hacheur en boucle ouverte et de la led de puissance en simulation

le programme de test des leds en mode continu et pediodique en piece jointe

MPU6050_nano_blue_v1.ino (6 KB)

Pour mesurer le courant et faire une boucle fermée de la régulation de courant, des transistors canal P sont utilisés. De plus, avec une tension d’alimentation de 3 à 4.2 V il n’y a plus besoin de mettre le transistor NPN pour driver le transistor canal P comme sur le schéma datant du 31 Janvier 2021.

L’Arduino NANO a été remplacé par un Arduino Pro mini car ce dernier consomme beaucoup moins d'énergie.

Le capteur de température sera retiré car la LED de puissance en mode flash aura un incrément de température faible de 2°C par rapport à la température ambiante, une fois que le rapport cyclique sera de 1/20 (temps allumé de 0.05s sur une période de 1s.

Voici le nouveau schéma électrique de simulation qui nous a permis de valider le fonctionnement global avec le transistor canal P :

|500x303

La boucle fermée de régulation numerique a été simulé sous Simulink, voici le résultat obtenu pour une consigne de 1A.

|500x108

Etant donné que le temps d'echantillon et faible par rapport à la constante de temps de la regulation, la fonction de transfert en laplace va etre determiner pour faire un choix de ki |459x500

A partir de la fonction de transfert precedente, la constante de temps de la régulation de courant correspond à l’équation suivante

Sur cette figure suivante de matlab, on voit que l’erreur statique du courant est nulle et que le temps de réponse est de 0.03s, grâce au correcteur Intégral ayant un ki=10. De meme, on peut observer que le courant est nul pendant 0.01s, cela correspond au temps pour que la tension du hacheur soit supérieure à la tension de seuil de la LED.

|500x356

Il faut tester les transistors MOS en réel pour vérifier que cela fonctionne malgré la variation de la tension dans la batterie.

1 Like

Une autre façon de travailler avec le transistor canal N tout en faisant la régulation du courant a été trouvée.

Voici la façon dont la solution a été trouvée :

Tout d’abord il a été ajouté sur le schéma datant du 31 janvier, une résistance de 1ohm à la source du transistor canal N car cela permet de mesurer une tension qui est l’image du courant, par exemple : s’il y a un courant de 1A à la source du transistor, la tension vaut : R*I=1*1=1V.

Voici le schéma :

|500x489

Résultat obtenu en simulation

Sur cette figure on voit bien que le courant mesuré ne correspond pas au courant souhaité car lorsque le transistor est bloqué le courant mesuré vaut 0 et lorsqu’il est passant on ne maîtrise pas la valeur mesurée.

|500x323

Afin de résoudre ce problème il a été ajouté un condensateur à la source du transistor de façon à avoir un montage RC à la source du transistor. Avec ce montage en jouant sur la constante de temps R.C il sera possible de mesurer le vrai courant sur la LED.

La valeur du condensateur a été calculée de la façon suivante comme pour un filtre du premier ordre qui donnera la valeur moyenne de la mesure du courant

De façon à ne plus voir les instants auxquels le transistor est soit bloqué ou soit passant, il faut que la constante de temps soit très supérieure à la période d’hachage.

La période d’hachage vaut 1/Freqhachage=1/64kHz=0.0000156S, donc il faut une constante de temps très supérieure à 0.0000156S.

La constante de temps vaut t=R*C, si C=47uF, R*C=1*47=0.0000047S, ce qui est très supérieure à la période d’hachage. Donc on prend une valeur de 47uF pour le condensateur.

Voici le schéma

|500x489

Résultat obtenu en simulation :

On voit bien que maintenant le courant mesuré correspond au courant moyen du transitor avec un regime continu, donc les mesures effectuées à l’aide de l’Arduino seront cohérentes et grâce à cela il sera possible de faire la régulation du courant.

le courant dans la LED correspond à l’equation suivante I led=Imoyen transitor*255/PWM decimale

|500x332

Voici le schéma complet qui nous a permis de valider notre régulation avec le transistor canal N :

|500x346

1 Like

Suite à la réalisation du montage sur ISIS, il a été effectué différents tests tels que :

L'évolution du courant en fonction du rapport cyclique généré par la PWM grace à l'asservissement de courant avec une consigne de 1A. L Le temps de reponse est bien de 0.3s de la regulation, avec un coefficient integral de 10

Un programme qui envoies les données( Intensité du courant et rapport cyclique ) sur le terminal virtuel (UART ou USART) a été fait afin de pouvoir extraire et visualiser correctement l'allure du courant grâce au logiciel Excel. Sur l'image ci-dessous il y'a un terminal virtuel contenant les données qui seront utilisées pour tracer la courbe.

|500x346

Voici les données du terminal en fonction traiter dans Excel des mesures de la simulation. On peut observer que le courant est moyennement filtré ce qui provoque de légère ondulation autour de la consigne à la période d’échantillonnage de 0.1s ce qui provoque aussi des variations faibles de la sortie de régulation PWM.

|500x290

On retrouve bien le temps de 0.4s pour atteindre la consigne, comme dans Matlab Etant donné que la période d’échantillonnage est faible, la réponse échantillonnée est similaire à celle en continu.

voici le programme de l'asservissement

#include 
#include      //https://www.arduino.cc/en/Reference/SoftwareSerialBegin
#include 
#include        //chien de garde
//#include    //mise en veille
//#include 
#include "LowPower.h"     //https://github.com/rocketscream/Low-Power




#define BP3        2       // 
#define battery    A0      //relay magnetron



LiquidCrystal lcd(9, 8, 4, 10, 11, 7);   // LiquidCrystal lcd(rs, en, d4, d10, d11, d7);
// Configuration des variables


unsigned int temps=0, PWM2;    //temps de la routine d'interruption
byte  temps1=0,mode=1,PWM=255,Integralbyte;   
float I=0,Iled,erreur=0,kp=10,ki=10,Ic=1,Integral=150;



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


   Timer1.initialize(1000);           // initialize timer1, and set a 0,1 second period =>  100 000  pour 0.01s  10 000
   Timer1.attachInterrupt(callback);   // attaches callback() as a timer overflow interrupt
   lcd.begin(16, 2);                   //modifier pour un afficheur 20x4


   TCCR0B = (TCCR0B & 0b11111000) | 0x01;         //pin 5  64khz    http://playground.arduino.cc/Main/TimerPWMCheatsheet
                                            
   pinMode(A5, OUTPUT);
   pinMode(2, INPUT);
   analogWrite(5,255);
   attachInterrupt(digitalPinToInterrupt(2), interBP, LOW);   //routine d'interruption exterieur broche 2
   
   analogReference(INTERNAL);

  
}



// Interruptions  tous les 0.1s fait par le timer1***********************************
void callback()  {
 temps++;


}


//interruption exterieur front descendant de la broche 2
void interBP() {
//interrupts();
  mode++;                  //incrementation des modes 
  if (mode>3) mode=1; 

  switch (mode) {
  case 1:Ic=1;Integral=180;   break;   //donne un ordre de grandeur de la valeur de la PWM=255*(Rshunt*Ic-Useuil)/Ubattery
  case 2:Ic=0.75;Integral=240;   break;
  case 3:Ic=1.5;Integral=250;   break;
     }
   } 

   
void loop() {  
   SoftwareSerial serial(0,1);
   serial.begin(9600);
         
  if (temps>1)         //affichage tous les 100ms
  {
      // Lecture de la tension*2=courant car ll y a une resistence de mesure de 0.5ohm
      I=analogRead(A1);
      I=I*0.00215;     //I*1.1/(1024*0.5ohms)  i moyen transistor      
      Iled=(I*255)/PWM;
 erreur=Ic-Iled;

      lcd.setCursor(0,0); lcd.print(Ic);
      lcd.setCursor(0,1);lcd.print("Er=");lcd.print(erreur,1);
      lcd.setCursor(8,1);lcd.print("I=");lcd.print(I);
      


      //Correcteur PI; PWM=ki*Erreur/P********************************************************
      Integral= Integral+erreur*ki; 
      if (Integral>=255) Integral=255;
      if (Integral<=0) {Integral=0;}
      Integralbyte=Integral;
      
      PWM=Integralbyte;// Rapport cyclique inversé car le transistor est un Canal P
                        // Rapport cyclique entre 255(100%) et 0 (0%)
      serial.print(I); serial.print(";");    //
      serial.print(PWM2); serial.println(";");                 
      
      analogWrite(5,PWM);    //commande de la LED de puissance
    
      lcd.setCursor(8,0);
      PWM2=(Integralbyte*100)/255;
      lcd.print("PWM=");
      lcd.print(PWM2);
      lcd.print("%  ");
      
      temps=0;
}

   
} // fin loop

Les résultats obtenus sont corrects car la courbe possède les mêmes caractéristiques obtenu sur le logiciel MATLAB.

2 Likes

Suite à la commande en boucle ouverte des 3 leds de ce post du feb 09 2021 des tests on été fait pour ajuster la Commande PWM pour avoir le bon courant. En effet, l'inductance a été changé.

L'étude de ces leds est sur le lien suivant post sur du Mardi 16 Février sur le forum Vélorizontal, les graphes et équations pour la commande en PWM des LED 10mA à 120mA.

|500x291

La commande est faite en référence à la courbe ci-dessous : |500x309 On incrémente la PWM petit à petit en mode continu d'éclairage pour connaitre le courant pour une tension de batterie de 4.2V

|500x309

Mais la courbe précédente n'est pas très utile car l'on désire un courant constant de 10mA. par conséquent, c'est la courbe suivante pour connaitre la PWM en fonction de la variation de la tension batterie.

|500x309 A partir de la courbe précédente, voici l’équation permettant de contrôler le courant des diodes : PWM = (14*Iconsigne+1)*225/Vbatt.

Et voilà le programme de l'Arduino qui gère la led de puissance et les leds auxiliaires

#include  
#include    
#include 

float IconsigneP=0.1;
float IconsigneAux = 0.01;
float Imax=0;
float Res=0.22;   //resistance
float Tension=4.2;
float pourcetage;
float outregul1;

float T_3=4.2;
float T_2=4.2;
float T_1=4.2;     

float TF3;
float TF2;
float TF1;
float TF;
float TensionF;


int16_t temperat;
bool flagmesure=0;

uint8_t  counter=0;
int8_t  counter13=0;
int8_t  periode13=0;
uint8_t  counteraffichage=0;
uint8_t out=0;
uint8_t outregul=70;
uint8_t outregul2=70;
uint8_t out2=0;

uint8_t  timer=0;
uint8_t  heure;
uint8_t minuTe;   //déclaration minute
uint8_t seconde;  //déclaration seconde


float IconsigneMaxP = 0.7;
float IconsigneMinP = 0.1;

float IconsigneMaxAux = 0.12;
float IconsigneMinAux = 0.01;

uint8_t  mode=0;

char BluetoothData;
char BluetoothData2;

//SoftwareSerial BT(0, 1);   // RX, TX mais il n'y a pas trop le choix sur la nano //pas nécessaire de définir un objet serial sur l'UART existant


/*   https://docs.rs-online.com/c150/0900766b81414edd.pdf      registre datashhet mpu6050
     https://docs.rs-online.com/e2e2/0900766b81414ed9.pdf     specificiation
*/
void setup() {
pinMode(13, OUTPUT);    //test le temps de programme  //initilisable par le PCB
pinMode(12, OUTPUT);    //test le temps du flash      //initilisable par le PCB
//pinMode(3, OUTPUT);   //PWM 3 timer2  32KHz hachage //initilisable par le PCB
pinMode(5, OUTPUT);     //PWM 5 timer0  64KHz hachage

pinMode(6,OUTPUT);      //PWM LED auxiliaires
pinMode (3, INPUT_PULLUP);   //inutilisable par le PCB
pinMode (4, INPUT_PULLUP);   //inutilisable par le PCB
//pinMode(7, INPUT);         //inutilisable par le PCB

  Timer1.initialize(50000);           // initialize timer1, and set a 0,1 second period =>  100 000  pour 0.01s  10 000
  Timer1.attachInterrupt(callback);   // attaches callback() as a timer overflow interrupt

// TCCR2B = (TCCR2B & 0b11111000) | 0x01;       //pin 3  32khz    http://playground.arduino.cc/Main/TimerPWMCheatsheet
TCCR0B = (TCCR0B & 0b11111000) | 0x01;          //pin 5  64khz 

analogReference(INTERNAL) ;   //1.1V tension de refenrence inernal
//analogReference(DEFAULT) ;  // ne peut être utilisé étant donné que la tension d'alimentation est inférieure à 5 V et variable

outregul=100;   //mettre la PWM

minuTe=EEPROM.read(0);                //minute de fonctionnement de l'eclairage
heure = EEPROM.read(2);               //heure
if (minuTe==255)  {EEPROM.put(0, 0);}   //la premier fois FF donc ecriture à 0 minute et heure
if (heure==255)   {EEPROM.put(2, 0);}

mode=EEPROM.read(3);      //changement de mode
mode++;
if (mode==1) {IconsigneP=0.7;periode13=3;}
if (mode==2) {IconsigneP=0.5;periode13=10;} 
if (mode>=3) {IconsigneP=0.2;mode=0;periode13=19;}
EEPROM.put(3, mode);

//BT.begin(9600);
Serial.begin(38400);
}


// Interruptions  tous les 0.05s fait par le timer1***********************************
void callback()  {

//utilité à vérifier, car le pin 13 est lié à rien !!!
counter++;      //fonctionnement mode flash
if (counter<=1)  {out=outregul;digitalWrite(12,HIGH);}           //temps de 50ms, 
if (counter>=2)  {out=0;digitalWrite(12,LOW);}
if (counter>=19)  {counter=0;}            //temps de 1s                                                             

out2 = 200;
analogWrite(6,out);   //PWM 64kHz LED principale
analogWrite(5,outregul2);   //PWM LED auxiliaires en fonctionnement continu

//utilité à vérifier, car le pin 13 est lié à rien !!!
counter13++;      //fonctionnement mode flash
if (counter13<=1)  {digitalWrite(13,HIGH);}          //temps de 50ms, 
if (counter13>=2)  {digitalWrite(13,LOW);}
if (counter13>=periode13)  {counter13=0;}            //periode variable  


counteraffichage++;
if (counteraffichage>=4)  {flagmesure=1;counteraffichage=0; }  //perdiode d'affichage 0.2s       2

timer++;
if (timer>=19 && Tension>3.1)  {    
      seconde++;timer=0;        //etude temps de fonctionnement                                             
      if(seconde >= 60){seconde =0;  minuTe++; EEPROM.put(0, minuTe);        //EEPROM.write(address, value)
          if(minuTe >= 60){ minuTe =0;  heure++;EEPROM.put(2, heure);    }   } } //pas grave que 24h soit depassé
                                
}//fin callback


//**********************************
void loop() {



if (flagmesure==1)   {
//digitalWrite(13,HIGH);                 //duree 20ms
Tension=analogRead(A7);   //10bit
Tension=(Tension*1.1*4.21)/1024;                //4.21 correspond au pont diviseur

T_3=T_2;
T_2=T_1;      //recurence n-2
T_1=Tension;  //recurence n-1

TF3=TF2;
TF2=TF1;
TF1=TF;

TF=Tension+3*T_1+3*T_2+3*T_3+0.278059*TF3-1.18289*TF2+1.76*TF1;   
//filtre numerique passe bas Fc=0.5s 3eme ordre  de la mesure de la tension fe=5Hz  periode0.2s
TensionF=TF/69;        //55 en theorie

pourcetage=83*TensionF-250;                       //a=(100-0)/(4.2-3)=83.33   b=-250


if (TensionF>=3.5) {
  outregul1 = (((1.6*IconsigneP+1.9)/TensionF)*255);     //mettre la PWM
  outregul2 = (((14*IconsigneAux+1)/TensionF)*255);     //PWM LED auxiliaires 
  if (outregul1>255) {outregul1=255;} 
  if (outregul1<70) {outregul1=70;}
  
  if (outregul2>255) {outregul2=255;} 
  if (outregul2<70)  {outregul2=70;}   
  
  outregul=outregul1;}
if (TensionF<3.5) {IconsigneP=0.3;}
if (TensionF<=3.1) {outregul=0;}  

//envoie des données en bluetooth
Serial.print("*O"+String(outregul)+"*");  
Serial.print("*F"+String(outregul2)+"*");
Serial.print("*P"+String(pourcetage)+"*");
Serial.print("*T"+String(TensionF,2)+"*");
Serial.print("*I"+String(IconsigneP,1)+"*");
Serial.print("*R"+String(IconsigneAux,2)+"*");
Serial.print("*m"+String(minuTe)+"*");
Serial.print("*h"+String(heure)+"*");
Serial.println();
//Serial.print("test"); //debug
flagmesure=0;
//digitalWrite(13,LOW);     
}


if (Serial.available()){
  BluetoothData = Serial.read();        //Get next character from bluetooth


if (BluetoothData == 'A') IconsigneP = IconsigneP + 0.1;
if (BluetoothData == 'B') IconsigneP = IconsigneP - 0.1;

if (BluetoothData == 'a')IconsigneAux = IconsigneAux + 0.01;
if (BluetoothData == 'b')IconsigneAux = IconsigneAux - 0.01;


if(BluetoothData == 'H' or BluetoothData2 == 'H') {seconde = 0;minuTe = 0;heure = 0;}      //remise à zero
BluetoothData = 0; 
  }

if(IconsigneP > IconsigneMaxP) IconsigneP = IconsigneMaxP; 
if(IconsigneP < IconsigneMinP) IconsigneP = IconsigneMinP;

if(IconsigneAux > IconsigneMaxAux) IconsigneAux = IconsigneMaxAux; 
if(IconsigneAux < IconsigneMinAux) IconsigneAux = IconsigneMinAux;  


}//fin loop
2 Likes

Etude d’une LED 65cd 50mA, 8° vendu par farnell. Ci-dessous vous trouverez le Lien de farnell avec la datasheet de la LED. farnell : https://fr.farnell.com/vishay/vlcs5830/led-aec-q101-5mm-rouge-65cd-624nm/dp/2889660?ost=2889660 Datasheet : https://4donline.ihs.com/images/VipMasterIC/IC/VISH/VISHS87555/VISHS87555-1.pdf?hkey=6D3A4C79FDBF58556ACFDE234799DDF0

La Jonction de la LED peut supporter une température de 92°C comme nous pouvons voir sur le calcul ci-dessous : T° jonction =T° Ambiant+RTHja*Power=20°C+300*(2.4V*0.1A)= 92°C

Ci-dessous les photos de son éclairage à 40cm. On peut observer que l’intensité lumineuse est légèrement plus faible au centre que sur les côtés. Le demi angle correspond bien au donnée constructeur de Atan(rayon eclairage/distance) =Atan(4cm/40cm)=5.7°

|409x500

|500x225

D’ailleurs, sur la courbe suivante, on peut observer les lux en fonction du rayon.

|500x407

Pour avoir le lumen total nous avons utiliser la relation suivante ( L2+L3*8 )0,02*0,02 (qui correspond à la somme (du lux à la surface 0 et du demi côté de 0 à 4cm) 8 (correspond aux 8 points du capteur)*la surface du capteur)

Voici l’intensité lumineuse à 40cm en fonction du courant On peut observer que l’intensité est maximum à 0.2A.

|500x244

1 Like

Ci-dessous vous trouverez l’image 3D du PCB et le lien pour télécharger les fichiers ISIS du schéma électrique ainsi que le typon(PCB) : TR ECLAIRAGE - Google Drive

Voici quelques mesures de courant en pratique.

Graphique pour C=220uF
Grâce au comportement du condensateur, le courant n’arrive pas à 0, en revanche le courant n’est pas en régime continu.

Graphique pour (C1+C2=440uF)

Il est maintenant remarquable qu’avec une constante de temps qui est deux fois plus grande que celle du graphique antérieur, le courant en fonction du temps se rapproche du régime continu.

2 Likes

Il n’y a pas qu’une seule solution pour réaliser un éclairage vélo……et pour faire sa commande, il va falloir faire une synthèse dans des dossiers

D’ailleurs, voici encore une nouvelle solution avec un TTGO+OLED Pour que le OLED du TTGO, il faut prendre la bibliothèque tft espI sur ce lien et pas ailleurs, sinon cela ne fonctionne pas https://github.com/Xinyuan-LilyGO/TTGO-T-Display Lorsque la bibliothèque est installée, il y a de nombreux exemple que l’on retrouve dans le compilateur IDE Arduino [](https://servimg.com/view/17563517/9753)https://i89.servimg.com/u/f89/17/56/35/17/a211.png[/img][/url[/iurl]] LE TTGO est alimenté par un TP4054 qui permet de charger la batterie à 0.4A

https://datasheetspdf.com/pdf/1090540/NanJingTopPower/TP4054/1 Le régulateur de tension entre la tension Vin et la tension 3.3V AP2112. il peut supporter un courant de 0.6A et peut fonctionner pour une tension de 5V à 3V pour alimenter l’ESP32 https://www.mouser.fr/datasheet/2/115/AP2112-271550.pdf Le TTGO avec l’OLED demande un courant d’environ 0.06A sur la tension d’entrée Vin Le schématique du TTGO peut être téléchargé sur ce lien https://github.com/Xinyuan-LilyGO/TTGO-T-Display/blob/master/schematic/ESP32-TFT(6-26).pdf Voici le schéma électrique de notre TTGO ou le transistor mos est command able en 3.3V |500x305 Voici le PCB avec le logiciel ARES Proteus électronique pour commander l’éclairage

|500x318 Voici juste le programme qui permet d’écrire sur le OLED

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

#include "BluetoothSerial.h"
BluetoothSerial SerialBT;

TFT_eSPI tft = TFT_eSPI();  //library   1,4" color 135, 240
#define TFT_GREY 0x5AEB // New colour

String lire;
String myChar;
int a;

const int ledPin32 = 32;       //
const int ledChannel = 2;
float tension;



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();
}

void setup() {
  pinMode(33, OUTPUT);
  pinMode(2, INPUT);   

 Serial.begin(9600);

 SerialBT.begin("ESP32test"); //Bluetooth device name

    
 tft.init();
  tft.setRotation(0); //format portrait a l'endroit
    tft.fillScreen(TFT_BLACK);     
   

   tft.setCursor(0, 0, 2);// (x,y,taille)

  tft.setTextColor(TFT_WHITE,TFT_BLACK);  
  tft.setTextSize(1); //(taille)
  
  tft.println("IUT GEII Soissons");

  tft.setCursor(0, 16, 4);  //taille paire
  tft.setTextColor(TFT_RED,TFT_RED); //(couleur police,background police)
  tft.setTextSize(1);
  
  tft.println("Light Rear");
  tft.setTextColor(TFT_WHITE,TFT_BLACK);  
  tft.setTextSize(1); //(taille)

ledcSetup(ledChannel, 78000, 10);     //PWM 78kHz  10bits
ledcAttachPin(ledPin32, ledChannel);  //broche 32 et 22 Ok  36,37 ne fonctionne pas


adc1_config_width(ADC_WIDTH_BIT_12);
//adc1_config_channel_atten(ADC1_CHANNEL_0,ADC_ATTEN_DB_2_5);   // input voltage of ADC will be attenuated, extending the range of measurement to up to approx. 1100 mV????  5V
    
}

void loop() {
  if ( digitalRead(33)== 1 ) {digitalWrite(33,0);}  else {digitalWrite(33,1);}   //time loop 1ms
//digitalWrite(33,1);
ledcWrite(ledChannel, 512);         //ledcWrite(Channel, dutyCycle);   PWM=1 1024


tension=analogRead(2);          //https://randomnerdtutorials.com/esp32-adc-analog-read-arduino-ide/
tension=(tension*5)/4096;      //12bits     analogSetSamples (8)    https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/adc.html
tft.setCursor(0, 40, 2);// (x,y,taille)
tft.print(tension,2);

tft.setCursor(0, 60, 2);// (x,y,taille)  
a++;
tft.println(a);
//SerialBT.print(a); 
//Serial.print(a);

//digitalWrite(33,0);

/*
  while (SerialBT.available()) {       //lit une chaine
  lire=(SerialBT.readString());        //reception en char avec string oled pour affichage correcte mais un seul
  myChar=lire+1;                       //accusé de receptionen rajoutant 1
  SerialBT.print(myChar);      //ecrit au terminal bluetooth 
  } 
*/  
  
 // espDelay(10000);
}//fin loop

|500x292 Le oled peut permettre de dire le temps de fonctionnement restant en fonction de la mesure de la batterie, peut communiquer en Bluetooth sans utiliser de HC 06. Un des boutons peut permettre de gérer la consigne et la mise en veuille de l’éclairage.

Le codage doit aussi gérer la batterie lithium et ce mettre en veuille profonde si la tension batterie est inférieur à 3.2V pour ne pas décharger trop la batterie

Mais quelle est la consommation du TTGO pour connaitre l’autonomie de l’eclairage ? Sachant que les consommation theoriques sont sur ce lien

[Tuto] : Les sleep modes de l’ESP32 (letmeknow.fr)

1 Like

[u]Comment choisir une led chez un distributeur(Farnell, radiospare…)?[/u] [u]Quelles sont les caractéristique entre une led rouge dite de puissance et de faible puissance ?[/u]

Les leds de faible puissance sont inférieures à 75mA chez les fournisseurs. Il y a des mots clefs (fabricant,couleur,intensité lumineuse (candela/lumen),CMS ou a trou, diamètre de la led, courant nominal, tension de seuil, angle de vision) Voici une recherche de led faible puissance. |500x208 Pour réaliser un éclairage arrière de vélo pour être vue de près sur les cotés un led de diamètre de 5mm suffit. Avec un angle de 8° Voici la led qui a le plus d’intensité lumineuse(65 candela) qui demande un courant de 50mA. |500x285 ces fournisseurs nous donne toujours les datasheets voici son liens : [u]https://4donline.ihs.com/images/VipMasterIC/IC/VISH/VISHS87555/VISHS87555-1.pdf?hkey=6D3A4C79FDBF58556ACFDE234799DDF0[/u] La conversion candela lumens est donné par l’équation suivante : Lumens = candela*2π(1-cos(Angle(π/180)) Lumens = 65*2π(1-cos(8(π/180)) Lumens = 130π(1-cos(8(π/180)) Lumens = 4 lumens Donc les lumens par Watt sont de 4/(2.2*0.05)= 36 lumens/W Ce qui est honorable sachant que a ce jour il n’est pas possible de dépasser les 50 lumens/W

Exemple les lux à 1m sera déterminer par l’équation suivante : Lux= (lumen*2)/(π(distance*tan(Angleπ/180))² = 128 Lux La température de jonction Tj= Temp ambiant+ Rthja*Puissance = 20+300*(2.2*0.05) = 53°C Est-ce qu’il est possible que cette led puisse fournir plus d’intensité lumineuse ? Voici la courbe des candela relative en fonction du courant sachant que pour 50mA on a 65 candela.

|474x269

Le point rouge ici présent représente les 100% de la led, mais on peut voir qu’on peut augmenter au-dessus de 100% comme ici avec le point voir qui a doublé donc on passe de 65 lumens à 130 lumens.

Sur la courbe données par le constructeur, il est possible d’alimenter la led en 100mA pour 120 candela (point vert). Mais sa durée de vie sera plus courte car la température de jonction sera plus importante : Tj= Temp ambiant+ Rthja*Puissance = 20°C+300*(2.4V*0.1A) = 92°C

Mais on a pas le MTBF en fonction de la température. Pour être vue à plus de 150m de jour, une led de 3W suffit. Mais ces leds ont un angle de 120° comme on peut l’observer sur les caractéristique du fournisseurs : |500x160 Voici le lien de la datasheet de la led cree qui fait 39 pages. Mais avec toutes les couleurs possibles. [u]http://www.farnell.com/datasheets/2574140.pdf[/u] |500x225 Le courant nominal est de 350mA |500x220 Nous avons déjà les lumens grâce au donnée constructeur qui est de 80.6 lumens.

Donc avec un exemple de lux à 10m on a: Lux= (lumen*2)/(π(distance*tan(Angleπ/180))² =0.36 Lux Par conséquent, il faut une optique qui concentre l’éclairage sur 4 ou 5°. La température de jonction Tj= Temp ambiant+ Rthja*Puissance. Tj=25+5°C/W*3W=40°C On peut faire une comparaison de la puissance en fonction du prix et une autre des lumens en fonction du prix. (Courbe faites en fonction de la led de puissance) Donc on a fait les 2 courbes ci-dessous :

|500x304

Figure 1: Courbe du Prix en fonction de la Puissance |500x302

Figure 2 : Courbe du Prix en fonction des Lumens

[u]Conclusion :[/u] Ce n’est pas si facile de trouver une led et cela prend beaucoup de temps à chercher chez les constructeurs. Avec les courbes (figure 1 et 2), on peut remarquer que le prix est en fonction du nombre de vente et non en fonction de l’efficacité de la led. Il y a une obsolescence rapide et une indisponibilité rapide des leds.

Évidemment sur aliexpress les caractéristique sont faibles et pas fiables. Par conséquent, il faut acheter quelqu’une et faire des mesures pour vérifier leurs données.

2 Likes

L'utilisation de la veille est fortement recommandée pour pouvoir garder de l'energie plus longtemps dans une batterie.

En mode deep_sleep le TTGO consommera 5mA alors qu'en fonctionnement il consomme en moyen 20mA avec le programme ci dessous sachant qu'il y a un delay de 500 ms qui tourne en boucle pour eviter que l'OLED se rafraichisse tout le temps au niveau du code. Sans le delay, la consommation passe à 120mA sans utiliser le OLED et 150mA avec le OLED et peut importe la couleur de fond

aavec le code suivant, pour mettre en veuille, il suffit d'appuyer sur le bouton 1 du TTGO

  #include 
#include 

TFT_eSPI tft = TFT_eSPI();  // Invoke library

   #define BUTTON_1            0    //fonctionne à 0L
   #define BUTTON_2            35// fonctionne à 0L et définir le BP en entrée au préalable en input
   int count=0;

   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();
}

void setup() {
    tft.init();
    tft.setRotation(0); //format portrait a l'endroit
    Serial.begin(115200);
    //Serial.println("setup");
    pinMode(BUTTON_2, INPUT_PULLUP);
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_35,LOW);    //gpio_num: Numéro GPIO utilisé comme source de réveil. Seuls les GPIO dotés de la fonctionnalité RTC peuvent être utilisés: 0,2,4,12-15,25-27,32-39.
    tft.fillScreen(TFT_BLACK);
}

void loop() {
  if (!(digitalRead(BUTTON_1))){    //bouton1 actif à 0L
      esp_sleep_enable_timer_wakeup(120000000); //120 seconds
      /*int ret = esp_light_sleep_start();
      Serial.print("light_sleep:");
      Serial.println(ret);*/
      
      esp_deep_sleep_start();
      //esp_light_sleep_start();
      }
      count++;
   
   tft.setCursor(0, 0, 2);// (x,y,taille)
  // put your main code here, to run repeatedly:
  tft.setTextColor(TFT_WHITE,TFT_BLACK);  
  tft.setTextSize(1); //(taille)
  
  tft.println(count);

  espDelay(500);
  
    
}

5mA en deep sleep sur l'entree d'alimentation 5V, on est loin des 10micro ampere annoncé ????? comment mesurer la tension de la batterie et déterminer le temps restant de fonctionnement ?

2 Likes