Aller au contenu


Photo
- - - - -

Gcom communication Pi Arduino.


95 réponses à ce sujet

#81 cocothebo

cocothebo

    Habitué

  • Membres
  • PipPip
  • 264 messages
  • Gender:Male

Posté 05 avril 2018 - 03:53

Salut,

 

Je maintiens mon analyse précédente, tu as un protocole qui est asynchrone (tu envoies des données sans attendre un quelconque accusé etc...) et tu fais des traitements comme si c'était synchrone.

 

Petit à petit ton arduino et Pi se désynchronisent puisque rien ne te garanti qu'en attendant 100ms des deux côté, il se passerra déjà exactement 100ms, et en plus le reste des traitements ne peuvent (théoriquement) pas durer le même temps sauf super gros coup de chance.

Bref petit à petit ça se dérègle. Et pour rajouter du "bruit" la dessus, sur le PI tu as un OS complexe, donc ton programme peut être plus ou moins interrompu, ce qui fait que d'une exécution à une autre ça va se synchroniser plus ou moins vite.

 

Pour vérifier si ce que je dis est bon, tu pourrais faire en sorte que l'arduino envoie qqc sur le port série après avoir reçu une trame compète. Et pendant ce temps ton Pi, après envoie de la trame doit attendre de recevoir ce "GO" pour envoyer la suivante.

De cette façon tu conserves une synchronisation, et si ma théorie est juste les pb devraient disparaitre (quoi si c'est l'unique cause bien sur :P)

 

 

Bon courage



#82 Oliver17

Oliver17

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 2 045 messages
  • Gender:Male
  • Interests:Glenn

Posté 05 avril 2018 - 04:03

Ok, j'ai bien compris, donc dans un premier temps j'ai testé justement ce problème de synchronisation avec les 100 ms de chaque coté, et j'en étais arrivé à me dire la même chose que toi (mais avec moins de classe lol ^^), donc j'ai fais un test tous simple, on va laisser ça en asynchrone si je dis pas de connerie en virant tous simplement les 100 ms coté Arduino, en fait arduino attend de recevoir quelque chose, on s'en fout un peu qu'il attende toutes les 100 ms une trame, vu que coter Pi on envoie tous les 100 ms.

 

En gros, ça fonctionne bien pour l'instant, j'ai fais tourner le bousin pendant un moment, ça plante pas, je vais refaire un test et laisser tourner quelques minutes pour voir ^^

 

Sinon, ben va falloir que je test ton idée Cocothebo avec les trames complète etc etc ^^

 

Merci, je fais tourner tous ça pendant un moment et je reviens vous tenir au courant ^^


signature_01.png -->
 
 

#83 Oliver17

Oliver17

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 2 045 messages
  • Gender:Male
  • Interests:Glenn

Posté 05 avril 2018 - 06:10

Hey hey heeyyyyy je crois que ça tiens mon histoire ^^

 

Ça tourne depuis 5 mn et pas d'erreurs pour l'instant, j'envoie des infos et reçois des deux cotés :)

 

Je laisse tourner un bon moment, je met le code au propre et post tous ça des que je peux.


signature_01.png -->
 
 

#84 cocothebo

cocothebo

    Habitué

  • Membres
  • PipPip
  • 264 messages
  • Gender:Male

Posté 05 avril 2018 - 07:53

Oui si tu retires la "fausse" synchro du 100ms ça devrait marcher, même si suivant le temps de traitement côté arduino des pb risques de se présenter quand même.

 

Moi je changerai quand même la ligne:

