Vélo-scooter électrique

{ Autres sujets du projet :
[Résolu] Mosfet/circuit ne marche pas bien
Chargeur de batterie plomb }

Bonjour, pour un projet de scooter électrique sur base de vélo, j’utilise un arduino. Il y a a deux message car limite de caractères.

L’arduino sert à gérer le moteur, les clignotants et l’affichage du pourcentage de la batteries, de l distance du trajet et de la vitesse instantanée.

1- Partie moteur
2- Partie clignotants
3- Partie batterie
4- Partie compteur de vitesse

Je vais parler uniquement du “circuit de commande” car le reste ne concerne que de la puissance et donc, étant assez simple, je suis sûr du circuit. Les schemas et photos sont en lien pdf

Mon problème de programmation est de mettre tous les codes ensembles pour n’en faire qu’un seul car cela ralentit tous le programme. Mes codes en “solo” fonctionnent très bien mais quand j’essaye de les réunir, tout le programme est ralenti et donc la mesure de vitesse ne se pase plus correctement. Je pense que c’est parce qu’il y a beaucoup de conditions ( if / else if ).

1- Partie moteur :

/* PWM pour moteur à courant continu avec réglage de la souplesse de conduite (2 potentiomètres).
 * On utilise un mosfet n sur le PWM 3 pour commander le moteur
 * Ainsi qu'une poignée accélératrice dont les valeurs min sont 170 et max 870 pour la puissance, et un potentiometre normal pour régler la souplesse de conduite.
  Version 1.4, Incroyables Expériences
  */

void setup() // Boucle d'initialisation.
{
    pinMode(3, OUTPUT);  // Broche 3 réglée comme sortie numérique.
}

float r=0; // Initialisation du rapport cyclique réel à 0.
float s=30; // Initialisation de la souplesse de conduite.
int a=0; // Initialisation du rapport cyclique demandé à 0.
int b=0; // Initialisation de la mémoire du rapport cyclique demandé.
int c=70; // Initialisation du seuil de sécurité (plus il est élevé, moins la sécurité est efficace).

void loop() { // Boucle principale
  a = constrain(a, 170, 870); // Fixation des valeurs extrêmes de l'accélérateur. Cette instruction n’est pas nécessaire si les valeurs de l’accélérateur lues varient bien entre 0 et 1023.
  analogWrite(3,r/1023*254); // Création du PWM.
  a=analogRead(0); // Lecture du rapport cyclique demandé.  (poignée accélératrice)
  s=analogRead(1); // Lecture de la souplesse de conduite demandée.       (potentiometre tableau de bord)

  if(a>b+c){ // Vérification d'une accélération trop brutale (d'origine volontaire ou non).
    digitalWrite(3,LOW); // Arrêt immédiat du moteur.
    while(a>c){ // Attente d'un rapport cyclique très faible pour redémarrer.
      a=analogRead(0); // Lecture continue du rapport cyclique demandé.
    }
  }
  b=a; // Mémorisation du rapport cyclique demandé.

  if(a>r){ // Vérification de la croissance du rapport cyclique demandé.
    delay(20); // Délai responsable de la souplesse de conduite.
    r=r+s/20+2; // Calibrage empirique de la souplesse de conduite.
  }
  if(a<r){ // Vérification de la décroissance du rapport cyclique demandé.
    r=a; // Diminution immédiate du rapport cyclique réel le cas échéant.
  }
  
}

2-Partie clignotants code

*           - 1 interrupteur 3 positions ET UN AUTRE 2 POSITIONS
 *           - 1 arduino
 *           - des fils
 *           
 *bien cabler les leds dans l'ordre sinon ce ne sera plus un chenillard : schema clignotant visuel ci dessous
 *
 *  pin13  pin12  pin11  pin10                         pin6   pin7   pin8   pin9
 *  0      0      0      0                             0      0      0      0
 *  Led4G  Led3G  Led2G  Led1G                         Led1D  Led2D  Led3D  Led4D 
 *  
 *  pour plus de confort, rajout de leds entre sorties des interrupteurs pour faire leds temoins
 */


//définie les pins de déclenchement des clignotants et d'arrêt de ceux-ci
int clignotantgauche = 0;
int clignotantdroit = 1;
int warning = 2;



//définie toutes les pins pour clignotants
int Led1D = 6;   
int Led2D = 7;
int Led3D = 8;
int Led4D = 9;

