servo moteur halloween

Tenez essayez ce code sur l'Arduino pour voir ce que vous recevez vraiment

Branchements:

Arduino pin 10 connectée au Tx du RPI
Arduino pin 11 connectée au Rx du RPI
GND de l'Arduino connecté au GND du RPI (vous l'aviez fait avant, hein?)

(si vous avez un MEGA car vous parlez de Serial1 plus haut alors pas la peine de prendre SoftwareSerial, faites juste #define RPISerial Serial1 et enlever la partie qui correspond à SoftwareSerial, et connectez bien sûr les fils du RPI aux pin de Serial1 (18 et 19))

Console série Arduino mise à 115200 bauds
RPI émettant à 57600 bauds

#include <SoftwareSerial.h>
SoftwareSerial RPISerial(10, 11); // RX, TX

//Le circuit:
// * Rx = pin 10 (connectée au Tx du RPI)
// * Tx = pin 11 (connectée au Rx du RPI)
// * Les GND reliés entre eux

void setup()
{
  Serial.begin(115200);   // On affiche sur la console série à 115200 bauds
  RPISerial.begin(57600); // le R-PI nous parle à 57600 bauds
}

void loop()
{
  static byte nbBytes = 0;
  
  if (RPISerial.available()) {
    byte b = RPISerial.read();
    if (b <= 0xF) Serial.print(F("0")); // on veut chaque octet sur 2 caractères
    Serial.print((byte) b, HEX);
    
    nbBytes++;

    if (nbBytes >= 9) {
      Serial.print(F("\n")); // assez sur cette ligne on passe à la suivante
      nbBytes = 0;
    }
    else 
    if ((nbBytes % 3) == 0) Serial.print(F("\t")); // on affiche des groupes de 3
    else Serial.print(F(" "));
  }
}

ça vous affichera par groupe de 3 octets dans la console Série Arduino ce que vous recevez vraiment et que vous interprétez pour le moment.

Copier / Coller ce que vous voyez en sortie et dites nous si c'est cohérent avec ce que vous êtes censé émettre

hello,

Ok , on va tester cela et revenons vers vous :wink:

Mille merci

bonjour j-m-l

j'ai testé, alors quand une info est envoyé de la pi " une lumière allumé" arduino me donne FF

donc dans le monitor serial quand la lampe 1 est allumée ça donne :

00 FF 00 00 FF 00 00 FF 00

lumière 2 allumé:

00 00 FF 00 00 FF 00 00 FF

lumière 3 allumé:

FF 00 00 FF 00 00 FF 00 00

les 3 lumières allumé:

FF FF FF FF FF FF FF FF FF

et éteinds:

00 00 00 00 00 00 00 00 00

je ne sais pas comment interpréter ça...

encore merci pour ton aide

on dirait donc

  • qu'il n'y a pas de début ni de fin de trame

  • que le système envoie toujours trois groupes d'octets

  • le premier octet correspond à la lampe #3,

  • le deuxième octet correspond à la lampe #1,

  • le troisième octet correspond à la lampe #2

  • qu'il envoie un octet à 255 (0xFF) pour dire allumé

  • qu'il envoie un octet à 0 pour dire éteint

EN SUPPOSANT QUE 2 TRAMES CONSECUTIVES NE SOIENT PAS TROP RAPPROCHEES

En premier approche, si le RPI ne balance pas d'information trop souvent un code comme celui ci devrait vous faire quelque chose.

connectez ainsi

pin 6 --> Servo (et son alimentation bien sûr)

pin 7 --> Anode d'une LED --> une résistance adaptée (220Ω disons) --> GND

pin 8 --> Anode d'une LED --> une résistance adaptée (220Ω disons) --> GND

Pin 0 (Rx) --> Tx du RPI
Pin 1 (Tx) --> Rx du RPI

GND Arduino --> GND RPI (important)

RPI configuré à 57600 bauds

(code tapé sans tester, je n'ai pas votre config)

#include <Servo.h>
Servo servo3;  // créer un object servo pour controler le servo

const byte servo3Pin = 6;
const byte led1Pin = 7;    // led1 pilotée par la pin 7
const byte led2Pin = 8;    // led2 pilotée par la pin 8


void setup()
{
  Serial.begin(57600);
  servo3.attach(servo3Pin);
  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
}


void loop()
{
  if (Serial.available() >= 3) {
    byte incomingByte[3];
    for (int i = 0; i < 3; i++) {
      incomingByte[i] = (byte) Serial.read();
    }
    digitalWrite(led1Pin, (incomingByte[1] == 0xFF) ? HIGH : LOW);
    digitalWrite(led2Pin, (incomingByte[2] == 0xFF) ? HIGH : LOW);    
    if (incomingByte[0] == 0xFF) moveServo3();
  }
}


void moveServo3() {
  const byte minAngle = 70, maxAngle = 130;
  const unsigned int tickPause = 15;

  // goes from 70 degrees to 130 degrees in steps of 1 degree
  for (int pos = minAngle; pos <= maxAngle; pos += 1) {
    servo3.write(pos); // tell servo to go to position in variable 'pos'
    delay(tickPause);   // waits tickPause ms for the servo to reach the position
  }

  delay (2000);  // wait for 2 seconds here

  // and go back
  for (int pos = maxAngle; pos >= minAngle; pos -= 1) {
    servo3.write(pos); // tell servo to go to position in variable 'pos'
    delay(tickPause);   // waits tickPause ms for the servo to reach the position
  }
}

il est important que le RPI n'envoie pas d'infos trop souvent sinon vous allez rater des octets dans la transmission au bout d'un moment où alors ça va se désynchroniser car le buffer Série sera plein

La fonction qui bouge le servo dure 2*61* tickPause + 2s comme j'ai mis tickPause à 15ms ça fait 3830ms --> près de 4s

donc côté séquenceur, si le servo doit bouger, ne pas envoyer d'autre instruction avant 4s.

j-m-l

excuse moi j-m-l

je pense ne pas avoir était claire, les infos sont en continue du début à la fin de la séquence je vais mettre une photo du serial monitor pour éviter des erreurs.

les infos sont en continue et fluide du début à la fin.

mais elle défilent à quelles vitesse? super rapidement ou pas ?

--> à quelle fréquence le RPI balance les 3 octets?

Oui très rapidement, rpi réglé 57600 le programme tourne 50fps. les 3 octets sont affichés instantanément

le programme tourne 50fps.

OK c'est un soucis alors :slight_smile:

il faudrait passer sur la AccelStepper library for Arduino qui est non bloquante et rajouter un peu d'intelligence qui dit "si j'ai reçu la même commande que la dernière fois pour le moteur je lui laisse continuer sa course, sinon je le stoppe"

Sinon pouvez vous pour tester passer le fps à 1 frame toutes les 4 secondes ? (0.25fps)

Bonjour j-m-l

OK je regarde pour accelstepper voir ce que je peux trouver et faire.

Pour fpp non malheureusement car il y a d'autres choses (lumières,..) qui tourne avec ce programme. Par contre je peux envoyer une impulsion très courte, car on peut choisir la duré de l'envoi de l'information, ça peut peut-être aidé

à 57600 bauds, vous recevez 5760 octets par seconde, soit environ 1920 commandes par seconde!

avec le code ci dessus il ne faut pas que des trames Serial de 3 octets s'accumulent si le moteur tourne (car la fonction qui fait bouger le servo est bloquante pendant environ 4 secondes donc pendant ces 4 secondes vous avez reçu 4 x 1920 commandes qui auront saturé le petit buffer de 64 octets du port série et vous ne lirez que les dernières reçues, mais comme 64 ça ne se divise pas par 3, le premier octet lu ne correspond plus au début de trame)

Sinon il faut changer le mode de fonctionnement du code en utilisant la librairie accelstepper pour que les demandes envoyées au moteur ne soient pas bloquantes et comme cela on peut revenir gérer le port série pour voir si on a reçu un contre-ordre par exemple ou juste piloter les LEDs

Pour la structure de ce genre de code le plus simple est de faire une machine a état (cf mon tuto sur les principes) qui est pilotée par la réception des 3 commandes sur le port série (cf mon tuto pour écouter le port série de manière non bloquante tant qu'on n'a pas une commande)

hello,

Bon Ben voila, nous avons trouvé une alternative en attendant vu que rien ne fonctionne lol... Nous avons decidé d'en rester un peu la pour le moment ( au vu que le montage marche lol ) nous nous sommes servi de relais pour ouvrir ou fermé l'info du servo . je publierai le lien de notre projet lorsque celui-ci sera en fonction ( bien qu'il est pret lol...mais halloween commencera ici le 17 octobre)

En tous les cas, merci de votre patience, de votre aide et tout ce qui va avec. Nous de notre coté, en meme temps que se plancher sur le projet noel, nous allons demarrer une formation afin d'encore evoluer dans ce monde fantastique qu'est l'electronique.

Encore un tout grand merci pour tout