Arduino et Course de voiture / PB pour classement

Bonjour,

Je te remercie lesept!! :slight_smile:
Le compte à rebours sera avant le déclenchement de la fonction classement donc pas besoin non? (C est dans classement que j enregistre la valeur de millis). Au pire je peux créer une variable boolean pour éviter de repasser par le compte à rebours.

Autres questions....

1/ Je peux mettre un multiplexage afin de limiter le nombre de port ? Je pose la question car les valeurs de ordre sont dans chaque case de tableau résultat. L ordre n est pas égale à 4321 mais à 4,3,2,1. Pour avoir 4231, il faudrait que je multiplie chaque valeur par 1000,100 et 10

2/ j ai lu des post sur le forum pour convertir les ms en secondes. L idée étant de transformer 7654ms en 7.654sec. Sauf que le post transforme en 7.65. Une idée ?

la valeur est la même

un coup elle est affichée avec 3 chiffre après la virgule,
un coup, c'est avec 2 chiffres.

Ne pas confondre la valeur de la variable et ce qui est affiché.
1/3 = 0.3333333333333333...
les affichages possibles sont
0.
0.3
0.33
0.333
....

Re :slight_smile:
Je te remercie lepset..."la remise à zero" fonctionne parfaitement !!!
Pour le compte à rebours, ca marche aussi..j'ai fait une boucle for :slight_smile: j'affiche finalement le meme nombre sur les 4 digits, ca rend super bien.... 8)

Sur le compte a rebours, j'ai soustraits 4000ul car je fais 4 boucles for, non?

Mes autres challenges à présent :
1/ la conversion des millisecondes en secondes. Avec le code ci dessous, ca s'affiche comme ceci:

car3 is 1  in: 1031ms
car2 is 2 en 1210ms a: +179ms de plus que la gagnante
car1 is 3 en 1654ms a: +623ms de plus que la gagnante
car4 is 4 en 2075ms a: +1044ms de plus que la gagnante

si je divise le chrono par 1000...j'obtients cela:

car3 is 1  in: 3s
car2 is 2 en 4s a: +1ms de plus que la gagnante
car1 is 3 en 4s a: +1ms de plus que la gagnante
car4 is 4 en 5s a: +2ms de plus que la gagnante

en reprenant le post que je citais précédemment, je n'y arrive pas.

2/ Il me reste que peu de port disponible (voir photo).
acheter 2 Uno ou 1 mega revient au meme d'un point de vue prix mais concernant le code....le mien marchera t il sur une mega ? ca m'éviterait de devoir gérer les émission/reception. :slight_smile:

3/ Quel écran OLED me conseillez vous? il faut qu'il soit assez grand pour qu'on puisse le voir à 3m.
Chaque ligne mentionnera
Piste Classement Temps Ecart
Piste 4 1 1.031 sec
Piste 3 2 1.210 sec + 0,179sec

Mon code actuel:

/*****************************/
/* 		LES VARIABLES 	     */
/*****************************/

int voie[5] = {0,1,2,3,4}; // tableau dont les valeurs sont les numeros de voie. La case 0 sert pour le compte a rebours
int resultat [4] = {0, 0, 0, 0} ; // tableau des places a l arrivee. la case 0 correspond a la piste 1, la case 1 a la piste 2 et ainsi de suite
int ordre = 1; // la premiere voiture qui franchira l'arrivée aura pour position ordre
unsigned long chronometre [4] = {0, 0, 0, 0} ; // tableau des temps de chaque voiture
int intervalle [4] = {0, 0, 0, 0} ; // tableau qui va enregistrer les intervalle de temps par rapport a la voiture qui a franchie en premier la ligne
int meilleur_chrono=0; // variable du meilleur temps de course

unsigned long start; // variable qui enregistre le moment où le depart est donné
int piste;

int tpsMax = 20000ul; // variable pour la durée maximale de la course. Ca sert surtout quand aucune voiture n'a franchie la ligne

// bouton pousoir 
const int pinBouton  = A4; 
int etatBouton  = 0;
bool race_go=false;

// Bouton pour remise a zero
const int pinRAZ  = A5; 


