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

Voici une publication pour les choix de la programmation d’un éclairage arrière de 3W avec Arduino qui reprend toutes les problématiques de ce post

Les leds de puissance doivent être régulé en courant par l’intermédiaire d’un hacheur
Voici 2 articles scientifiques qui en parlent

Sur ce forum, il est possible de commander tous les éléments pour créer son éclairage
http://velorizontal.bbfr.net/t16874p525-eclairage-a-del-pour-velo-led-light-for-bike-light-emitting-diode

Dans un premier temps, nous allons voir comment gérer un éclairage arrière qui est constitué d’une led principale de 3W et de 3 petites leds de 0.1W.
Un BP poussoir permet de gérer les différentes puissances et le clignotement par une routine d’interruption extérieure. Ce BP permettra de mettre en veille et reveiller l’Arduino.
Un afficheur LCD est utilisé juste pour verifier la programmation.
2 batteries 2.5A.H série 18650 seront utilisées pour alimenter la carte Arduino et le hacheur qui fera varier le courant dans la led.
L’affichage de l’état de charge SOC (state of charge) est déterminé approximativement en fonction de la tension OCV (open circuit voltage) par linéarisation.

Avec la pente a et b correspondant à l’équation suivante sachant que pour Umax=8.4V le SOCmax sera de 100% et pour Umini=6V pour SOCmini de 5%:

Un capteur de température LM35 permettra de diminuer de mode, si la température du dissipateur de la led devient trop grande à cause de la température ambiante.

On peut observer sur la figure suivante la liste des entrées sorties et la simulation sous ISIS qui est telechargeable sur ce lien.

Voici l’Algo pour gérer la led de 3W

Routine interruption toutes les 1ms qui permet de gérer le temps

Routine d’interruption extérieur par le bouton poussoir active les diffèrent mode de 0 à 6.
Mode 0 :  (0A)
Mode 1 : régulation de courant led P 0.35A (0.75W) mais clignotement de toutes les leds avec une période de 1s et un rapport cyclique de 0.4.
Mode 2 : régulation de courant  led P 0.7A (1.5W) avec clignotement
Mode 3 : régulation de courant led P  1.4A  (3W) avec clignotement
Mode 4 : régulation de courant led P 0.35A (0.75W) sans clignotement
Mode 5 : régulation de courant  led P 0.7A (1.5W) sans clignotement
Mode 6 : régulation de courant  led P 1.4A (3W) sans clignotement

Main
Tous les 100ms
Affichage du courant de consigne
Mesure du courant et réajustement de la PWM pour avoir le courant désiré
Mesure de la tension de 2 batterie lithium série dont la tension varie de 8.4V (100% chargé) à 6V (0% de charge)
Affichage de l’état de charge avec 4 leds
Mesure de la temperature
Si la température est supérieure à une certaine temperature minimisation de puissance

le programme en Piece Jointe

Perspectives :
Pour préserver la durée de vie de la batterie
Lorsque l’état de charge sera inférieur à 40% alors le mode 4 sera activé
Lorsque l’état de charge sera inférieur à 30% alors le mode 1 sera activé
Lorsque l’état de charge sera inférieur à 10% alors l’éclairage sera éteint et l’Arduino en veuille.

Utilisation d’un mode veuille, pour minimiser la consommation de l’Arduino lorsque l’éclairage n’est pas activé pour ne pas mettre d’interrupteur entre l’Arduino et la batterie.

Gérer un accéléromètre qui détectera si le vélo ne bouge plus et dans ce cas au bout de 2 minutes, il éteindra la lumière et se mettra en veuille
un capteur MPU6050 pourra etre utilisé

Réguler le courant de 3 leds rouge à 0.2W pour avoir une puissance lumineuse constante et ne plus avoir de perte d’énergie dans la résistance de limitation de courant R3.

le driver CH340 de nos arduinos peut etre telechargé ici

led_velo_nano.ino (4.75 KB)

1 Like

Pour un courant led de 3A, la puissance utile dans une led blanche qui a une tension de seuil de 3V
P=tension de seuilIled=3V3A=9W

Pour ce courant de 3A, les pertes dans le transistor bipolaire PNP TIP127
P=Vce satIledPWM=1V3A0.5=1.5W sachant que la PWM varie en fonction de la tension de la batterie
La puissance dans le diode de roue libre est egale à l’equation suivante
P=Ud seuilIled(1-PWM)=0.3V3A(1-0.5)=0.45W

Ces 2 puissances sont relativement important par rapport à la puissance utile dans la led.

Donc, pour ameliorer les performances du hacheur, pour augmenter l’autonomie de l’eclairage et pour minimiser l’encombrement des dissipateur, un transistor MOS surdimensionné a été choisi

En appliquant filtres dans farnell, le transistor FDD4243 a été choisi en fonction de son prix faible et de ces performances
https://fr.farnell.com/on-semiconductor/fdd4243/mosfet-canal-p-40v-14a-to-252/dp/2323170

Le FDD4243 pouvant supporter 23A avec une résistance RDS on=0.036Ω pour 0.25€ boitier CMS TO252.
La résistance thermique jonction ambiant d’un boitier to252 simple couche est de 132°C/W

Donc la puissance max dissipable sans dissipateur
Pdissipable=(TJontoin max-Tambiante)/RTHja=(150-25)°C/ 132°C/W)=1Watt
Avec une surface de cuivre de 200mm^2, alors la resistance RTHJA=70°C et permettra de dissiper 2W.

Alors qu’un boitier TO220 a une résistance thermique environ 62°C/W aurait été plus facile à utiliser mais le prix minimum est de 0.85€ pour le transistor IRF9540.

https://fr.farnell.com/infineon/irf9540npbf/trans-mosfet-canal-p-to-220-100v/dp/8648620?MER=sy-me-pd-mi-alte

Mais quel est la puissance que devra dissiper le transistor ?
La puissance théorique perdue dans ce transistor FDD4243 sans prendre en compte les pertes à la commutation
P=Rds onIled^2 PWM =0.123A^2PWM =1.35W, il faudra
Les pertes à la commutation théorique sont négligeables comme on peut l’observer sur la figure suivante
P=Ubattery* Iled*(trise+tfall)FrequenceHachage/2=8V3A*(26+14)10^-932khz/2=0.015W

Le choix de la diode Switch-mode Power Rectifier ,
MBRS320T3G supportant 4A en boitier DO-241 à 0.14€ pourrait etre utilisé.
https://fr.farnell.com/w/c/semiconducteurs-composants-discrets/diodes/diodes-schottky/prl/resultats?courant-if-moy-=4a&st=diode%204A&sort=P_PRICE

