Commande et instrumentation de trottinette électrique 500W avec Arduino méga

1. Présentation
Commande de moteur DC 500W avec un Arduino mega pour limiter le courant de démarrage et faire varier la vitesse de la trottinette. La batterie est en 24V, 10A.h. le tableau suivant résume leur caractéristiques :

2. Bibliographie :
Lien download :
sketch_escooter_feed_back_reel_V1.ino

escooter_ampli_SIMULINK.mdl

escooter feed back ISIS.DSN

En anglais
https://forum.arduino.cc/index.php?topic=477397.0

article : « Etude de trottinettes électriques 100W et 500W (Arduino), Revue 3EI 2017 »
En attente

3. Programme en boucle ouverte
Pour tester la programmation, nous simulons le programme dans ISIS, comme on peut le voir sur la figure suivante. De plus, nous avons un afficheur LCD pour afficher des données (rapport cyclique correspondant à la PWM à 32Khz, le courant moteur, la tension moteur, l’action sur les boutons poussoirs. En effet, 4 boutons poussoirs sont utilisés.
BP1 pour incrémenter manuellement le rapport cyclique, BP2 le décrémenter. BP3 mettre le rapport cyclique à 0, correspondant au contact frein.
La vitesse du moteur est pratiquement proportionnelle au rapport cyclique

Nous avons réalisé notre propre amplificateur de courant qui s’appelle un hacheur abaisseur mais il est possible d’acheter un shield
Il existe de nombreuses cartes pour Arduino pour commander des moteurs DC surtout de faibles puissances et aussi de grandes puissances comme on peut l’observer sur les liens suivants.
http://www.robotpower.com/products/MegaMotoPlus_info.html
http://www.robotshop.com/en/dc-motor-driver-2-15a.html


mais, tous ces hacheurs shields mesurent le courant en interne mais il n’y a pas de limitation de courant.

Pour avoir une limitation de courant il faut une boucle de courant analogique en utilisant des AOP ou CI spécialisée ou une boucle de courant numerique rapide.
Mais quel doit être la valeur du courant de limitation ?
Le choix de la valeur du courant est normalement pour le Service de fonctionnement 1 heure pour pouvoir effectuée des montées relativement longue sans atteindre la température critique du moteur.
Dans notre cas, le courant de limitation devra etre de

Imoteur limitation=Puissance/Ubatterie=500W/24 V=20A

De plus, le transistor de puissance du hacheur ne peut supporter que 50A dans notre cas.

Mais en boucle ouverte, il n’a pas de régulation de courant, pour ne pas avoir de dépassement du courant maximum, une rampe du rapport cyclique sera utilisé.
Une routine d’interruption de 0.1 seconde sera utilisé pour faire la mesure de la tension est du courant (échantillon de mesure, sample ). Ce temps de sampler est arbitraire, mais ne permet pas d’être plus rapide que le temps de montée du courant car la constante de temps électrique du moteur étant de L/R= 1.5ms.

Le fonctionnement en boucle ouverte avec une rampe de 25.5s (8bit et routine d’interruption de 0.1s) permet de bien comprendre la problématique du fonctionnement d’une commande à moteur DC.
l'affichage se fera seulement tous les 0.2s pour avoir une stabilité des chiffres à l'ecran. De plus, un filtrage numerique, se fera sur le courant et la tension sur 4 valeurs donc sur 0.4s.

[b]Algo boucle ouverte[/b]

Routine d’interruption toutes les 0.1S
Lire tension et courant

Boucle loop (scrutation des boutons poussoirs) 
Si BP1=1 alors incrementer PWM
Si BP2=1 alors décrementer PWM
Si BP3=1 alors PWM=0
Affichage des variables tous les 0.2s
// include the library code:
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>
#include <TimerOne.h>
 
#define SERIAL_PORT_LOG_ENABLE 1
#define Led     13       // 13 pour la led jaune sur la carte
#define BP1     30       // 30 BP1
#define BP2     31       // 31 BP2           
#define BP3     32       // 32 BP3
#define LEDV    33       // 33 led
#define LEDJ    34       // 34 led
#define LEDR    35       // 35 led
#define relay   36       // 36 relay
#define PWM10    10      //11   timer2    

LiquidCrystal lcd(27, 28, 25, 24, 23, 22); // RS=12, Enable=11, D4=5, D5=4, D6= 3, D7=2, BPpoussoir=26
// Configuration des variables

unsigned   int UmoteurF = 0;  // variable to store the value coming from the sensor
unsigned   int Umoteur = 0;
unsigned   int Umoteur2 = 0;
unsigned   int Umoteur3 = 0;
unsigned   int Umoteur4 = 0;

unsigned   int ImoteurF = 0;  
unsigned   int Imoteur = 0;
unsigned   int Imoteur2 = 0;
unsigned   int Imoteur3 = 0;
unsigned   int Imoteur4 = 0;
           byte Rcy=0 ;    //rapport cyclique  8bit
unsigned    int temps;

// the setup function runs once when you press reset or power the board
void setup() {
  pinMode(Led, OUTPUT);   //led carte arduino
  pinMode(LEDV, OUTPUT);
  pinMode(LEDR, OUTPUT);
  pinMode(LEDJ, OUTPUT);
  pinMode (PWM10,OUTPUT);     // broche (10) en sortie  timer2

  
//  digitalWrite(LEDV,LOW);
  Timer1.initialize(100000);         // initialize timer1, and set a 0,1 second period =>  100 000
  Timer1.attachInterrupt(callback);  // attaches callback() as a timer overflow interrupt
  lcd.begin(20, 4);  
  Serial1.begin(9600); 

  TCCR2B = (TCCR2B & 0b11111000) | 0x01;         //pin 10  32khz    http://playground.arduino.cc/Main/TimerPWMCheatsheet
                                                  //http://www.pobot.org/Modifier-la-frequence-d-un-PWM.html
  //   analogWriteResolution(bits)      https://www.arduino.cc/en/Reference/AnalogWriteResolution

lcd.setCursor(0,1);
lcd.print("Rcy");

lcd.setCursor(10,1);
lcd.print("Um");

lcd.setCursor(5,1);
lcd.print("Im");

lcd.setCursor(10,1);
lcd.print("Um");

lcd.setCursor(20,1); //afficheur 4lignes*20 caracteres
lcd.print("BP1+");

lcd.setCursor(25,1);
lcd.print("BP2-");

lcd.setCursor(29,1);
lcd.print("BP3=0");
}

// Interruptions  tous les 0.1s
void callback()  {
temps++;
//toogle state ledv for check 
  if ( digitalRead(LEDV)== 1 ) {digitalWrite(LEDV,LOW);}
    else {digitalWrite(LEDV,HIGH);}
    
analogWrite(PWM10,Rcy);   //frequence
Umoteur=analogRead(A0);
Imoteur=analogRead(A1);

Imoteur2=Imoteur;
Imoteur3=Imoteur2;
Imoteur4=Imoteur3;
ImoteurF=(Imoteur4+Imoteur3+Imoteur2+Imoteur)/4 ;


Umoteur2=Umoteur;
Umoteur3=Umoteur2;
Umoteur4=Umoteur3;
UmoteurF=(Umoteur4+Umoteur3+Umoteur2+Umoteur)/4 ;
  
}//fin routine


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

  // BP + LED
  if ((digitalRead(BP1))==1) {
    lcd.setCursor(20,0);      //colonne, ligne
    lcd.print("BP1");
    digitalWrite(LEDR, LOW);    
    digitalWrite(LEDJ, LOW); 
    Rcy++;                        //incrementation PWM
    if ( Rcy>254)  {Rcy=254;}
    delay(100);               //8bits*100ms=25S   pente de l'incremetation 25ssecondes
    }  
    
  if ((digitalRead(BP2))==1) {
    lcd.setCursor(20,0); 
    lcd.print("BP2");
            Rcy--;
     if ( Rcy<2)  {Rcy=2;}  //PWM presque à 0, arret moteur
        delay(100);  
    digitalWrite(LEDR, HIGH);
    digitalWrite(LEDJ, HIGH); 
    } 
  if ((digitalRead(BP3))==1) {
    lcd.setCursor(20,0);
    lcd.print("BP3"); 
     Rcy=2;               //PWM presque à 0, arret moteur
    }

if (temps>=2)  {
lcd.setCursor(0,0);
lcd.print("                "); //effacement ligne donnée

lcd.setCursor(0,0);     
lcd.print(Rcy);

lcd.setCursor(5,0);
ImoteurF=(ImoteurF)/20;     //resistance (5/1024)*(10/0.25ohm) si ACS712 66mV/A
                           //pour resistance 1ohm (ImoteurF)/20;   simulation 5/25
lcd.print(ImoteurF);


lcd.setCursor(10,0);
UmoteurF=UmoteurF*10/38;                              //10/38   10/30 simula
if (Umoteur>ImoteurF){UmoteurF=UmoteurF-ImoteurF;  }  //U-R*I

lcd.print(UmoteurF);


temps=0;
}//fin if temps
   
} // fin loop