int Led1G = 10;
int Led2G = 11;
int Led3G = 12;
int Led4G = 13;



void setup() {
  
   //définie les pins de déclenchement comme entrées = INPUT
   pinMode(clignotantgauche, INPUT_PULLUP);
   pinMode(clignotantdroit, INPUT_PULLUP);
   pinMode(warning, INPUT_PULLUP);

  
//Définie les pins clignotants comme sortie = OUTPUT
  pinMode(Led1D,OUTPUT);
  pinMode(Led2D,OUTPUT);
  pinMode(Led3D,OUTPUT);
  pinMode(Led4D,OUTPUT);

  pinMode(Led1G,OUTPUT);
  pinMode(Led2G,OUTPUT);
  pinMode(Led3G,OUTPUT);
  pinMode(Led4G,OUTPUT);  
}

void loop() {

   while(digitalRead(clignotantgauche) == 1){   // si on active le clignotant gauche chenillard vers la gauche
    
    digitalWrite(Led1G, HIGH);
    delay(100);
    digitalWrite(Led2G, HIGH);
    delay(100);
    digitalWrite(Led3G, HIGH);
    delay(100);
    digitalWrite(Led4G, HIGH);
    delay(100);
    
    digitalWrite(Led1G, LOW);
    delay(100);
    digitalWrite(Led2G, LOW);
    delay(100);
    digitalWrite(Led3G, LOW);
    delay(100);
    digitalWrite(Led4G, LOW);
    delay(100);  
  }





   while(digitalRead(clignotantdroit) == 1){       //si l'on active le clignotant droit chenillard vers la droite
    
    digitalWrite(Led1D, HIGH);
    delay(100);
    digitalWrite(Led2D, HIGH);
    delay(100);
    digitalWrite(Led3D, HIGH);
    delay(100);
    digitalWrite(Led4D, HIGH);
    delay(100);
    
    digitalWrite(Led1D, LOW);
    delay(100);
    digitalWrite(Led2D, LOW);
    delay(100);
    digitalWrite(Led3D, LOW);
    delay(100);
    digitalWrite(Led4D, LOW);
    delay(100);  
   }


   //partie warning

   while(digitalRead(warning) == 1){     //si l'on active le second switch les deux chenillard s'allument en meme temps 
    digitalWrite(Led1D, HIGH);
    digitalWrite(Led1G, HIGH);
    delay(100);
    digitalWrite(Led2D, HIGH);
    digitalWrite(Led2G, HIGH);
    delay(100);
    digitalWrite(Led3D, HIGH);
    digitalWrite(Led3G, HIGH);
    delay(100);
    digitalWrite(Led4D, HIGH);
    digitalWrite(Led4G, HIGH);
    delay(100);
    
    digitalWrite(Led1D, LOW);
    digitalWrite(Led1G, LOW);
    delay(100);
    digitalWrite(Led2D, LOW);
    digitalWrite(Led2G, LOW);
    delay(100);
    digitalWrite(Led3D, LOW);
    digitalWrite(Led3G, LOW);
    delay(100);
    digitalWrite(Led4D, LOW);
    digitalWrite(Led4G, LOW);
    delay(100);
    
   }
 
}

La partie clignotants est bloquante car il y a des instructions delay. Donc lorsque tu vas joindre tous tes codes en un seul, elle risque de bloquer l'exécution d'autres fonctions...

Il va falloir la réécrire sans utiliser les delays. C'est faisable, il faut juste apprendre.

Sinon il est probable que ton appli puisse être vue comme une grosse machine à états, et donc programmée comme tel. Ça simplifierait le codage et l'évolution, mais si elle est un peu complexe, ça sera un gros boulot.

3-Partie compteur de vitesse

/*
   Compteur de vitesse
   Merci à Lesept 08/2019
   On utilise un capteur à effet hall analogique qui envoie - de 2v quand un aimant pole nord passe devant le capteur ou + de 3v quand un aimant pole sud passe et 2.5v quand il n'y a rien.
   On utilise un afficheur oled SSD1306 128*64 en I2C pour afficher les infos.
   Ce programme fonctionne, il a été vérifié
   
*/
#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>
#define OLED_RESET 4
Adafruit_SSD1306 display( OLED_RESET );

 
#define valMin 410                          // Définir ici les seuils min      2v
#define valMax 615                          // et max de l'analogRead.         3v
 