Mais une MBRD835LT4G supportant 8A en boitier TO-252 à 0.2€ est plus pertinent car elle chauffera moins

Avec le transistor MOS, le courant dans la led, n’est plus le meme en fonction de la PWM.
Un réajustement des valeurs du correcteur integral a du etre fait.

Pour la mise en veuille, on a utilisé la bibliothèque low-power,

Le réveil se fait par interruption extérieur en mode 5.
Mais, pour réactiver le timer1, on a du faire un reset par l’intermédiaire de la biblioteque wachdog avr/wdt.h.
on aurait pu aussi réactiver le timer1, en faisant un reset par l’intermédiaire de la sortie A5 q

L’algorithme a donc changer

Timer1 Routine interruption toutes les 1ms qui permet de gérer le temps

Routine d’interruption extérieur par le bouton poussoir active les diffèrent mode de 0 à 5.
Mode 1 : régulation de courant led P 0.35A (0.75W) mais clignotement de toutes les leds avec une période de 1s et un rapport cyclique de 0.4.
Mode 2 : régulation de courant  led P 0.7A (1.5W) avec clignotement
Mode 3 : régulation de courant led P  1.4A  (3W) avec clignotement
Mode 4 : mode 4
Mode 5 : reset

Main
Si mode 4 mise, arret PWM et mise en veuille de l’arduino

Tous les 100ms
Affichage du courant de consigne
Mesure du courant et réajustement de la PWM pour avoir le courant désiré
Mesure de la tension de 2 batterie lithium série dont la tension varie de 8.4V (100% chargé) à 6V (0% de charge)
Affichage de l’état de charge avec 4 leds
Mesure de la temperature
Si la température est supérieure à une certaine temperature minimisation de puissance

un lien pour telecharger le fichier ISIS

Perspectives :

Si la connaissance de l’état de charge des batteries est facilement déterminée pas la tension avec les éléments 18650 li-ion, ce n’est pas possible de le faire avec des batteries Lipofer car la tension reste constante malgré la diminution du SOC
Par conséquent, la consommation du courant doit être déterminée (A.h). Or dans ce cas, la résistance de mesure du courant dans la led doit se faire mais aussi celle absorbée par l’Arduino.
Donc, la mesure du courant doit se faire avec une résistance shunt sur l’alimentation avec des ponts diviseurs à la place de le faire sur la masse.

Il est serait idiot que l’Arduino gère la charge des 2 batteries.
En effet, Le chargeur extérieur étant limité à 1A avec une tension identique à la tension seuil des 2 éléments donc 8.4V, donc ce n’est pas valable de réguler le courant de charge avec l’Arduino.
De plus, un BMS est obligatoire pour d’équilibrer les 2 cellules, mais aussi arrêter l’alimentation du système si la batterie est trop déchargée pour ne pas la détruire

Attention avec le programme suivant, si les 3 leds sont commandé par la PWM broche 11 et si leur puissance lumineuse peut varier grâce à la PWM, il y a toujours les pertes dans la résistance R3 de limitation de courant. Pour ne plus avoir ces pertes, il faut obligatoirement réaliser un hacheur abaisseur.

En mode 3, ou la puissance de la led est la plus importante, à la place de réguler le courant à 1.5A, il serait possible de réguler la température à 90°C ce qui permettrait d’avoir la puissance lumineuse

Mais tous ceux-ci seront d’autres histoires….

led_velo_nano.ino (5.27 KB)

Salut.

Aurais-tu un schéma plus précis ? Dans ton code je vois que tu utilises la référence VCC pour la mesure de la batterie. Je suppose que tu alimentes l'ARDUINO à travers un régulateur ?

Question : pourquoi une NANO alors qu'une PRO MINI serait bien plus économe en énergie ?

@+

la batterie alimente directement la tension Vin de l’arduino par l’intermédiare du regulateur interne de l'arduino LM2940 fournit le 5V.

j’ai modifié le programme dans le post précedent et isis.... et ajouté, un lien pour telecharger le fichier ISIS

Nous avons utilisé l’arduino nano, car nous en avions d’avance……

Mais très bonne idée, dans la version finale d’utiliser la version pro mini que je ne connaissais pas…. Car la différence de consommation entre le pro mini et l’Arduino nano….doit etre de 15mA car le pro mini n’a pas le convertisseur USB RS232

Car la différence de consommation entre le pro mini et l'Arduino nano….doit etre de 15mA car le pro mini n'a pas le convertisseur USB RS232

Exactement.

J'ai réuni pas mal d'infos ICI au sujet de la PRO MINI : - réduction de la consommation - mode veille - chargement - etc. Il y a des versions 5V ou 3.3V.

1 Like

Génial, le site et la consommation, superbe travail https://riton-duino.blogspot.com/2018/02/arduino-pro-mini-basse-consommation.html

si j’ai bien compris, la carte arduino et mini peuvent fonctionner sans regulateur de 1.8V à 5.5V donc sur la plage de tension dune batterie lithium qui varie de 4.2V à 3.3V. et cela permet de minimiser la consommation car le regulateur demande 5mA. Dans ce cas, les 2 batteries lithium ion 18650 devrait etre mis en //. Par contre, il va falloir utiliser une tension de reference pour la Conversion analogique si la tension d'alimentation change. il faut changer de capteur de temperature LM35 qui a besoin de 4V minimum par une PT1000

Suite aux perspectives précédentes, la led peut être commandé en régulation de température ce qui permet de la commander pour le maximum de sa puissance.

Le schéma automatique de la régulation de courant qui s'imbrique dans la regulation de température est le suivant : |500x153

Exemple : La consigne de température maximum du dissipateur a été choisi de 100°C sachant le dissipateur ou est placé la led est de 15°C/W à 0km/h mais passe à 7°C/W avec une vitesse de 20km/h. Donc avec une température ambiante de 25°C, la puissance maximale dans la led en fonction de la vitesse sera de Pmax=(100°C-25°C)/15°C/W=4.33W à la vitesse de 0 km/h Pmax=(100°C-25°C)/7°C/W=10W à la vitesse de 20 km/h

La température de jonction de la led avec sa résistance thermique de 3.5°C/W sera de Tjonction=Tboitier+ Pmax*RTHjc=100°C+10W*3.5=135°C Mais la température de jonction peut atteindre 150°C/W

La régulation de température n’est pas trop compliquée à programmer. Par contre, le coefficient intégral est à modifier par rapport à celui du courant. Car si la température de la led est au départ de 30°C pour atteindre les 100°C alors la Puissance admissible par la led precedente sera tres vite dépassé. Il faut donc limiter le courant à une certaine valeur pour ne pas detruire la led car la regulation precedente augmentera inutilement la PWM, aisni que le courant