etant donné qu'il y a une limite de 9000 caracteres du forum la suite ci dessous

caracteristique programme en boucle ouverte precedent

La routine d’interruption dure que 250 micro seconde, la boucle du programme principal qui scrute l’action de boutons poussoirs est de 13micros et le temps d’affichage de toutes les données est de 11ms. Donc, on peut améliorer la période d’échantillonnage donc la rapidité de la régulation du courant.
L’Arduino permet de faire l’instrumentation de la trottinette donc de connaitre la puissance, la consommation en A.h et W.h, de mesurer la vitesse, de connaitre la consommation en fonction des W.h/km, de mesurer la température du moteur et d’avoir une sécurité de fonctionnement.

Mais pour l’instant nous allons voir comment limiter le courant

4. Programme en boucle fermé, commande à courant limité

la periode d'echantillonnage passera à 0.01seconde (routine d'interruption)
si le courant est inferieur à la valeur desirée, alors la le rapport cyclique peut etre augmenté ou diminué jusqu'a la valeur desirée qui est la consigne.
par contre si le courant moteur est superieur à la valeur de limitation, il y a une diminution rapide du rapport cyclique.

pour ne pas avoir de depassement de la valeur du rapport cyclique celui si sera saturé à 254 maximum et à la valeur minimum 6.

