Mon Hexapod maison

Bonjour à tous !

Après une longue période ou j'avais plus trop le temps :confused: j'ai dépoussiéré mon projet d'Hexapod pour m'y remettre :slight_smile:
J'avais créé un autre Topic ici : Conseils Hexapod
Mais il a été fermé tellement j'ai été long à revenir :open_mouth:

Bref ... je suis reparti de tous mes petits brouillons et toute l'aide que vous m'aviez déjà apporté et j'ai recommencé mieux armé ^^
Je refais le tout pas à pas !

Petit historique d'où j'en suis actuellement :
1- je me suis fais une télécommande avec ESP32, 2 joysticks et 2 boutons
2- Je l'ai interfacé avec mon récepteur qui contrôle mon Hexapod, également avec ESP32
3- J'ai configuré mes PCA9685 (x2) pour contrôler les 18 Servomoteurs (Pins, Servomin, Servomax etc ...)
4- j'ai créé un code qui me permet de déplacer les servos moteurs selon les angles que je lui indique et sur 1 appui bouton (histoire que ca vienne de la télécommande dès maintenant).

==> Toutes ces parties fonctionnent bien, et sur l'appui bouton, je fais switcher une patte entre une position de départ et une position cible. Et de manière instantané.

grâce au code suivant :

void MoveLeg(uint8_t Leg[3], int angle[3], int SERVOMIN[3], int SERVOMAX[3]) {
  for (int i=0; i<3; i++){
    board_right.setPWM(Leg[i], 0, angleToPulse(angle[i], LegRF_SERVOMIN[i], LegRF_SERVOMAX[i]) );
  }

Et que j'execute dans le void suivant :

void gestionEtat() {
  if (etatActuel == ACTIVE) {
    Serial.print("Activé");
    //MoveLegTarget();
    MoveLeg(LegRF, targetAngles, LegRF_SERVOMIN, LegRF_SERVOMAX);
  } else {
    Serial.print("Désactivé");
    //MoveLegInit();
    MoveLeg(LegRF, initAngles, LegRF_SERVOMIN, LegRF_SERVOMAX);
  }

  if (readingData.right_B_state == 0) {
    Serial.println(" // Bouton droit appuyé");
  } else {
    Serial.println(" // RAS");
  }

  // Vérifier l'état du bouton left_B_state
  if (readingData.left_B_state == 0) {
    // Si le bouton est activé, mettre à jour l'état actuel
    etatActuel = (etatActuel == ACTIVE) ? DESACTIVE : ACTIVE;

    // Attendre que le bouton soit relâché
    while (readingData.left_B_state == 0) {
      delay(50);
    }
  }
}

5- Mais le mouvement est saccadé (c'est à dire que les servomoteurs se déplacent l'un après l'autre. J'ai donc voulu le rendre plus fluide. Sur mon ancien Topic, @J-M-L m'avait proposé un bout de code qui fonctionnait très bien et qui m'a bien aidé à comprendre certaines choses ^^. Mais n'étant pas développeur, j'étais vraiment pas a l'aise avec le mécanisme et j'ai souhaité tenté d'obtenir cette fluidité à l'aide de la fonction lerp suivante :

float lerp(float a, float b, float t) {
  return a + t * (b - a);
}

J'ai donc transformé mon code plus haut ainsi :

void MoveLeg(uint8_t Leg[3], int angle[3], int SERVOMIN[3], int SERVOMAX[3]) {
  for (float t = 0.0; t <= 1.0; t += 0.2) { // Variation progressive de t de 0 à 1
    int smoothedAngles[3]; // Stocker les angles lissés
    
    // Lissage linéaire pour chaque angle
    for (int i = 0; i < 3; i++) {
      // Utilisation de l'interpolation lerp pour lisser les angles
      smoothedAngles[i] = lerp(currentAngles[i], angle[i], t);
    }
    
    // Appliquer les angles lissés aux servomoteurs
    for (int i = 0; i < 3; i++) {
      board_right.setPWM(Leg[i], 0, angleToPulse(smoothedAngles[i], SERVOMIN[i], SERVOMAX[i]));
    }
    
    // Attendre un court laps de temps pour la transition douce
    delay(50);
  }
  // Copie des valeurs de angle dans CurrentAngles
  for (int i = 0; i < 3; i++) {
      currentAngles[i] = angle[i];
  }
}

Ce qui fonctionne ! Mais par contre, le mouvement ne se refait pas de maniere instantanné quand j'appui sur mon bouton de telecommande !? il peut reagir apres un certain temps ou apres plusieurs appui. Meme des fois il reagit plus avant de reagir de nouveau.
J'ai essayé de chasser les delay ou autre ... j'ai changé le temps "t" utilisé pour le lerp mais ca change le temps de deplacement (normal) mais pas la reacitivté.

Auriez-vous une idée de pourquoi !?

Merci par avance pour votre aide toujours aussi précieuse :slight_smile:

Et si tu déplaces le delay à l'extérieur de la boucle for ?

Coucou,

Merci pour le retour.
Non, ca n'a rien changé :wink:

Alors je suis reparti sur autre chose ... en m'inspirant de ce que m'avait communiqué @J-M-L . C'est a dire en utilisant le Millis.

Je transforme donc ce code :

void MoveLeg(uint8_t Leg[3], int angle[3], int SERVOMIN[3], int SERVOMAX[3]) {
  for (int i=0; i<3; i++){
    board_right.setPWM(Leg[i], 0, angleToPulse(angle[i], LegRF_SERVOMIN[i], LegRF_SERVOMAX[i]) );
  }

par ce code :

void MoveLeg(uint8_t Leg[3], int angle[3], int SERVOMIN[3], int SERVOMAX[3], unsigned long d) {
  
  unsigned long debut = millis();
  int positionDepart[3];
  int positionActuelle[3];
  int positionCible[3];

  for (int i = 0; i < 3; i++) {
    positionDepart[i] = currentAngles[i];
    positionActuelle[i] = currentAngles[i];
    positionCible[i] = angle[i];
  }

  while (positionActuelle[0] != angle[0] || positionActuelle[1] != angle[1] || positionActuelle[2] != angle[2]) {
    unsigned long temps_ecoule = millis() - debut;
    if (temps_ecoule >= d) break;

    for (int i = 0; i < 3; i++) {
      int pos = map(temps_ecoule, 0, d, positionDepart[i], positionCible[i]);
      if (pos != positionActuelle[i]) {
        positionActuelle[i] = pos;
        board_right.setPWM(Leg[i], 0, angleToPulse(positionActuelle[i], SERVOMIN[i], SERVOMAX[i]));
        currentAngles[i] = positionActuelle[i];
      }
    }
  }
}

et ca fonctionne au niveau du mouvement, mais ca manque de reactivité toujours et apres quelques appuies boutons (donc quelques déplacement), ca ne bouge plus :confused:

toujours ... si vous avez des idées du pourquoi ... merci

j'ai également essayé de modifier la condition de fin de mon While pour vérifier si les positions sont atteintes comme ca :

void MoveLeg(uint8_t Leg[3], int angle[3], int SERVOMIN[3], int SERVOMAX[3], unsigned long d) {
  
  unsigned long debut = millis();
  int positionDepart[3];
  int positionActuelle[3];
  int positionCible[3];

  for (int i = 0; i < 3; i++) {
    positionDepart[i] = currentAngles[i];
    positionActuelle[i] = currentAngles[i];
    positionCible[i] = angle[i];
  }

  // Détermine si toutes les positions actuelles ont atteint les positions cibles
  bool toutesAtteintes = false;

  while (!toutesAtteintes) {
    unsigned long temps_ecoule = millis() - debut;
    if (temps_ecoule >= d) break;

    toutesAtteintes = true; // Supposons initialement que toutes les positions sont atteintes

    for (int i = 0; i < 3; i++) {
      int pos = map(temps_ecoule, 0, d, positionDepart[i], positionCible[i]);
      if (pos != positionActuelle[i]) {
        positionActuelle[i] = pos;
        board_right.setPWM(Leg[i], 0, angleToPulse(positionActuelle[i], SERVOMIN[i], SERVOMAX[i]));
        currentAngles[i] = positionActuelle[i];
        // Vérifie si la position actuelle est différente de la position cible
        if (positionActuelle[i] != positionCible[i]) {
          toutesAtteintes = false; // Si au moins une position n'est pas atteinte, la condition est fausse
        }
      }
    }
  }
}

Mais ca ne reagit meme plus :frowning:

Coucou !

mmmh ... j'ai l'impression que j'ai pas inspiré grand monde ^^
Pas grave. Je ne désespère pas de trouver :slight_smile:

++

en revenant dans la version précédente dans le fils de discussion de ma fonction MoveLeg, ca fonctionne ... mais bon faut insister sur le bouton pour que ca réagisse ... manque de réactivité :confused:

Hum...
Ton problème est de faire bouger 6 pattes en même temps, avec le minimum de latence. C'est bien ça ?
Dans ce cas, il faut concevoir ton code pour réaliser une sorte d'exécution parallèle de plusieurs fonctions (une par patte). C'est assez difficile. Une possibilité est de passer par une machine d'états, mais compte tenu des 6 pattes, ça devient à mon humble avis très complexe.

Une autre est de te renseigner sur ce pseudo-parallélisme. J'ai fait un tuto en anglais ici :

Mais il est très simple par rapport à ton problème.

Une dernière possibilité est d'utiliser une bibliothèque qui va faire ce multitasking pour toi. Tu peux chercher sur Google et sélectionner ou tester celle(s) qui te semble(nt) mieux adaptée(s).
Google

Pour ces solutions, le principe est de faire bouger chaque patte d'un tout petit mouvement au bon moment et pendant la bonne durée. Donc ça nécessite de faire des calculs en amont pour bien savoir s'il faut ou non faire bouger chaque patte. Pas forcément simple, mais faisable.

Voila, c'était mes 2 cents...

Merci pour ton retour !

Je vais étudier tout ca ...

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.