Aller au contenu


Photo
- - - - -

Transmission PC->Arduino

Transmission Arduino PC

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

#1 Phil2P

Phil2P

    Membre

  • Membres
  • 44 messages
  • Gender:Male

Posté 23 février 2022 - 08:13

Bonjour,
Nos élèves peuvent maintenant mettre en mouvement notre bras robotisé basé sur le Moveo.
Nous commandons les mouvements du bras à partir d'un PC qui envoie des consignes (trame de coordonnées articulaires+ouverture de la pince) à une carte Arduino par le port série (usb). Cette carte commande la rotation des axes motorisés (moteurs pas-à-pas) et la pince.

Malheureusement, nous constatons des arrêts ou des ralentissements lors de plusieurs mouvements (trames) successifs.

Nous avons confié au PC les "calculs complexes" et le programme sur Arduino utilise la fonction CASE.

Est-ce la bonne méthode ?

Cette fonction CASE permet aussi de stopper le bras par l'appui d'un bouton sur le PC.

Si j'ai bien compris, l'usage du "case" impose de :
- soit calculer le temps de mouvement entre deux positions (traitement des données par l'arduino plus mouvement du bras) et ainsi de permettre au PC de ne pas envoyer de trames trop rapidement,
- soit envoyer une information "traitement terminé" de l'arduino au PC pour permettre au PC d'envoyer une nouvelle trame sans empiéter sur la précédente.

Est-ce que j'ai bien compris ?

Dans ce cas, ne serait-il pas judicieux de créer une pile FIFO que le PC remplirait et que l'arduino viderait au fur et à mesure des différentes trames traitées ?

Merci de me donner votre point de vue car j'ai très peu de connaissance en informatique et en programmation.

Bonne soirée,
Philippe

#2 Ludovic Dille

Ludovic Dille

    Habitué

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

Posté 23 février 2022 - 10:55

Bonjour Phil2P,

pour moi ta méthode actuelle (le PC pour les calcules complexe et l'arduino pour le contrôle des moteurs) est la bonne.

Si je comprends bien le soucis actuelle c'est que l'arduino reçoit trop de trames que le système (arduino + bras) ne sait traiter et qu'il faut donc diminuer le nombre de trame (ou bien accéléré les éxecutions des trames mais ce n'est pas spécialement possible).
Tes 2 propositions vont marcher à mon avis mais je pense que réduire le nombre de trame envoyée par l'ordinateur sera le plus simple à implémenter. Une autre amélioration que tu peux ajouter c'est que l'arduino vide le buffer de la communication série et n'utilise que le dernier message complet (elle pourrait donc passer des trames).

 

Et pour mieux comprendre le problème, les trames que vous envoyez c'est pour juste obtenir une position finale ou bien vous voulez suivre une trajectoire précise ?


Bien cordialement,
Ludo



#3 Phil2P

Phil2P

    Membre

  • Membres
  • 44 messages
  • Gender:Male

Posté 24 février 2022 - 12:24

Bonsoir,
Merci Ludovic pour tes conseils.

Les trames comportent une lettre (M pour Mouvement, P pour Pince et S pour Stop) et contiennent les positions articulaires finales attendues lors d'un mouvement. Pour une trajectoire complexe, on peut décomposer cette trajectoire par plusieurs points dans l'espace correspondants chacun à des positions articulaires finales attendues.

Je pense que les soucis actuels résultent du fait que l'envoi d'une nouvelle trame interompe (par l'utilisation de CASE) l'exécution de la précédente. Nous avons triché en imposant sur le PC un délai grossièrement calculé entre chaque envoi de trame.

D'où mon idée d'envoyer au PC une info indiquant que l'exécution de la trame est terminée pour pouvoir envoyer une nouvelle trame.
Ou, autre solution, utiliser une sorte de pile Fifo sur la carte Arduino.

Qu'en pensez-vous ?

Je n'ai pas compris ta proposition :
"Une autre amélioration que tu peux ajouter c'est que l'arduino vide le buffer de la communication série et n'utilise que le dernier message complet (elle pourrait donc passer des trames)."

Bonne nuit,
Philippe

#4 Ludovic Dille

Ludovic Dille

    Habitué

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

Posté 24 février 2022 - 09:35

Rebonsoir,

En gros ma proposition était de n’utiliser que la dernière trame envoyée par le PC (et donc de ne pas utiliser les autres). Mais vu ce que vous voulez faire, ça ne s’applique pas vraiment.

 

Réaliser une pile Fifo sur l’Arduino va me sembler plus compliqué à gérer (si vous êtes des crack pas de soucis :P). Quelque chose où il faut faire attention c’est la taille du buffer de la communication Série entre le PC et l’arduino. Si je ne me trompe pas l’arduino ne vas stocker que 64 Bytes.
Renvoyer l’info au PC est un bon moyen de ne pas se préoccuper de ça.

Une autre piste à explorer est d’envoyer plus de trame pour une même trajectoire (et donc d’avoir des différences entre la position actuelle et la position suivante plus petite ce qui pourrait améliorer le résultat).

Une video du bras en action pourrait intéresser les membres du forum ;) !


Ludo



#5 Phil2P

Phil2P

    Membre

  • Membres
  • 44 messages
  • Gender:Male

Posté 24 février 2022 - 11:08

Bonsoir,

La solution la plus simple semble donc :
Renvoyer linfo au PC lorsque la trame est traitée.

C'est vrai qu'une pile Fifo me plairait bien car elle permettrait d'envoyer plusieurs "trames d'avance" et laisserait l'Arduino traiter les trames "à son rythme".
En effet, nous ne sommes pas des pro. Loin de là... 😉
Je croyais qu'un librairie comme "CircularBuffer" aurait pu faciliter l'utilisation d'une pile Fifo.

Tu trouveras ci-dessous un lien pour voir le 1er proto du bras en fonctionnement.




Encore merci de ton aide précieuse,
Philippe

#6 Ludovic Dille

Ludovic Dille

    Habitué

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

Posté 27 février 2022 - 01:11

Mais déjà beau boulot pour la réalisation actuelle :)