if (Imoteur<4000)                    // pas de limitation de courant à (20A*10)*20=4000
  {if (consigne>Rcy)   {Rcy=Rcy+1;}   // rampe de de la Pwm +1*0.01seconde  integrateur pur
   if (consigne<Rcy &&  Rcy!=0)    {Rcy=Rcy-1;}     //la decrementation est faite seulement pour la poignée d'acceleration ou avec BP2
   if ( Rcy>254)  {Rcy=254;}           //limitation du rapport cyclique
   analogWrite(PWM10,Rcy);   //frequence 32kHz timer2}     
    }
if (Imoteur>4000)  { Rcy=Rcy-5;              //pas de filtrage du courant, pour etre plus rapide  
                    if ( Rcy<6)  {Rcy=5;}       //rcy n'est pas signé, ni la PWM   donc Rcy minimun ne doit pas etre inferieur à 6                     
                  analogWrite(PWM10,Rcy);   //frequence 32kHz timer2}      
                  }

5. Programme en boucle fermé, commande à courant limité avec poignée d’accélération

Une poignée d’accélération fournit une tension 0.8V lorsqu’elle n’est pas actionnée et une tension 4.5V lorsque la poignée est à fond.
A la place d’utiliser des boutons poussoirs pour augmenter ou diminuer la consigne de vitesse, une poignée d’accélération sera donc utilisée

Upoignee=analogRead(A3); //la relation en Upoignée et la consigne qui correspondra au rapport cyclique correspond à 
if (Upoignee>100) { consigne=(Upoignee/2);     //0=a*200+b    et 255=a*800+b   
                   consigne= consigne-100;
                  }               
             else { consigne=0;   }               
if (Upoignee<100) { consigne=0;  }     //redondance

6. Programme mesure température et sécurité du moteur avec la mesure courant
La mesure de température extérieure peut être facilement effectuée par le composant LM35 qui fournit 0.01V par degrés Celsius