while (Serial1.available() > 0) { //if any data available // >0
    Serial1.readBytes (ardRec.dataRece, BUF_SIZEREC); //BUF_SIZEREC);

qui a n'a à mon avis pas le rôle que tu veux lui donner.

 

On est dans la fonction qui veut reconstruire les trames, cette fonction étant dans la fonction de boucle infinie "loop". A priori cette fonction devrait attendre d'avoir assez d'octets à lire pour une trame et la traiter, donc un truc du genre

while (Serial1.available() < BUF_SIZEREC) {} //boucle d'attente d'une trame

// Ici on met le traitement d'une trame vu qu'on a recu le bon nombre d'octets
Serial1.readBytes (ardRec.dataRece, BUF_SIZEREC); //BUF_SIZEREC);
...

Bon après si tu veux pas que ce soit bloquant, il faudra forcément passer par les interruptions...



#85 Oliver17

Oliver17

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 2 045 messages
  • Gender:Male
  • Interests:Glenn

Posté 06 avril 2018 - 08:26

Effectivement, évitons d'avoir des fonctions bloquante, :) 

 

Bon, je met déjà au propre ce que j'ai fais, je post et ensuite je cherche du coté "interruptions et les threads" (oui j'ai déjà un peu cherché tout à l'heure lol).


signature_01.png -->
 
 

#86 cocothebo

cocothebo

    Habitué

  • Membres
  • PipPip
  • 264 messages
  • Gender:Male

Posté 06 avril 2018 - 08:55

Une première approche simple sans utiliser les interruptions (même si en embarqué ça reste quand même important de savoir les gérer) est de faire un code du style:

void loop()
{
   //Traitements si nécessaire avant la reception de trames
   ...

   //Si on a recu une trame complète
   //Ça reste non bloquant, si tu as rien reçu ou pas encore assez, on passe à la suite
   if (Serial1.available() >= BUF_SIZEREC) 
   { 
      //Traiter la réception de la trame
      ...
   }

   //On continue les traitements normaux, genre la gestion des moteurs
   //A chaque passage dans loop(), on passerra par ce code
   ...

}

qui permet de ne pas attendre la reception de BUF_SIZEREC octets comme dans ma proposition précédente.



#87 Oliver17

Oliver17

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 2 045 messages
  • Gender:Male
  • Interests:Glenn

Posté 06 avril 2018 - 04:24

Ok Cocothebo, je test ça au plus vite, j'avais dis que je posterais aujourd'hui pour le code, mais pas eu le temps, bon en même temps c'est pas comme si tout le monde l'attendait lol :(

 

Je vais voir un peu ce que j'ai trouvé sur les interruptions et les threads, le multithreading ça a l'air pas mal. :)


signature_01.png -->
 
 

#88 Oliver17

Oliver17

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 2 045 messages
  • Gender:Male
  • Interests:Glenn

Posté 07 avril 2018 - 10:50

Coucou, donc voici le code, actuellement il fonctionne sans aucunes pertes de données ^^ cool.

Mais c'est loin d'être fini.

 

@Cocothebo : merci et si tu as d'autres suggestions no prob ;)

 

Gcom.cpp

#include <iostream> //Permet d'utiliser In et Out du moniteur série
#include "rs232.h"  //Librairie de communication RS232

using namespace std;

int cport_nr(0);                        // 0 = ttyS0  ls /dev/tty*

struct S_SERVO
{
    char ms_membre ;                    //1 octet/bytes (8 bits)  : 0 / 255
    char ms_servo ;                     //1 octet/bytes (8 bits)  : 0 / 255
    unsigned short int ms_acceleration ;//2 octet/bytes (16 bits) : 0 / 65 535
    //short int ms_vitesse ;            //2 octet/bytes (16 bits) : -32 768 / +32 767
    //short int ms_cible ;              //2 octet/bytes (16 bits) : -32 768 / +32 767
};

struct S_ARDUINO
{
    short int roll;             //2 octet/bytes (16 bits) : -32 768 / +32 767
    short int pitch;            //2 octet/bytes (16 bits) : -32 768 / +32 767
    short int yaw;              //2 octet/bytes (16 bits) : -32 768 / +32 767
    unsigned short int boussole;//2 octet/bytes (16 bits) : 0 / 65 535
};

union U_DATA
{
    S_SERVO s_servo;
    S_ARDUINO s_arduino;
    unsigned char cast_servo[sizeof (s_servo)];
    unsigned char cast_arduino[sizeof (s_arduino)];

}u_servo, u_arduino, u_buf;

//class permettant la création d'objet (servo) 
class C_SERVO
{
    public :
    C_SERVO(char, char, unsigned short int);
    ~C_SERVO();
    U_DATA *cu_servo;     //pointeur sur un type U_DATA, on utilise la même case mémoire
    void affiche() const;
};

C_SERVO::C_SERVO (char mbr, char servo, unsigned short int acceleration) 
{
    cu_servo = &u_servo;
    cu_servo->s_servo.ms_membre = mbr;
    cu_servo->s_servo.ms_servo = servo;
    cu_servo->s_servo.ms_acceleration = acceleration;
    
    //l'objet est crée, on peut l'envoyer
    cout << "Création objet : \n"; 
    RS232_SendBuf(cport_nr, cu_servo->cast_servo, sizeof (u_buf.cast_servo));
    cout << "----- \n";
 
}

C_SERVO::~C_SERVO()
{
    cout << "Objet détruit... \n";
    cout << "----- \n";
}

void C_SERVO::affiche () const
{
    cout << "&cu_servo->s_servo : \t\t" << &cu_servo->s_servo << "\n";
    cout << "cu_servo->s_servo.ms_membre : \t\t" << cu_servo->s_servo.ms_membre << "\n";
    cout << "cu_servo->s_servo.ms_servo : \t\t" << cu_servo->s_servo.ms_servo << "\n";
    cout << "cu_servo->s_servo.ms_acceleration : \t" << cu_servo->s_servo.ms_acceleration << "\n";
    //cout << "ms_vitesse : \t\t" << ms_vitesse << "\n";
    //cout << "ms_cible : \t\t" << ms_cible << "\n";
    cout << "----- \n";
}

void fctDelete (C_SERVO *);

int main ()
{
    short int i = 0;
    //int cport_nr(0);              // 0 = ttyS0  ls /dev/tty*
    int bdrate(115200);             // Baud
    char mode []={'8','N','1',0};   // 8 data bits, no parity, 1 stop bit

    //Si toutes les conditions recquises sont bonnes, on test le port de communication
    if (RS232_OpenComport(cport_nr, bdrate, mode))
    {
        cout <<"Ne peut pas ouvrir le port com. \n";
        return 0;
    }
    cout << "----- \n";
    cout << "Raspberry connecté : \n";
    cout << "----- \n";

    //pour le test j'ai été un peu barbare, :)
    //on crée un objet, on argumente, on test en affichant les données grâce à la fonction "affiche"
    //on attend 100 ms et on efface l'objet avec la fonction "fctDelete"
    while(1)
    {
        C_SERVO *teteY;
        teteY = new C_SERVO (65, 85, 110); //65 = A ; 85 = U
        teteY->affiche();
       
        usleep(100000); //usleep est en ms - 1 - 100000 pause pour 100 milliSeconds
        fctDelete (teteY);

        C_SERVO *teteZ;
        teteZ = new C_SERVO (66, 86, 120); //66 = B ; 86 = V
        teteZ->affiche();
       
        usleep(100000); //usleep est en ms - 1 - 100000 pause pour 100 milliSeconds
        fctDelete (teteZ);

        C_SERVO *brasDY;
        brasDY = new C_SERVO (67, 87, 130); //67 = C ; 87 = W
        brasDY->affiche();
       
        usleep(100000); //usleep est en ms - 1 - 100000 pause pour 100 milliSeconds
        fctDelete (brasDY);

        C_SERVO *brasDX;
        brasDX = new C_SERVO (68, 88, 140); //68 = D ; 88 = X
        brasDX->affiche();
       
        usleep(100000); //usleep est en ms - 1 - 100000 pause pour 100 milliSeconds
        fctDelete (brasDX);

        C_SERVO *brasDZ;
        brasDZ = new C_SERVO (69, 89, 150); //69 = E ; 89 = Y
        brasDZ->affiche();

        usleep(100000); //usleep est en ms - 1 - 100000 pause pour 100 milliSeconds
        fctDelete (brasDZ);
    
        //Récupére un tableau de données de la pi dans le buffer envoyé d'Arduino
        //Via la RS232
        int n = RS232_PollComport(cport_nr, u_arduino.cast_arduino, sizeof (u_buf.cast_arduino));
        cout << "----- \n";
       
        cout << "Taille sizeof u_buf.cast_arduino : " << sizeof (u_buf.cast_arduino) << " octets/bytes. \n";

        if (n > 0)
        {
            u_arduino.cast_arduino[n] = 0;
            cout <<"Pi reçoit d'Arduino : "<< n <<" bytes. \n";
        }

        //On regarde ce qu'Arduino nous envoie
        cout << "Pi reçoit u_arduino.s_arduino.roll :\t\t " << u_arduino.s_arduino.roll <<" \n";
        cout << "Pi reçoit u_arduino.s_arduino.pitch :\t\t " << u_arduino.s_arduino.pitch <<" \n";
        cout << "Pi reçoit u_arduino.s_arduino.yaw :\t\t " << u_arduino.s_arduino.yaw <<" \n";
        cout << "Pi reçoit u_arduino.s_arduino.boussole :\t " << u_arduino.s_arduino.boussole <<" \n"; 

        usleep(100000); //usleep est en ms - 1 - 100000 pause pour 100 milliSeconds
   
    }
    return 0;
}

void fctDelete (C_SERVO * del)
{
    cout << "Appel fctDelete !! \n";
    delete del;
}

Arduino : 

//incomingByte initialisée pour tester l'entrée de données
int incomingByte = 0;

//Structure pour l'émission de données vers la PI
struct S_PI
{
  int roll;               //2 octet/bytes (16 bits) : -32 768 / +32 767
  int pitch;              //2 octet/bytes (16 bits) : -32 768 / +32 767
  int yaw;                //2 octet/bytes (16 bits) : -32 768 / +32 767
  unsigned int boussole;  //2 octet/bytes (8 bits)  : 0 / 65 535
 
};

//Structure pour la récepetion des données des servomoteurs
struct S_SERVO
{
  byte membre ;               //1 octet/bytes (8 bits)  : 0 / 255
  byte servo ;                //1 octet/bytes (8 bits)  : 0 / 255
  unsigned int acceleration ; //2 octet/bytes (8 bits)  : 0 / 65 535
  //int vitesse ;             //2 octet/bytes (16 bits) : -32 768 / +32 767
  //int cible ;               //2 octet/bytes (16 bits) : -32 768 / +32 767
 
}; 

//Union pour envoyer nos types struct dans un tableau unsigned char
union U_DATA
{
  S_PI s_pi;
  S_SERVO s_servo;
 
  //L'envoie et la réception sont dans des tableaux
  //(sizeof) permet de récupérer la taille en byte de nos structures
  unsigned char cast_servo[sizeof s_servo];
  unsigned char cast_pi[sizeof s_pi];
}u_servo, u_pi, u_buf;

byte j = 0;

void setup(){
  Serial.begin (115200);
  Serial1.begin(115200); //ici j'utilise un convertisseur de niveau logique, que l'on peut trouver sur la boutique

  //Initisalisation de la structure s_pi
  u_pi.s_pi.roll = 180;
  u_pi.s_pi.pitch = 90;
  u_pi.s_pi.yaw = 45;
  u_pi.s_pi.boussole = 360;
 
}
void loop() {
 
  arduinoSend();
 
  if (Serial1.available() >= sizeof u_buf.cast_servo) //= u_buf.cast_servo)
  {
    incomingByte = Serial1.readBytes (u_servo.cast_servo, sizeof u_buf.cast_servo);
    piReceive();   
  }
   
}

//fonction pour l'envoi de données
void arduinoSend(){

  unsigned int waitingTime = 100;  // 0.100 secondes
  unsigned long refTime = 0;
 
  //Envoie un tableau de données u_pi.cast_pi au format unsigned char dans le buffer à la pi
  Serial1.write (u_pi.cast_pi, sizeof u_buf.cast_pi);
 
  Serial.print ("u_pi.s_pi.roll :\t ");
  Serial.println (u_pi.s_pi.roll);
  Serial.print ("u_pi.s_pi.pitch :\t ");
  Serial.println (u_pi.s_pi.pitch);
  Serial.print ("u_pi.s_pi.yaw :\t\t ");
  Serial.println (u_pi.s_pi.yaw);
  Serial.print ("u_pi.s_pi.boussole :\t ");
  Serial.println (u_pi.s_pi.boussole);
  Serial.print ("u_buf.cast_pi : ");
  Serial.println (sizeof (u_buf.cast_pi));
 
  Serial.println("Données envoyées toutes les 100 ms :");
  refTime = millis();
  // début de l'attente :
  while((millis()-refTime)<waitingTime){
    //Attends
  }
}

//fonction affichant la réception de données
void piReceive (){

  Serial.println ("----------");
  Serial.println ("u_servo.s_servo : ");
  Serial.println (u_servo.s_servo.membre);
  Serial.println (u_servo.s_servo.servo);
  Serial.println (u_servo.s_servo.acceleration);
  //Serial.println (u_servo.s_servo.vitesse);
  //Serial.println (u_servo.s_servo.cible);
  Serial.println ("-----");
  Serial.print ("u_buf.cast_servo : ");
  Serial.println (sizeof (u_buf.cast_servo));

  Serial.print ("Compteur j : ");
  Serial.println (j);
  j++;

  Serial.println ("-----");
 
}

Même si ce n'est pas parfais je le reconnais, mais je progresse et c'est super sympa je trouve ^^

Faut améliorer tous ça  ;)

 