#7 Phil2P

Phil2P

    Membre

  • Membres
  • 44 messages
  • Gender:Male

Posté 27 février 2022 - 01:28

Merci Ludovic !
Peux-tu me dire si une librairie comme "CircularBuffer" pourrait faciliter la création et l'utilisation d'une pile Fifo?

Je te souhaite une très bonne journée,
Philippe

#8 Sandro

Sandro

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 1 262 messages
  • Gender:Male

Posté 28 février 2022 - 10:57

Bonjour,

est-ce que tu pourrais partager ton code?

Selon comment tu utilises les cases et comment tu fais bouger les moteurs, c'est bien possible que la structure en "case" soit le problème, ou pas (tout dépend si tu peux rester "bloqué" (par exemple en attendant la fin de la trame) ou pas).

 

Pour là "pile Fifo" : attention, pile et Fifo sont des contraires : une pile, c'est "dernier arrivé, premier sorti" (comme une pile d'assiètes dans ton placard), alors qu'une Fifo, c'est "first in, first out", c'est à dire "premier arrivé, premier servi/sorti" (comme la file d'attente au supermarché) : ici, je penses que c'est une Fifo (ie file) qu'il te faut.

 

Sinon, la librairie "CircularBuffer" peut servir à créer une Fifo, mais avec quelques contraintes :

- la Fifo a une taille limitée (mais ça, sur un microcontroleur avec peu de RAM, comme l'arduino, c'est inévitable)

- elle ne supporte que les types de bases(char, int, float, ...) et "void* " : pour enregistrer des objets "trame", il vas donc falloir créer des objets/structures, puis récuperer le pointeur correspondant et le transformer en "void *" : c'est pas

un vrai problème, mais dès qu'on utilise du void*, on a vite fait de se tromper et d'avoir des erreurs dur à débogguer

