Aller au contenu


Photo

Commande servo moteurs en simultané


  • Veuillez vous connecter pour répondre
19 réponses à ce sujet

#1 Mika9091

Mika9091

    Membre

  • Membres
  • 12 messages

Posté 07 juin 2020 - 06:58

Bonjour à tous,
Je me lance dans un petit projet concernant à faire bouger des yeux animatronics de façon autonome. J'utilise un shield 16ch adafruit et pilote mes servos en pwm.
J'ai cependant un petit souci, je souhaite faire tourner 4 servos en même temps sachant qu'il n'ont pas tous le même point d'arrivée ni le même point de depart et que je commande la vitesse par un delay() dans une boucle for. Mes servos se lancent un par un. Besoin d'aide svp

#2 Ludovic Dille

Ludovic Dille

    Habitué

  • Membres
  • PipPip
  • 186 messages
  • Gender:Male
  • Location:Belgique

Posté 07 juin 2020 - 07:57

Hello,

Partager son code quand on demande de l'aide ça peut vachement aider :)
En gros je suppose que les servomoteurs que tu as ne peuvent que se gérer en position donc je dirais :
1) Tu calcules le delta de position à appliquer à chacun de tes servos (dS1 = Angle_servo_1_fin - Angle_servo_1_debut)
2) Tu vas définir un temps de trajet pour tout tes servos et nombre d'étape par lesquels tu veux les faire passer.
3) Tu fais une boucle sur ces n étapes ou tu fais un incrément pour chacun de tes servos
 

Petit exemple en pseudo code:

N = ....

t = ....
dS1 = ...

dS1 /= N
dS2 = ...
dS2 /= N

for i in N:

  Angle_servo_1_debut += dS1
  S1.write(Angle_servo_1_debut)
  Angle_servo_2_debut += dS2
  S2.write(Angle_servo_2_debut)

  delay(t/N)

Mais ça c'est si tu veux vraiment les synchroniser donc qu'ils partent en même temps pour finir en temps. Mais si ce que tu recherches c'est juste qu'ils partent en même temps ça vient de ton code et la encore il nous le faut pour qu'on puisse t'aider.

Ludo



#3 Mika9091

Mika9091

    Membre

  • Membres
  • 12 messages

Posté 07 juin 2020 - 08:43

Très bien merci pour l'explication, effectivement je souhaite juste un départ simultané. Je regarde pour vous transmettre le code.

#4 Mika9091

Mika9091

    Membre

  • Membres
  • 12 messages

Posté 07 juin 2020 - 08:57

Re,

 

Voici le code

 

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
 
//////////// Déclaratin des servos /////////////
 
//#define SERVOMIN (140)
//#define SERVOMAX (520)
uint16_t servonum = 0;// Avant uint8_t
int servo0=0;
int servo1=1;
int servo2=2;
int servo3=3;
int servo4=4;
int servo5=5;
 
////////////////////////////////////////////////
 
void setup() {
pwm.begin();// On initialise la biblio pwm
pwm.setPWMFreq(49);// Les servos analogiques tourne vers 50Hz, on définit la fréquence
 
randomSeed(analogRead(0));//Gestion des delay aléatoires sur broche fictive
 
pwm.setPWM(servo0,0,300);
pwm.setPWM(servo1,0,345);
pwm.setPWM(servo2,0,435);
pwm.setPWM(servo3,0,240);
pwm.setPWM(servo4,0,240);
pwm.setPWM(servo5,0,420);
}
void setServoPulse(uint8_t n,double pulse){
  double pulselength;
pulselength=1000000;
pulselength/=49;
pulselength/=4096;
pulse*=1000;
pulse/=pulselength;
pwm.setPWM(n,0,pulse);
}
 
void loop() {
  
ouvre();
delay(2000);
ferme_lent();
delay(2000);
 
}
 