Merci


signature_01.png -->
 
 

#89 Oliver17

Oliver17

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 2 045 messages
  • Gender:Male
  • Interests:Glenn

Posté 11 avril 2018 - 10:07

Plop les maker's, voici un peu les news :

- J'ai laissé tomber la class avec création d'objet, c'était super intéressant de tester les class :) , du coup je suis revenu à l'union avec structure et ça fonctionne très bien, me suis fais un ptit truc en plus qui dit que si la donnée cible est identique alors on ne l'envoie pas. :)

 

Bref pour l'instant c'est cool ^^

 

Hop j'y retourne...
 


signature_01.png -->
 
 

#90 Oliver17

Oliver17

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 2 045 messages
  • Gender:Male
  • Interests:Glenn

Posté 26 avril 2018 - 02:15

Plop les maker's, alors voilà, j'ai voulu découper mon programme et j'avoue que je suis un peu perdu sur la façon de procéder pour une meilleur lisibilité du code, bien entendu j'ai des erreurs ^^

J'ai bien réussi à en corriger quelques unes mais je tourne un peu en rond.

 

main.cpp

#include <iostream> //Permet d'utiliser In et Out du moniteur série
#include "rs232.h"  //Librairie de communication RS232
#include "Gcom.h"

using namespace std;

short int posDegres = 0;
unsigned short int vitesse = 0;