- je sais pas si le comportement de supprimer la plus vielle trame lorsque le buffer est plein te convient (nb : tu peux aussi vérifier si la trame est pleine, et décider toi même quoi faire le cas échéant (ne pas ajouter, ou ajouter en supprimant l'élément le plus ancien)

- il faut faire attention à la gestion de la mémoire : a toi de supprimer chaque objet lorsqu'il est retiré de la Fifo et que tu n'en a pas besoin

 

Donc globalement, oui, tu peux utiliser "CircularBuffer", mais pour à peine plus d'effort, tu peux écrire ta propre Fifo et ainsi bien comprendre comment ça marche. A toi de choisir. NB : si ta file est assez courte (disons quelque dizaines d'éléments max) et que tu utilises des pointeurs vers tes trames, alors tu peux faire le bourrin et juste copier (memcpy) tes éléments vers l'avant à chaque fois que tu sors un élément : c'est un peu moins efficace, mais plus simple conceptuellement qu'un buffer circulaire


Aidez-nous à vous aider : partagez toutes les informations pertinentes : description précise du problème, contexte, schéma de câblage, liens vers la documentation des composants, votre code (ou encore mieux un code minimal reproduisant le bug), ...

Vous recevrez ainsi plus de réponses, et elles seront plus pertinentes.


#9 Phil2P

Phil2P

    Membre

  • Membres
  • 44 messages
  • Gender:Male

Posté 01 mars 2022 - 11:27

Bonjour Sandro,
Je te remercie pour ton aide.

Je veux bien partager mon code, mais je ne sais pas trop comment : j'ai essayé de le joindre à ce message. Tu me diras si ça a marché.

Il s'agit probablement d'un code récupéré sur le net par mes élèves car il y a des commentaires en anglais...

Pour pouvoir l'utiliser, nous trichons sur le PC en calculant grossièrement le temps de traitement d'une trame par l'Arduino et envoyant la trame suivante quand nous sommes sûrs que la trame actuelle est traitée. Cela occasionne probablement ces délais, retards et arrêts lors du traitement de plusieures trames successives.

Pour résoudre ce problème, nous avons donc pensé demander à l'Arduino d' envoyer une info au pc lorsque la trame actuelle est traitée pour que le pc puisse envoyer la nouvelle trame.

Pour envoyer plusieurs trames d'avance à l'Arduino, une autre solution serait une file Fifo (j'ai compris ta remarque je crois) qui ne devra supprimer une trame que lorsqu'elle a était traitée.
Ces trames sont composées de 12 float (un angle et une vitesse pour chaque articulation).
Quelle serait alors le nombre de trames que pourrait stocker notre Arduino Mega dans sa mémoire ?

Nous avons un niveau très faible en programmation Arduino. Je pensais qu'une librairie pourrait limiter les difficultés pour créer et utiliser cette file FIFO...

Encore merci de votre aide,
Philippe

Fichier(s) joint(s)



#10 Sandro

Sandro

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 1 262 messages
  • Gender:Male

Posté 02 mars 2022 - 12:10

Bonsoir,

 

ta méthode pour joindre le code fonctionne (on peut le télécharger). Ce qui est encore mieux, c'est d'utiliser la balise code, comme ça c'est lisible depuis le forum : cf https://www.robot-ma...obot-Maker.html partie 4.

 

 

Pour le fait que le robot se fige lors de la réception d'une nouvelle trame, c'est normal vu la manière dont le code est écrit : quand tu reçois une instruction (par exemple 'M'), alors tu attends de recevoir la suite de la trame (les Serial.parseFloat sont bloquants jusqu'à ce qu'un flotant soit détecté). Donc tant que tu n'as pas entièrement reçu la trame, plus rien ne se passe.

 

Pour empirer les choses, vous avez choisi une vitesse très faible pour la communication série (9600 bits/s), ce qui fait 9600/8=2400 octets/s. Pour un float sous forme de caractères, il faut de l'ordre de 6 octets, donc tu peux envoyer 400 floats par seconde, soit 400/12=33 frames/s au maximum (un peu moins en pratique). Tu peux sans problème monter a des vitesses bien supérieures (115200 bits/s voir plus), il suffit de modifier la valeur du Serial.begin, et de donner la même valeur coté PC.

 

Si tu veux que la réception des trames ne soit plus du tout bloquante, alors il faut que tu récupère juste les octets reçus à l'instant t (et que tu les stockes), puis que tu interprète la trame qu'un fois complète. NB : détecter une trame complète est plus facile si tu envoie la trame en binaire qu'en texte, car la longueur de la trame en octets est alors toujours la même.

 

 

Si une petite intéruption dans l'exécution entre le traitement de 2 trmaes succéssives ne pose pas de problème, alors signaler au PC qu'une trame est finie et qu'on veut la suivante me semble une bonne solution (nb : il faut accepter la tramme stop à tout instant).

 

 

Pour la Fifo, sur une Arduino Mega, tu as 8 ko de RAM. Ton programme utilise environ 1ko pour les variables globales, et vu ton code, je penses que 1ko suffit actuellement pour les variables locales. ça laisserait donc environ 6ko pour la Fifo.

Si la Fifo contient des trames de 12 float, alors chaque trame contient 12*4=48 octets, donc tu peux socker environ 6000/48= 125 trames.

 

 

Si tu veux une solution la plus facile possible, je te suggèrerais l'une des solutions suivantes :

1) tu envoie toute la trajectoire au début, puis le robot ne fait qu'exécuter (sans interaction jusqu'à avoir fini la séquence)

