ordinateur de bord karting

Bonjour

je voudrais créer un ordinateur de bord pour mon karting qui me donnerai :

  • le régime du moteur (en tour/minute)
  • la température du moteur (en °C)
  • le nombre de tour de circuit réaliser
  • le temps par tour

le tout serai afficher sur un lcd de 20x4 (pour les test c’est un 16x2)
cela serai gérer par un arduino pro mini 16ghz

amélioration:
j’aimerais aussi (si c’est possible) que les 3 derniers temps soit afficher sur l’écran et que a chaque tour l’arduino enregistre le temps du tour et la température du moteur sur une carte SD

j’ai deja commencé le programme

  • le thermomètre fonctionne parfaitement
  • le compte tour de circuit fonctionne lui aussi mais si le contacte est maintenu trop longtemps celui si s’incrémente de plusieurs tour
  • et le chronomètre fonction mais il se contente de ce réinitialiser a chaque tour

c’est pour ca que je viens vers vous !
car je débute tout juste la programmation et la je ne voit pas trop comment faire :confused:

voila la partie du programme que j’ai fais :
( ! attention les eoils ! )

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display
 int TourCi = 0;
 int TourCiaff = 0;
 int ThermistorPin = 0;
 int Vo;
 float R1 = 100000;
 float logR2, R2, T;
 int TE;
 float c1 = 8.2458e-04, c2 = 2.0913e-04, c3 = 7.9780e-08;
 
 unsigned long time;
 unsigned long nextTime;
 int heures;
 int minutes;
 int secondes;
 int disec;
 int capteur;
 
 void setup()
{
 
 
 lcd.init();                      // initialize the lcd 
 lcd.backlight();
 lcd.print("     ALFANO");
 lcd.setCursor(0, 1);
 lcd.print("    by alexis");
 delay(4000);
lcd.clear();
delay(1000);
  pinMode(3,INPUT);
  pinMode(2,INPUT);
  heures = 0;
  minutes = 0;
  secondes = 0;
  disec = 0;
  
 
  
 
}