//union U_DATA u_servo[NB_SERVO], u_arduino, u_buf;

int main ()
{
    short int i = 0;
    srand ((int)time(0));   //Random chiffre aléatoire pour chaque boucle

    //Fonction pour tester la conexion entres les deux cartes
    F_CONNECTION();
  
    u_servo[0].s_servo.ms_membre = 1;
    u_servo[0].s_servo.ms_servo = 0;
    u_servo[0].s_servo.ms_vitesse = 420; //vitesse en milliseconde ; ms
    u_servo[0].s_servo.ms_cible = 0;
   
    u_servo[1].s_servo.ms_membre = 1;
    u_servo[1].s_servo.ms_servo = 1;
    u_servo[1].s_servo.ms_vitesse = 420; //vitesse en milliseconde ; ms
    u_servo[1].s_servo.ms_cible = 0;

    u_servo[2].s_servo.ms_membre = 2;
    u_servo[2].s_servo.ms_servo = 2;
    u_servo[2].s_servo.ms_vitesse = 420; //vitesse en milliseconde ; ms
    u_servo[2].s_servo.ms_cible = 0;

    u_servo[3].s_servo.ms_membre = 2;
    u_servo[3].s_servo.ms_servo = 3;
    u_servo[3].s_servo.ms_vitesse = 420; //vitesse en milliseconde ; ms
    u_servo[3].s_servo.ms_cible = 0;

    u_servo[4].s_servo.ms_membre = 2;
    u_servo[4].s_servo.ms_servo = 4;
    u_servo[4].s_servo.ms_vitesse = 420; //vitesse en milliseconde ; ms
    u_servo[4].s_servo.ms_cible = 0;
    //u_servo[4].s_servo.ms_vitesse = 420; //vitesse en milliseconde ; ms

    while(1)
    {

        cout << "Vitesse en ms : \n";
        cin >> vitesse;
        cout << "\n" ;
        cout << "Target en degrès : \n";
        cin >> posDegres;
        cout << "\n" ;
        
        //Fonction qui envoie les informations des servos
        piSend(4, posDegres, vitesse);
        piReceive();

        //i++;
        //i %= NB_SERVO;
    }

    return 0;

}  