/////////// Fonctions gauche droite///////////////
void gauche_droite(){
  for(uint16_t pulselen=250;pulselen<=370;pulselen+=random(1,10)){
  pwm.setPWM(servo0,0,pulselen);
  delay(random(15));
}
delay(random(1500));
for (uint16_t pulselen=370;pulselen>=250;pulselen-=random(1,10)){
  pwm.setPWM(servo0,0,pulselen);
  delay(random(15));
}
}
///////////// yeux haut ///////////////////
void yeux_haut(){
  for(uint16_t pulselen=345;pulselen<=420;pulselen+=random(1,10)){
  pwm.setPWM(servo1,0,pulselen);
  delay(random(15));
}
  delay(random(1500));
  for (uint16_t pulselen=420;pulselen>=345;pulselen-=random(1,10)){
  pwm.setPWM(servo1,0,pulselen);
  delay(random(15));
}
}
///////////////////// yeux bas ////////////////////////
void yeux_bas(){
  for(uint16_t pulselen=345;pulselen>=295;pulselen-=random(1,10)){
  pwm.setPWM(servo1,0,pulselen);
  delay(random(15));
}
  delay(random(2500));
  for (uint16_t pulselen=295;pulselen<=345;pulselen+=random(1,10)){
  pwm.setPWM(servo1,0,pulselen);
  delay(random(15));
}
}
/////////////// Cligne //////////////////////////////////
void cligne(){
  pwm.setPWM(4,0,240);
  pwm.setPWM(5,0,420);
  pwm.setPWM(2,0,435);
  pwm.setPWM(3,0,240);
  delay(100);
  pwm.setPWM(4,0,400);
  pwm.setPWM(5,0,280);
  pwm.setPWM(2,0,300);
  pwm.setPWM(3,0,400);
  delay(200);
  pwm.setPWM(4,0,240);
  pwm.setPWM(5,0,420);
  pwm.setPWM(2,0,435);
  pwm.setPWM(3,0,240);
  delay(100);
  pwm.setPWM(4,0,400);
  pwm.setPWM(5,0,280);
  pwm.setPWM(2,0,300);
  pwm.setPWM(3,0,400);
}
///////////// ouvre les yeux /////////////
void ouvre (){
  pwm.setPWM(2,0,300);
  pwm.setPWM(3,0,400);
  pwm.setPWM(4,0,400);
  pwm.setPWM(5,0,280);
}
//////////// Ferme lent ///////////////
void ferme_lent(){
  for(uint16_t pulselen=300;pulselen<=435;pulselen+=2){
  pwm.setPWM(servo2,0,pulselen);
  delay(20);
  }
  for(uint16_t pulselen=400;pulselen>=240;pulselen-=2){
    pwm.setPWM(servo3,0,pulselen);
  delay(20);
  }
  for(uint16_t pulselen=400;pulselen>=240;pulselen-=2){
    pwm.setPWM(servo4,0,pulselen);
  delay(20);   
  }
  for(uint16_t pulselen=280;pulselen<=420;pulselen+=2){
    pwm.setPWM(servo5,0,pulselen);
  delay(20);
  }
  }
//////////////////////////////////////////////////////


#5 Ludovic Dille

Ludovic Dille

    Habitué

  • Membres
  • PipPip
  • 186 messages
  • Gender:Male
  • Location:Belgique

Posté 07 juin 2020 - 09:19

Il y a une balise faite pour mettre du code sinon on a vraiment du mal à lire le code



#6 Mika9091

Mika9091

    Membre

  • Membres
  • 12 messages

Posté 07 juin 2020 - 09:28

Ludovico, j'ai essayé en pièce ce n'est pas passé. C'est au niveau de la fonction ferme lent que ça bloque.. à la fin

#7 Ludovic Dille

Ludovic Dille

    Habitué

  • Membres
  • PipPip
  • 186 messages
  • Gender:Male
  • Location:Belgique

Posté 07 juin 2020 - 09:31

Et sinon pour t'aider à corriger ton code, le problème vient que tu mets tes boucles à la suite et donc tu vas agir sur un seul servo à la fois. Donc ici tu veux faire une boucle qui touche à tous tes servo.

Par exemple pour ferme_lent()
 

ferme_lent()
{
  // Nombre max d'etape
  uint16_t max_pulse = 160;

  // position de depart et de fin de chacun des servo
  uint16_t begin_S1 = ...
  uint16_t end_S1 = ...
  uint16_t begin_S2 = ...
  uint16_t end_S2 = ...
  
  for(uint16_t i = 0; i < max_pulse; i++){
    // condition for each servo
    if(begin_S1 + i < end_S1){
      pwm.setPWM(servo1,0,begin_S1 + i);
    }

    if(begin_S2 - i > end_S2){
      pwm.setPWM(servo2,0,begin_S2 - i);
    }

    delay(..)
  }
}

Ce qui devrait déjà t'aider à régler ton problème :)



#8 Ludovic Dille

Ludovic Dille

    Habitué

  • Membres
  • PipPip
  • 186 messages
  • Gender:Male
  • Location:Belgique

Posté 07 juin 2020 - 09:32

Ludovico, j'ai essayé en pièce ce n'est pas passé. C'est au niveau de la fonction ferme lent que ça bloque.. à la fin

 

C'est la dans l'edit du forum

screenshot_20200607_103152.png



#9 Mika9091

Mika9091

    Membre

  • Membres
  • 12 messages

Posté 07 juin 2020 - 09:44

Merci je vais essayer ça en réglant mon max pulse parce que 160 est trop bas. Je vous tiendrait au courant

#10 Mika9091

Mika9091

    Membre

  • Membres
  • 12 messages

Posté 07 juin 2020 - 02:16

Re, je viens d'essayer ça à l'air de prendre sauf que mes servos forcent alors qu'il ne devraient pas. La ligne uint16 max_pulse correspond à quoi exactement? Merci pour votre coup de pouce

#11 Ludovic Dille

Ludovic Dille

    Habitué

  • Membres
  • PipPip
  • 186 messages
  • Gender:Male
  • Location:Belgique

Posté 07 juin 2020 - 02:26