/* affectation des pins */
int ledPin[8] = {8, 9, 10, 2, 3, 5, 4, 11}; // tableau des segments de l'afficheur
int cellPin[4] = {A0, A1, A2, A3}; /* affectation de la cellule*/
int d[4] = {6, 12, 13, 7};
/* Codes affichage 7 segments */
byte code7segments [10][8] { // LOW = allumé
//  0     1     2     3     4     5     6      7
  {LOW, LOW, LOW, LOW, LOW, LOW, HIGH, HIGH},  // code 0 = ne rien n'afficher si une voiture n'est pas arrivée
  {HIGH, LOW,  LOW,  HIGH, HIGH, HIGH, HIGH, HIGH},  // code 1
  {LOW,  LOW,  HIGH, LOW,  LOW,  HIGH, LOW,  HIGH},  // code 2
  {LOW,  LOW,  LOW,  LOW,  HIGH, HIGH, LOW,  HIGH},  // code 3
  {HIGH, LOW,  LOW,  HIGH, HIGH, LOW,  LOW,  HIGH},  // code 4
  {LOW,  HIGH, LOW,  LOW,  HIGH, LOW,  LOW,  HIGH},  // code 5
  {LOW,  HIGH, LOW,  LOW,  LOW,  LOW,  HIGH, HIGH},  // code 6  
  {LOW,  LOW,  LOW,  HIGH, HIGH, HIGH, HIGH, HIGH},  // code 7  
  {LOW,  LOW,  LOW,  LOW,  LOW,  LOW,  LOW,  HIGH},  // code 8  
  {LOW,  LOW,  LOW,  HIGH, HIGH, LOW,  LOW,  HIGH},  // code 9
} ;



/* initialisation des sorties */
void setup()
{
  Serial.begin(9600); /* connection entre port série de la carte et le PC */
  pinMode(pinBouton,INPUT_PULLUP); // le bouton est pullup envoi 0 à la broche quand on appuie dessus
  pinMode(pinRAZ,INPUT_PULLUP); // bouton pour remettre le circuit a l'etat intial
  for (int i = 0; i < 4; i++) pinMode (cellPin[i], INPUT); // les broches des cellules photo electriques sont des entrées
  for (int i = 0; i < 8; i++) pinMode (ledPin[i], OUTPUT);
  for (int i = 0; i < 4; i++) pinMode (d[i], OUTPUT);
}

void Classement () {
    // boucle for pour remplir le tableau resultat et affficher le classement sur le digit de chaque piste
    for (piste = 0 ; piste < 4 ; piste++) { /* debut de la boucle for */
      if ( resultat[piste] == 0) { // on ne lit que les pistes qui ne sont pas arrivées
        if (digitalRead(cellPin[piste]) == HIGH)  // RAJOUTER ICI UNE CONDITON FALSE QUI PASSERA A TRUE DANS LA BOUCLE
        	{ // si la voiture coupe la ligne d'arrivée
          	resultat[piste] = ordre; 
          	chronometre[piste] = ((millis()- 4000ul - start)); // le chrono de chaque voiture est enregistre dans le tableau chronometre
          	Serial.print("car"); Serial.print(voie[piste+1]);	Serial.print(" is "); Serial.print(resultat[piste]);
          	if (ordre == 1) // on enregistre le meilleur temps
          		{
         		meilleur_chrono = chronometre[piste];
              	Serial.print("  in: "); Serial.print(chronometre[piste]); Serial.println("ms");
          		}
          	else 
           		{
         		intervalle[piste] = chronometre[piste] - meilleur_chrono;
          		Serial.print(" en "); Serial.print(chronometre[piste]); Serial.print("ms");
          		Serial.print(" a: +"); Serial.print(intervalle[piste]);Serial.println("ms de plus que la gagnante");
            	}
          ordre++ ; // on incremente ordre pour la prochaine boucle for 
        	} // fin de la boucle if de digital read
      } // fin de if de resultat[piste]
    } /*fin de la boucle for*/  
} // fin de void classement

void afficherDigit () 
	{
	for (int j = 0 ; j < 4 ; j++) 
    	{ // ici, on va afficher le classement de la piste - on va aller chercher dans tableau la valeur la case 0 qui correspond a la voie 1
      	for (int i = 0 ; i < 4 ; i++) digitalWrite (d[i], i==j ? HIGH : LOW) ;  
      		for (int segment = 0 ; segment <8 ; segment++)
      			digitalWrite (ledPin [segment], code7segments [resultat[j]][segment]);
     	 		delay(50);
    } // end for
}

// fonction pour relancer l'arduino
void(* resetFunc) (void) = 0;


void loop()
{

  etatBouton= digitalRead(pinBouton);
  //Serial.print("etatBouton");Serial.println(etatBouton);
  if (etatBouton == LOW)// depart de la course equand on appuie sur le bouton
    { 
    race_go=true;
	for (int j =4 ; j > 0 ; j--) 
    	{ // ici, on va afficher le classement de la piste - on va aller chercher dans tableau la valeur la case 0 qui correspond a la voie 1
      	for (int i = 4 ; i > 0 ; i--) digitalWrite (d[i-1],HIGH) ;  
      		for (int segment = 0 ; segment <8 ; segment++)
      			digitalWrite (ledPin [segment], code7segments [voie[j-1]][segment]);
     	 		delay(1000);
    	} 
    // mettre le compte à rebours 3,2,1, GO
    Serial.println("etat bouton a change d'etat");
    }   
  if ((race_go==true) && (ordre <= 4) && (millis() < tpsMax))
  	{
    // ICI faire tourner le servo moteur pour liberer les voitures uis lancer millis
    millis ();
    Classement ();
  	}  
  else 
    {
    afficherDigit () ;
  	if (digitalRead (pinRAZ)==LOW) resetFunc ();
    }
  
}