ou

2) l'arduino demande une nouvelle séquence au PC dès que l'arduino a fini la séquence en cours.


Aidez-nous à vous aider : partagez toutes les informations pertinentes : description précise du problème, contexte, schéma de câblage, liens vers la documentation des composants, votre code (ou encore mieux un code minimal reproduisant le bug), ...

Vous recevrez ainsi plus de réponses, et elles seront plus pertinentes.


#11 Phil2P

Phil2P

    Membre

  • Membres
  • 44 messages
  • Gender:Male

Posté 02 mars 2022 - 08:33

Fichier joint  FirmwareArduinoV1.ino   13,53 Ko   116 téléchargement(s)

/*
 * Commande Robot depuis Scilab
 * 
 * Créé par P. Dalmeida et P. de Poumayrac
 * Version du 17/03/2021
 */

/* format des commandes utilisées
     'M q1 q2 q3 q4 q5 q6' : Mouvement en coordonées articulaires absolues
     'P pince' : Mouvement de la pince.
     'T q1 s1 q2 s2 q3 s3 q4 s4 q5 s5 q6 s6' : 
     'S' : Stops the motor immediately.
     'F' : Updates the position current position and makes it as the new values.
 */
 
#include <AccelStepper.h> // Importation librairie gestion des Steppers
#include <Wire.h>         // Importation librairie gestion port I2C
#include <Servo.h>        // Importation librairie gestion servomoteur

Servo pince;              // create servo object to control a servo

const int colorR = 255;   // Couleur fond écran
const int colorG = 0;
const int colorB = 0;
const int step1=200;     // Nb Step Motor 1
const int step2=200;     // Nb Step Motor 2
const int step3=200;     // Nb Step Motor 3
const int step4=200;     // Nb Step Motor 4
const int step5=200;     // Nb Step Motor 5
const int step6=200;     // Nb Step Motor 6

float q1 = 0;                       // Angles
float q2 = 0;
float q3 = 0;
float q4 = 0;
float q5 = 0;
float q6 = 0;
float r1 = 8.333;                       // Rapports de réduction
float r2 = 5.5;
float r3 = 21.429;
float r4 = 1;
float r5 = 3.667;
float r6 = 1;