const int valMoy = (valMin + valMax) / 2;
const int seuil = (valMax - valMin) / 2;
const int perimetre = 2;                    //entrer le périmètre de la roue en m, le périmètre est égal à   pi*diamètre     ou      pi*2* rayon                       !!!!! EN METRE !!!!!
bool flagMesure = false;
unsigned long tempstrouve = 0;
unsigned long dernierPassage = 0;
float vitesse = 0;
float distance = 0;

void Affiche (float distance, float vitesse) {
  display.setTextSize(1);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(53, 2);
  display.print(distance, 1);

  display.setTextSize(4);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(0, 2);
  display.print(vitesse, 0);
 
  display.display();
}

void setup () {
  display.begin( SSD1306_SWITCHCAPVCC, 0x3C );
  display.clearDisplay();
  Affiche (distance, vitesse);
}


void loop() {
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(74, 2);
  display.print("km");

  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(52, 18);
  display.print("km/h");
  
  int diff = abs(analogRead(A0) - valMoy);
  if (diff >= seuil) { //si un aimant pole nord ou un aimant pole sud passe devant le capteur
    if (flagMesure) {
      tempstrouve = millis() - dernierPassage;
      dernierPassage = millis();
      vitesse = (perimetre / (tempstrouve / 1000.0)) * 3.6; //donne la vitesse en km/h grace à v = d/t
      flagMesure = false;     // pour attente cycle suivant
      distance = distance + (perimetre / 1000.0);
      Affiche (distance, vitesse);
    }
  }
  else
  {
    flagMesure = true;  // prêt pour une nouvelle mesure
  } 
}

4-Partie pourcentage batterie

/*                                                    programme pour afficher et mesurer une tension max de 30VDC pour batteries
 *schema de montage pont diviseur de tension         VIN 30vdc        R1 = 10kOhm     R2 = 2KOhm    Vout = 5V quand Vin 30v
 * 
 * pour plus de précision mesurer avec précision les résistances r1 et r2 et calculer   Vout    sur digikey___calcul_pont_diviseur_de_tension faire 204,6 / ( VIN / Vout )
 * 
 * 
 * les valeurs de capacité selon tensions sont trouvées sur internet et à peu près vrai ( la capacité ne dépent pas que de la tension )  
 */

 
 
#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>

#define OLED_RESET 4
Adafruit_SSD1306 display( OLED_RESET );



void setup () {
  display.begin( SSD1306_SWITCHCAPVCC, 0x3C );
  display.clearDisplay();
  
  
  
}

void loop(){


   //partie bitmap affiché continuellement
  display.display();
  display.drawRect( 101,  0,  27,  11,  WHITE);  //changer les x et y ( la position)              ligne 1
  display.drawRect( 96,  3,  5,  5,  WHITE);  //si ligne 1 changé de position, faire 2 premieres valeurs -3 et les recopier
  display.display();


  
 float tension = analogRead(A0);  //définie la broche mesurant la tension
  tension = ( tension / 34.1 );   //calcule la tension réelle

  int restant;
  if ( tension >= 25.46 ) {
    restant = 100;
  }

  else if ( tension >= 25.24 ) {
    restant = 90;
  }

  else if ( tension >= 25 ) {
    restant = 80;
  }

  else if ( tension >= 24.74 ) {
    restant = 70;
  }

  else if ( tension >= 24.48 ) {
    restant = 60;
  }

  else if ( tension >= 24.20 ) {
    restant = 50;
  }

  else if ( tension >= 23.92 ) {
    restant = 40;
  }

  else if ( tension >= 23.63 ) {
    restant = 30;
  }

  else if ( tension >= 23.32 ) {
    restant = 20;
  }

  else if ( tension >= 23.02 ) {
    restant = 10;
  }
  
  delay(750);
  display.fillRect( 102,  1,  25,  9,  BLACK);
  
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(103, 2);
  display.print(restant);
  display.print("%");
  display.display();


}

Mon problème est donc de réunir tous les codes sans que ça lague car si je réunis juste batterie et compteur de vitesse, je ne peux mesurer plus que 14 km/h.
Si vous avez des idées pour réunir les codes sans que ça ralentisse, je suis preneur car je ne sais absolument pas comment faire.

Merci beaucoup au forum qui m’a aidé à réaliser ces programmes.

Je mets le lien pdf contenant les schemas et deux trois trucs sur ce message.

lien tchat forum.pdf (384 KB)