temperature=analogRead(A2); //lm35 0.01V/°C
temperature=temperature/2;       //coefficient de mesure de temperature
lcd.setCursor(5,2);
lcd.print("      ");
lcd.setCursor(5,2);
lcd.print(temperature);   // affichage en °C
lcd.setCursor(9,2);      // effacement de l'affichage secu
lcd.print("     ");

  if (temperature>80 ) {lcd.setCursor(9,2);         // si temperature extern moteur est superieur à 80°C
                     lcd.print("secuT");  
                     Rcy=0;}

De plus, une sécurité thermique par la mesure du courant moteur sera ajoutée.
si le courant de limitation est superieur à 10s alors le moteur ne sera plus alimenté pendant 30s.
un affichage "secu" sur l'afficheur LCD sera indiqué.
Cette securité permet de couper le moteur lors de pente trop importante et lors du blocage du moteur mais il faudrait rajouter la mesure de la vitesse dans ce dernier cas

if (timesecurite>=10000 ) {flagarret=1;      
 // si courant de limitation pour un courant de plus de 10s
                              timerepos=0;
                              consigne=0;
                              Rcy=0;   
                              timesecurite=0;}       //   alors arret moteur pendant un temps d'arret 
  
  if (flagarret==1 ) {lcd.setCursor(9,2);         // si courant de limitation pour un courant de plus de 20s
                     lcd.print("secU");  }     //   alors arret moteur pendant 60 un temps d'arret et affichage 

    
                                            
    if (timerepos>=30000 &&  flagarret==1) {flagarret=0;
                                          lcd.setCursor(9,2);      // apres un temps de repos ici de 30s
                                           lcd.print("       ");   }

on peut observer l'affichage si la temperature est superieure à 80°C

Une sécurité thermique par la mesure du courant moteur (relais thermique numérique) qui permet de connaitre l’image de la température interne du moteur serait idéale. Mais pour cela, il faut bien connaitre le modelé thermique du moteur.

7. Programme mesure de la capacité énergétique de la batterie
La capacité énergétique d’une batterie est en A.H, nous afficherons la valeur en mA.H pour avoir une grande précision. La capacité sera en A.Seconde dans l’equation suivante. Donc pour avoir en mA.H, il faudra divisé par la capacité par3600.
Capacité(A.s)n=I*Te+Cn-1 avec Te=0.01s et I multiplié par 10

Donc dans la routine d’interruption

capacity=ImoteurF+capacity ;

et dans l’affichage

lcd.setCursor(0,3); //affichage de la capacité energetique
lcd.print("C mA.h=");
capacity1=capacity/(18000);   //18000=3600*5  5=>coefficient mesure courant
lcd.print(capacity1);

pour verifier mettre un courant de 10A avec une resitance ajustable et au bout de 30s, la capacité devra etre de 83mA.H

8. Bilan puissance et modélisation avec SIMULINK

La modélisation permet de bien comprendre le véhicule et sa commande. De plus, il est possible de compiler la partie régulation directement en programme Arduino à partir de la simulation sous Simulink. Mais il ne sera pas possible de simuler l’instrumentation avec l’afficheur LCD.
Sur la figure suivante, on peut observer la simulation de la programmation du hacheur avec la limitation de courant avec Simulink. Sur la figure suivante, l’encadrée en vert montre la commande du rapport cyclique pour faire varier la vitesse et l’encadrée en rouge la limitation du courant. Le correcteur de la régulation est ici un simple intégrateur mais il est possible d’effectuer une multitude de commande.

Sur la figure precedente, on peut observer que le courant est bien limité à 25A de 2s à 9.5s. Puis, le courant atteint 10.8A en régime établi de vitesse à 22.5km/h. les dynamiques sont similaires aux essais effectués.
Avec une pente de 5%, le rapport cyclique n’atteint tout juste 100% comme on peut l’observer sur la figure suivante. La vitesse atteindra péniblement 19km/h avec un courant de 24A et une puissance moteur de 580W.
Voir l’article : Etude de trottinettes électriques 100W et 500W (Arduino),

9. Premiere conclusion
Il est facile de commander un moteur DC de 500W avec un Arduino et quelques composants
Donc de réparer nombreuses trottinettes qui sont en moteur DC.
mais il faut quelques connaissances (automatique, moteur) pour savoir gérer correctement le moteur et limiter son courant pour ne pas l'endomager
l'affichage de la vitesse, la distance, de l'heure de fonctionnement pour connaitre les Watt.heure/km pourra etre aussi réalisé avec un menu 2.