En gros cette ligne permet de définir le nombre d'étape par lesquels tu veux passer: si max_pulse vaut 100 tu feras 100 tour de boucle. Donc pour bien choisir la valeur, tu dois prendre max_pulse = max(abs(end_Si - start_Si)) comme ça la fin de la boucle coïncide avec le mouvement du servo qui doit parcourir le plus grand trajet. Que veux tu dire par "les servos forcent" ?



#12 Mika9091

Mika9091

    Membre

  • Membres
  • 12 messages

Posté 07 juin 2020 - 02:35

J'ai fais le test sur deux servos au lieu de 4 déjà et sur les deux, un sort de sa course..

#13 Ludovic Dille

Ludovic Dille

    Habitué

  • Membres
  • PipPip
  • 186 messages
  • Gender:Male
  • Location:Belgique

Posté 07 juin 2020 - 02:53

Tu adapté correctement les conditions à des mouvement positifs ou négatif ? Sinon tu peux déjà remontrer ton code :)



#14 Mika9091

Mika9091

    Membre

  • Membres
  • 12 messages

Posté 07 juin 2020 - 03:51

//////////// Ferme lent ///////////////
void ferme_lent(){
uint16_t max_pulse=520;//???
uint16_t begin_S2=300;
uint16_t end_S2=435;
uint16_t begin_S3=400;
uint16_t end_S3=240;

for(uint16_t i=0; i<max_pulse;i++){
  if(begin_S2+i<end_S2){
    pwm.setPWM(servo2,0,begin_S2+i);
  }
  if(begin_S3-i>end_S3-i){
  pwm.setPWM(servo3,0,begin_S3-i);
  }
  delay(vitesse);
}
}



#15 Ludovic Dille

Ludovic Dille

    Habitué

  • Membres
  • PipPip
  • 186 messages
  • Gender:Male
  • Location:Belgique

Posté 07 juin 2020 - 04:11

le soucis vient de ta deuxième conditon, dans le fonctionnement normal tu veux que lorsque tu arrives à ta positon de fin tu arrêtes de bouger. Ici tu as noté que begin_S3 - i > end_s3 - i ce qui revient à écrire que begin_S3 > end_S3 ce qui est toujours le cas et donc ton servo continue sa course. Donc si tu veux arrêter la course tu dois remplacer ça par begin_S3 - i > end_S3.

et ici pour revenir sur le max pulse, tu vois que pour S2 tu as 135 pulse (435-300) et pour S3 tu en as 160 (400 - 240) donc idéalement tu veux set up ton max plus à 160.
- Si tu en mets moins, S3 (et peut-être S2 en fonction de la valeur) ne va pas atteindre sa position finale.Ç
- Si tu en mets plus, ton programme va tourner dans ta boucle sans rien faire, c'est pas très grave mais c'est pas idéal.

Une solution plus robuste ça serait:
1) définir ton begin et ton end pour chacun de tes servos
2) calculer le delta step pour chacun des servos abs(end - start)
3) stocker le max de ces delta dans un max_pulse;



#16 Mika9091

Mika9091

    Membre

  • Membres
  • 12 messages

Posté 07 juin 2020 - 04:34

Ah oui je commence à y voir plus clair, et du coup comment j'écris le stockage de tous mes delta? Uint16_t max_pulse =(160,135,...) et dans ma boucle for je laisse comme ça?

#17 Ludovic Dille

Ludovic Dille

    Habitué

  • Membres
  • PipPip
  • 186 messages
  • Gender:Male
  • Location:Belgique

Posté 07 juin 2020 - 05:00

Alors l'organisation de ton code ça dépend pas mal de toi et de ton projet.
Tu peux partir du fait que tu voudrais peut-être changer la valeur de begin et end et donc il faudrait que tu utilises ces variables pour calculer tes deltas
 

uint16_t d1 = abs(end_S1 - begin_S1);
uint16_t d2 = abs(end_S2 - begin_S2);
...

uint16_t max_pulse = max(max(d1,d2),max(d3,d4));

mais pour être plus rapide tu peux directement assigner à max_pluse la valeur que tu calcules à la main mais c'est beaucoup moins flexible.

Et après il y a d'autres façon de faire encore mais tout dépend de la taille du projet, de l'investissement que tu veux y mettre.

Normalement la boucle fort ne devrait pas changer.



#18 Mika9091

Mika9091

    Membre

  • Membres
  • 12 messages

Posté 07 juin 2020 - 05:05

Merci pour toutes les infos. Je potasse pas mal le bouquin et quelques tutos. Je vous tiendrait au courant

#19 Mika9091

Mika9091

    Membre

  • Membres
  • 12 messages

Posté 13 juin 2020 - 05:50

Merci Ludovic pour ce gros coup de pouce! Ça fonctionne nickel!

#20 Ludovic Dille

Ludovic Dille

    Habitué

  • Membres
  • PipPip
  • 186 messages
  • Gender:Male
  • Location:Belgique

Posté 13 juin 2020 - 10:24

Top !
N'hésite pas à partager une vidéo de ton projet :)






0 utilisateur(s) li(sen)t ce sujet

0 members, 0 guests, 0 anonymous users