LOCODUINO
Parlons Arduino => Vos projets => Discussion démarrée par: Mcarmina le juin 13, 2017, 12:10:42 am
-
Bonsoir à vous tous,
je développe (j'essaye) un décodeur accessoire basé sur un nano et la bibliothèque de minabay pour piloter 7 servo d'aiguillage avec un relais pour la pointe de coeur.
mon système fonctionne bien, pas de soucis mais :
pour plus de réalisme j'ai ralenti la vitesse du décodeur dans une boucle comme ci dessous (les serial.print sont uniquement là pour comprendre ce qui se passe)
le temps de déplacement d'une butée à l’autre est de 1sec. Pendant ce temps le nano n'est pas capable de lire une commande DCC. Je suis sur Train Controller et Train Controller envoi les ordres les uns derrière les autres sans delai, le résultat fait que mon système n'est pas capable de lire toutes les commandes DCC envoyées par la centrale. en fait il lit la premiere et puis plus rien tant que le servo n'est pas arrivé
Logiquement j'ai inserré une commande DCC.loop() dans la boucle for pour pouvoir lire plusieurs commande DCC en provenance de la centrale.
case 0: // bouge le servo vers position droite
for (pos = Aig[xx][2] ; pos <= Aig[xx][1] ; pos = pos + Pas) {
Aig1.writeMicroseconds(pos);
Serial.println (pos);
delay(30);
if (pos == xP + Aig[xx][2] ) {
Serial.println("vers pos droite pos Droit > devié relais actionne");
digitalWrite (NumPinR[xx], LOW);
DCC.loop();
}
}
Aig1.writeMicroseconds(Aig[xx][1] + Ressort);
break;
case 1: // bouge le servo vers position deviee
for (pos = Aig[xx][1] ; pos >= Aig[xx][2] ; pos = pos - Pas) {
Aig1.writeMicroseconds(pos);
Serial.println (pos);
delay(30);
if (pos == Aig[xx][1] - xP) {
Serial.println("vers pos deviee pos Droit > devié relais actionne");
digitalWrite (NumPinR[xx], HIGH);
DCC.loop();
}
}
dans la routine de lecture de la commande j'ai cree une pile pour sauvegarder les commandes DCC envoyées par la centrale
void BasicAccDecoderPacket_Handler(int address, boolean activate, byte data)
{
// Convert NMRA packet address format to human address
address -= 1;
address *= 4;
address += 1;
address += (data & 0x06) >> 1;
Etat = (data & 0x01) ? HIGH : LOW;
Serial.print ("addresse lue DCC: ");
Serial.print (address);
Serial.print (" Position cde: ");
Serial.print (Etat);
Serial.print (" pointeur pile: ");
Serial.println (PileAdrPointeur);
if ((address >= DCC_AddressDeb) && (address < DCC_AddressDeb + NbrServo) && (PileAdrPointeur < NbrServo + 2)) {
if ((PileAdrPointeur >= 1)) { // gestion de la pile a l'empilage
DCC_AddressLu = PileAdr[PileAdrPointeur-1] ;
EtatCdeDCC = PileAigPos[PileAdrPointeur-1] ;
}
else {
DCC_AddressLu = 0;
}
if ((DCC_AddressLu == address) && (EtatCdeDCC != Etat) || (DCC_AddressLu != address)) {
PileAdrPointeur = PileAdrPointeur + 1 ;
PileAdr[PileAdrPointeur-1] = address ;
PileAigPos[PileAdrPointeur-1] = Etat;
Serial.print ("addresse sauver sur pile: ");
Serial.print (address);
Serial.print (" Position Cde sauve: ");
Serial.print (Etat);
Serial.print (" pointeur :");
Serial.println (PileAdrPointeur);
}
}
}
et dans ma void loop() je depile et actionne mes servos
void loop()
{
Tp1 = millis();
DCC.loop();
if (PileAdrPointeur >= 1) { // Gestion de la pile au depilage
DCC_AddressLu = PileAdr[0] ;
EtatCdeDCC = PileAigPos
AigPos[DCC_AddressLu - DCC_AddressDeb] = EtatCdeDCC;
EtatChange = true ;
for (xx = 2 ; xx <= PileAdrPointeur ; xx++) { // depile
PileAdr[xx - 2] = PileAdr[xx - 1];
PileAigPos[xx - 2] = PileAigPos[xx - 1];
}
PileAdrPointeur = PileAdrPointeur - 1;
}
if (EtatChange == true) { // actionne le servo lu par le DCC
Serial.print("@ à bouger: ");
Serial.print(DCC_AddressLu);
Serial.print(" etat: ");
Serial.println(EtatCdeDCC);
Tp = millis();
switch (DCC_AddressLu - DCC_AddressDeb) {
case 0: // aiguillage 1
xx = 0;
Update_Aig();
Update_Aig1();
break ;
case 1: // aiguillage 2
xx = 1;
Update_Aig();
Update_Aig2();
break;
case 2: // aiguillage 3
bon ben ça ne marche pas, j'ai comme l'impression que les commandes DCC.loop() dans les boucles for ne fonctionnent pas
un peu d'aide svp, merci, je bloque et ne comprends pas pourquoi.
pour info, il y a 10 mois je ne connaissais pas l’existence du langage C, donc il doit bien y avoir dans mon code quelques problemes, soyez donc indulgent :)
-
...
le temps de déplacement d'une butée à l’autre est de 1sec. Pendant ce temps le nano n'est pas capable de lire une commande DCC. Je suis sur Train Controller et Train Controller envoi les ordres les uns derrière les autres sans delai, le résultat fait que mon système n'est pas capable de lire toutes les commandes DCC envoyées par la centrale. en fait il lit la premiere et puis plus rien tant que le servo n'est pas arrivé
Logiquement j'ai inserré une commande DCC.loop() dans la boucle for pour pouvoir lire plusieurs commande DCC en provenance de la centrale.
Bonjour,
Une première piste : je ne sais pas quelle est la finalité des instructions delay(30) dans la routine mais toujours est-il que la fonction delay() met en pause totale le programme. Donc si des commandes DCC arrivent durant cette pause, elles seront perdues.
Par ailleurs, et à titre personnel, je ne trouve pas très heureux le choix de la police utilisée pour retranscrire du code.
L'utilisation de la balise "Code" (bouton #) serait sans doute plus judicieux. Exemple :
case 0: // bouge le servo vers position droite
for (pos = Aig[xx][2] ; pos <= Aig[xx][1] ; pos = pos + Pas) {
Aig1.writeMicroseconds(pos);
Serial.println (pos);
delay(30);
if (pos == xP + Aig[xx][2] ) {
Serial.println("vers pos droite pos Droit > devié relais actionne");
digitalWrite (NumPinR[xx], LOW);
DCC.loop();
}
}
Aig1.writeMicroseconds(Aig[xx][1] + Ressort);
break;
case 1: // bouge le servo vers position deviee
for (pos = Aig[xx][1] ; pos >= Aig[xx][2] ; pos = pos - Pas) {
Aig1.writeMicroseconds(pos);
Serial.println (pos);
delay(30);
if (pos == Aig[xx][1] - xP) {
Serial.println("vers pos deviee pos Droit > devié relais actionne");
digitalWrite (NumPinR[xx], HIGH);
DCC.loop();
}
}
Jean-Michel :)
-
Bonjour Jean-Michel,
Tu as raison, il ne faut absolument pas utiliser l'instruction delay() qui te fera perdre tous les événements arrivant pendant ce temps là (sauf à utiliser les interruption, et encore...).
Il faut mémoriser le temps machine avec millis() au début d'une phase d'attente et tester ensuite, à chaque tour de loop, la position du temps machine par rapport à la valeur mémorisée augmentée du temps d'attente désiré.
Voilà !
Il y a plein d'exmples dans Locoduino (utiliser la fonction de recherche)
Amicalement
Dominique
-
L'utilisation de la balise "Code" (bouton #) serait sans doute plus judicieux
C'est fait pour cela ;D ;D
-
merci pour vos réponses je vais donc aller vers une orientation plutôt millis() que delay()
et pour l'option "code" , promis je n'utiliserai que cette option pour visualiser du code
-
Sinon, tu peux t'inspirer de ce que j'ai fait dans la bibliothèque Accessories qui déplace le servo d'un pas à chaque loop(), jusqu'à ce que le mouvement soit terminé. Cela permet aussi de déplacer plusieurs servos simultanément... Au final, pourquoi ne pas utiliser Accessories et Commanders qui ont déjà géré tout ça ?
-
Sinon, tu peux t'inspirer de ce que j'ai fait dans la bibliothèque Accessories qui déplace le servo d'un pas à chaque loop(), jusqu'à ce que le mouvement soit terminé. Cela permet aussi de déplacer plusieurs servos simultanément... Au final, pourquoi ne pas utiliser Accessories et Commanders qui ont déjà géré tout ça ?
Merci pour ta reponse,
honnêtement je n'ai pas regardé les codes de ces programmes et encore une fois je n'ai pas une grande experience du C, donc il m'est difficile de comprendre.
Avec ceux ci pendant le déplacement du (des) servo , peux tu recevoir d'autres commandes DCC pour le même Nano ?
en d'autres termes, Accessories et commanders enregistrent ils les commandes en provenance de la centrale sans pertes pendant un déplacement servo ?
-
Un déplacement n'est pas bloquant pour le reste du programme, donc oui, les événements DCC sont reçus, y compris pendant les mouvements des servos. C'est même plutôt l'inverse: comme c'est géré par des interruptions, le Dcc est prioritaire. Du coup les mouvement des servos peuvent être perturbés par la réception Dcc, mais vu les timings concernés, je ne pas sûr que l'interruption soit détectable...
-
Un déplacement n'est pas bloquant pour le reste du programme, donc oui, les événements DCC sont reçus, y compris pendant les mouvements des servos. C'est même plutôt l'inverse: comme c'est géré par des interruptions, le Dcc est prioritaire. Du coup les mouvement des servos peuvent être perturbés par la réception Dcc, mais vu les timings concernés, je ne pas sûr que l'interruption soit détectable...
merci pour cette rapide reponse,
il ne me reste plus qu'à me pencher un peu plus sur Accessories et commanders
mais honnêtement je ne comprends pas pourquoi mon code ne peut pas interpretrer une commande DCC si un servo est en mouvement.