voici le code de la programmation

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



#define led0     10       // 
#define led1     A4       // 
#define led2     12       // 
#define led3     13       // 13      
#define BP3        2       // 
#define battery    A0      //relay magnetron



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


unsigned    int temps=0;    //temps de la routine d'interruption
            byte  temps1=0;
            byte mode=1;    // etat du bouton poussoir
            float Ic=0.35;   // courant de consigne
            float Ba=0;   //tension batterie
            byte SOC=0;  //etat de charge en pourcentage
            byte barreled=0;    
            byte PWM=0;   
            float I=0;   //courant led principal
            float erreur=0;   //courant led principal
            float kp=10;        //coefficient proportionel integral
            float ki=4;
            float Integral=34;
float   T=0;     //temperature
float   Tc=80;   //consigne de temperature 
float  erreurT=0;



// the setup function runs once when you press reset or power the board
void setup() {
//  digitalWrite(A5,HIGH);
//   delay(200); 


pinMode(led0, OUTPUT);   //
pinMode(led1, OUTPUT);   //
pinMode(led2, OUTPUT);   //
pinMode(led3, OUTPUT);   //led carte arduino
pinMode(3, OUTPUT);      //PWM
pinMode(11, 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
 // Serial1.begin(9600); 

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

  pinMode(2, INPUT);
  attachInterrupt(digitalPinToInterrupt(2), interBP, LOW);   //routine d'interruption exterieur broche 2
//wdt_enable(WDTO_15MS);
}



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

  //if ( digitalRead(LEDV)== 1 ) {digitalWrite(LEDV,LOW);}  else {digitalWrite(LEDV,HIGH);}
//wdt_reset();
}//fin routine


//interruption exterieur
void interBP() {
//interrupts();

mode++;                  //incrementation des modes
if (mode>=6) mode=1; 

  switch (mode) {
  case 1:Ic=0.35;Integral=34;   break;   //donne un ordre de grandeur de la valeur de la PWM=255*(Rshunt*Ic-Useuil)/Ubattery
  case 2:Ic=0.75;Integral=43;   break;
  case 3:Tc=80;Ic=1.5;   break;
  case 4:analogWrite(3,0); analogWrite(11,0);digitalWrite(led0,LOW);digitalWrite(led1,LOW);digitalWrite(led2,LOW);digitalWrite(led3,LOW);  break; //puis mise  en veuille
  case 5: wdt_reset();    break;   //remise à zero    https://www.instructables.com/id/two-ways-to-reset-arduino-in-software/
     }
                               
   }


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


if (mode==4)  {lcd .clear ();LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);}
           //   LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
           //mode veuille



if (temps>1)         //affichage tous les 100ms
{
Ba=analogRead(A0);     //mesure tension
Ba=Ba/79;              //
SOC=40*Ba-233;    // cacul de l'etat de charge 
lcd.setCursor(0,1);   //colonne, ligne
lcd.print("SOC");
lcd.print(SOC);
barreled=(SOC/18)-1;    

  switch (barreled) {
  case 0:digitalWrite(led0,LOW);digitalWrite(led1,LOW);digitalWrite(led2,LOW);digitalWrite(led3,LOW);     break;               //valeur deu courant dans la led principale
  case 1:digitalWrite(led0,HIGH);digitalWrite(led1,LOW);digitalWrite(led2,LOW);digitalWrite(led3,LOW);   break;
  case 2:digitalWrite(led0,HIGH);digitalWrite(led1,HIGH);digitalWrite(led2,LOW);digitalWrite(led3,LOW);   break;
  case 3:digitalWrite(led0,HIGH);digitalWrite(led1,HIGH);digitalWrite(led2,HIGH);digitalWrite(led3,LOW);   break;
  case 4:digitalWrite(led0,HIGH);digitalWrite(led1,HIGH);digitalWrite(led2,HIGH);digitalWrite(led3,HIGH);   break;          }

I=analogRead(A1);
I=I/102;
lcd.setCursor(7,1);
lcd.print("I=");
lcd.print(I,1);

  
T=analogRead(A2);   //mesure temperature
T=T/2;
lcd.setCursor(13,1);
lcd.print(T,0);
lcd.print(" "); 

if ((T>90) && (mode==2)) {erreurT=Tc-T; Ic=Ic+erreurT*0.05;}    //diminution du courant si la temperature atteint 90°C
if (mode==1 || mode==2 )  {lcd.setCursor(0,0);lcd.print("I"); }    //limitation du courant à cause de la  temperature

              
if (mode==3) {erreurT=Tc-T; Ic=Ic+erreurT*0.05 ;lcd.setCursor(0,0);lcd.print("T");}  // regulation temperature
if (Ic>=2) {Ic=2; }             // limitation du courant de la consigne
if (Ic<=0.35) {Ic=0.35; }      

lcd.setCursor(1,0); 
lcd.print(Ic);
erreur=Ic-I; 

//Proportionnel=kp*erreur;
//derive=(erreur-erreurP)*kd;             //derive=(erreur-erreur*Z^Ts)/Ts   avec Ts=Tsampleur
//output=Proportionnel+Integral;   //ce n'est pas la peine de divisée par Ts car si Ts est petit cela donne des valeurs enormes 
Integral= Integral+erreur*ki;
if (Integral>=255) Integral=255;
if (Integral<=0) {Integral=0;} 
PWM=Integral;
if (Ic==0) {PWM=0;}  

lcd.setCursor(7,0);
lcd.print("PWM=");
lcd.print(PWM);
lcd.print("  ");
analogWrite(3,PWM);    //broche et valeur PWM
//analogWrite(11,127);


temps1++;
if (temps1<2)  {analogWrite(11,255);          }
if (temps1>2)  {analogWrite(11,0);temps1=0;   }
               


temps=0;
}//temps>100

   
} // fin loop

Perspectives :

On pourrait aussi faire un mode qui gere l’eclairage en fonction de la lumière extérieure en mettant un capteur LDR sur le dessus de l’éclairage. En effet en plein jour cela permettrait de couper l’éclairage. Attention, parfois on veut meme en plein jour ce faire voir. Donc, il faut garder les anciens modes.

Maintenant que le programme est effectué l’afficheur LCD peut etre retiré. Etant donné que l’on a plus des sorties non utilisées, les 8 leds du barled pourraient etre utilisées sachant que leur consommation est dérisoire par rapport à la led de puissance

De plus à la place du LCD, la liaison serie pourrait exporter les dynamiques de la regulation de courant et de temperature pour optimiser la commande.

1 Like

il faut changer de capteur de temperature LM35 qui a besoin de 4V minimum par une PT1000