void loop()
{
 // nombre de tour de circuit  


 
 TourCi = digitalRead(3);
  if(TourCi == (HIGH) {
    TourCiaff = TourCiaff + 1;
  }

 // temps par tour de circuit (chronometre)

// Tout les 100 millis aller dans la routine
if (millis() > nextTime) {
   nextTime += 100;
   Affichage();
   }




 // régime moteur 
 


 

 // thermometre 

  Vo = analogRead(ThermistorPin);
  R2 = R1 * (1023.0 / (float)Vo - 1.0);
  logR2 = log(R2);
  T = (1.0 / (c1 + c2*logR2 + c3*logR2*logR2*logR2));
  T = T - 273.15;

  TE = (int) T;

 // affichage sur l'écran
   


 lcd.print("regim");
 lcd.print("T/MIN  ");
 lcd.print(TourCiaff);
 lcd.print("t");
 lcd.setCursor(0, 1);
 lcd.print(TE);
 lcd.print((char)223);
 lcd.print("C  ");
lcd.print(minutes);
lcd.print(":");
lcd.print(secondes);
lcd.print(":");
lcd.print(disec);
lcd.home();


}

 void Affichage()
{
 if (TourCi == HIGH) {
   heures = 0;
minutes = 0;
secondes = 0;
disec = 0;
  }

  else
{ 
disec++;

if(disec == 10){
  disec = 0;
  secondes++;
  }
if(secondes == 60)
  {
  secondes = 0;
  minutes++;
  }
if(minutes == 60)
  {
  minutes = 0;
  heures++;
  }
if (heures == 24)
  {
  heures = 0;
  }



}
}

et voila le schéma :

  • le composant gris c’est la thermistance
  • la bobine représente le capteur d’allumage (l’entré de l’arduino sera bien entendu protégé contre les surtension)
  • et l’ILS c’est le capteur qui permet de détecter quand on commence et quand on termine un tour

voila voila
j’espère ne pas vous avoir trop embêté avec mon projet
merci d’avance
alexis

Salut

Concernant l'ILS tu as deux problèmes. Tu tiens seulement compte de l'état du contact. Tu dois tenir compte du changement d'état, c'est à dire incrémenter le compteur sur la montée ou la descente du signal. Tu dois aussi éliminer les rebonds, car un ILS n'est pas un interrupteur parfait.

Tu peux installer la librairie Bounce2, et t'inspirer de cet exemple.

@+

salut @hbachetti

je ne comprend pas trop ce que cela change car au lieu de recommencer a chaque impulsion tu recommence a chaque changement d'état

sinon pour le rebond je vais voir

alexis

C'est simple à comprendre :

   // nombre de tour de circuit  
   TourCi = digitalRead(3);
   if(TourCi == (HIGH) {
     TourCiaff = TourCiaff + 1;
   }

Tant que ton entrée est lue à 1 ton compteur est incrémenté. Donc si l'ILS se ferme trop longtemps le compteur s'incrémente plusieurs fois.

Je te cite :

  • le compte tour de circuit fonctionne lui aussi mais si le contacte est maintenu trop longtemps celui si s'incrémente de plusieurs tour

@+

mais du coup comment je met ca en place dans mon programme ?

car je comprend pas tout la dedans

#include <Bounce2.h>

#define BUTTON_PIN 2
#define LED_PIN 13

int ledState = LOW;


Bounce debouncer = Bounce(); // Instantiate a Bounce object

void setup() {
  
  debouncer.attach(BUTTON_PIN,INPUT_PULLUP); // Attach the debouncer to a pin with INPUT_PULLUP mode
  debouncer.interval(25); // Use a debounce interval of 25 milliseconds
  
  
  pinMode(LED_PIN,OUTPUT); // Setup the LED
  digitalWrite(LED_PIN,ledState);
 
}

void loop() {

   debouncer.update(); // Update the Bounce instance
   
   if ( debouncer.fell() ) {  // Call code if button transitions from HIGH to LOW
     ledState = !ledState; // Toggle LED state
     digitalWrite(LED_PIN,ledState); // Apply new LED state
   }
}

Tu prends les lignes intéressantes de l'exemple et tu les inclus dans ton code. A part les lignes qui gèrent la LED, toutes les autres doivent être copiées au bons endroits.

Un indice : Dans ton cas BUTTON_PIN vaut 3.

Avec le nombre de commentaires figurant dans ce code, tu pourrais faire un effort de traduction.

@+

Je te propose ça :

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display
#include <Bounce2.h>
#define BUTTON_PIN 3
Bounce debouncer = Bounce(); // Instantiate a Bounce object

int TourCi = 0;
int TourCiaff = 0;
int ThermistorPin = 0;
int Vo;
float R1 = 100000;
float logR2, R2, T;
int TE = 0;
float c1 = 8.2458e-04, c2 = 2.0913e-04, c3 = 7.9780e-08;

unsigned long nextTime;
int heures;
int minutes;
int secondes;
int disec;
int capteur;
boolean TourCi = false;

void setup()
{
  lcd.init();                      // initialize the lcd
  lcd.backlight();
  lcd.print("     ALFANO");
  lcd.setCursor(0, 1);
  lcd.print("    by alexis");
  delay(4000);
  lcd.clear();
  delay(1000);
  pinMode(3, INPUT);
  pinMode(2, INPUT);
  heures = 0;
  minutes = 0;
  secondes = 0;
  disec = 0;
  debouncer.attach(BUTTON_PIN, INPUT_PULLUP); // Attach the debouncer to a pin with INPUT_PULLUP mode
  debouncer.interval(25); // Use a debounce interval of 25 milliseconds
}

void loop()
{
  // nombre de tour de circuit
  debouncer.update(); // Update the Bounce instance
  if (debouncer.fell()) {
    TourCi = true;
    TourCiaff = TourCiaff + 1;
  }
  // temps par tour de circuit (chronometre)
  // Tout les 100 millis aller dans la routine
  if (millis() > nextTime) {
    nextTime += 100;
    Affichage();
  }
  // régime moteur

  // thermometre
  Vo = analogRead(ThermistorPin);
  R2 = R1 * (1023.0 / (float)Vo - 1.0);
  logR2 = log(R2);
  T = (1.0 / (c1 + c2 * logR2 + c3 * logR2 * logR2 * logR2));
  T = T - 273.15;
  TE = (int) T;
  // affichage sur l'écran
  lcd.print("regim");
  lcd.print("T/MIN  ");
  lcd.print(TourCiaff);
  lcd.print("t");
  lcd.setCursor(0, 1);
  lcd.print(TE);
  lcd.print((char)223);
  lcd.print("C  ");
  lcd.print(minutes);
  lcd.print(":");
  lcd.print(secondes);
  lcd.print(":");
  lcd.print(disec);
  lcd.home();
}

void Affichage()
{
  if (TourCi) {
    heures = 0;
    minutes = 0;
    secondes = 0;
    disec = 0;
    TourCi = false;
  }
  else
  {
    disec++;
    if (disec == 10) {
      disec = 0;
      secondes++;
    }
    if (secondes == 60)
    {
      secondes = 0;
      minutes++;
    }
    if (minutes == 60)
    {
      minutes = 0;
      heures++;
    }
    heures = heures % 24;
  }
}

J’ai fait ce que dit Henri, mais en même temps que sa réponse. Bounce2 suppose que ton bouton (ILS ?) est câblé en Pullup (voir ici au besoin)


Pour toi, la résistance est interne à l’Arduino, pas besoin de l’ajouter. Comme je ne connais pas ce “ILS”, je ne sais pas si c’est correct de le déclarer ainsi.

Sinon, ta gestion du temps (la recherche des dixièmes de secondes) n’est pas précise à mon avis. Tu devrais faire ça :

  • Déclarer un unsigned long chrono; dans l’entête
  • L’initialiser à la fin du setup : chrono = millis();
  • Puis :
if (millis()-chrono >= nextTime) {
  chrono = millis();  
  Affichage();

merci lesept et hbachetti !
sa fonctionne parfaitement ! :wink:

lesept

Sinon, ta gestion du temps (la recherche des dixièmes de secondes) n’est pas précise à mon avis. Tu devrais faire ça :
Déclarer un unsigned long chrono; dans l’entête
L’initialiser à la fin du setup : chrono = millis();
Puis :

Code: [Select]
if (millis()-chrono >= nextTime) {
chrono = millis();
Affichage();

j’ai fais exactement ce que tu ma dis mais les secondes son désormais plus “rapide” qu"une seconde “normale”

je vous en demande beaucoup mais si vous pouviez corrigé mon programme pour qu’il fonctionne parfaitement je vous en serait très reconnaissant

alexis

J'ai oublié de fermer l'accolade après l'appel de Affichage() : tu l'as ajoutée ?

je pense que oui car il ne ma rein dit

qu'on soit bien d'accord

if (millis()-chrono >= nextTime) {
  chrono = millis();  
  Affichage();

c'est censé remplacer ca

if (millis() > nextTime) {
    nextTime += 100;
    Affichage();
  }

car c'est ce que j'ai fais

if (millis()-chrono >= nextTime) {
  chrono = millis();  
  Affichage();
  }

remplace

if (millis() > nextTime) {
    nextTime += 100;
    Affichage();
  }

Je ne vois pas comment ça ferait aller les secondes plus vite... Essaye avec > au lieu de >= mais je ne pense pas que ça change grand chose...

Tu peux ajouter chrono = millis();à la fin du setup.

je viens de tester - le miens tout seul : secondes 2 fois plus rapide de 0 a 10 puis elle devient normale - le tiens tous seule : secondes 2 fois plus rapide tout le temps - les 2 ensembles : meme chose que pour le miens tout seul

J"ai oublié il faut initialiser dans l'entête : unsigned long nextTime = 100;

cela donne exactement la même chose que le mien tout seul les 10 premières secondes sont plus rapide (2x)

Je pense qu'il faut ôter le else dans Affichage()

cela fonctionne a peut près le chrono est plus rapide les 10 premières secondes du premier tour et après il redevient normale (même sur les autre tour) donc vu que le premier tour c'est celui ou on ne tape pas trop de dans c'est pas un problème

maintenant il me reste a faire le compte tour moteur je ne vois pas trop comment faire mais je suis le poste de @Diabolux qui est en train dans réaliser un

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

si malgré tout vous avez des conseille a me donné je suis preneur

alexis

J’ai un peu revu ton code, notamment tu faisais une mesure de température à chaque tour de loop ce qui est trop souvent. C’est peut-être pour ça que le chrono ne fonctionnait pas : dans cette version, elle est mesurée tous les dixièmes de seconde, ce qui est encore bien trop souvent. J’ai aussi changé lcd.init en lcd.begin (mais c’est peut-être parce que je n’ai pas la même bibliothèque).

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Bounce2.h>
#define BUTTON_PIN 3
LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display
Bounce debouncer = Bounce(); // Instantiate a Bounce object

int TourCiaff = 0;
unsigned long nextTime = 100;
unsigned long chrono;
byte heures = 0;
byte minutes = 0;
byte secondes = 0;
byte disec = 0;
int capteur;
int TE = 0;

void setup()
{
  lcd.begin();
  lcd.backlight();
  lcd.print("     ALFANO");
  lcd.setCursor(0, 1);
  lcd.print("    by alexis");
  delay(4000);
  lcd.clear();
  // Préparation de l'affichage
  Affichage ();
  //
  pinMode(2, INPUT);
  pinMode(BUTTON_PIN, INPUT);
  debouncer.attach(BUTTON_PIN, INPUT_PULLUP); // Attach the debouncer to a pin with INPUT_PULLUP mode
  debouncer.interval(25); // Use a debounce interval of 25 milliseconds
  chrono = millis();
}

void loop()
{
  // nombre de tour de circuit
  debouncer.update(); // Update the Bounce instance
  if (debouncer.fell()) {
    TourCiaff = TourCiaff + 1;
    heures = 0;
    minutes = 0;
    secondes = 0;
    disec = 0;
  }
  // temps par tour de circuit (chronometre)
  // Tout les 100 millis aller dans la routine
  if (millis() - chrono >= nextTime) {
    chrono = millis();
    MaJTime();
    // régime moteur

    // thermometre
    TE = MesureTemp ();
    // affichage sur l'écran
    Affichage ();
  }
}

void MaJTime()
{
  disec++;
  if (disec == 10) {
    disec = 0;
    secondes++;
  }
  if (secondes == 60)
  {
    secondes = 0;
    minutes++;
  }
  if (minutes == 60)
  {
    minutes = 0;
    heures++;
  }
  heures = heures % 24;
}

int MesureTemp () {
  int ThermistorPin = 0;
  int Vo = analogRead(ThermistorPin);
  float R1 = 100000;
  float c1 = 8.2458e-04, c2 = 2.0913e-04, c3 = 7.9780e-08;
  float R2 = R1 * (1023.0 / (float)Vo - 1.0);
  float logR2 = log(R2);
  float T = (1.0 / (c1 + c2 * logR2 + c3 * logR2 * logR2 * logR2));
  T = T - 273.15;
  int Temp = (int) T;
  return Temp;
}

void Affichage () {
  lcd.setCursor(0, 0);
  lcd.print("Regime T/MIN ");
  lcd.print(TourCiaff);
  lcd.setCursor(0, 1);
  lcd.print("T ");
  lcd.print(TE);
//  lcd.print((char)223);
  lcd.print("C ");
  lcd.print(minutes);
  lcd.print(":");
  lcd.print(secondes);
  lcd.print(".");
  lcd.print(disec);
}

Il faudra que tu refasses la fonction d’affichage, que j’ai faite en aveugle (je n’ai pas d’écran ici et je ne sais pas comment tu veux organiser ton afficheur).

franchement merci a toi lesept pour ton aide ;) le programme fonctionne parfaitement plus que le compte tour et c'est fini

alexis

pour le regime moteur j’ai trouvé un programme qui faisait a quelque chose près ce que je voulais

je l’ai adapter a mes besoin ce qui donne se programme la :

#include <LiquidCrystal_I2C.h>
#include <Wire.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

volatile long comptageImpuls=0; // variable accessible dans la routine interruption externe 0

long timeRef=0; // variable pour temps de référence en millisecondes
long delai=1000; // variable pour délai de comptage en millisecondes 


void setup() {  

lcd.init();
  lcd.backlight();




attachInterrupt(0, gestionINT0, RISING); // attache l'interruption externe n°0 à la fonction gestionINT0()
// mode déclenchement possibles = LOW, CHANGE, RISING, FALLING




timeRef=millis(); // initialisation de la référence du comptage 

} // fin de la fonction setup()
// ********************************************************************************

////////////////////////////////// 3. FONCTION LOOP = Boucle sans fin = coeur du programme //////////////////
// la fonction loop() s'exécute sans fin en boucle aussi longtemps que l'Arduino est sous tension

void loop(){ // debut de la fonction loop()

if (millis()>(timeRef+delai)) { // si le delai de comptage est écoulé

  timeRef=timeRef+delai; // réinitialise le délai de comptage

comptageImpuls = comptageImpuls*60;


lcd.backlight();
lcd.setCursor(0, 0);
lcd.print(comptageImpuls);
lcd.print(" T/MIN");
  
  

  comptageImpuls=0; // RAZ comptage impulsions
} // fin si délai de comptage s'est écoulé





} 
void gestionINT0() {

comptageImpuls=comptageImpuls+1; // incrémente comptage Impulsion

}

en voyant qu’il fonctionnait bien (le regime afficher est a 99% le régime réelle du moteur 1% d’erreur sa reste acceptable) j’ai décidé de l’intégré au programme que lesept a refait

ce qui donne ca

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Bounce2.h>
#define BUTTON_PIN 3
LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display
Bounce debouncer = Bounce(); // Instantiate a Bounce object

volatile long comptageImpuls=0; // variable accessible dans la routine interruption externe 0

long timeRef=0; // variable pour temps de référence en millisecondes
long delai=1000; // variable pour délai de comptage en millisecondes 



int TourCiaff = 0;
unsigned long nextTime = 100;
unsigned long chrono;
byte heures = 0;
byte minutes = 0;
byte secondes = 0;
byte disec = 0;
int capteur;
int TE = 0;

void setup()
{
  lcd.init();
  lcd.backlight();
  lcd.print("     ALFANO");
  lcd.setCursor(0, 1);
  lcd.print("    by alexis");
  delay(4000);
  lcd.clear();
  // Préparation de l'affichage
  Affichage ();
  //
  pinMode(2, INPUT);
  pinMode(BUTTON_PIN, INPUT);
  debouncer.attach(BUTTON_PIN, INPUT_PULLUP); // Attach the debouncer to a pin with INPUT_PULLUP mode
  debouncer.interval(25); // Use a debounce interval of 25 milliseconds
  chrono = millis();

 attachInterrupt(0, gestionINT0, RISING); // attache l'interruption externe n°0 à la fonction gestionINT0()
// mode déclenchement possibles = LOW, CHANGE, RISING, FALLING




timeRef=millis(); // initialisation de la référence du comptage 
  
}

void loop()
{
  // nombre de tour de circuit
  debouncer.update(); // Update the Bounce instance
  if (debouncer.fell()) {
    TourCiaff = TourCiaff + 1;
    heures = 0;
    minutes = 0;
    secondes = 0;
    disec = 0;
  }
  // temps par tour de circuit (chronometre)
  // Tout les 100 millis aller dans la routine
  if (millis() - chrono >= nextTime) {
    chrono = millis();
    MaJTime();
    
    // régime moteur

 regime();

comptageImpuls = comptageImpuls*60;



  comptageImpuls=0; // RAZ comptage impulsions
} // fin si délai de comptage s'est écoulé


    // thermometre
    TE = MesureTemp ();
    // affichage sur l'écran
    Affichage ();
  }

void regime() {

if (millis()>(timeRef+delai)) { // si le delai de comptage est écoulé

  timeRef=timeRef+delai; // réinitialise le délai de comptage
}
}
void gestionINT0() {

comptageImpuls=comptageImpuls+1; // incrémente comptage Impulsion

}


void MaJTime()
{
  disec++;
  if (disec == 10) {
    disec = 0;
    secondes++;
  }
  if (secondes == 60)
  {
    secondes = 0;
    minutes++;
  }
  if (minutes == 60)
  {
    minutes = 0;
    heures++;
  }
  heures = heures % 24;
}

int MesureTemp () {
  int ThermistorPin = 0;
  int Vo = analogRead(ThermistorPin);
  float R1 = 100000;
  float c1 = 8.2458e-04, c2 = 2.0913e-04, c3 = 7.9780e-08;
  float R2 = R1 * (1023.0 / (float)Vo - 1.0);
  float logR2 = log(R2);
  float T = (1.0 / (c1 + c2 * logR2 + c3 * logR2 * logR2 * logR2));
  T = T - 273.15;
  int Temp = (int) T;
  return Temp;
}

void Affichage () {
  lcd.setCursor(0, 0);
  lcd.print(comptageImpuls);
  lcd.print(" T/MIN ");
  lcd.print(TourCiaff);
  lcd.setCursor(0, 1);
  lcd.print("T ");
  lcd.print(TE);
  lcd.print((char)223);
  lcd.print("C ");
  lcd.print(minutes);
  lcd.print(":");
  lcd.print(secondes);
  lcd.print(".");
  lcd.print(disec);
}

mais cela ne fonctionne pas du tout
il m’affiche bien une valeur mais celle si est comme qui dirait accès loin ! (1% de la réalité :o )

j’imagine que mon erreur est une erreur de débutant mais je n’arrive pas a la trouver (j’ai testé plusieurs truc mais sa ne change strictement rien)

si quelqu’un la trouve je veux bien qu’il m’explique quelle est mon erreur

merci d’avance
alexis

Après lecture rapide, je pense qu'il faut mettre les lignes

    // régime moteur



comptageImpuls = comptageImpuls*60;



  comptageImpuls=0; // RAZ comptage impulsions

après l'accolade et pas avant

} // fin si délai de comptage s'est écoulé