long receivedSteps1;                // Number of steps
long receivedSpeed1 = 100;          // Steps / second
long receivedAcceleration1 = 50;   // Steps / second^2
long receivedSteps2;                // Number of steps
long receivedSpeed2 = 100;          // Steps / second
long receivedAcceleration2 = 50;   // Steps / second^2
long receivedSteps3;                // Number of steps
long receivedSpeed3 = 100;          // Steps / second
long receivedAcceleration3 = 50;   // Steps / second^2
long receivedSteps4;                // Number of steps
long receivedSpeed4 = 100;          // Steps / second
long receivedAcceleration4 = 50;   // Steps / second^2
long receivedSteps5;                // Number of steps
long receivedSpeed5 = 100;          // Steps / second
long receivedAcceleration5 = 50;   // Steps / second^2
long receivedSteps6;                // Number of steps
long receivedSpeed6 = 100;          // Steps / second
long receivedAcceleration6 = 50;   // Steps / second^2
long receivedGripper;
char receivedCommand;

bool newData, runallowed = false;   // booleans for new data from serial, and runallowed flag

#define STEPPER1_DIR_PIN 2
#define STEPPER1_STEP_PIN 3
#define STEPPER2_DIR_PIN 4
#define STEPPER2_STEP_PIN 5
#define STEPPER3_DIR_PIN 6
#define STEPPER3_STEP_PIN 7
#define STEPPER4_DIR_PIN 8
#define STEPPER4_STEP_PIN 9
#define STEPPER5_DIR_PIN 10
#define STEPPER5_STEP_PIN 11
#define STEPPER6_DIR_PIN 12
#define STEPPER6_STEP_PIN 13
#define motorInterfaceType 1

// Create a new instance of the AccelStepper class:
AccelStepper stepper1 = AccelStepper(motorInterfaceType, STEPPER1_STEP_PIN, STEPPER1_DIR_PIN);
AccelStepper stepper2 = AccelStepper(motorInterfaceType, STEPPER2_STEP_PIN, STEPPER2_DIR_PIN);
AccelStepper stepper3 = AccelStepper(motorInterfaceType, STEPPER3_STEP_PIN, STEPPER3_DIR_PIN);
AccelStepper stepper4 = AccelStepper(motorInterfaceType, STEPPER4_STEP_PIN, STEPPER4_DIR_PIN);
AccelStepper stepper5 = AccelStepper(motorInterfaceType, STEPPER5_STEP_PIN, STEPPER5_DIR_PIN);
AccelStepper stepper6 = AccelStepper(motorInterfaceType, STEPPER6_STEP_PIN, STEPPER6_DIR_PIN);

void setup()
{
    Serial.begin(9600);
    Serial1.begin(9600);
    pince.attach(22);                                 // attaches the servo on pin 22 to the servo object
    //setting up some default values for maximum speed and maximum acceleration
    stepper1.setMaxSpeed(receivedSpeed1);             //SPEED = Steps / second
    stepper1.setAcceleration(receivedAcceleration1);  //ACCELERATION = Steps /(second)^2
    stepper2.setMaxSpeed(receivedSpeed2);             //SPEED = Steps / second
    stepper2.setAcceleration(receivedAcceleration2);  //ACCELERATION = Steps /(second)^2
    stepper3.setMaxSpeed(receivedSpeed3);             //SPEED = Steps / second
    stepper3.setAcceleration(receivedAcceleration3);  //ACCELERATION = Steps /(second)^2
    stepper4.setMaxSpeed(receivedSpeed4);             //SPEED = Steps / second
    stepper4.setAcceleration(receivedAcceleration4);  //ACCELERATION = Steps /(second)^2
    stepper5.setMaxSpeed(receivedSpeed5);             //SPEED = Steps / second
    stepper5.setAcceleration(receivedAcceleration5);  //ACCELERATION = Steps /(second)^2
    stepper6.setMaxSpeed(receivedSpeed6);             //SPEED = Steps / second
    stepper6.setAcceleration(receivedAcceleration6);  //ACCELERATION = Steps /(second)^2 
    stepper1.disableOutputs();                        //disable outputs
    stepper2.disableOutputs();                        //disable outputs
    stepper3.disableOutputs();                        //disable outputs
    stepper4.disableOutputs();                        //disable outputs
    stepper5.disableOutputs();                        //disable outputs
    stepper6.disableOutputs();                        //disable outputs
}