PT1000 c'est surdimensionné. DS18B20 plutôt (-55°C à +125°C et 3.0V - 5.5V) ?

Bonne idée pour le DS18B20 mais en boitier TO92 ce n’est pas idéal ni en 8 pin So. Prix plus cher qu’une PT1000 qui est de l’ordre de 1€

La PT1000 est assez facile d’utilisation, par rapport aux circuits intégrés mais consomme tout le temps 0.7mA sous 4.1V.
Alors que DS18B20 consomme 1 mA lorsqu’il est actif et 0.0001mA en standby. Mais il faudrait faire un test.

Etant donné que la tension de référence 5V n’existe plus. L’utilisation de la référence interne 1.1V sera utilisée. Donc, il faut changer aussi le pont diviseur
analogReference(INTERNAL) ; //1.1V tension de référence internal
La résistance shunt de mesure de courant passe à 0.1 ohms, ce qui permet d’avoir moins de perte de puissance.

Donc, pour minimiser la consommation, la broche A3 en sortie numérique sera utilisée pour alimenter les 2 ponts diviseurs sachant que la chute de tension dans les transistors interne de l’ATMEL est négligeable.
La PT 1000 est linéaire et vaut 1346 ohms à 100°C
Mais la tension fournie par la mesure de température, va varier en fonction de la tension de la batterie mais comme cette tension est mesurée, cela se corrige mathématiquement
L’équation pour la PT1000, T=(A2-816Ba/5)/(0.48Ba)
avec Ba correspondant à la tension de la batterie.

Voici les nouvelles valeurs du schéma électrique
Lors de la simulation la sortie A3 sera de 5V et pas à la valeur de la tension Vin malheureusement.
Attention, il faut obligatoirement mettre VCC sur 5V sur l’Arduino, les convertisseurs de l’Arduino nano de la simulation du programme ne fonctionnent pas.

Le coefficient du programme de la mesure de tension change, ainsi que l’état de charge
Ba=A0/221; //4.2Vpont diviseur=1V 11023/(1.1V4.2)=221
SOC=79
Ba-232; // calcul de l’état de charge.
Le coefficient de la mesure de courant change aussi est passe à I=A1/93

le shema de simulation est telechargeable sur ce lien

Réalisation du typon
Proteus (ISIS et ARES) n’a pas les packages de l’Arduino nano….Donc, il faut le créer et le voici il sur mon drive et ainsi que mes librarys car j’ai du réalisé de nombreux composants qui faudra mettre dans la Library userpkg et userdevice

Le schéma du typon n’est pas identique à celui de simulation donc le voici aussi téléchargeable

Le fichier du typon de l’eclairage

mes differentes library et le cours ISIS ARES peuvent etre retrouvé ici
https://drive.google.com/drive/folders/0B_fB3GAsM02FfkRxVFRzVG8zeU52QkZ3cFR4RFRRS3NQakRQZnpvaDBBVElkZExQMkxPSWc?usp=sharing

Pour ne pas avoir de fil à souder, toute l’électronique doit s’emboiter.

  • La Première carte est l’Arduino évidement
  • La Deuxième carte est le hacheur
  • La Troisième carte est pour la led d’éclairage, la band graph, le Bouton poussoir et le capteur de température.

Une inductance 0.1mH/3A en CMS (IDP1451 128x550 INDC3225X135 BOBINE05MH) est assez grosse donc cela ne vaut pas être pas trop le cout de mettre des transistors et diode CMS à plat….autant mettre les composants debout en boitier T0 220
Pour un prototype, mettre des composants à trous est plus facile si l’on doit changer quelques composants.

Perspectives ;
Dans un futur, un nouveau typon avec que des composants CMS sera effectué, pour savoir si c’est cela prend moins de place ou pas.

Est-ce que la simulation du programme fonctionne avec la version Pro mini avec la tension Vin ?

led_velo_nano_temper_sans_5V.ino (6.08 KB)

Mais la tension fournie par la mesure de température, va varier en fonction de la tension de la batterie mais comme cette tension est mesurée, cela se corrige mathématiquement

La référence interne varie aussi pas mal en fonction de la température.

Si ça peut aider : Alimenter un arduino sur pile ou batterie : 7.1. Mesure

Super bien écrit ce blog et tres pedagogique
https://riton-duino.blogspot.com/
Mais, je suis un spécialiste des batteries, des chargeurs, régulations….par contre découvreur de l’Arduino
http://velorizontal.bbfr.net/t20802-bms-et-depannage-ou-maintenance-de-pack-de-batterie
D’ailleurs, j’ai bien avancé sur le programme et la réalisation du chargeur lithium mais je ne peux encore le mettre sur le forum Arduino car j’attends le résultat de mes étudiants.

En effet, j’utilise le forum comme départ avec mes étudiants et voir l’avancement des différentes possibilités de réalisation.

Entre 0 et 100°C, il y a environ 5% de variation de la tension de référence et même si la tension de refendre a une variation de 5%. Mais ce n’est pas très grave puisque le barographe est à 25% (avec ces 4 leds) et que la mesure du courant et de température ne sont pas à 10% près.
Nous avons un BMS

Avec la pro mini Malgré qu’il n’y ait pas la sortie A4 pour la led 1, le compilateur compile quand même
Là encore, la simulation des convertisseurs analogique numérique ne fonctionnent pas correctement si +5V, n’est pas à Vcc.

En simulation, la nano ne peut lire la tension reference encore un bug de isis

Etant donné, qu’il n’y a plus que 2 batteries 18650 en //
La charge se fera par ce module

#include <LiquidCrystal.h>
//#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



#define led0     10       // 
#define led1     A4       // 
#define led2     12       // 
#define led3     13       // 13      
#define BP3        2       // 
#define battery    A0     



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


unsigned    int temps=0;    //temps de la routine d'interruption
            byte  temps1=0;
            byte mode=1;    // etat du bouton poussoir
            float Ic=0.35;   // courant de consigne
            float Ba=0;   //tension batterie
            byte SOC=0;  //etat de charge en pourcentage
            byte barreled=0;    
            byte PWM=0;   
            float I=0;   //courant led principal
            float erreur=0;   //courant led principal
            float kp=10;        //coefficient proportionel integral
            float ki=4;
            float Integral=150;
float   T=0;     //temperature
float   Tc=80;   //consigne de temperature 
float  erreurT=0;