Ok d'accord, je vais faire ça. Il faut utiliser millis du coup ? Je vais essayer mais je n'ai jamais fait de fonction non bloquante comme ça.

J'ai publié le second message du coup avec les schémas.

Mais je ne pense pas qu'il n'y a que ça car j'avais juste essayé le programme batterie et compteur de vitesse et ça ralentissait tout : je n'arrivai qu'a mesurer 14 km/h max. Je me dis que c'est à cause du nombre infernal de if / else if mais je ne sais pas trop.

Bonjour

Si vous avez des idées pour réunir les codes sans que ça ralentisse, je suis preneur car je ne sais absolument pas comment faire.

Quand des bouts de code ont été conçus indépendemment les uns des autres sans penser au départ à leur 'cohabitation' il n'y a pas de recette infaillible pour les 'fusionner'; les 'mettre ensemble'.

Tout au plus peut on suggérer de remplacer les delays() bloquants par une utilisation de la fonction millis() On gère alors le temps en surveillant l'écart entre deux valeurs successives renvoyées par millis() Etudier l'exemple 'Blink without delay'

Une représentation de l'assemblage actuel sous forme d'algorigrame (rectangles, losanges) permettrrait peut être de faire resortir les causes de ralentissement. le nomnre de if()... n'est pas mais leur imbrication actuelle , oui probablement, en tenant compte de ce qui se passe dans chaque branche.

Autre piste proposée par lesept : repenser globalement l'application en utilisant une organisation sous forme de 'machine à états' Tutoriel : https://forum.arduino.cc/index.php?topic=470879.0

Ton calcul de l'état de la batterie n'est pas tellement optimisé. Tu calcules la tension (en flottant) et tu ne l'utilises pas vraiment, je veux dire pas d'affichage de la valeur. Les calculs en flottant utilisent de la mémoire et du temps CPU pour pas grand chose dans ton cas.

Il serait plus économique de travailler en entier (valeur retournée par analogRead()) et de déterminer la fonction qui lie la valeur d'analogRead() à l'état de la batterie. Excel (ou un autre tableur) permet de faire ça facilement si la fonction n'est pas simple à déterminer.

Le problème de travailler en entier est que la tension doit être en loop car mes échelons tension -> pourcentage utilisent des nombres à deux chiffres après la virgule :