void loop()
{
    checkSerial(); //check serial port for new commands
    RunTheMotor(); //function to handle the motor
}

void checkSerial() //function for receiving the commands
{  
if (Serial.available() > 0) //if something comes from the computer
    {
        receivedCommand = Serial.read(); // pass the value to the receivedCommad variable
        newData = true; //indicate that there is a new data by setting this bool to true
 
        if (newData == true) //we only enter this long switch-case statement if there is a new command from the computer
        {
            switch (receivedCommand)      //we check what is the command
            {
 
            case 'M':     //M is used to move the robot absolutely to the current position           
               
                receivedSteps1 = Serial.parseFloat();
                receivedSteps2 = Serial.parseFloat(); 
                receivedSteps3 = Serial.parseFloat();
                receivedSteps4 = Serial.parseFloat();
                receivedSteps5 = Serial.parseFloat();
                receivedSteps6 = Serial.parseFloat();

                receivedSpeed1 = 50*r1;
                receivedSpeed2 = 50*r2;
                receivedSpeed3 = 50*r3;
                receivedSpeed4 = 50*r4;
                receivedSpeed5 = 50*r5;
                receivedSpeed6 = 50*r6;
                
                RotateAbsolute();         //Run the function
                
                break;         

            case 'P':     //P is used to move the robot gripper           
               
                receivedGripper = Serial.parseFloat();
                
                receivedGripper = map(receivedGripper, 0, 100, 95, 40); // scale it to use it with the servo (value between 0 and 180)
                pince.write(receivedGripper);                           // sets the servo position according to the scaled value
                delay(15);                                              // waits for the servo to get there

                break;         

            case 'T':       //T is used to move the robot absolutely to the current position           
               
                receivedSteps1 = Serial.parseFloat();
                receivedSpeed1 = Serial.parseFloat();
                receivedAcceleration1 = Serial.parseFloat();
                receivedSteps2 = Serial.parseFloat();
                receivedSpeed2 = Serial.parseFloat();
                receivedAcceleration2 = Serial.parseFloat(); 
                receivedSteps3 = Serial.parseFloat();
                receivedSpeed3 = Serial.parseFloat();
                receivedAcceleration3 = Serial.parseFloat();
                receivedSteps4 = Serial.parseFloat();
                receivedSpeed4 = Serial.parseFloat();
                receivedAcceleration4 = Serial.parseFloat();
                receivedSteps5 = Serial.parseFloat();
                receivedSpeed5 = Serial.parseFloat();
                receivedAcceleration5 = Serial.parseFloat();
                receivedSteps6 = Serial.parseFloat();
                receivedSpeed6 = Serial.parseFloat();
                receivedAcceleration6 = Serial.parseFloat();
                receivedGripper = Serial.parseFloat();
                receivedGripper = map(receivedGripper, 0, 100, 95, 40); // scale it to use it with the servo (value between 0 and 180)
                pince.write(receivedGripper);                           // sets the servo position according to the scaled value
                delay(15);                                              // waits for the servo to get there

                RotateAbsolute();         //Run the function
                
                break;         
  
            case 'S':                         // Stops the motor
               
                stepper1.stop();              //stop motor
                stepper1.disableOutputs();    //disable power
                stepper2.stop();              //stop motor
                stepper2.disableOutputs();    //disable power
                stepper3.stop();              //stop motor
                stepper3.disableOutputs();    //disable power
                stepper4.stop();              //stop motor
                stepper4.disableOutputs();    //disable power
                stepper5.stop();              //stop motor
                stepper5.disableOutputs();    //disable power
                stepper6.stop();              //stop motor
                stepper6.disableOutputs();    //disable power
                runallowed = false;           //disable running
                
                break;
 
            case 'F':
 
                runallowed = false;                 //we still keep running disabled
                receivedSteps1 = Serial.parseFloat();
                receivedSteps2 = Serial.parseFloat(); 
                receivedSteps3 = Serial.parseFloat();
                receivedSteps4 = Serial.parseFloat();
                receivedSteps5 = Serial.parseFloat();
                receivedSteps6 = Serial.parseFloat();

                stepper1.disableOutputs();          //disable power
                stepper2.disableOutputs();
                stepper3.disableOutputs();
                stepper4.disableOutputs();
                stepper5.disableOutputs();
                stepper6.disableOutputs();

                stepper1.setCurrentPosition(receivedSteps1);     //Reset current position. "new home"
                stepper2.setCurrentPosition(receivedSteps2);
                stepper3.setCurrentPosition(receivedSteps3);
                stepper4.setCurrentPosition(receivedSteps4);
                stepper5.setCurrentPosition(receivedSteps5);
                stepper6.setCurrentPosition(receivedSteps6);
             
                break; 
  
            default:  

                break;
            }
        }
        //after we went through the above tasks, newData is set to false again, so we are ready to receive new commands again.
        newData = false;       
    }
}