C'était pas moi, c était Biggil ! ! :smiley:

Les écrans OLED que j'utilise ont une diagonale de 2.5 cm, c'est peu pour être lisible a 3 mètres. Si tu prends un écran I2C, il te faut 2 pins supplémentaires.

Les écrans plus grands que je connais sont des TFT, ils vont jusqu'à 6 ou 7 cm de diagonale. En SPI, il te faudra 4 pins.

Merci lesept.

Donc si je rajoute encore 1 pin pour mon servo moteur, 2 ou 4 pins pour l'écran et 4 pins pour des cellules photo électrique si je veux aussi mesures la vitesse .....bref, il me faut a minima alors 7 pins en plus. Car comme sur l'image, une seule UNO est trop limite pour ce montage.

Je n'aurai pas a changer mon code pour la Arduino mega?

Oui avec une méga tu auras de la place. Il existe des versions compactes de la méga qui ont une taille intermédiaire entre UNO et nano

Quand tu dis "je divise par 1000", c'est très insuffisant pour qu'on comprenne ce que tu fais exactement.
ça dépend du type des variables mises en jeu :

int duree_ms  = 4321; // des millisecondes

int iduree_s = duree_ms / 1000; // résultat = 4 

iduree_s = duree_ms / 1000.0000 ; // résultat = 4

float fduree_s = duree_ms / 1000; // résultat = 4.000000

fduree_s = duree_ms / 1000.000 ; // résultat = 4.321000

fduree_s = (float) (duree_ms / 1000); résultat = 4.000000

fduree_s = (float) (duree_ms) / 1000; résultat = 4.321000

Il faut que tu comprennes bien les types int et float, ainsi que la façon dont ils se combinent.
Essaye de retrouver par toi-même les résultats ci dessus.

Je te remercie bigill

Je vais lire plus de doc sur la dénomination des variables

Je vous tiens au courant

Ca fait un joli plat de spaghettis... Est-ce qu'il ne serait pas possible de multiplexer les signaux des afficheurs 7 segments ou des cellules photo électriques, pour gagner quelques pins du Uno ?

lesept:
Ca fait un joli plat de spaghettis... Est-ce qu'il ne serait pas possible de multiplexer les signaux des afficheurs 7 segments ou des cellules photo électriques, pour gagner quelques pins du Uno ?

Je me suis posé la même question lesept mais entre 1 UNO et 1 Mega, c est 20€. Entre mes compétences et le temps pour re apprendre le multiplexage, modifier le code .... Ca vaut plus que 20€.

biggil:
Quand tu dis “je divise par 1000”, c’est très insuffisant pour qu’on comprenne ce que tu fais exactement.
ça dépend du type des variables mises en jeu :

int duree_ms  = 4321; // des millisecondes

int iduree_s = duree_ms / 1000; // résultat = 4

iduree_s = duree_ms / 1000.0000 ; // résultat = 4

float fduree_s = duree_ms / 1000; // résultat = 4.000000

fduree_s = duree_ms / 1000.000 ; // résultat = 4.321000

fduree_s = (float) (duree_ms / 1000); résultat = 4.000000

fduree_s = (float) (duree_ms) / 1000; résultat = 4.321000



Il faut que tu comprennes bien les types int et float, ainsi que la façon dont ils se combinent.
Essaye de retrouver par toi-même les résultats ci dessus.

Bigill,
j’ai ma lecture…
j’en déduis dans mon cas que :

  • start = millis donc float ( s’exprime en entier en ms)
  • chronométre (s’exprime en nombre a virgule en sec) = (millis - start)/1000 mais comme start et millis sont des int je mets (float) avant le calcul
  • meilleur_temps = chronométré (de la première voiture) donc je le déclare en float aussi car il va me servir pour calculer les chrono des autres voitures et il me faut la précision des ms
  • intervalle = meilleur chrono - chrono de la voiture donc je déclare intervalle intervalle en float car je veux la précision sec.ms
int voie[5] = {0,1,2,3,4}; // tableau dont les valeurs sont les numeros de voie. La case 0 sert pour le compte a rebours
int resultat [4] = {0, 0, 0, 0} ; // tableau des places a l arrivee. la case 0 correspond a la piste 1, la case 1 a la piste 2 et ainsi de suite
int ordre = 1; // la premiere voiture qui franchira l'arrivée aura pour position ordre
float chronometre [4] = {0, 0, 0, 0} ; // tableau des temps de chaque voiture
float intervalle [4] = {0, 0, 0, 0} ; // tableau qui va enregistrer les intervalle de temps par rapport a la voiture qui a franchie en premier la ligne
float meilleur_chrono=0; // variable du meilleur temps de course