else if ( tension >= 24.74 ) {
    restant = 70;

Sinon pour le code clignotants j'ai réécrit un bout de code :

   while(digitalRead(clignotantgauche) == 1){   // si on active le clignotant gauche chenillard vers la gauche
    
    temps = millis();
    digitalWrite(Led1G, HIGH); 
    if((millis() - temps)> intervalle){
      temps = millis();
      digitalWrite(Led2G, HIGH);
    else if((milis - temps)> intervalle){
      temps = millis();
      digitalWrite(Led3G, HIGH);
    else if((milis - temps)> intervalle){
      temps = millis();
      digitalWrite(Led4G, HIGH);
    else if((milis - temps)> intervalle){
      temps = millis();
      digitalWrite(Led1G, LOW);
    else if((milis - temps)> intervalle){
      temps = millis();
      digitalWrite(Led2G, LOW);
    else if((milis - temps)> intervalle){
      temps = millis();
      digitalWrite(Led3G, LOW);
    else if((milis - temps)> intervalle){
      temps = millis();
      digitalWrite(Led4G, LOW);
    
    }}}}}}}
  }

Mais par contre je ne l'ai pas encore testé. J'aimerais juste savoir si le concept est bien.

Un autre problème est que l'affichage de la vitesse se fait trop souvent. Trop dépendant de la vitesse. Une fois par seconde est largement suffisant.

Ok d'accord. J'ai commencé à réaliser un code complet en modifiant quelque trucs:

  • Affichage du pourcentage seulement toutes les min et dés le début( 60 000 millisecondes ), j'ai donc mis une variable valeurPrecedente2 que je définie à -60000 pour que ça mettes le pourcentage dés le début. Puis j'ai mis tout le programme batterie dans un
if((millis() - valeurPrecedente2)  60000){
  • Je vais continuer en réactualisant la vitesse toutes les secondes comme dit par savoriano

Est ce que ce bout de code des clignotants marcherai ? Je veux juste savoir si la structure est bonne mais j'ai peur que tous les if / else if ralentissent le programme.

while(digitalRead(clignotantgauche) == 1){   // si on active le clignotant gauche chenillard vers la gauche
    
    temps = millis();
    digitalWrite(Led1G, HIGH);
    if((millis() - temps)> intervalle){
      temps = millis();
      digitalWrite(Led2G, HIGH);
    else if((milis - temps)> intervalle){
      temps = millis();
      digitalWrite(Led3G, HIGH);
    else if((milis - temps)> intervalle){
      temps = millis();
      digitalWrite(Led4G, HIGH);
    else if((milis - temps)> intervalle){
      temps = millis();
      digitalWrite(Led1G, LOW);
    else if((milis - temps)> intervalle){
      temps = millis();
      digitalWrite(Led2G, LOW);
    else if((milis - temps)> intervalle){
      temps = millis();
      digitalWrite(Led3G, LOW);
    else if((milis - temps)> intervalle){
      temps = millis();
      digitalWrite(Led4G, LOW);
    
    }}}}}}}
  }

Merci pour toutes vos réponses et vos raisonnement.

[u]PS[/u] Pour le lien machines à états, je suis en cours de lecture. https://forum.arduino.cc/index.php?topic=470879.0

Belo:
Le problème de travailler en entier est que la tension doit être en loop

Je ne comprends pas trop ce que tu entends par là.

Belo:
mes échelons tension → pourcentage utilisent des nombres à deux chiffres après la virgule :

Tu connais la relation qui relie la tension à la valeur retournée par analogRead() donc tu pourrais très facilement remplacer les constantes flottantes par des constantes entière. Et ce serait encore plus simple si tu modélisais la relation tension <==> pourcentage de charge.

while(digitalRead(clignotantgauche) == 1)

While monopolise ton arduino pendant tout le temps du clicnotage.

savoriano:

while(digitalRead(clignotantgauche) == 1)

While monopolise ton arduino pendant tout le temps du clicnotage.

Du coup, comment je fais ?
Car ça ne doit pas etre un if : je m’explique.

Je veux faire une boucle “tant que …, répéter indéfiniment …”
d’ou la présence du while. Existe-il une autre façon de faire ça ?

fdufnews:
Je ne comprends pas trop ce que tu entends par là.
Tu connais la relation qui relie la tension à la valeur retournée par analogRead() donc tu pourrais très facilement remplacer les constantes flottantes par des constantes entière. Et ce serait encore plus simple si tu modélisais la relation tension <==> pourcentage de charge.

Je suis désolé mais je ne comprends pas, j’utilise l’analogRead pour passer d’une valeur entre 0 et 1023 en une tension entre 0 et 30v (pont diviseur de tension).

Ensuite, je prends cette tension pour calculer un pourcentage de 0 à 100 pourcent par échelons de 10 pourcent. Mes échelons sont selon ce tableau ( en lien )trouvé sur Internet et ils sont en flottant.
( 25.46 v… ).
Ce qui fait que j’ai besoin de la tension en flottant car sinon je serais avec soit 26v ou 25v ou 24v ou 23v. Soit 4 Valeurs différentes imprécises.

volts-capacite.jpg

long tempsCligno = 0;
byte pippo = 0, clignotantgauche;
#define Led1G 1
#define Led2G 2
#define Led3G 3
#define Led4G 4
void setup() {
  // put your setup code here, to run once:

}

void loop() {

  if (digitalRead(clignotantgauche) == 1)
  {
    if (tempsCligno < millis())
    {
      pippo++;
      tempsCligno = millis() + 200;
      switch (pippo)
      {
        case 1:
          {
            digitalWrite(Led1G, HIGH);
            break;
          }
        case 2:
          {
            digitalWrite(Led2G, HIGH);
            break;
          }
        case 3:
          {
            digitalWrite(Led3G, HIGH);
            break;
          }
        case 4:
          {
            digitalWrite(Led4G, HIGH);
            break;
          }
        case 5:
          {
            digitalWrite(Led1G, LOW);
            break;
          }
        case 6:
          {
            digitalWrite(Led2G, LOW);
            break;
          }
        case 7:
          {
            digitalWrite(Led3G, LOW);
            break;
          }
        case 8:
          {
            digitalWrite(Led4G, LOW);
            pippo = 0;
            break;
          }
      }
    }
  } else
  {
    tempsCligno = 0;
    digitalWrite(Led1G, LOW);
    digitalWrite(Led2G, LOW);
    digitalWrite(Led3G, LOW);
    digitalWrite(Led4G, LOW);
    pippo = 0;

  }
}

Bon, ça peut marcher.
C’est la première idée qui m’a survolé la tête: Ne me tuez pas!! :confused:

Déjà merci beaucouppppppp et ensuite, vu que je suis un débutant intermédiaire je ne comprends pas tout donc je me renseigne sur le switch case etc sur arduino.cc.

En regardant sur le site, je crois que j’ai compris switch case ( à peu près :confused: ) mais je m’interroge sur plusieurs choses:

savoriano:

if (digitalRead(clignotantgauche) == 1)

{
    If (tempsCligno == 0) tempsCligno = millis + 200;()
    If (tempsCligno < millis’) pippo +=[;
    switch pippo
      Case 1:
      {
        digitalWrite(Led1G, HIGH);     
        digitalWrite(Led2G, LOW);
        digitalWrite(Led3G, LOW);
        digitalWrite(Led4G, LOW);
      }
      Case 2:
      {
        digitalWrite(Led1G, HIGH);     
        digitalWrite(Led2G, HIGH);
        digitalWrite(Led3G, LOW);
        digitalWrite(Led4G, LOW);
      }
      Case 3:
      {
        digitalWrite(Led1G, HIGH);     
        digitalWrite(Led2G, HIGH);
        digitalWrite(Led3G, HIGH);
        digitalWrite(Led4G, LOW);
      }
      Case 4:
      {
        digitalWrite(Led1G, HIGH);     
        digitalWrite(Led2G, HIGH);
        digitalWrite(Led3G, HIGH);
        digitalWrite(Led4G, HIGH);
      }
      Case 5:
      {
        digitalWrite(Led1G, LOW);     
        digitalWrite(Led2G, HIGH);
        digitalWrite(Led3G, HIGH);
        digitalWrite(Led4G, HIGH);
      }
      Case 6:
      {
        digitalWrite(Led1G, LOW);     
        digitalWrite(Led2G, LOW);
        digitalWrite(Led3G, HIGH);
        digitalWrite(Led4G, HIGH);
      }
      Case 7:
      {
        digitalWrite(Led1G, LOW);     
        digitalWrite(Led2G, LOW);
        digitalWrite(Led3G, LOW);
        digitalWrite(Led4G, HIGH);
        pippo = 0;
      }
} else tempsCligno = 0;/code]
Bon ça peut marcher. ( pas compilé!!)
C’est la première idée qui m’a survolé la tête: Ne me tuez pas!! :confused:

  • Les deux Ifs qui se suivent, il ne faut pas mettre des minuscules plutôt que une majuscule : If => if
  • pippo c’est une variable à créer ou un truc arduino genre int ou if ou main…
  • à la fin else tempsCligno = 0;/code] je n’ai pas compris le 0;/code]