void RunTheMotor() //function for the motor
{
    if (runallowed == true)
    {
        stepper1.enableOutputs(); //enable pins
        stepper2.enableOutputs(); //enable pins
        stepper3.enableOutputs(); //enable pins
        stepper4.enableOutputs(); //enable pins
        stepper5.enableOutputs(); //enable pins
        stepper6.enableOutputs(); //enable pins
        stepper1.run();           //step the motor (this will step the motor by 1 step at each loop)
        stepper2.run();           //step the motor (this will step the motor by 1 step at each loop)
        stepper3.run();           //step the motor (this will step the motor by 1 step at each loop)
        stepper4.run();           //step the motor (this will step the motor by 1 step at each loop)
        stepper5.run();           //step the motor (this will step the motor by 1 step at each loop)
        stepper6.run();           //step the motor (this will step the motor by 1 step at each loop)
    }
    else //program enters this part if the runallowed is FALSE, we do not do anything
    {
        stepper1.disableOutputs(); //disable outputs
        stepper2.disableOutputs(); //disable outputs
        stepper3.disableOutputs(); //disable outputs
        stepper4.disableOutputs(); //disable outputs
        stepper5.disableOutputs(); //disable outputs
        stepper6.disableOutputs(); //disable outputs
        return;
    }
}

void RotateAbsolute()
{
    //We move to an absolute position.
    //The AccelStepper library keeps track of the position.
 
    runallowed = true; //allow running - this allows entering the RunTheMotor() function.
    stepper1.setMaxSpeed(receivedSpeed1);   //set speed
    stepper2.setMaxSpeed(receivedSpeed2);   //set speed
    stepper3.setMaxSpeed(receivedSpeed3);   //set speed
    stepper4.setMaxSpeed(receivedSpeed4);   //set speed
    stepper5.setMaxSpeed(receivedSpeed5);   //set speed
    stepper6.setMaxSpeed(receivedSpeed6);   //set speed
    stepper1.moveTo(receivedSteps1);        //set absolute position 
    stepper2.moveTo(receivedSteps2);        //set absolute position
    stepper3.moveTo(receivedSteps3);        //set absolute position 
    stepper4.moveTo(receivedSteps4);        //set absolute position
    stepper5.moveTo(receivedSteps5);        //set absolute position 
    stepper6.moveTo(receivedSteps6);        //set absolute position  
}

 


Modifié par Melmet, 02 mars 2022 - 06:36 .
Plus lisible :)


#12 Phil2P

Phil2P

    Membre

  • Membres
  • 44 messages
  • Gender:Male

Posté 14 mars 2022 - 10:01

Bonsoir,

"Donc tant que tu n'as pas entièrement reçu la trame, plus rien ne se passe."

Nous souhaitons que l'Arduino commence à mettre en mouvement toutes les articulations en même temps.

Il faut pour cela qu'il ait reçu toutes les infos nécessaires inclues dans une trame..

 

Nous allons augmenter la vitesse de transmission sur l'Arduino et le PC à 115200 bits/s. Merci !

 