// the setup function runs once when you press reset or power the board
void setup() {
 
pinMode(led0, OUTPUT);   //
pinMode(led1, OUTPUT);   //
pinMode(led2, OUTPUT);   //
pinMode(led3, OUTPUT);   //led carte arduino
pinMode(3, OUTPUT);      //PWM
pinMode(11, OUTPUT);      //PWM
pinMode(1, OUTPUT);      
pinMode(A3, OUTPUT);
digitalWrite(A3,HIGH);


  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
 // Serial1.begin(9600); 

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

  pinMode(2, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(2), interBP, LOW);   //routine d'interruption exterieur broche 2
//wdt_enable(WDTO_15MS);

analogReference(INTERNAL) ;   //1.1V tension de refenrence inernal
//analogReference(DEFAULT) ; 
}



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

  //if ( digitalRead(LEDV)== 1 ) {digitalWrite(LEDV,LOW);}  else {digitalWrite(LEDV,HIGH);}

//wdt_reset();
}//fin routine


//interruption exterieur
void interBP() {
//interrupts();

mode++;                  //incrementation des modes
if (mode>=6) mode=1; 

  switch (mode) {
  case 1:Ic=0.35;Integral=150;  digitalWrite(A3,HIGH);   break;   //donne un ordre de grandeur de la valeur de la PWM=255*(Rshunt*Ic-Useuil)/Ubattery
  case 2:Ic=0.75;Integral=170;   digitalWrite(A3,HIGH);   break;
  case 3:Tc=80;Ic=1.5;   digitalWrite(A3,HIGH);  break;
  case 4:analogWrite(3,0); analogWrite(11,0);digitalWrite(led0,LOW);digitalWrite(led1,LOW);digitalWrite(led2,LOW);digitalWrite(led3,LOW);digitalWrite(A3,LOW);  break; //puis mise  en veuille
  case 5: wdt_reset();    break;   //remise à zero    https://www.instructables.com/id/two-ways-to-reset-arduino-in-software/
     }
                               
   }


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


if (mode==4)  {lcd .clear ();LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);}
           //   LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
           //mode veuille






if (temps>100)         //100 affichage tous les 100ms
{
Ba=analogRead(A0);     //mesure tension
Ba=Ba/221;              //4.2V*pont diviseur=1V   1*1023/(1.1V*4.2)=221

if (Ba<3.2)  {mode=4;}   //mise en veuil car pas de BMS.

SOC=79*Ba-232;    // cacul de l'etat de charge 
lcd.setCursor(0,1);   //colonne, ligne
lcd.print("SOC");
lcd.print(SOC);
barreled=(SOC/18)-1;    

  switch (barreled) {
  case 0:digitalWrite(led0,LOW);digitalWrite(led1,LOW);digitalWrite(led2,LOW);digitalWrite(led3,LOW);     break;               //valeur deu courant dans la led principale
  case 1:digitalWrite(led0,HIGH);digitalWrite(led1,LOW);digitalWrite(led2,LOW);digitalWrite(led3,LOW);   break;
  case 2:digitalWrite(led0,HIGH);digitalWrite(led1,HIGH);digitalWrite(led2,LOW);digitalWrite(led3,LOW);   break;
  case 3:digitalWrite(led0,HIGH);digitalWrite(led1,HIGH);digitalWrite(led2,HIGH);digitalWrite(led3,LOW);   break;
  case 4:digitalWrite(led0,HIGH);digitalWrite(led1,HIGH);digitalWrite(led2,HIGH);digitalWrite(led3,HIGH);   break;          }



I=analogRead(A1);
I=I/93;               //0.1ohms*1A=0.1V   0.1V*1023/1.1=93
lcd.setCursor(6,1);
lcd.print("I=");
lcd.print(I,2);

  
T=analogRead(A2);   //mesure temperature
T=T-814;
T=T/(0.48*Ba);
lcd.setCursor(13,1);
lcd.print(T,0);
lcd.print(" "); 

if ((T>90) && (mode==2)) {erreurT=Tc-T; Ic=Ic+erreurT*0.05;}    //diminution du courant si la temperature atteint 90°C
if (mode==1 || mode==2 )  {lcd.setCursor(0,0);lcd.print("I");lcd.print(Ic,2);lcd.print(" "); }    //limitation du courant à cause de la  temperature
 
              
if (mode==3) {erreurT=Tc-T; Ic=Ic+erreurT*0.05 ;lcd.setCursor(0,0);lcd.print("T");lcd.print(Tc,0);lcd.print("  ");}  // regulation temperature
if (Ic>=2) {Ic=2; }             // limitation du courant de la consigne
if (Ic<=0.35) {Ic=0.35; }      

lcd.setCursor(1,0); 
lcd.print(Ic);
erreur=Ic-I; 

//Proportionnel=kp*erreur;
//derive=(erreur-erreurP)*kd;             //derive=(erreur-erreur*Z^Ts)/Ts   avec Ts=Tsampleur
//output=Proportionnel+Integral;   //ce n'est pas la peine de divisée par Ts car si Ts est petit cela donne des valeurs enormes 
Integral= Integral+erreur*ki;
if (Integral>=255) Integral=255;
if (Integral<=0) {Integral=0;} 
PWM=Integral;
if (Ic==0) {PWM=0;}  

lcd.setCursor(6,0);
lcd.print("PWM=");
lcd.print(PWM);
lcd.print("  ");
analogWrite(3,PWM);    //broche et valeur PWM
//analogWrite(11,127);


temps1++;
if (temps1<2)  {analogWrite(11,255);          }
if (temps1>2)  {analogWrite(11,0);temps1=0;   }
            
temps=0;
}//temps>100


   
} // fin loop

Les BMS de protection d’une batterie S1 arrête la décharge à 2,75V, voir 2,5V. Or, c’est un peu faible pour éviter des décharges profondes

Par conséquent, on préféra s’en passer et si l’Arduino mesure une tension batterie inférieure à 3.2V alors il devra se mettre en mode veuille.

led_velo_nano_temper_sans_5V.ino (6.08 KB)

Entre 0 et 100°C, il y a environ 5% de variation de la tension de référence et même si la tension de refendre a une variation de 5%. Mais ce n'est pas très grave puisque le barographe est à 25% (avec ces 4 leds) et que la mesure du courant et de température ne sont pas à 10% près.

Juste pour de l'affichage : en effet, pas très grave.

TP4056 : bon choix.

Les BMS de protection d'une batterie S1 arrête la décharge à 2,75V, voir 2,5V. Or, c'est un peu faible pour éviter des décharges profondes

J'en ai déjà testé qui s'arrêtaient à 3V pile (9.05V pour un 3S).

Le test ICI

https://forum.arduino.cc/index.php?topic=538070.0

Je vais me pencher dessus, surtout la partie NIMH.

Bonne continuation

J'en ai déjà testé qui s'arrêtaient à 3V pile (9.05V pour un 3S).

La carte que j'ai testé :

Over discharge protection : 2.5V typiques.

Il y a certainement une erreur de la part du vendeur.