J'ai corrigé les erreurs que tu m'as signalé. Je répète: je ne suis pas sur si ça va marcher!! byte pippo et long tempsCligno sont 2 variable globale. change le nom de pippo , c'est mieux. (stepCligno?) Je ne suis pas sur sur la syntaxe de switch!

Regarde https://www.arduino.cc/reference/en/language/structure/control-structure/switchcase/

"Comme les instructions if, switch case contrôle le flux des programmes en permettant aux programmeurs de spécifier un code différent à exécuter dans diverses conditions. En particulier, une instruction switch compare la valeur d'une variable aux valeurs spécifiées dans les instructions case. Lorsqu'une instruction case est trouvée et que sa valeur correspond à celle de la variable, le code de cette instruction case est exécuté.

Le mot clé break quitte l'instruction switch et est généralement utilisé à la fin de chaque cas. En l'absence d'instruction break, l'instruction switch continuera à exécuter les expressions suivantes ("chute directe") jusqu'à ce qu'une pause soit atteinte ou que la fin de l'instruction switch soit atteinte."

copié et traduit du lien

En gros si la condition de case est la meme que celle de switch, ça exécute ce case. Si j'ai bien compris.

Devant son propre ordi c’est mieux.
Il y avait beaucoup d"erreurs.
J’ai modifié le code.
J’ai mis 200 millisecondes entre chaque phase, tu peux modifier comme ça te plaît.

Edit: je re-modifié le code.

Tu connais la relation qui relie la tension à la valeur retournée par analogRead() donc tu pourrais très facilement remplacer les constantes flottantes par des constantes entière. Et ce serait encore plus simple si tu modélisais la relation tension <==> pourcentage de charge.