La solution N°1, la plus simple, me semble en effet que l'Arduino envoie un signal au PC lorsque les moteurs sont arrivées dans la configuration choisie. Il reste à tenir compte tout de même d'un éventuel "STOP" envoyé du PC OU d'un appui sur l’arrêt d'urgence qui, pour l'instant, coupe brutalement l'alimentation.

 

Pour la FIFO, 125 "trames d'avance" seraient largement suffisant. En effet, la solution N°2 serait alors d'envoyer toutes les trames et de laisser l'Arduino finir tranquillement son travail.

 

La solution N°3 serait d'utiliser "dynamiquement" la FIFO et d'envoyer au fur et à mesure les trames du PC à l'Arduino. Chacun travaillant à son rythme...

 

Voyez-vous une meilleur solution ?

 

Est-ce qu'une librairie comme CircularBuffer, MD_CirQueue ou Ringbuf permettrait de mettre en œuvre une FIFO pour les solutions 2 et 3 ?

 

Merci de partager vos connaissances et votre expérience.

 

Je vous souhaite une très bonne soirée,

Philippe

 

 

 

 



#13 Sandro

Sandro

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 1 262 messages
  • Gender:Male

Posté 14 mars 2022 - 10:37

Bonsoir

"Donc tant que tu n'as pas entièrement reçu la trame, plus rien ne se passe."

Nous souhaitons que l'Arduino commence à mettre en mouvement toutes les articulations en même temps.

Il faut pour cela qu'il ait reçu toutes les infos nécessaires inclues dans une trame..

Ce que je veux dire, c'est que pendant que tu reçois une trame, actuellement les moteurs s'arrêtent (alors que tu pourrais poursuivre le mouvement en cours jusqu'à avoir reçu la nouvelle trame entièrement)
 

 

La solution N°3 serait d'utiliser "dynamiquement" la FIFO et d'envoyer au fur et à mesure les trames du PC à l'Arduino. Chacun travaillant à son rythme...

C'est ma "meilleure" solution d'un point de vu de l'utilisateur. Mais un poil plus compliqué que la solution 2

 

 

Est-ce qu'une librairie comme CircularBuffer, MD_CirQueue ou Ringbuf permettrait de mettre en œuvre une FIFO pour les solutions 2 et 3 ?

Pour la solution 2, tu n'as pas besoin de Fifo, vu que tu envoie toutes les trames avant l'exécution du programme : il suffit de créer un tableau, que tu remplie de 1 à N au début, puis que tu lis de 1 à N.
Pour les 3 libraires que tu mentionnes, elles n'acceptent que soit des types de bases, soit éventuellement des structures (de taille fixe). Tu peux te débrouiller avec n'importe quelle de ces librairies en utilisant des pointeurs, ou éventuellement des structures (ce qui t'oblige à créer une trame "universelle" répondant à toutes les commandes possibles).

Si tu veux une approche plus "intuitive", ça peut être intéressant d'avoir des classes pour les différents types de trames, et une classe mère "trame" qui les englobe tous. Tu peux faire ça avec les librairies dont tu parles en manipulant des pointeurs sur des objets trames. Mais une solution plus simple serait d'utiliser une FIFO qui accepte les objets : celle-ci pourrait (à première vue) pourrait faire l'affaire : https://github.com/w...ded_RingBuf_CPP (nb : c'est la version C++ de RingBuf, du même auteur)
 



 


Aidez-nous à vous aider : partagez toutes les informations pertinentes : description précise du problème, contexte, schéma de câblage, liens vers la documentation des composants, votre code (ou encore mieux un code minimal reproduisant le bug), ...

Vous recevrez ainsi plus de réponses, et elles seront plus pertinentes.


#14 Phil2P

Phil2P

    Membre

  • Membres
  • 44 messages
  • Gender:Male

Posté 31 mars 2022 - 05:43

Merci beaucoup Ludovic Dille et Sandro pour vos conseils précieux.

Je vais tester vos solutions dès que je retrouve un peu de temps et je viendrais vous montrer le résultat.

 

Je vous souhaite une très bonne soirée,

Philippe






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

0 members, 0 guests, 0 anonymous users