le programme .ino en fichier attaché,
mais il n'est pas possible de mettre un fichier attaché .dns de ISIS labcenter electronic ?
c'est quoi ce forum !
il serait souhaitable que le compilateur puisse generer le.cof pour pouvoir debugger dans isis et tester le programme ligne par ligne....
Arduino doit encore faire beaucoup d'effort pour etre au meme niveau que d'autre microcrontoleur

sketch_trotinette_feed_back_reel_V1.ino (8.47 KB)

10. mesure de la vitesse (tachymetre)

La mesure de la vitesse est effectuée avec un capteur effet hall SS495 ou A1324 qui permet de compter chaque tour de roue. Il suffit de rentrer la périmètre de la roue de la trottinette (130mm de rayon donc 0.816m dans le cas
Pour avoir la vitesse, il suffit juste de diviser le nombre de tour de roue sur un temps arbitraire de 1s pour avoir une vitesse minimum de de 0.81m/s donc de 2.93 km/h. De plus, un filtrage moyen avec 3 valeurs sera utilisé pour afficher la vitesse. A 25km/h, il y aura 8.5 tours.
Pour compter les tours, une routine d’interruptions extérieure sera utilisée sur l’entrée INT0 21 de la carte mega.
http://www.locoduino.org/spip.php?article64
Pour simuler la vitesse, un pulse sur l’entrée 21 sera utilisé avec un rapport cyclique de 10%.

void INT0b21() {
  Tspeed++;   //interruption exterieure pour compter le nombre de tour
}

//dans le set up declarer la routine d'interruption lorsque le front 5V de la detection de l'aimant se fait
  attachInterrupt(digitalPinToInterrupt(21), INT0b21, RISING );  //interruption exterieur

//dans loop
if (temps09>=5)  {        //boucle de 1 seconde
lcd.setCursor(13,2);      // effacement de la vitesse
lcd.print("kph     ");
lcd.setCursor(16,2); 
speed1=Tspeed*2937;      //1tour*816*3.6/1s=2.937km/h
speed2=speed1;           //Tspeed (rate/seconde)
speed3=speed2;
speedF=(speed1+speed2+speed3)/3000;   //pour mettre en kph
lcd.print(speedF,1);    //affichage au dixieme pres
Tspeed=0;   //reset compteur
temps09=0;  //reset time
}

Pour ameliorer la precision de la mesure de la vitesse, il est possible que le temps d'echantilonnage de la mesure de la vitesse soit en fonction de la vitesse.
exemple :
pour les vitesses inferieures à 10km/h echantillon à 1seconde, mais au dessus de 10km/h echantillon à 2 secondes.

11. Mesure distance pour connaitre l’autonomie

La distance correspond au nombre de tour total de la roue multipliée par le périmètre de la roue.
Donc il ne faut pas remettre à 0, le nombre de tour à chaque échantillon.
Par contre, la remise à zéro de la distance sera effectuée lors l’appuie sur le reset de l’Arduino Mega.
L’affichage de la distance s’effectuera au deuxième près.
A 32km/h, il faudra 2 minutes pour faire 1km comme on peut l’observer sur la figure suivante :

void INT0b21() {
  Tspeed++;   //interruption exterieure pour compter la vitesse
  nbrRate++;
}

lcd.setCursor(13,4);      
lcd.print("km      ");  //
distance=(nbrRate*816)/1000;  //distance m
distance=distance/1000;  //distance km
lcd.setCursor(15,4);      
lcd.print(distance,1);

on peut observer l'installation electrique avec le hacheur, l'arduino, et l'afficheur lors de la mise au point du programme

12. Synthèse

L’espace RAM est utilisé que à 4% et l’espace ROM à 3%, pour un Arduino mega. Donc, on pourrait prendre un arduino un peu plus petit.
Mais, il y a 8 cellules Lipo pour faire l’alimentation 24V pour alimenter le moteur via le hacheur. Par conséquent, la mesure de la tension de chaque élément sera sur l’Arduino avec un connecteur JST. Cette mesure permet de savoir si une cellule à une résistance interne qui commence à poser problème et pour savoir si l’équilibrage de chaque cellule a bien été effectué.
Il est possible de passer à 36V avec 12 cellules aussi avec l'ardui mega sans utiliser de shield exterieur qui multiplexe 24 entrées analogiques sur l'entrée A0

Il est possible d’envoyer toutes les données à un smarthphone via le bluetooth HC06 par les broches 20, 21, RX1 et TX1. Mais L’application sous android realisée sous JAVA Studio ne peut pas etre partagé sur ce forum. Cette partie ne sera pas explicitée.

Apres avoir fait l'instrumentation de cette trotinnette, une etude devrait etre effectué sur la precision des mesures, il est possible de lire
« Instrumentation d’un véhicule motorisé électrique faible consommation de type « éco marathon » Revue 3EI N°81, Juillet 2015

Voici les schémas électriques, 3 cartes sont utilisées
une carte qui va s'afficher dans l'arduino, mesure température, courant, et qui fait le lien vers la carte afficheur

voici le PCB ou typon sous ARES
telechargeable : PCB Ares arduino mega.LYT - Google Drive

une carte 4 boutons poussoirs et un afficheur LCD recuperer d'ancien systeme microcontroleur qui utilisait des connecteurs HE10

voici le typon double face

une carte hacheur qui va s'enficher dans la premiere carte.
le schema electrique de la commande du hacheur n'a rien à voir avec la carte réelle car l'optocoupleur n'est pas simulable, et il n'y a pas de modele spice de nos composants

a la place d'utiliser, un optocoupleur un driver IRF2110 est preferable d'utilisation.

le condensateur entre le Drain et la source permet de minimiser les oscillations lors des commutations.
de plus, il permet de minimiser les pertes à la commutations dans le transistor.

plus d'infos dans la revue 3EI :
file:///C:/arnaud/EVER%202012/3EI%202017/trotinnette/SIVERT-25.pdf
video
youtube : "study trotinette electric e-scooter 100W et 350W, wiring"

sepduino - Google Search

un livre
« je réalise mon véhicule électrique » chez DUNOD
sur d'autres forums

http://beta.wikifab.org/index.php/Spécial:AjouterDonnées/Tutoriel/Commande_et_instrumentation_de_trottinette_électrique_500W_avec_Arduino_méga

Je n'ai pas eu le temps de regarder en détail mais déjà on peut dire que c'est un superbe travail.

Merci à la section G2I de l'IUT de Soissons à ses professeurs et à ses étudiants.

effectivement, c'est un sacré travail, lequel semble très complet

Je n'ai pas compris l'utilité de la capacité de 470 nF aux bornes du FDU8880 à part créer une pointe de courant d'une centaine d'ampères dans le MOS-FET quand il va conduire ? Ou alors on est en bord de schéma et il faut lire 470 pF ?

Cordialement.

Pierre

pourquoi apres 120 jours, on ne peut rajouter des commentaires ?

C'est possible, mais en français....

Il est plus facile de mettre un contrôleur à 10Euros pour commander la trottinette.
Comme on peut l’observer sur le lien suivant :
http://www.electricscooterparts.com/hookup/SPD-YK31C.htm

Il faut juste relier la batterie au contrôleur, ainsi que le moteur, le bouton on/off et la poignée d’accélération.
Il est possible d’utiliser des dominos, mais des connecteurs Anderson sont plus aisé à utiliser comme on peut l’observer sur la photo ci-jointe.

Par contre, il n’y a aucune instrumentation pour connaitre l’état de l’énergie restante de la batterie, ni la vitesse, ni la puissance demandée par le moteur.
Un cycle analyst pourrait faire cette instrumentation mais cela coute 150euros

Suite à certain message perso

Le fichier ISIS est téléchargeable ici
https://drive.google.com/drive/folders/0B_fB3GAsM02FZkxScXh0cGR5SDA

Le point .ino en Pièce Jointe précédemment
Dans le compilateur Arduino, il faut choisir outil\carte mega 2560
Dans le compilateur Arduino pour faire la simulation dans Isis, il faut croquis\exporter les binaires compilés pour avoir un fichier .hex
Enfin dans Isis, il faut éditer propriété la carte méga et mettre le lien du fichier.
Puis lancer la simulation….