En mode veuille avec 5micro ampère, l’autonomie théorique avec 100% de charge est de 33 333Jours avec 2 éléments 18650. Temps=2A.H*2/(5*10^-6*24h)=33 333Jour Si l’éclairage se met en mode veuille lorsque 20% restante d’énergie, Le temps de décharge pour atteindre les 100% de la batterie sera de 6666 jours.

Mais une autre solution que le bouton poussoir avec le mode veuille est possible : C’est un interrupteur sur l’alimentation. Cet interrupteur devra changer de mode de puissance de la led à chaque coupure de l’alimentation En utilisant EEPROM avec l’incrément des modes sur une adresse

Evidemment, si la personne oublie d’éteindre l’éclairage, il faudra que l’Arduino se mettent en mode veuille à 20% de la capacité énergétique.

Algorithme du setup avec l’interrupteur ; Lire le mode sur eeprom Incrémenter le mode Si eeprom est superieure à 3 alors valeur 0. Ecrire le mode eeprom

Mais L’utilisation de EEPROM diminue la durée de fonctionnent de l’éclairage. En effet, le nombre d’écriture avoisine 100 000 fois par adresse et dure 3.3ms. Donc avec 2 utilisations d’éclairage par jour et une extinction éteint 3 fois l’alimentation à chaque fois pour revenir Durée de vie =100 000/2J*3=16666J=>45 ans

Evidemment, il serait possible aussi d’utiliser une iteration de la mémoire EEPROM pour écrire dans une adresse différente mais vu les 45 ans, ce n’est pas très utile. https://www.arduino.cc/en/Tutorial/EEPROMIteration

Il n’y a pas qu’une solution, mais plusieurs….

En fonction du besoin, la programmation Arduino permet d’ajuster la puissance led et de la capacité énergétique. On pourrait faire aussi un programme avec un seul mode pleine puissance en mode flash et il n’y plus besoin EEPROM. Exemple :

Avec une seule batterie lithium de 1A.h mais d’utilisation que de 0.8Ah à cause des 20%, l’autonomie en 3Watt mode flash avec rapport cyclique de 0.5, l’autonomie chute à 1heure. mais cette batterie permet de minimiser la masse et l'encombrement |500x168 Mais pourquoi pas faire un rapport cyclique de 0.1 sur 1s. L’autonomie théorique en mode veuille avec cette batterie est toujours correcte Temps=0.2A.H/(5*10^-6*24h)=1666Jour

Il y a de nombreux à choix à faire sur ce sujet

33 333Jour : n'y compte pas trop, car l'auto-décharge de la batterie n'est pas négligeable. J'ai flingué une LIPO comme ça : oubliée dans un tiroir pendant 1 an.

Evidemment, c’est une valeur théorique de l’autonomie qui permet de donner un ordre de grandeur.
Elle ne prend pas en compte, l’autodécharge de la batterie par exemple.

Pour débuguer le programme, on aime utiliser ISIS, ce qui permet de tester le programme sans détruire hacheur et led, batterie….
Mais dans ISIS, l’EEPROM ne fonctionne pas si l’on coupe l’alimentation Vcc.
Par contre, cela fonctionne à chaque fois que l’on redémarre la simulation ou que l’on active le reset.
Voici la copie d’écran de la simulation ou le programme demande 0.5A, puis demande 1A, avec une initailisation de la valeur integral de 148 et ki=4

Donc, le courant est directement à 0.5A avec cette valeur de PWM à 148, mais il faut attendre 2.5s pour avoir un PWM de 169 pour atteindre la valeur de 1A comme on peut l’observer sur la figure suivante :

Evidemment, dans le programme final, il vaut mieux augmenter la valeur de cette initialisation dans le cas le plus défavorable de la tension batterie 3.2V.
Donc, il y aura un léger dépassement du courant lorsque l’alimentation sera de 4.2V à cause de l’initialisation du coefficient intégral.

On pourra observer la variation du courant qui est de 10% autour de la valeur moyenne correspondant aux choix de notre inductance mais cela ne gene pas la regulation. donc, pas besoin de filtrer le courant de façon analogique ou numerique

Voici le nouveau programme utilisant EEPROM en PJ

Pour visualiser les dynamiques de la régulation en réel, il faut mesurer en fonction du temps, la tension image du courant de la résistance shunt avec la valeur moyenne de la PWM.
Pour mesure la valeur de la PWM à l’oscilloscope, il faudrait utiliser un filtre passe bas de fréquence de coupure bien inférieur à la période de hachage et supérieur à 10Hz correspondant à l’inverse de la période d’échantillonnage.
Un filtre sallen key du deuxième ordre de fréquence de coupure de 100hz est un bon compromis ou un RC du premier ordre.

Une autre solution et d’utiliser la liaison série et le terminal et faire un copier-coller du terminal pour faire un fichier CSV dans Excel….D’ailleurs c’est pour cela que l’on a jamais utilisé le Tx sur ce post
pour cela, il faut inclure la bibliothèque #include <SoftwareSerial.h>
Initialisation à Serial.begin(9600);
Ces enregistrements prouvent le bon fonctionnement des régulations en simulation et en réel.

led_velo_sans_5V_eeprom.ino (6.44 KB)

Notre système n’a pas besoin d’une grande précision de la mesure de température de la led (plus ou moins quelques °C suffit) Une PTC (positive température coefficient) (kty81) est 2 fois moins cher qu’une PT 1000 (environ 0.4 euros) |500x184 Mais, est qu’il y a plus de sensibilité dans une PTC que dans une PT 1000 ?

Remarque, Dans Isis, c’est la kty 81/110 1000ohms à 25°C qui est simulable http://www.farnell.com/datasheets/1503771.pdf?_ga=2.252704713.1576310020.1552658034-1358927439.1552558264