fdufnews a raison. Tu fais un calcul inutile et en plus en float.
Au lieu de ça:

float tension = analogRead(A0);  //définie la broche mesurant la tension
  tension = ( tension / 34.1 );   //calcule la tension réelle

  int restant;
  if ( tension >= 25.46 ) {
    restant = 100;
  }

tu peux simplifier en ça

if (analogRead(A0) >= 1000){
  int restant = 100;
}

J’ai mis 1000 car je ne connais pas la valeur lue quand t’as >=25.46 Volts

Et ce serait encore plus simple si tu modélisais la relation tension <==> pourcentage de charge.

C’est encore mieux mais il faut un peux de mathématique.

Tu sais que la tension vaut ADC/34,1 donc tu peux calculer les constantes entières équivalentes pour éviter le calcul en flottant

Tension Val ADC
25,46     868
25,24     861
25        853
24,74     844
24,48     835
24,2      825
23,92     816
23,63     806
23,32     795
23,02     785

Tu prends les chiffres colonne de droite dans tes tests à la place des valeur en float.
Par exemple:

float tension = analogRead(A0);  //définie la broche mesurant la tension
 
  int restant;
  if ( tension >= 868 ) {
    restant = 100;
  }

Cette solution fonctionne de la même manière que ton code actuel. Et donc tu affiches toujours l’état de ta batterie par pas de 10%

Autre solution
Tu modélises la courbe de décharge

Tension   Val ADC   Pourcent
25,46      868         100
25,24      861         90
25         853         80
24,74      844         70
24,48      835         60
24,2       825         50
23,92      816         40
23,63      806         30
23,32      795         20
23,02      785         10

Tu calcules la pente dy/dx = (100-10)/(868-785)=1,0843
Et tu en déduis une fonction
Charge = 10+ (ADC-785)*1,0843
Là tu es obligé de faire un calcul en flottant mais en contrepartie tu bénéficies d’un variation continue de l’état de ta batterie.
il faut quand même prendre la précaution de forcer l’affichage à 100% si l’ADC retourne une valeur supérieure à 868.

La modélisation n’est pas trop mauvaise et la courbe est très proche des valeurs que tu donnes.

Ne pas perdre de vue que les valeurs de décharge que tu as sont fortement conditionnées par le mode de décharge. Ta courbe est vrai pour une consommation donnée suivant un cycle de décharge donné. Si le courant est plus (ou moins) fort, si les cycles de décharge sont plus (ou moins) rapprochés la courbe sera moins pertinente et tu peux avoir des surprises sur l’état réel de la batterie.

Merci beaucoup maintenant je comprends ce que vous vouliez dire.
J’ai tout compris grâce à fdufnews et son super tableau-graphique.
Je sais bien que la tension est une valeur approximative et non exacte : le pourcentage restant dépend de la température, du courant de décharge, du nombre de cycles endurées par la batterie…

Du coup j’ai changé le programme et il ressemble à ça :

/*                                                    programme pour afficher et mesurer une tension max de 30VDC pour batteries
 *schema de montage pont diviseur de tension         VIN 30vdc        R1 = 10kOhm     R2 = 2KOhm    Vout = 5V quand Vin 30v
 * 
 * pour plus de précision mesurer avec précision les résistances r1 et r2 et calculer   Vout    sur digikey___calcul_pont_diviseur_de_tension faire 204,6 / ( VIN / Vout )
 * 
 * 
 * les valeurs de capacité selon tensions sont trouvées sur internet et à peu près vrai ( la capacité ne dépent pas que de la tension )  
 */

 
 
#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>

#define OLED_RESET 4
Adafruit_SSD1306 display( OLED_RESET );



void setup () {
  display.begin( SSD1306_SWITCHCAPVCC, 0x3C );
  display.clearDisplay();
  
  
  
}

