tu as une arduino méga...
Tu dois pouvoir faire des petits prints sur serial, pendant que pi et arduino communiquent sur un autre sérial ...
D'ailleurs pour la com PC et arduino met toi au moins en 115200 bauds et pas juste en 9600 ...
( bon si ça se trouve c'est déjà le cas mais vu que tu ne poste pas le code ... je sais pas ... )

Gcom communication Pi Arduino.
#61
Posté 24 février 2018 - 03:31
Si mon commentaire vous a plus laissez nous un avis !
Nouveau sur Robot Maker ?
Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope aux articles, à la boutique et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être !
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!
#63
Posté 24 février 2018 - 04:19
non se servir d'un autre serial ( serial1 2 ou 3 ) pour la communication afin de laisser serial pour la comunication avec ton PC via usb
Si mon commentaire vous a plus laissez nous un avis !
Nouveau sur Robot Maker ?
Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope aux articles, à la boutique et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être !
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!
#64
Posté 24 février 2018 - 04:33
Donc voici le code sur la pi
Gcom.cpp
#include <iostream> //Permet d'utiliser In et Out du moniteur série #include "rs232.h" //Librairie de communication RS232 #define NB_SERVO 3 using namespace std; //Union pour envoyer nos types struct dans un tableau unsigned char union COMM { //Structure pour l'émission struct SEN { short int vitesse ; //2 octet/bytes (16 bits) : -32 768 / +32 767 short int cible ; //2 octet/bytes (16 bits) : -32 768 / +32 767 char acceleration ; //1 octet/bytes (8 bits) : 0 / 255 char servo ; //1 octet/bytes (8 bits) : 0 / 255 /* int intform ; //4 octet/bytes (32 bits) : -2 147 483 648 / +2 147 483 647 int intform2 ; //4 octet/bytes (32 bits) : -2 147 483 648 / +2 147 483 647 //float floatform ; //4 octet/bytes (32 bits) : -3.4028235E+38 / +3.4028235E+38 //short int shortintform ; //2 octet/bytes (16 bits) : -32 768 / +32 767 char charform ; //1 octet/bytes (8 bits) : -128 / +127 char charform2 ; //1 octet/bytes (8 bits) : -128 / +127 char charform3 : 1; //1 octet/bytes (8 bits) : -128 / +127 char charform4 : 1; //1 octet/bytes (8 bits) : -128 / +127 */ } dataSen; //Structure pour la récepetion struct REC { int intard; //4 octet/bytes (32 bits) : -2 147 483 648 / +2 147 483 647 float floatard; //4 octet/bytes (32 bits) : -3.4028235E+38 / +3.4028235E+38 short int shortintard; //2 octet/bytes (16 bits) : -32 768 / +32 767 char charard; //1 octet/bytes (8 bits) : -128 / +127 } dataRec; //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 dataSend[sizeof (dataSen)]; unsigned char dataReceive[sizeof (dataRec)]; }piSend[NB_SERVO], piReceive;//, piTorse; int BUF_SIZESEND = sizeof (piSend.dataSend); int BUF_SIZEREC = sizeof (piReceive.dataReceive); int main() { int = 0; //initisialisation de notre structure pour l'émission - dataSen piSend[0].dataSen.servo = 0; piSend[0].dataSen.cible = 10; piSend[0].dataSen.acceleration = 110; piSend[0].dataSen.vitesse = 70; //initisialisation de notre structure pour l'émission - dataSen piSend[1].dataSen.servo = 1; piSend[1].dataSen.cible = 90; piSend[1].dataSen.acceleration = 210; piSend[1].dataSen.vitesse = 60; //initisialisation de notre structure pour l'émission - dataSen piSend[2].dataSen.servo = 2; piSend[2].dataSen.cible = 180; piSend[2].dataSen.acceleration = 96; piSend[2].dataSen.vitesse = 40; 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 ouvre 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"; while(1) { //Envoie un tableau de données dataSend au format unsigned char dans le buffer à la pi //Via la RS232 RS232_SendBuf(cport_nr, piSend[i].dataSend, BUF_SIZESEND); cout << "----- \n"; //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, piReceive.dataReceive, BUF_SIZEREC); cout << "----- \n"; cout << "Taille sizeof BUF_SIZESEND : " << BUF_SIZESEND << " octets/bytes. \n"; cout << "Taille sizeof piSend.dataSend : " << sizeof(piSend.dataSend) << " octets/bytes. \n"; if (n > 0) { piReceive.dataReceive[n] = 0; cout <<"Pi reçoit d'Arduino : "<< n <<" bytes. \n"; } //On regarde ce qu'Arduino nous envoit cout << "Pi reçoit d'Arduino le short int : " << piReceive.dataRec.intard <<" \n"; cout << "Pi reçoit d'Arduino le float : " << piReceive.dataRec.floatard <<" \n"; cout << "Pi reçoit d'Arduino le short int : " << piReceive.dataRec.shortintard <<" \n"; cout << "Pi reçoit d'Arduino le char : " << piReceive.dataRec.charard <<" \n"; cout << "Taille sizeof piReceive.dataReceive : " << sizeof(piReceive.dataReceive) << " octets/bytes. \n"; cout << "\n"; usleep(100000); //usleep est en ms - 1 /* 100000 pause pour 100 milliSeconds */ i++; i %= NB_SERVO; } return 0; }
Arduino
//Union pour envoyer nos types struct dans un tableau unsigned char union COMM{ //Structure pour l'émission struct SEN { //taille de notre structure 11 bytes long intard ; //4 octet/bytes (32 bits) : -2 147 483 648 / +2 147 483 647 float floatard; //4 octet/bytes (32 bits) : -3.4028235E+38 / +3.4028235E+38 int shortintard; //2 octet/bytes (16 bits) : -32 768 / +32 767 char charard; //1 octet/bytes (8 bits) : -128 / +127 }dataSen; //Structure pour la réception struct REC { //taille de notre structure 6 bytes int vitesse ; //2 octet/bytes (16 bits) : -32 768 / +32 767 int cible ; //2 octet/bytes (16 bits) : -32 768 / +32 767 byte acceleration ; //1 octet/bytes (8 bits) : 0 / 255 byte servo ; //1 octet/bytes (8 bits) : 0 / 255 }dataRec; //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 dataSend[sizeof dataSen]; unsigned char dataRece[sizeof dataRec]; }ardSend, ardRec; void setup(){ Serial.begin (115200); //Initisalisation de notre structure dataSen ardSend.dataSen.intard = 1234567891; ardSend.dataSen.floatard = 128.354; ardSend.dataSen.shortintard = 16569; ardSend.dataSen.charard = 120; //x } void loop() { //Envoie un tableau de données dataSend au format unsigned char dans le buffer à la pi Serial.write (ardSend.dataSend, sizeof ardSend.dataSend); //Récupére un tableau de données de la pi dans le buffer que l'on initialise dans dataRec while (Serial.available() > 0) { //if any data available Serial.readBytes (ardRec.dataRece, sizeof ardRec.dataRece); /* Serial.println ("-----"); Serial.println (ardRec.dataRec.servo); Serial.print ("-----"); Serial.println (ardRec.dataRec.cible); Serial.print ("-----"); Serial.println (ardRec.dataRec.acceleration); Serial.print ("-----"); Serial.println (ardRec.dataRec.vitesse); */ } delay(100); }
Par contre j'ai testé de plusieurs façons d'utiliser Serial1.print, sans grand succès pas grave.
Il ne faut pas que j'oublie de virer le delay() pour le remplacer par la gestion de temps. millis().
Sinon j'ai mis un tableau dans la structure coter PI, genre j'envoie des infos de plusieurs servomoteurs, là aux nombres de 3, bien entendu ça multiplie la taille du buffer à l'envoie, normal on multiplie par 3 les données.
Donc pour 3 servomoteurs ce n'est pas grave, mais si j'en ai 30, ça change tout.
Comment faire pour envoyer les informations les unes après les autres, genre, servo1 (6 bytes) envoyé, servo2 (6 bytes) etc etc et non pas 18 bytes d'un coup, car si je fais ça pour 30 servos, outch, ça va pas le faire, non ?!
Merci ^^
Edit : Ah ok, se servir d'un autre Serial de la uno avec la pi et garder celui par défaut pour le pc, ok ok, je vois mieux maintenant
Je vais tester ça tout à l'heure.
Edit2 :
- pour le Serial1 c'est bon c'est nickel
- pour l'envoi de plusieurs données séparés, apparemment c'est bon, je créer un tableau au niveau de l'union genre piSend[3] et pour la récupération du buffer, vu que c'est toujours la même structure (pour l'instant) que j'envoie je créer une nouvelle variable de mon union buffer.
Cela a l'air de fonctionner Le seul hic maintenant, c'est que mon incrémentation se passe bien, mais incrémente en continue dépassant la taille du tableau, hop, c'est parti pour de nouvelles recherches argh ^^
Un modulo et c'est bon ^^
Modifié par Oliver17, 24 février 2018 - 06:21 .
#65
Posté 25 février 2018 - 05:50
@Mike : Plop je reviens sur ton post
Il y a énormément de moyen différent de faire ...
Je ne les connais pas tous et ce que moi je fais n'est peut être pas optimal .En gros je cré un tableau côté arduino, et je cré un tableau côté raspberry pi.
Et quand l'un demande des information à l'autre elle envoi la case du tableau souhaité et le nombre n de case souhaité après.
La réponse sera alors les n cases demandées.
- Quels autres moyens connais tu, cela me donnera des pistes pour chercher, par curiositer.
- Sinon, aurais tu un p'tit exemple avec tes tableaux stp ?
PS : j'ai réussi à "gérer" le temps avec millis(), mais je gère que dans une boucle, des que je veux jouer avec pour utiliser le driver pololu et donc rajouter des pauses en plus, ben c'est le bordel ^^ mais sans erreurs lol
Merci ^^
#66
Posté 25 février 2018 - 05:58
Faudra que je fasse un tuto à l'occasion ou autre ...
C'est long d'expliquer ce genre de chose complexe ... ça va à la suite des structure et des unions ...
C'est pour ça que j'ai découpé ça en plusieurs tuto ... je pense que j'en ferais un ouvrage complet un de ces 4 ...
Là je me suis mis aux tuto vidéo, j'en ai fais un et je suis pas super satisfait x) mais bon je vais quand même le mettre sur youtube pour avoir votre avis. =)
bref beaucoup de projets ... ^^ ( et j'ai encore un truc que j'ai promis à Jekert que j'ai commencé mais toujours pas fini ... =/ )
Si mon commentaire vous a plus laissez nous un avis !
Nouveau sur Robot Maker ?
Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope aux articles, à la boutique et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être !
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!
#68
Posté 13 mars 2018 - 01:37
Plop les maker's, bon j'essaye depuis quelques jours de copier le contenu du buffer dans un tableau, j'y arrive, mais au bout d'un moment le résultat des données qui transit via le buffer partent en vrilles...
Les données ne correspondent plus.
Je procède de cette façon, la PI envois plusieurs tableaux les uns après les autres dans le buffer, chacun font 6 bytes, sur Arduino, je reçois les informations une par une, regarde si la structure de transition au niveau du servo correspond bien à mon compteur, si c'est le cas, je copie d'une structure à une structure tableau, mais dans le moniteur série lorsque je vérifie, tous ce passe bien mais comme dis plus haut, ben arrive un moment ou ça part en sucette...
J'ai essayé de plusieurs façons, sans succès.
Gcom.cpp
#include <iostream> //Permet d'utiliser In et Out du moniteur série #include "rs232.h" //Librairie de communication RS232 #define NB_SERVO 4 using namespace std; //Union pour envoyer nos types struct dans un tableau unsigned char union COMM { //Structure pour l'émission struct SEN { char servo ; //1 octet/bytes (8 bits) : 0 / 255 char acceleration ; //1 octet/bytes (8 bits) : 0 / 255 short int vitesse ; //2 octet/bytes (16 bits) : -32 768 / +32 767 short int cible ; //2 octet/bytes (16 bits) : -32 768 / +32 767 } dataSen; //Structure pour la récepetion struct REC { int intard; //4 octet/bytes (32 bits) : -2 147 483 648 / +2 147 483 647 float floatard; //4 octet/bytes (32 bits) : -3.4028235E+38 / +3.4028235E+38 short int shortintard; //2 octet/bytes (16 bits) : -32 768 / +32 767 char charard; //1 octet/bytes (8 bits) : -128 / +127 } dataRec; //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 dataSend[sizeof (dataSen)]; unsigned char dataReceive[sizeof (dataRec)]; }piSend[NB_SERVO], piReceive, buffer; int BUF_SIZESEND = sizeof (buffer.dataSen); int BUF_SIZEREC = sizeof (piReceive.dataReceive); int main() { int i = 0; //initisialisation de notre structure pour l'émission - dataSen piSend[0].dataSen.servo = 0; piSend[0].dataSen.acceleration = 110; piSend[0].dataSen.vitesse = 70; //Code ascii 70 vaut F piSend[0].dataSen.cible = 10; //initisialisation de notre structure pour l'émission - dataSen piSend[1].dataSen.servo = 1; piSend[1].dataSen.acceleration = 210; piSend[1].dataSen.vitesse = 60; //Code ascii 70 vaut F piSend[1].dataSen.cible = 90; //initisialisation de notre structure pour l'émission - dataSen piSend[2].dataSen.servo = 2; piSend[2].dataSen.acceleration = 96; piSend[2].dataSen.vitesse = 40; //Code ascii 70 vaut F piSend[2].dataSen.cible = 180; //initisialisation de notre structure pour l'émission - dataSen piSend[3].dataSen.servo = 3; piSend[3].dataSen.acceleration = 56; piSend[3].dataSen.vitesse = 30; //Code ascii 70 vaut F piSend[3].dataSen.cible = 75; 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 ouvre 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"; while(1) { //Envoie un tableau de données dataSend au format unsigned char dans le buffer à la pi //Via la RS232 RS232_SendBuf(cport_nr, piSend[i].dataSend, BUF_SIZESEND); cout << "----- \n"; //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, piReceive.dataReceive, BUF_SIZEREC); cout << "----- \n"; cout << "Taille sizeof BUF_SIZESEND : " << BUF_SIZESEND << " octets/bytes. \n"; cout << "Taille sizeof buffer.dataSend : " << sizeof(buffer.dataSend) << " octets/bytes. \n"; if (n > 0) { piReceive.dataReceive[n] = 0; cout <<"Pi reçoit d'Arduino : "<< n <<" bytes. \n"; } //On regarde ce qu'Arduino nous envoie cout << "Pi reçoit d'Arduino le short int : " << piReceive.dataRec.intard <<" \n"; cout << "Pi reçoit d'Arduino le float : " << piReceive.dataRec.floatard <<" \n"; cout << "Pi reçoit d'Arduino le short int : " << piReceive.dataRec.shortintard <<" \n"; cout << "Pi reçoit d'Arduino le char : " << piReceive.dataRec.charard <<" \n"; cout << "Taille sizeof piReceive.dataReceive : " << sizeof(piReceive.dataReceive) << " octets/bytes. \n"; cout << "\n"; usleep(100000); //usleep est en ms - 1 /* 100000 pause pour 100 milliSeconds */ i++; i %= NB_SERVO; } return 0; }
Arduino :
#include <PololuMaestro.h> #define NB_SERVO 4 //Union pour envoyer nos types struct dans un tableau unsigned char union COMM{ //Structure pour l'émission de données struct SEN { //taille de notre structure 11 bytes long intard ; //4 octet/bytes (32 bits) : -2 147 483 648 / +2 147 483 647 float floatard; //4 octet/bytes (32 bits) : -3.4028235E+38 / +3.4028235E+38 int shortintard; //2 octet/bytes (16 bits) : -32 768 / +32 767 char charard; //1 octet/bytes (8 bits) : -128 / +127 }dataSen; //Structure pour la récepetion des données des servomoteurs struct SERVO { byte servo ; //1 octet/bytes (8 bits) : 0 / 255 byte acceleration ; //1 octet/bytes (8 bits) : 0 / 255 int vitesse ; //2 octet/bytes (16 bits) : -32 768 / +32 767 int cible ; //2 octet/bytes (16 bits) : -32 768 / +32 767 }s_dataRec, 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 dataSend[sizeof dataSen]; unsigned char dataRece[6]; }ardSend, ardRec,u_servo[NB_SERVO], buf; int BUF_SIZEREC = sizeof (buf.dataRece); MiniMaestro maestro(Serial2); byte i = 0; byte j = 0; void setup(){ Serial.begin (115200); //Print des infos sur le serial Serial1.begin(115200); //Arduino Serial2.begin(115200); //Pololu Maestro //Initisalisation de la structure dataSen ardSend.dataSen.intard = 1234567891; ardSend.dataSen.floatard = 128.354; ardSend.dataSen.shortintard = 16569; ardSend.dataSen.charard = 73; // I } void loop() { communication(); //Test pour voir ce qui circule dans le tableau Serial.println ("----- Loop "); Serial.println ("u_servo[j] : "); Serial.println (u_servo[j].s_servo.servo); Serial.println (u_servo[j].s_servo.acceleration); Serial.println (u_servo[j].s_servo.vitesse); Serial.println (u_servo[j].s_servo.cible); Serial.println (j); j++; j%=NB_SERVO; } void communication (){ unsigned int waitingTime = 100; // 0.100 secondes unsigned long refTime = 0; //Envoie un tableau de données dataSend au format unsigned char dans le buffer à la pi //Serial1.write (ardSend.dataSend, sizeof ardSend.dataSend); //Récupére un tableau de données de la pi dans le buffer que l'on initialise dans s_dataRec if (Serial1.available() > 0) { //Si des données cicrules Serial1.readBytes (ardRec.dataRece, BUF_SIZEREC); Serial.println ("----------"); Serial.println ("ardRec.s_dataRec : "); Serial.println (ardRec.s_dataRec.servo); Serial.println (ardRec.s_dataRec.acceleration); Serial.println (ardRec.s_dataRec.vitesse); Serial.println (ardRec.s_dataRec.cible); Serial.println ("-----"); Serial.print ("BUF_SIZEREC : "); Serial.println (BUF_SIZEREC); Serial.print ("Compteur : "); Serial.println (i); refTime = millis(); // début de l'attente : while((millis()-refTime)<waitingTime){ Serial.println("Test de la gestion de temps 100 ms :"); //Attends } //On test si le servo du buffer correspond au compteur if (ardRec.s_dataRec.servo == i){ u_servo[i].s_servo = ardRec.s_dataRec; Serial.println ("----- If "); Serial.println ("u_servo[i].s_servo : "); Serial.println (u_servo[i].s_servo.servo); Serial.println (u_servo[i].s_servo.acceleration); Serial.println (u_servo[i].s_servo.vitesse); Serial.println (u_servo[i].s_servo.cible); i++; //Incrémentation i%= NB_SERVO; //"modulo" } //Si les informations ne sont pas identiques else { Serial.println ("Erreur de correspondance : "); Serial.print ("ardRec.s_dataRec.servo : "); Serial.println (ardRec.s_dataRec.servo); //structure de réception, servo Serial.print ("ardRec[i].s_servo.servo : "); Serial.println (u_servo[i].s_servo.servo); //structure de stockage, servo Serial.print ("Compteur : "); Serial.println (i); //compteur Serial.println ("-----"); } Serial.println ("-----"); } } //--------------------------
Résultat dans le moniteur série Arduino :
---------- ardRec.s_dataRec : 0 110 70 10 ----- BUF_SIZEREC : 6 Compteur : 0 Test de la gestion de temps 100 ms : ----- If u_servo[i].s_servo : 0 110 70 10 ----- ----- Loop u_servo[j] : 0 110 70 10 Compteur j : 0 ---------- ardRec.s_dataRec : 1 210 60 90 ----- BUF_SIZEREC : 6 Compteur : 1 Test de la gestion de temps 100 ms : ----- If u_servo[i].s_servo : 1 210 60 90 ----- ----- Loop u_servo[j] : 1 210 60 90 Compteur j : 1 ---------- ardRec.s_dataRec : 2 96 40 180 ----- BUF_SIZEREC : 6 Compteur : 2 Test de la gestion de temps 100 ms : ----- If u_servo[i].s_servo : 2 96 40 180 ----- ----- Loop u_servo[j] : 2 96 40 180 Compteur j : 2 ---------- ardRec.s_dataRec : 3 56 30 75 ----- BUF_SIZEREC : 6 Compteur : 3 Test de la gestion de temps 100 ms : ----- If u_servo[i].s_servo : 3 56 30 75 ----- ----- Loop u_servo[j] : 3 56 30 75 Compteur j : 3 ---------- ardRec.s_dataRec : 0 110 70 10 ----- BUF_SIZEREC : 6 Compteur : 0 Test de la gestion de temps 100 ms : ----- If u_servo[i].s_servo : 0 110 70 10 ----- ----- Loop u_servo[j] : 0 110 70 10 Compteur j : 0 ---------- ardRec.s_dataRec : 1 210 60 90 ----- BUF_SIZEREC : 6 Compteur : 1
Pour l'instant tous va bien, mais au bout d'un moment...
...C'est le drame
---------- ardRec.s_dataRec : 0 180 768 7736 ----- BUF_SIZEREC : 6 Compteur : 2 Test de la gestion de temps 100 ms : Erreur de correspondance : ardRec.s_dataRec.servo : 0 ardRec[i].s_servo.servo : 2 Compteur : 2 ----- ----- ----- Loop u_servo[j] : 2 96 40 180 Compteur j : 2 ---------- ardRec.s_dataRec : 0 75 0 18030 ----- BUF_SIZEREC : 6 Compteur : 2 Test de la gestion de temps 100 ms : Erreur de correspondance : ardRec.s_dataRec.servo : 0 ardRec[i].s_servo.servo : 2 Compteur : 2 ----- ----- ----- Loop u_servo[j] : 3 56 30 75 Compteur j : 3 ---------- ardRec.s_dataRec : 0 10 512 10336 ----- BUF_SIZEREC : 6 Compteur : 2 Test de la gestion de temps 100 ms : Erreur de correspondance : ardRec.s_dataRec.servo : 0 ardRec[i].s_servo.servo : 2 Compteur : 2 ----- ----- ----- Loop u_servo[j] : 0 110 70 10 Compteur j : 0 ---------- ardRec.s_dataRec : 0 180 768 7736 ----- BUF_SIZEREC : 6 Compteur : 2 Test de la gestion de temps 100 ms : Erreur de correspondance : ardRec.s_dataRec.servo : 0 ardRec[i].s_servo.servo : 2 Compteur : 2 ----- ----- ----- Loop u_servo[j] : 1 210 572 10336 Compteur j : 1 ---------- ardRec.s_dataRec : 0 75 0 18030 ----- BUF_SIZEREC : 6 Compteur : 2 Test de la gestion de temps 100 ms : Erreur de correspondance : ardRec.s_dataRec.servo : 0 ardRec[i].s_servo.servo : 2 Compteur : 2 ----- ----- ----- Loop u_servo[j] : 2 96 40 180 Compteur j : 2 ---------- ardRec.s_dataRec : 0 10 256 15570 ----- BUF_SIZEREC : 6 Compteur : 2 Test de la gestion de temps 100 ms : Erreur de correspondance : ardRec.s_dataRec.servo : 0 ardRec[i].s_servo.servo : 2 Compteur : 2 ----- ----- ----- Loop u_servo[j] : 3 56 30 75 Compteur j : 3 ---------- ardRec.s_dataRec : 0 90 768 7736 ----- BUF_SIZEREC : 6 Compteur : 2
Et cela est aléatoire à chaque fois que je relance le programme...
Merci ^^
#70
Posté 14 mars 2018 - 02:59
Salut,
C'est difficilement lissible ton post très long, mais la comme ça a première vue je dirai que c'est un pb de synchro, la condition
Serial1.available() > 0
est valable des que 1 octet est sur le port série.
Et après tu fais:
Serial1.readBytes (ardRec.dataRece, BUF_SIZEREC);
ou la tu lis arbitrairement BUF_SIZEREC octets, mais si jamais ta première condition s'est déclenchée quand seulement 2 octets sont arrivés et que le timeout arrive avant la lecture de 6 octets (ta valeur BUF_SIZEREC), tu n'auras que max 5 octets.
ardRec.dataRece contiendra donc que maximum 5 nouveaux octets et le reste d'avant.
Au même moment tu auras le 6eme octet qui arrive sur le port série, dc ta prière condition est vraie, puis le Pi renvoie les 6 octets, comme tu as déjà des octets en attente, tu vas arriver à 6 octets avec d'abord la fin du message précédent puis le début du nouveau (tronqué) donc et ainsi de suite.
Bref sans synchro c'est difficile d'avoir le PI et l'arduino qui soit pile en même temps avec les risques de désynchronisés.
Donc à voir si le problème vient de la, mais il y a pour moi un problème de synchronisation si tu ne reste pas en attente jusqu'a avoir le bon nombre d'octets reçus
#71
Posté 14 mars 2018 - 03:58
@Cocothebo : merci d'avoir pris le temps de répondre et surtout de lire
Désolé pour le code, mais sinon je ne savais pas trop quoi poster comme partie du code, donc j'ai tous mis
Donc, ma synchro aurait peut être un problème, actuellement je suis à 100 ms pour pi et arduino, j'ai monté le temps à 1 seconde, et j'ai toujours le même problème.
Ensuite j'ai cherché sur google "synchronisation arduino raspberry", et j'ai trouvé des infos utilisant checksum, je lis un peu le sujet, cela peut être une bonne piste ?
Puis j'ai vu une discussion ou le gars utilisé un byte de départ au début de chaque paquet (et pourquoi pas un de fin aussi), ce qui lui permet donc de vérifier ce qu'il envoie comme paquet...
Je cherche, car ça fonctionne pourtant bien au début, donc je continue mes recherches sur la synchro et autres infos trouvé en cour de route ^^
Edit : Effectivement, peut être avec un byte de fin serait une bonne idée avant de passer à la chaîne suivante ...?!
Hum avec un de début aussi en fait ^^ erf
Modifié par Oliver17, 14 mars 2018 - 04:38 .
#72
Posté 14 mars 2018 - 04:46
Moi j'essayerai d'abord de mettre un octet (ou une pattern, à toi de voir) de début, suivi par exemple immédiatement par la taille de ce que tu dois attendre. Ça te permet de détecter facilement le début de chaine, puis de connaitre combien d'octets tu dois attendre.
Le problème de l'octet de fin, c'est que si une valeur avant vaut ça tu risque de croire que c'est la fin, donc c'est pas aussi simple que dire je mets 0 pour la fin...
Après si tu augmentes les temporisations des deux cotes (arduino et pi), ça me semble pas délirant que le problème continue.
Tu pourrais déjà faire une condition
Serial1.available() = 6 (ou > 5 si jms)
Comme ca côté arduino ça attendra d'avoir 6 octets dans le pipe avant que tu fasses la lecture.
Si tu es sur de toujours envoyer 6 octets par 6 octets et que la liaison série n'est pas trop mauvaise, ça devrait déjà permettre d'avoir une synchro correcte.
Après oui tu peux rajouter plein de chose sur ton protocole pour faire du contrôle de parité ou autre, mais c'est peut être pas nécessaire surtout maintenant.
Après aussi si tu veux pas trop te fatiguer, tu peux utiliser de l'i2c entre l'arduino et le Pi, c'est un protocole un peu plus haut niveau et donc tu auras moins de soucis de ce type normalement (le protocole i2c défini bcp de chose pour être sur que le message envoyé est bien reçu et autre joyeusetés).
Pour généraliser ce problème (vu que peut être que ton problème n'est pas ce que j'ai dit), en fait ici tu veux utiliser une liaison asynchrone de façon synchrone, il faut donc faire un peu plus de traitements et rendre du point de vue de ton applicatif ette liaison synchrone. L'i2c c'est du synchrone de base donc pas besoin de le faire.
#73
Posté 14 mars 2018 - 05:29
Ben déjà j'ai bien galérer pour trouver une liaison dont j'arrive " " à me servir à peu prés, je vais donc rester comme je suis faut juste que j'apprenne le pourquoi du comment, et déjà avec les pistes que tu me donnes cela devrait m'aider une partie
J'ai encore joué sur la temporisation, j'ai toujours le même problème, je vais aussi chercher du coup avec asynchrone ^^
Effectivement, l'idée serait d'envoyer des tableaux de différentes tailles,
Ex coté C++ :
- tete[2]
- brasgauche [6]
- brasdroit [6]
- colonne [3]
Chaque ligne de chaque tableau correspondraient à un servo.
1 x servo = :
- servo (servo sur le driver)
- acceleration
- vitesse
- cible (ça position cible)
Pour l'organisation pour l'envoie coté C++, j'avais pensé à un tableau (éventuellement dynamique) d'objet puisque la tête, les bras, et la colonne ne contiennent pas le même nombres de servo.
Coté Arduino lui devrait être en mesure de récupérer les informations par catégorie au moment voulu et de ranger tous ça dans un tableau qui communique avec le driver pololu.
Le fait de gérer ce que l'on envoie dans le pipe permettrait de ne pas envoyer en continue des informations qui ne sont pas utilisé en permanence, sauf à certains moment.
Genre si seule la tête doit bouger, on envoie seulement le tableau de la tête 2x 6 octets puisque 2 servomoteurs de 6 octets chacun.
Si la tête et un des bras doivent bouger, alors une priorité genre d'abord la tête est envoyé puis le bras correspondant.
Bon, en même temps j'apprend, j'y vais donc petit à petit
L'idée est peut être farfelu, mais je la trouve intéressante (je ne sais pas si c'est réalisable).
#74
Posté 24 mars 2018 - 10:44
Plop les maker's, bon je suis toujours à faire des tests pour le Gcom
En m'amusant j'ai réussi à faire un truc dont je ne suis pas sur de comprendre.
Gcom.cpp
#include <iostream> //Permet d'utiliser In et Out du moniteur série #include "rs232.h" //Librairie de communication RS232 //#define NB_SERVO 4 using namespace std; struct S_DATA { char ms_servo ; //1 octet/bytes (8 bits) : 0 / 255 char ms_acceleration ; //1 octet/bytes (8 bits) : 0 / 255 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 }; union U_SERVO { unsigned char cast_servo[]; }; int main () { 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 ouvre 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"; S_DATA s_data, s_data2; U_SERVO u_servo; s_data.ms_servo = 73; s_data.ms_acceleration = 110; s_data.ms_vitesse = 70; s_data.ms_cible = 20; cout << "ms_servo : \t\t" << s_data.ms_servo << "\n"; cout << "ms_acceleration : \t" << s_data.ms_acceleration << "\n"; cout << "ms_vitesse : \t\t" << s_data.ms_vitesse << "\n"; cout << "ms_cible : \t\t" << s_data.ms_cible << "\n"; s_data2.ms_servo = 70; s_data2.ms_acceleration = 50; s_data2.ms_vitesse = 200; s_data2.ms_cible = 90; cout << "ms_servo : \t\t" << s_data2.ms_servo << "\n"; cout << "ms_acceleration : \t" << s_data2.ms_acceleration << "\n"; cout << "ms_vitesse : \t\t" << s_data2.ms_vitesse << "\n"; cout << "ms_cible : \t\t" << s_data2.ms_cible << "\n"; //Envoie un tableau de données dataSend au format unsigned char dans le buffer à la pi //Via la RS232 RS232_SendBuf(cport_nr, u_servo.cast_servo, 6); cout << "----- \n"; usleep(100000); //usleep est en ms - 1 - 100000 pause pour 100 milliSeconds }
Le truc que je trouve bizarre, à aucun moment j'argumente
u_servo.cast_servo
et pourtant ça passe dans le pipe...
C'est là que je ne comprend pas.
Est du fait qu'il soit juste déclaré dans le main
U_SERVO u_servo
c'est suffisent ??
Résultat PI :
Raspberry connecté : ----- ms_servo : I ms_acceleration : n ms_vitesse : 70 ms_cible : 20 ms_servo : F ms_acceleration : < ms_vitesse : 200 ms_cible : 90 -----
Et le résultat et le même coté arduino.
---------- ardRec.s_dataRec : 70 60 200 90 ----- BUF_SIZEREC : 6 Test de la gestion de temps 100 ms : Test de la gestion de temps 100 ms : -----
Merci
Edit : je viens de voir que parfois des valeurs changent
Bref, la dernière structure à être créer a l'air de passer, je pige pas.
Modifié par Oliver17, 24 mars 2018 - 11:09 .
#75
Posté 24 mars 2018 - 12:05
Arduino reçoit des valeurs pas initialisées. -> Pas initialisées, ça peut être n'importe quoi. La valeur de la variable voisine ou n'importe quel endroit de la mémoire. Cela ne se fait pas. C'est dangereux. Il faut initialiser toutes le variables.
Si tu mets des valeur dans ton tableau cast_servo, tu reçois bien ces valeurs du coté de l'arduino ?
#76
Posté 24 mars 2018 - 01:07
Euh, mes valeurs sont initialisées dans Gcom.cpp le truc c'est que ça passe tout de même dans le tableau u_servo.cast_servo[], et arduino reçoit la dernière structure créer.
J'ai refais un test avec la création de 3 struct, et c'est la dernière qui est pris en compte.
Coté arduino ça passe bien, je reçois.
#77
Posté 24 mars 2018 - 01:18
Je n'ai peut-être pas compris ce que tu fais dans le code que tu as posté. Je n'ai pas vu où tu initialise u_servo.cast_servo. Et il me semble que tu envois u_servo.cast_servo.
#79
Posté 24 mars 2018 - 03:31
Ben quand c'est pas initialisé, c'est un emplacement mémoire aléatoire. D'où le besoin d'initialiser.
#80
Posté 05 avril 2018 - 03:28
Coucou les maker's, bon toujours dans mon road trip programming lol j'ai testé les objets, pointeur, référence, constructeur, destructeur et objet dynamique..., et tous ça en restant sur la même case mémoire pour tous les objets, bon le hic c'est que je retrouve toujours ces mêmes problèmes qu'au début avec la structure et l'union, vu que l'envoie se fait en boucle au bout d'un moment j'ai des pertes de données
Gcom.cpp :
#include <iostream> //Permet d'utiliser In et Out du moniteur série #include "rs232.h" //Librairie de communication RS232 using namespace std; /** membres : tête 001 - servo 2 brasD 002 - servo 6 brasG 003 - servo 6 colonne 004 - servo 3 **/ int cport_nr(0); // 0 = ttyS0 ls /dev/tty* struct S_DATA { 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 }; union U_SERVO { S_DATA s_data; unsigned char cast_servo[sizeof (s_data)]; }u_servo, u_buf; class C_DATA { public : C_DATA(char, char, unsigned short int); ~C_DATA(); U_SERVO *cu_servo; void affiche() const; }; C_DATA::C_DATA (char mbr, char servo, unsigned short int acceleration) { cu_servo = &u_servo; cu_servo->s_data.ms_membre = mbr; cu_servo->s_data.ms_servo = servo; cu_servo->s_data.ms_acceleration = acceleration; cout << "Création objet : \n"; RS232_SendBuf(cport_nr, cu_servo->cast_servo, sizeof (u_buf.cast_servo)); cout << "----- \n"; //usleep(100000); //usleep est en ms - 1 - 100000 pause pour 100 milliSeconds } C_DATA::~C_DATA() { cout << "Objet détruit... \n"; cout << "----- \n"; } void C_DATA::affiche () const { cout << "&cu_servo->s_data : \t\t" << &cu_servo->s_data << "\n"; cout << "cu_servo->s_data.ms_membre : \t\t" << cu_servo->s_data.ms_membre << "\n"; cout << "cu_servo->s_data.ms_servo : \t\t" << cu_servo->s_data.ms_servo << "\n"; cout << "cu_servo->s_data.ms_acceleration : \t" << cu_servo->s_data.ms_acceleration << "\n"; cout << "----- \n"; } void fctDelete (C_DATA *); int main () { short int i = 0; //int cport_nr(0); // 0 = ttyS0 ls /dev/tty* //Déclaré en global. 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 ouvre 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"; while(1) { //Mode pas terrible je trouve pour envoyer les données. C_DATA *teteY; teteY = new C_DATA (65, 85, 110); teteY->affiche(); usleep(100000); //usleep est en ms - 1 - 100000 pause pour 100 milliSeconds fctDelete (teteY); C_DATA *teteZ; teteZ = new C_DATA (66, 86, 120); teteZ->affiche(); usleep(100000); //usleep est en ms - 1 - 100000 pause pour 100 milliSeconds fctDelete (teteZ); C_DATA *brasDY; brasDY = new C_DATA (67, 87, 130); brasDY->affiche(); usleep(100000); //usleep est en ms - 1 - 100000 pause pour 100 milliSeconds fctDelete (brasDY); C_DATA *brasDX; brasDX = new C_DATA (68, 88, 140); brasDX->affiche(); usleep(100000); //usleep est en ms - 1 - 100000 pause pour 100 milliSeconds fctDelete (brasDX); C_DATA *brasDZ; brasDZ = new C_DATA (69, 89, 150); brasDZ->affiche(); usleep(100000); //usleep est en ms - 1 - 100000 pause pour 100 milliSeconds fctDelete (brasDZ); } return 0; } void fctDelete (C_DATA * del) { cout << "Appel fctDelete !! \n"; delete del; }
Arduino :
#include <PololuMaestro.h> #define NB_SERVO 5 //Union pour envoyer nos types struct dans un tableau unsigned char union COMM{ //Structure pour l'émission de données struct SEN { //taille de notre structure 11 bytes long intard ; //4 octet/bytes (32 bits) : -2 147 483 648 / +2 147 483 647 float floatard; //4 octet/bytes (32 bits) : -3.4028235E+38 / +3.4028235E+38 int shortintard; //2 octet/bytes (16 bits) : -32 768 / +32 767 char charard; //1 octet/bytes (8 bits) : -128 / +127 }dataSen; //Structure pour la récepetion des données des servomoteurs struct SERVO { byte membre ; byte servo ; //1 octet/bytes (8 bits) : 0 / 255 unsigned int acceleration ; //1 octet/bytes (8 bits) : 0 / 255 }s_dataRec, 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 dataSend[sizeof dataSen]; unsigned char dataRece[sizeof s_dataRec]; }ardSend, ardRec,u_servo[NB_SERVO], buf; int BUF_SIZEREC = sizeof (buf.dataRece); MiniMaestro maestro(Serial2); byte i = 0; byte j = 0; void setup(){ Serial.begin (115200); Serial1.begin(115200); Serial2.begin(115200); //Initisalisation de la structure dataSen ardSend.dataSen.intard = 1234567891; ardSend.dataSen.floatard = 128.354; ardSend.dataSen.shortintard = 16569; ardSend.dataSen.charard = 73; // I } void loop() { communication(); } void communication (){ unsigned int waitingTime = 100; // 0.100 secondes unsigned long refTime = 0; //Envoie un tableau de données dataSend au format unsigned char dans le buffer à la pi //Serial1.write (ardSend.dataSend, sizeof ardSend.dataSend); //Récupére un tableau de données de la pi dans le buffer que l'on initialise dans s_dataRec while (Serial1.available() > 0) { //if any data available // >0 Serial1.readBytes (ardRec.dataRece, BUF_SIZEREC); //BUF_SIZEREC); Serial.println ("----------"); Serial.println ("ardRec.s_dataRec : "); Serial.println (ardRec.s_dataRec.membre); Serial.println (ardRec.s_dataRec.servo); Serial.println (ardRec.s_dataRec.acceleration); Serial.println ("-----"); Serial.print ("BUF_SIZEREC : "); Serial.println (BUF_SIZEREC); Serial.print ("Compteur i : "); Serial.println (i); Serial.print ("Compteur j : "); Serial.println (j); i++; i%= NB_SERVO; j++; Serial.println("Test de la gestion de temps 100 ms :"); refTime = millis(); // début de l'attente : while((millis()-refTime)<waitingTime){ //Attends } Serial.println ("-----"); } }
Donc au début tous ce passe bien, mais au bout d'un moment les données reçu coté arduino ça devient une vrai teuf techno numérique ^^
1 utilisateur(s) li(sen)t ce sujet
0 members, 1 guests, 0 anonymous users