Le modèle mathématique d’une PTC est bien présenté sur ce lien http://mathscinotes.com/2011/07/thermistor-mathematics/ Car ce n’est pas terrible dans wiki https://en.wikipedia.org/wiki/Thermistor Voici le modelé mathématique exponentiel et la linéarisation de la tension image de la température entre 0°C et 140°C Dans les datasheet, si la résistance R25 est donné, le coefficient B (kelving) est parfois pas donné, mais c’est facile de le retrouver |500x463 |500x455 Le boitier des kty 81 est souvent, un TO92 et pas TO220; donc il y a une erreur de la mesure en fonction du contact et un retard de la mesure à cause de la constante de temps thermique. Le boitier TO220 permet de fixer correctement le capteur mais prend de la place D’ailleurs, la kty 81 dans ISIS est paramétré avec une constante de temps de 10s, une résistance thermique de 2000°C/W et une résistance de contact de 0.5°C/W. Mais un boitier TO 92, a une constante de temps de 30s avec une résistance thermique de 140°C/W et une résistance de contact de 30°C/W. Le temps de réponse du capteur est bien inférieur à celui du dissipateur de la LED grâce au dissipateur. Exemple : si la température mesurée est de 53°C avec une température ambiante de 20°C, alors la température du radiateur sera de 60°C. Il y a une différence de 7°C Si la température mesurée est de 80°C, la température réelle est de 91°C. La différence est de 11°C On peut observer cette différence sur la simulation suivante et en réel avec une caméra infrarouge |500x269 Donc, il faut corriger cette différence, avec l’équation précédente, mais la mesure de la température ambiante n’étant pas mesuré, elle sera estimée à 25°C ce qui donnera une erreur par défaut sur la température ambiante est plus grande. On peut observer sur la simulation que la valeur de la température du capteur et identique à celle donné par l’Arduino avec la correction précédente |500x169

Si les PTC sont très courantes pour mesurer la température, les NTC sont très utilisées aussi.

Perspectives futur; Avec le programme, le bargraphe n’indique pas s’il y a un état de charge. Or, ce serait bien qu’il clignote lors de la charge pour indiquer à l’utilisateur que le micro usb est bien connecté.

La régulation de courant de l’Arduino Nano est avec un hachage à 32 kHz. Contrainte : La taille de l’inductance du hacheur est relativement importante. Pour 320 kHz elle serait divisée par 10. Perspective : Le hacheur de la carte électronique peut-être remplacer par un composant électronique FL7760. Ce composant est destiné aux applications d’éclairage à Led et comporte des hacheurs.

http://www.farnell.com/datasheets/2363644.pdf

Suivant la documentation du constructeur, nous avons réaliser une carte électronique de régulation de courant. Sur la doc on peut trouver les performances de la fréquence de hachage (1MHz) et la consommation du circuit intégrer (300 microA). L’hystérésis est de plus ou moins 30mV, le reste n’est pas trop indiquée. Donc pour un courant Led de 0,4 A

|500x37

On néglige dans un premier temps la puissance du transistor et de la diode., qui sont surdimensionnés par rapport au courant Led pour ne pas mettre de dissipateur.

Voici le schéma ISIS avec le choix des composants |500x410

|500x202

Voici nos mesures expérimentales visant à caractériser les performances du régulateur 7760 : D’une part pour une tension d’alimentation de 10 V puis 16 V. Puis en variant la résistance de mesure de 1 Ω à 0,5 Ω. Car elle n’est pas précisée dans la documentions constructeur... - Détermination du rapport cyclique - Détermination de la fréquence de fonctionnement - Vérification de l’ondulation de courant - Mesure du courant d’entrée et détermination de la puissance absorbé - Détermination des caractéristiques de la Led (tension, courant et puissance utile) - Calcul du rendement - Éclairement Tableau récapitulatif des mesures : |500x61 Pour l’éclairement : 860 Lux à 10 cm pour une puissance de 0,42 W.

La régulation de courant dans la Led fonctionne bien Les pertes deviennent négligeables pour un courant supérieur à 0.4A avec une résistance Rsense de 0,5ohms, donc un rendement de 70% à la place de 90% théorique. On a effectué une mesure à vide de la consommation du 7760 et on trouve 400 μA au lieu de 300microA Mais ça ne change pas tant que ça la valeur théorique du rendement. On pense que cette différence de 100 μA est dû à la commande du transistor…c’est une hypothèse.

Avec une inductance de 100 μH, on a une fréquence entre 300 kHz et 200 kHz correspondant à l’équation théorique suivante avec 60mV Donc, en théorie, si on divise notre inductance par deux on multiplie d’autant notre fréquence. On a effectué une vérification pratique avec une valeur d’inductance de 50 μH. On obtient une valeur de 400 kHz. Mais une valeur de 33 μH, On obtient une toujours une fréquence de 400 kHz qui est certainement dû aux ondulations parasite du typon que l’on peut observer sur les figures suivantes.

Ondulation pour 200 kHz

Ondulation pour 400 kHz

Mais comment faire varier la puissance de la led avec l’arduino

A partir de la doc constructeur et sur notre schéma, il y a une broche DIMMING du FL7760. Cette broche sert à faire varier le courant de la LED. Il faut pour cela appliqué un signal PWM et faire varier le rapport cyclique normalement supérieure à 2KHz. On a appliqué un signal PWM de 32 kHz et d’amplitude 5 V, en faisant varié le rapport cyclique on observe une variation de la tension Vsense image du courant de notre LED. On a effectué une série de mesures sur la broche DIM ainsi que sur la résistance Rsense : |500x38 Donc le courant led correspond à l’équation suivante :

Conclusions : Avec le choix de nos composant, le courant led peut atteindre 3A avec une fréquence de 400khz en minimisant l’inductance à 30μH avec un rendement qui va être aux alentours de 90%. Mais qu’il faudra vérifier.

Test de la durée d’exécution du programme utilisant EEPROM

On souhaite connaître la durée d’exécution de notre programme, cependant arduino ne réalise pas de fichier .cof que l’on peut simuler sur ISIS pour visualiser la durée du programme. Donc on décide tout simplement, d’allumer une LED au lancement de la boucle des 100ms puis de l’éteindre à la fin de son exécution ; ensuite on visualise ce changement d’état à l’oscilloscope et on effectue notre mesure en simulation et en réalité.

|500x350