void loop(){


   //partie bitmap affiché continuellement
  display.display();
  display.drawRect( 101,  0,  27,  11,  WHITE);  //changer les x et y ( la position)              ligne 1
  display.drawRect( 96,  3,  5,  5,  WHITE);  //si ligne 1 changé de position, faire 2 premieres valeurs -3 et les recopier
  display.display();

 int restant;
 
  if ( analogRead(A0)> 868) {
    restant = 100;
  }

  else if ( analogRead(A0)> 861 ) {
    restant = 90;
  }

  else if ( analogRead(A0)> 853 ) {
    restant = 80;
  }

  else if ( analogRead(A0)> 844 ) {
    restant = 70;
  }

  else if ( analogRead(A0)> 835 ) {
    restant = 60;
  }

  else if ( analogRead(A0)> 825 ) {
    restant = 50;
  }

  else if ( analogRead(A0)> 816 ) {
    restant = 40;
  }

  else if ( analogRead(A0)> 806 ) {
    restant = 30;
  }

  else if ( analogRead(A0)> 795 ) {
    restant = 20;
  }

  else if ( analogRead(A0)> 785 ) {
    restant = 10;
  }
  else if ( analogRead(A0)< 785 ) {
    restant = 0;
  }
  
  delay(750);
  display.fillRect( 102,  1,  25,  9,  BLACK);
  
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(103, 2);
  display.print(restant);
  display.print("%");
  display.display();


}

Et le code rassemblant la mesure de vitesse et ce nouveau code:

#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>
#define OLED_RESET 4
Adafruit_SSD1306 display( OLED_RESET );


 
#define valMin 410                          // Définir ici les seuils min      2v
#define valMax 615                          // et max de l'analogRead.         3v
 
const int valMoy = (valMin + valMax) / 2;
const int seuil = (valMax - valMin) / 2;
const int perimetre = 2;                    //entrer le périmètre de la roue en m, le périmètre est égal à   pi*diamètre     ou      pi*2* rayon                       !!!!! EN METRE !!!!!
bool flagMesure = false;
unsigned long tempstrouve = 0;
unsigned long dernierPassage = 0;
long valeurPrecedente2 = -60000;            //on met - 6000 pour que les infos batteries apparaissent dés le début
float vitesse = 0;
float distance = 0;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Compteur (float distance, float vitesse) {
  display.setTextSize(1);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(53, 2);
  display.print(distance, 1);

  display.setTextSize(4);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(0, 2);
  display.print(vitesse, 0);
 
  display.display();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void setup () {
  display.begin( SSD1306_SWITCHCAPVCC, 0x3C );
  display.clearDisplay();
  Compteur (distance, vitesse);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void loop() {
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(74, 2);
  display.print("km");

  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(52, 18);
  display.print("km/h");
  
  int diff = abs(analogRead(A0) - valMoy);
  if (diff >= seuil) { //si un aimant pole nord ou un aimant pole sud passe devant le capteur
    if (flagMesure) {
      tempstrouve = millis() - dernierPassage;
      dernierPassage = millis();
      vitesse = (perimetre / (tempstrouve / 1000.0)) * 3.6; //donne la vitesse en km/h grace à v = d/t
      flagMesure = false;     // pour attente cycle suivant
      distance = distance + (perimetre / 1000.0);
      Compteur (distance, vitesse);
    }
  }
  else
  {
    flagMesure = true;  // prêt pour une nouvelle mesure
  } 


if((millis() - valeurPrecedente2) > 60000){                                                                                            //réactualisation donc calculs du pourcentage batterie toutes les min

    display.display();
    display.drawRect( 101,  0,  27,  11,  WHITE);  //changer les x et y ( la position)              ligne 1
    display.drawRect( 96,  3,  5,  5,  WHITE);  //si ligne 1 changé de position, faire 2 premieres valeurs -3 et les recopier
    display.display();
  
    
    int restant;
 
  if ( analogRead(A0)> 868) {
    restant = 100; }
  else if ( analogRead(A0)> 861 ) {
    restant = 90; }
  else if ( analogRead(A0)> 853 ) {
    restant = 80; }
  else if ( analogRead(A0)> 844 ) {
    restant = 70; }
  else if ( analogRead(A0)> 835 ) {
    restant = 60; }
  else if ( analogRead(A0)> 825 ) {
    restant = 50; }
  else if ( analogRead(A0)> 816 ) {
    restant = 40; }
  else if ( analogRead(A0)> 806 ) {
    restant = 30; }
  else if ( analogRead(A0)> 795 ) {
    restant = 20; }
  else if ( analogRead(A0)> 785 ) {
    restant = 10; }
  else if ( analogRead(A0)< 785 ) {
    restant = 0; }
  
    display.fillRect( 102,  1,  25,  9,  BLACK);
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(103, 2);
    display.print(restant);
    display.print("%");
    display.display();
}
    
}