Gcom.h

#ifndef DEF_GCOM
#define DEF_GCOM
#define NB_SERVO 5

//On envoie les données des servos à arduino
struct S_SERVO
{
    char ms_servo;                          //1 octet/bytes (8 bits)  : 0 / 255
    char ms_membre;                         //1 octet/bytes (8 bits)  : 0 / 255
    unsigned short int ms_vitesse ;         //2 octet/bytes (8 bits)  : 0 / 65 535
    short int ms_cible ;                    //2 octet/bytes (16 bits) : -32 768 / +32 767
    void affiche() const;
};

//On reçoit les données arduino
struct S_ARDUINO
{
    short int ms_roll;                     //2 octet/bytes (16 bits) : -32 768 / +32 767
    short int ms_pitch;                    //2 octet/bytes (16 bits) : -32 768 / +32 767
    short int ms_yaw;                      //2 octet/bytes (16 bits) : -32 768 / +32 767
    unsigned short int ms_boussole;        //2 octet/bytes (16 bits) : 0 / 65 535
    void affiche() const;
};

union U_DATA
{
    S_SERVO s_servo;
    S_ARDUINO s_arduino;
    unsigned char cast_servo[sizeof (s_servo)];
    unsigned char cast_arduino[sizeof (s_arduino)];
}u_servo[NB_SERVO], u_arduino, u_buf;

void piSend(short int, short int, unsigned short int);
void piReceive();   
void F_CONNECTION();  

#endif

Gcom.cpp

#include <iostream> //Permet d'utiliser In et Out du moniteur série
#include "rs232.h"  //Librairie de communication RS232
#define NB_SERVO 5

using namespace std;

int cport_nr(0);                // 0 = ttyS0  ls /dev/tty*
int bdrate(115200);             // Baud
char mode []={'8','N','1',0};   // 8 data bits, no parity, 1 stop bit

void F_CONNECTION ()
{

    if (RS232_OpenComport(cport_nr, bdrate, mode))
    {
        cout <<"Ne peut pas ouvrir le port com. \n";
        //return 0;
    }
    cout << "----- \n";
    cout << "Raspberry connecté : \n";
    cout << "----- \n";
}


//On envoie les données pour controler les servomoteurs
struct S_SERVO
{
    char ms_servo;                          //1 octet/bytes (8 bits)  : 0 / 255
    char ms_membre;                         //1 octet/bytes (8 bits)  : 0 / 255
    unsigned short int ms_vitesse ;         //2 octet/bytes (8 bits)  : 0 / 65 535
    short int ms_cible ;                    //2 octet/bytes (16 bits) : -32 768 / +32 767

    void affiche() const;
};

//On reçoit les données arduino
struct S_ARDUINO
{
    short int ms_roll;                     //2 octet/bytes (16 bits) : -32 768 / +32 767
    short int ms_pitch;                    //2 octet/bytes (16 bits) : -32 768 / +32 767
    short int ms_yaw;                      //2 octet/bytes (16 bits) : -32 768 / +32 767
    unsigned short int ms_boussole;        //2 octet/bytes (16 bits) : 0 / 65 535

    void affiche() const;
};

union U_DATA
{
    S_SERVO s_servo;
    S_ARDUINO s_arduino;
    unsigned char cast_servo[sizeof (s_servo)];
    unsigned char cast_arduino[sizeof (s_arduino)];
}u_servo[NB_SERVO], u_arduino, u_buf;

