Salut à tous !
Après de nombreuses recherches infructueuses, je me tourne vers vous afin de partager mon désarroi face à ce symptôme étrange.
Je suis en train de créer un réseau de synchronisation entre un RPi 2 qui joue le rôle de diffuseur de synchro et d'Arduino DUE équipées du Shiel Ethernet 2 qui jouent le rôle d'esclaves à synchroniser.
J'emets donc une trame avec le RPi en broadcast UDP sur le réseau, mes Arduinos se synchronisent sur une trame et envoient une réponse au serveur.
Symptôme :
- La récupération des réponses des clients fonctionne parfaitement bien 2 fois, je récupère simultanément la réponse de mes esclaves.
- Les réceptions suivantes, je reçois un coup l'un, un coup l'autre... Mais à aucun moment je ne récupère les deux ensembles alors que, côté Arduino, je vois bien la récupération se faire sur les différents clients, simultanément toujours.
Voici mon code "serveur" (récupéré et assemblé avec différentes sources sur le net) :
Comme vous pouvez le constater, j'ai tenté différentes méthodes pour résoudre le problème (elles ne sont pas toutes présentes ici mais je vais vous les détailler immédiatement) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126 #include <stdio.h> //printf #include <string.h> //memset #include <stdlib.h> //exit(0); #include <arpa/inet.h> #include <sys/socket.h> #include <poll.h> #define SERVER "192.168.1.255" #define BUFLEN 512 //Max length of buffer #define PORT 8888 //The port on which to send data #define MY_IP "192.168.1.2" //Master's IP #define NB_SLAVES 2 void die(char *s) { perror(s); exit(1); } char readNonBlock(int fd,struct sockaddr_in * si,int slen) { char c='0'; char buf[BUFLEN]; char ip_sender[BUFLEN]; struct pollfd fds; /* on regarde sur l'entree standard */ fds.fd = fd; fds.events = POLLIN; memset(buf,'\0', BUFLEN); if ( ! poll(&fds, 1, 1) ) { printf("en attente d'un caractère\n" ); return c; } /*if ( fds.revents & ( POLLOUT | POLLERR | POLLHUP ) ) { printf("Deconnexion ... fin de fichier\n" ); ici on sait que le read va retourner 0 }*/ if ( recvfrom(fd, buf, BUFLEN, 0, (struct sockaddr *) si, &slen)< 0 ) { printf("Probleme de lecture..." ); /* ici le read à foiré */ } else{ //sprintf(ip_sender," %s\0",inet_ntoa(si->sin_addr)); //printf("port is: %d\n", (int) ntohs(si.sin_port)); puts(inet_ntoa(si->sin_addr)); puts(buf); c='a'; } // on a lu un caractère return c; } int main(void) { struct sockaddr_in si_other; int s, slen=sizeof(si_other); //char buf[BUFLEN]; char waitingSlaves[12]={'1','1','1','0','0','1','1','0','1','0','1','0'}; if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { die("socket"); } int broadcastEnable=1; int ret=setsockopt(s, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable)); memset((char *) &si_other, 0, sizeof(si_other)); si_other.sin_family = AF_INET; si_other.sin_port = htons(PORT); if (inet_aton(SERVER , &si_other.sin_addr) == 0) { fprintf(stderr, "inet_aton() failed\n"); exit(1); } if (bind(s, (struct sockaddr* ) &si_other, sizeof(si_other))==-1) { err("bind"); }else{ printf("Server : bind() successful\n"); } while(1) { int j; char ip_sender[12]; puts("BIIIIP"); for(j=0;j<12;j++){ //send waitingSlaves if (sendto(s, waitingSlaves+j, 1 , 0 , (struct sockaddr *) &si_other, slen)==-1) { die("sendto()"); } } //receive a reply and print it //clear the buffer by filling null, it might have previously received data //memset(buf,'\0', BUFLEN); //try to receive some data, this is a blocking call /*if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == -1) { die("recvfrom()"); }*/ while((recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)>=0)&&(compteur<=NB_SLAVES)){ sprintf(ip_sender," %s\0", inet_ntoa(si_other.sin_addr)); //printf("port is: %d\n", (int) ntohs(si_other.sin_port)); puts(ip_sender); puts(buf); memset(buf,'\0', BUFLEN); compteur++; if(compteur==NB_SLAVES){ break; } } while(readNonBlock(s,&si_other,slen)!='0'); sleep(3); } close(s); return 0; }
- Ligne 105 : C'est le code de base que j'avais récupéré, un code bloquant mais qui récupérait bien tous les messages. J'étais juste obligé de le ctrl+c et de relancer à la mano.
- Ligne 110 : Récupération du précédent et sortie de boucle avec un compteur de réponses. Le symptôme est apparu là...
- Ligne 121 : Ré-utilisation d'un code que j'avais sous le coude pour de la lecture Serial, adapté à notre cas. Le symptôme est toujours là.
De plus j'ai tenté :
- Thread de l'écoute. J'ai du bidouiller pour le faire fonctionner mais toujours le même symptôme.
- Création de plusieurs sockets d'écoute (1 pour chaque client chacun sur un port différent) même symptôme.
Côté Arduino : Il récupère la trame paquet par paquet et dès que la trame est complète, il envoie un message au serveur.
En plus de ce qui est présenté au dessus, j'ai tenté :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93 /* UDPSendReceiveString: This sketch receives UDP message strings, prints them to the serial port and sends an "acknowledge" string back to the sender A Processing sketch is included at the end of file that can be used to send and received messages for testing with a computer. created 21 Aug 2010 by Michael Margolis This code is in the public domain. */ #include <SPI.h> // needed for Arduino versions later than 0018 #include <Ethernet2.h> #include <EthernetUdp2.h> // UDP library from: bjoern@cs.stanford.edu 12/30/2008 // Enter a MAC address and IP address for your controller below. // The IP address will be dependent on your local network: byte mac[] = {0x90, 0xA2, 0xDA, 0x10, 0x1C, 0xFD}; //byte mac[] = {0x90, 0xA2, 0xDA, 0x10, 0x1C, 0xB8}; IPAddress ip(192, 168, 1, 3); //IPAddress ip(192, 168, 1, 4); unsigned int localPort = 8888; // local port to listen on // buffers for receiving and sending data char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet, char ReplyBuffer[] = "synchronized"; // a string to send back char structSync[12]={'1','1','1','0','0','1','1','0','1','0','1','0'}; // An EthernetUDP instance to let us send and receive packets over UDP EthernetUDP Udp; int compteur; char phrase[12]; void setup() { // start the Ethernet and UDP: Ethernet.begin(mac, ip); Udp.begin(localPort); Serial.begin(9600); Serial.println("Listening UDP"); } void loop() { // if there's data available, read a packet Serial.print("loop n "); Serial.println(compteur); int packetSize = Udp.parsePacket(); if (packetSize==1) { IPAddress remote = Udp.remoteIP(); // read the packet into packetBufffer Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE); phrase[compteur]=packetBuffer[0]; compteur++; if(compteur==12){ compteur=0; if(phrase[0]==structSync[0]){ if(phrase[1]==structSync[1]){ if(phrase[2]==structSync[2]){ if(phrase[3]==structSync[3]){ if(phrase[4]==structSync[4]){ if(phrase[5]==structSync[5]){ if(phrase[6]==structSync[6]){ if(phrase[7]==structSync[7]){ if(phrase[8]==structSync[8]){ if(phrase[9]==structSync[9]){ if(phrase[10]==structSync[10]){ if(phrase[11]==structSync[11]){ // send a reply to the IP address and port that sent us the packet we received Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); Udp.write(ReplyBuffer); Udp.endPacket(); //Udp.flush(); } } } } } } } } } } } } } } }
- Mettre l'adresse ip du serveur en dur
- Mettre le port de réponse en dur (le même pour tous et 1 unique pour chacun)
Voilà, j'espère avoir été clair sur ma méthodologie, si l'un d'entre vous pourrait m'expliquer d'où vient le soucis et, peut-être, m'aider à le résoudre, ce serait fortement sympathique
Partager