Comme on peut le voir, le programme s’exécute en 15ms avec l’afficheur LCD et un temps d’échantillonnage de 100ms (boucle d’affichage et de régulation si temps= 100ms (if temps>100).

Mais pour faire cet éclairage, il n’est pas utile d’utiliser un afficheur LCD (qui est utilisé pour faire du debuggage), donc le programme s’exécute en 3,3ms sans l’afficheur LCD avec un temps d’échantillonnage de 100ms.

|500x355

On en conclut qu’on peut diminuer la période d’échantillonnage à 5ms tout en sachant que l’œil à une persistance rétinienne de 20 Hertz, donc un rafraichissement des valeurs de l’afficheur LCD toutes les 0,1s.

pour faire un feu stop arriere automatique un accelerometre va être utilisé

Les accéléromètres numériques sont nombreux avec des micro-usiné capacitif intelligent à trois axes et à faible consommation avec des résolutions de 10bits à 14 bits. Des fonctions intégrées sont multiples avec des options flexibles programmables par l’utilisateur (filtrées passe-bas, et passe haut, interruption). Pour ce projet, nous n’avons pas besoin d’une grande résolution pour détecter la décélération du vélo pour activer l’éclairage arrière. S’il y a une décélération en roue libre, on passe de 15km/h (4.1m/s) à l’arrêt en 19s minimum sur du plat. Donc la décélération est de -0.22m/s^2 Lors de freinage intensif, on passe de 16.6m/s à l’arrêt en 2.5s onc décélération de -6.6m/s^2

Donc pour une déclaration de -1m/s^2 mettra l’éclairage arrière en action full pendant 10s Mais une accélération de +1m/s^2 arrêtera l’éclairage et remettra à 0. Car cela voudra dire que l’on a redémarré

Remarque 1 g est égale à 9,81 m/s² D’ailleurs, le programme suivant a choisi la valeur -30=>-0.117g=-1.14m/s^2 pour actionner sa lumière arrière https://www.instructables.com/id/passive-brake-light/ Quels sont les capteurs d’accélération possibles ? Sachant que l’on veut minimiser le cout de fonctionnement. L’accéléromètre analogique tel que ADXL335 est relativement cher (environ 3€) mais c’est possible de faire un filtre analogique. L’accéléromètre numérique tel que ADXL345 est vendu pour environ 1€ |500x154 Le MCU 6050 qui a un gyroscope interne est plus cher que le composant précédent |500x180

Voici, les Performances ADXL345 https://www.sparkfun.com/datasheets/Sensors/Accelerometer/ADXL345.pdf

Alimentation: 2,0 Vcc à 3,6 Vcc Consommation: - en mesure: 40 µA à 2,5 Vcc - au repos: 0,1 µA à 2,5 Vcc Interface: I2C ou SPI 16 bits Plage de mesure: ±16 g Sensibilité: 3,9 mg/LSB 2g Résolution: 4 mg/LSB (13 bits) 1bits(signe) 16g/2^12=16/4096=3.9mg Filtre interne de ? FiFo de 32 valeurs Le temps de mesurer l’accélération sur un axe est de ?

Pour notre programme precedent ; L’échantillonnage de la commande de la led a été choisi à 0.1seconde (fréquence 10hz). Pour ne pas avoir de décélération intempestifs, un filtre passe bas de la mesure d’accélération à la fréquence de coupure légèrement inférieur à 10hz serait souhaitable. Donc, un filtre avec une fréquence de coupure de 0.05s ne nuira pas aux dynamiques de détection de l’accélération qui est de quelques secondes. Remarque avec notre programme qui a une routine d’interruption de 1ms, la période d’échantillonnage de l’accélération se fera à cette valeur. Il est facile de faire un filtre passe bas numérique qui atténue les fréquences les plus élevées du signal, offrant ainsi une variation plus douce de la sortie. Ce filtre passe-bas est facilement implémentable en utilisant l'équation suivante avec correspondant à la constante de temps désirée : |500x134 Mais comment vérifier les résultats les dynamiques du filtre numérique ?

On peut vérifier le filtrage en mettant un signal carré de période 0.1s et la sortie du filtre passe bas devra donner une exponentielle croissante et décroissante comme en analogique. Exemple avec une constante de temps de 10ms, donc e^-aTe= e^-(1ms/10ms)= 0.91 Matlab permet de faire cette vérification très facilement |500x305 On peut observer que la constante de temps est bien de 10ms et que le gain statique du filtre est de 1 car l’amplitude en sortie est identique à celle de l’entrée. |500x353

Maintenant, si l’on désire, une constate de temps de 50ms e^-aTe= e^-(1ms/50ms)= 0.98 On peut observer sur la figure suivante que la sortie du filtre à bien correspond à la valeur moyenne du signal carré d’entré qui a un rapport cyclique de 50% donc de 0.5V mais avec une oscillation d’amplitude de 20%. |500x353

Pour tester le filtre, il serait possible de rajouter sur le signal carré precedent du bruit à haute frequence pour bien vérifier que ce dernier serait atténué. Evidemment, il est possible de faire des filtres plus complexes pour avoir encore plus d’atténuation

Il aurait été possible que l’Arduino lise un signal carré extérieur et de faire une sortie analogique des valeurs sur une PWM pour démontrer l’utilisation d’un filtre numérique sur un oscilloscope avec une routine d’interruption de 1ms pour faire les calculs du filtrage qui a été présenté précédemment. Mais, nous avons utilisé juste le terminal pour observer les calculs du filtre et vérifier que le float avec ces 7 chiffres significatif fonctionne bien comme on peut l’observer sur le code suivant qui ont été placé dans Excel pour observer les dynamiques du filtre.

#include 
#include 
#include 
#include    //chien de garde
//#include "LowPower.h"     //https://github.com/rocketscream/Low-Power


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


unsigned    int     temps=0; 
            float  entree=0;
            float  sortie=0;



// Filtre numerique premier ordre
void setup() {
     

  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
  Serial.begin(9600); 

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

//wdt_enable(WDTO_15MS);
}



// Interruptions  tous les 0.001s fait par le timer1***********************************
void callback()  {
temps++;
sortie=entree*0.008+sortie*0.992;   //filtre passe pas
  Serial.print(temps);
  Serial.print(";");
  Serial.print("\t");
    
  Serial.print(entree);
  Serial.print(";");
  Serial.print("\t");
  
  Serial.print(sortie,2);
  Serial.print("\t");
  Serial.println(";");  //mise à la ligne

//wdt_reset();
}//fin routine



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

if (temps>=50)         //1=singnal carré de 100ms
{
temps=0;  //reset : attention cette boucle doit etre infereir à son temps d'execution
if (entree==16384) {entree=0;}  else {entree=16384;}  
  
}//temps>100

   
} // fin loop

Avec le terme 0.91 du filtre échantillon à 1ms, On peut observer que la constante de temps est environ celle théorique de 10ms, pour une amplitude de 1023 de l’entrée (10bits).

Avec le terme 0.98 du filtre échantillon à 1ms, On peut observer que la constante de temps est légèrement inférieure à la valeur théorique de 50ms, pour une amplitude de 16384 (14bits) de l’entrée. Lorsque la constante de temps devient très grande devant la période du signal, la sortie du filtre donnera une oscillation avec une amplitude correspondant à l’équation suivant autour de la valeur moyenne du signal d’entrée |500x258 Avec le terme 0.992 du filtre échantillon à 1ms, la constante de temps theorique on peut observer que l’amplitude |500x200 Donc, il y a des petites différences entre la théorique et la pratique mais globalement, cela fonctionne correctement.

Remarque : ne jamais depasser la valeur de 1, sinon c'est instable, d'ou l'obligation de declarer en float faut il des bibliotheques filtre pour cela ? ? ? ? ? ? ? ? https://playground.arduino.cc/Code/Filters/ https://github.com/sebnil/FIR-filter-Arduino-Library