void S_SERVO::affiche() const
{
    //cout << "&u_servo.s_servo : \t\t" << &u_servo[c].s_servo << "\n";
    cout << "u_buf.cast_servo : " << sizeof (u_buf.cast_servo) << " bytes\n";
    cout << "ms_membre : \t\t" << ms_membre << "\n";
    cout << "ms_servo : \t\t" << ms_servo << "\n";
    cout << "ms_vitesse : \t\t" << ms_vitesse << "\n";
    cout << "ms_cible : \t\t" << ms_cible << "\n";
    cout << "----- \n";
}

void S_ARDUINO::affiche() const
{
    //On regarde ce qu'Arduino nous envoit
    cout << "Pi reçoit u_arduino.s_arduino.ms_roll :\t\t " << u_arduino.s_arduino.ms_roll <<" \n";
    cout << "Pi reçoit u_arduino.s_arduino.ms_pitch :\t\t " << u_arduino.s_arduino.ms_pitch <<" \n";
    cout << "Pi reçoit u_arduino.s_arduino.ms_yaw :\t\t " << u_arduino.s_arduino.ms_yaw <<" \n";
    cout << "Pi reçoit u_arduino.s_arduino.ms_boussole :\t " << u_arduino.s_arduino.ms_boussole <<" \n";
}

void piSend(short int c, short int posD, unsigned short int vit)
{  
    u_servo[c].s_servo.ms_cible = posD; //tabCibleData[c]; //on copie la donnée nouvellement reçue
    u_servo[c].s_servo.ms_vitesse = vit;

    //Envoie un tableau de données u_servo[c].cast_servo au format unsigned char dans le buffer à la pi
    //Via la RS232
    RS232_SendBuf(cport_nr, u_servo[c].cast_servo, sizeof (u_buf.cast_servo));

    cout << "----- \n";
    cout << "&u_servo[c].s_servo : \t\t" << &u_servo[c].s_servo << "\n";

    u_servo[c].s_servo.affiche();

    usleep (100000); //0.100 s
 
}

void piReceive ()
{
    //Récupére un tableau de données de la pi dans le buffer envoyé d'Arduino
    //Via la RS232
    int n = RS232_PollComport(cport_nr, u_arduino.cast_arduino, sizeof (u_buf.cast_arduino));
    cout << "----- \n";

    cout << "Taille sizeof u_buf.cast_arduino : " << sizeof (u_buf.cast_arduino) << " octets/bytes. \n";

    if (n > 0) //(n >= sizeof (u_buf.cast_arduino)) //if (n > 0)
    {
    u_arduino.cast_arduino[n] = 0;
    cout <<"Pi reçoit d'Arduino : "<< n <<" bytes. \n";
    }

    u_arduino.s_arduino.affiche();

    usleep(100000); //usleep est en ms - 1 - 100000 pause pour 100 milliSeconds       
    
}

Erreurs : 

Gcom.o:(.bss+0x4): définitions multiples de « u_servo »
main.o:(.bss+0x0): défini pour la première fois ici
Gcom.o:(.bss+0x2c): définitions multiples de « u_arduino »
main.o:(.bss+0x28): défini pour la première fois ici
Gcom.o:(.bss+0x34): définitions multiples de « u_buf »
main.o:(.bss+0x30): défini pour la première fois ici
collect2: error: ld returned 1 exit status

signature_01.png -->
 
 

#91 Oliver17

Oliver17

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 2 045 messages
  • Gender:Male
  • Interests:Glenn

Posté 26 avril 2018 - 05:14

Bon ben j'ai trouvé apparemment, mais je bloque sur un truc, pige pas, je cherche, merci de me lire ^^

 

Edit : problème réglé, désolé pour le dérangement ^^


Modifié par Oliver17, 26 avril 2018 - 05:28 .

signature_01.png -->
 
 

#92 R1D1

R1D1

    Modérateur et Membre passionné

  • Modérateur
  • PipPipPipPipPip
  • 1 049 messages
  • Gender:Male
  • Location:Autriche

Posté 27 avril 2018 - 09:52

Bon ben j'ai trouvé apparemment, mais je bloque sur un truc, pige pas, je cherche, merci de me lire ^^
 
Edit : problème réglé, désolé pour le dérangement ^^