int start; // variable qui enregistre le moment où le depart est donné

dans le code

resultat[piste] = ordre; 
          	chronometre[piste] = (float)((millis()- 4000ul - start))/1000; // le chrono de chaque voiture est enregistre dans le tableau chronometre
          	Serial.print("car"); Serial.print(voie[piste+1]);	Serial.print(" is "); Serial.print(resultat[piste]);
          	if (ordre == 1) // on enregistre le meilleur temps
          		{
         		meilleur_chrono = chronometre[piste];
              	Serial.print("  in: "); Serial.print(chronometre[piste]); Serial.println("ms");
          		}
          	else 
           		{
         		intervalle[piste] = (chronometre[piste] - meilleur_chrono);

donne comme résultat:

car3 is 1  in: 6.15sec
car4 is 2 en 6.44sec a: +0.29sec de plus que la gagnante
car2 is 3 en 6.84sec a: +0.69sec de plus que la gagnante
car1 is 4 en 7.11sec a: +0.96sec de plus que la gagnante

j’aurais pu utiliser “double float” mais je n’ai pas besoin d’avoir une précision a 15 décimales…“simple” float a déjà une précision a 6 décimales 8)

ma question est “pourquoi ca affiche que 2 décimales???” …j’imagine Bigill que tu va me dire que c’est parce qu’une chose est la valeur et autre chose ce qui est affiché :frowning:

Bigill, Lesept...

ce qui m'embête vraiment en fait dans mon code est que si une voiture se crash....les digits ne s'affichent pas car le "else" attend la 4eme voiture.

si j'affiche a chaque passage de voiture..ca va me fausser les temps...sauf si éventuellement (la seule solution que je vois) j'affiche que la voiture qui vient de passer et non toutes celles qui viennent de passer non? malheureusement, si elles arrivent les 4...les afficheurs vont bouger car il n'y aura pas de Delay.

c'est peut être un faux problème ....

2eme: je pourrais peut etre m'en sortir en envoyant le classement en direct a chaque franchissement sur l'écran LCD ou OLED,qu'en pensez vous? je ne sais pas car j'ai pas encore mis le nez sur ce sujet.

Tu as une réponse dans le message 23 : un timeout.
Sinon, oui, tu peux afficher chaque temps en direct

Pour afficher 3 chiffres après la virgule, dans le cas d'un float, tu fais

Serial.print(x, 3);

Je te remercie lesept…j’avais zappé pour le timeout.

je n’avais pas fait de Tuto sur serial.print…donc merci aussi :slight_smile:

il ne me reste plus qu’à aller faire mes courses (+le servomoteur et les 4 cellules pour le calcul de vitesse mais plus de place sur la UNO de tinkercad :smiley: ) …je laisse le sujet ouvert au cas où j’aie un souci lors du montage (les bibliothèques etc…).

Dans tous les cas, je vous remercie tous: lesept, bigill, jipe38, dfgh, …sur ce post et plus largement ceux qui aident sur ce forum.

Je vous mettrai une video sur la chaine YouTube que j’ai avec mes jumeaux pour que vous ayez le rendu final : LGX Express - YouTube

Cool, j'ai hâte de voir le résultat en vrai... À bientôt

Salut .... en cherchant un grand écran ....

Certaines fois les écrans ont besoin seulement de 4 broches et d’autres fois il y a un Shield qui prend 12 broches ou plus ....pourquoi une telle différence?

bref ... une idée d écran SPI de 10cm de côté pur arduino mega?

Il te faut un écran de 4 pouces. On en trouve sur Aliexpress pour 10€
Vendeur GREATZT STORE

Édit. Il n'est pas SPI, mais avec une méga, tu n'auras pas de problème de manque de pins.

Il faut t'assurer que tu trouveras une bibliothèque qui prenne en compte ce type d'écran ST7796

Je ne trouve pas le lien sur Ali express... peux tu me le donner?

L
Importante pour moi est que l écran ne prenne pas 50 broches, qu on puisse écrire suffisamment gros pour être lu de loin, mettre les infos sur une ligne (voir,classement, temps, vitesse et écart de temps), idéalement avec de la couleur (1 pour chaque voie de voiture)

Le voici
Des promos arrivent dans 2 jours, si tu peux attendre un peu il est possible que le prix baisse

Il semble que la bibliothèque MCUFriend_kbv supporte cet écran.
Le fichier how_to explique comment l'installer et l'utiliser. Tu as intérêt à tester les exemples avant de te lancer dans l'utilisation pour ton code.

David Prentice, son auteur, est très présent sur le forum (partie anglaise), il est sympa et n'hésite pas à aider ceux qui en ont besoin.