C'était quoi la solution ? Ça bénéficiera à tout le monde, et pour toi c'est bien de faire l'exercice d'expliquer :)
Ca ressemble à du code dupliqué / inclus plusieurs fois (et du coup des problèmes lors de l'édition de liens (encore).
R1D1 - Calculo Sed Ergo Sum -- en ce moment, Projet Ballista
Avatar tiré du site bottlebot
Donnez votre avis sur la restructuration des catégories du forum : http://www.robot-mak...ation-du-forum/

#93 cocothebo

cocothebo

    Habitué

  • Membres
  • PipPip
  • 264 messages
  • Gender:Male

Posté 27 avril 2018 - 10:05

Moi en lecture très rapide, je dirai qu'il faut virer les déclarations de Gcom.cpp (genre les structs tout ça) qui sont déjà dans GCom.h et bien sur inclure Gcom.h dans Gcom.cpp.

 

Façon par défaut pour moi si tu sépares en .cpp .h, les déclaration d'un fichier .cpp doivent se trouver dans le .h correspondant, pas dans le .cpp.

 

 

Edit: Pour être plus précis, l'erreur te dit bien que les 3 types sont définis plusieurs fois.

Ici c'est dans main.cpp tu inclus Gcom.h qui définit les types "u_*", puis quand tu utilises par exemple qqc de Gcom.cpp (à priori F_CONNECTION), ben la ça va aller voir GCom.cpp et paf ça redéfini les "u_*" et la le compilateur il est pas content. C'est que c'est strictes ces petites bêtes, ça laisse rien passer  :angry22:



#94 Oliver17

Oliver17

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 2 045 messages
  • Gender:Male
  • Interests:Glenn

Posté 27 avril 2018 - 12:17

Plop voici le code :)

 

Effectivement, vu le message d'erreur de toutes façons cela me donnée des doublons (je sais pas si on peut le dire comme ça), j'avais bien compris mais je ne savais pas comment y remedier, maintenant il est possible que ma façon de faire ne soit pas la bonne :( ou du moins faire mieux.

@Cocothebo : ouais j'ai rajouté le Gcom.h dans le Gcom.cpp, je l'avais viré car j'avais des erreurs, je l'ai donc replacé ;)

 

Ici j'envoie une vitesse et une position pour un servo qui est envoyé à arduino, ce sont pour les tests.

 

main.cpp

#include <iostream> //Permet d'utiliser In et Out du moniteur série
#include "rs232.h"  //Librairie de communication RS232
#include "Gcom.h"   

using namespace std;

char membre = 0;

unsigned short int vitesse = 0;
short int posDegres = 0;

int main ()
{
   
    //Fonction pour le test de connection entre pi et arduino
    F_CONNECTION();
   
    while(1)
    {

        cout << "Vitesse en ms : \n";
        cin >> vitesse;
        cout << "\n" ;
        cout << "Target en degrès : \n";
        cin >> posDegres;
        cout << "\n" ;
       

        //Fonction qui envoie les informations des servos
        piSend(4, vitesse, posDegres);

        //Fonction permettant le réception d'informations d'arduino
        piReceive();

    }
    return 0;
}

Gcom.h

#ifndef DEF_GCOM
#define DEF_GCOM

void F_CONNECTION();
void piSend(char, unsigned short int, short int);
void piReceive();   
 
#endif

Gcom.cpp

#include <iostream> //Permet d'utiliser In et Out du moniteur série
#include "rs232.h"  //Librairie de communication RS232
#include "Gcom.h"

using namespace std;

#define NB_SERVO 5

int cport_nr(0);                // 0 = ttyS0  ls /dev/tty*
int bdrate(115200);             // Baud
char mode []={'8','N','1',0};   // 8 data bits, no parity, 1 stop bit

//On envoie les données pour controler les servomoteurs
struct S_SERVO
{
    char ms_servo;                          //1 octet/bytes (8 bits)  : 0 / 255
    char ms_membre;                         //1 octet/bytes (8 bits)  : 0 / 255
    unsigned short int ms_vitesse ;         //2 octet/bytes (8 bits)  : 0 / 65 535
    short int ms_cible ;                    //2 octet/bytes (16 bits) : -32 768 / +32 767

    void affiche() const;
};

//On reçoit les données arduino
struct S_ARDUINO
{
    short int ms_roll;                     //2 octet/bytes (16 bits) : -32 768 / +32 767
    short int ms_pitch;                    //2 octet/bytes (16 bits) : -32 768 / +32 767
    short int ms_yaw;                      //2 octet/bytes (16 bits) : -32 768 / +32 767
    unsigned short int ms_boussole;        //2 octet/bytes (16 bits) : 0 / 65 535

    void affiche() const;
};

//Union pour l'envoie, la réception et la gestion des paquets
union U_DATA
{
    S_SERVO s_servo;
    S_ARDUINO s_arduino;

    unsigned char cast_servo[sizeof (s_servo)];
    unsigned char cast_arduino[sizeof (s_arduino)];

}u_servo[NB_SERVO], u_arduino, u_buf;

//Test de connection
void F_CONNECTION ()
{
    if (RS232_OpenComport(cport_nr, bdrate, mode))
    {
        cout <<"Ne peut pas ouvrir le port com. \n";
        //return 0;
    }
    cout << "----- \n";
    cout << "Raspberry connecté : \n";
    cout << "----- \n";
    
    usleep (100000); //0.100 s
}

void S_SERVO::affiche() const
{
    cout << "u_buf.cast_servo : " << sizeof (u_buf.cast_servo) << " bytes\n";
    cout << "ms_membre : \t\t" << ms_membre << "\n";
    cout << "ms_servo : \t\t" << ms_servo << "\n";
    cout << "ms_vitesse : \t\t" << ms_vitesse << "\n";
    cout << "ms_cible : \t\t" << ms_cible << "\n";
    cout << "----- \n";
}

void S_ARDUINO::affiche() const
{
    //On regarde ce qu'Arduino nous envoit
    cout << "Pi reçoit u_arduino.s_arduino.ms_roll :\t\t " << u_arduino.s_arduino.ms_roll <<" \n";
    cout << "Pi reçoit u_arduino.s_arduino.ms_pitch :\t " << u_arduino.s_arduino.ms_pitch <<" \n";
    cout << "Pi reçoit u_arduino.s_arduino.ms_yaw :\t\t " << u_arduino.s_arduino.ms_yaw <<" \n";
    cout << "Pi reçoit u_arduino.s_arduino.ms_boussole :\t " << u_arduino.s_arduino.ms_boussole <<" \n";
}

void piSend(char c, unsigned short int vit, short int posD)
{  
    u_servo[c].s_servo.ms_servo = c;
    u_servo[c].s_servo.ms_membre = 1;
    u_servo[c].s_servo.ms_vitesse = vit;
    u_servo[c].s_servo.ms_cible = posD; 
   
    //Envoie un tableau de données u_servo[c].cast_servo au format unsigned char dans le buffer à la pi
    //Via la RS232
    RS232_SendBuf(cport_nr, u_servo[c].cast_servo, sizeof (u_buf.cast_servo));
    cout << "----- \n";
    cout << "&u_servo[c].s_servo : \t\t" << &u_servo[c].s_servo << "\n";

    u_servo[c].s_servo.affiche();

    usleep (100000); //0.100 s
 
}

void piReceive ()
{
    //Récupére un tableau de données de la pi dans le buffer envoyé d'Arduino
    //Via la RS232
    int n = RS232_PollComport(cport_nr, u_arduino.cast_arduino, sizeof (u_buf.cast_arduino));
    cout << "----- \n";

    cout << "Taille sizeof u_buf.cast_arduino : " << sizeof (u_buf.cast_arduino) << " octets/bytes. \n";

    if (n > 0) //(n >= sizeof (u_buf.cast_arduino)) //if (n > 0)
    {
    u_arduino.cast_arduino[n] = 0;
    cout <<"Pi reçoit d'Arduino : "<< n <<" bytes. \n";
    }
    u_arduino.s_arduino.affiche();

    usleep(100000); //usleep est en ms - 1 - 100000 pause pour 100 milliSeconds       

}

Bon j'espère que c'est pas trop le bazar, j'ai essayé de faire ça propre, si vous avez des suggestions ou même me dire si le code vous sembles propre correct etc etc (histoire de me féliciter dans mon apprentissage) :)

Je me suis remis sur l'écran E-PAPER et faire communiquer tous ça, genre, dans un premier temps envoyer de Pi à Arduino (là ou l'écran est branché) l'information comme quoi les deux cartes sont bien connectées ^^

 

Merci ^^

 

 

 


signature_01.png -->
 
 

#95 cocothebo

cocothebo

    Habitué

  • Membres
  • PipPip
  • 264 messages
  • Gender:Male

Posté 28 avril 2018 - 10:35

Salut,

 

En regardant rapidement je vois rien de "choquant", juste les déclarations au début de Gcomm.cppp pourraient aller dans le .h (quoi sauf si tu ne veux pas que les gens qui utilisent ta lib aient accès à ces varibales). Genre le #define, les constantes (qui ne sont pas déclarées comme telle :P) cport_nr, baudrate etc.

 

Mais aussi après moi j'ai un adage, si qqc marche il est urgent de ne rien changer. Bien sur "marche" veut dire que fonctionnellement tout est correct, et que toutes les contraintes associées aussi (respect des règles de notation par exemple, ou la sécurité, les performances, etc.)

 

bref FELICITATIONS tu avances bien :)



#96 Oliver17

Oliver17

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 2 045 messages
  • Gender:Male
  • Interests:Glenn

Posté 28 avril 2018 - 11:13

MMEERRCCIII ^^

 

juste les déclarations au début de Gcomm.cppp pourraient aller dans le .h (quoi sauf si tu ne veux pas que les gens qui utilisent ta lib aient accès à ces varibales). Genre le #define, les constantes (qui ne sont pas déclarées comme telle :P) cport_nr, baudrate etc.

 

 

J'ai bien compris dans les grandes lignes, mais pourrais tu développer stp 

 

Les déclarations tu penses au :

 

#define NB_SERVO qui pourrait être dans le .h ?

 

Quelle constante ??

 

Pour cport_nr, baudrate etc etc je les ai placés dans le .cpp car c'est ce qui me semblait le plus logique " " vu que pour le test de connexion j'ai besoin de faire appel à ces variables.

 

Merci.


signature_01.png -->
 
 



Répondre à ce sujet



  


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

0 members, 0 guests, 0 anonymous users