Xbee Api + Serveur Web

Bonjour à tous,
Je viens à vous car j'ai déployé un réseau de xbee (Api) avec des capteurs de température LM35DZ. En effet, j'utilise les entrées analogiques des xbees afin de récupérer les différentes températures. Chaque pièce comporte un xbee, en receveur j'ai un autre xbee qui récupère tous les paquets des transmetteurs.Afin d'afficher les températures, j'utilise un arduino + ethernet shield afin de convertir ses paquets en valeurs décimales et l'envoyer sur une page HTML. L'acquisition se fait pendant un petit moment puis au bout de quelques jours la page HTML ne se génère plus (elle reste en perpétuelle recherche).

Est ce que cela pourrait venir de la mémoire du serveur qui serait saturée au bout d'un certain temps? Dois-je vider mon buffer?

Voici mon code :

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x14, 0x46 };
IPAddress ip(162,38,115, 28);


unsigned long delayMax = 0;
int packet[32];
int analogSamples[5];
int moduleID[1];
float v[4];
float z[5];
float y[6];
EthernetServer server(80);

void setup()
{
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.begin(9600);
  delay(1);
}

void loop()
{

  readpacket();
  EthernetClient client = server.available();
  
  if (client) 
    {
       boolean currentLineIsBlank = true; 
       while (client.connected()) 
         {
           if (client.available()) 
             {
               char c = client.read();
               if (c == '\n' && currentLineIsBlank) 
                 {
                    client.println("HTTP/1.1 200 OK");
                    client.println("Content-Type: text/html");
                    client.println();
                   
                        
                        client.println(v[1]);
                        client.println(v[2]);
                        client.println(v[3]);
                        client.println(v[4]);
                        client.println();
                     
                       
                       client.println(z[1]); 
                       client.println(z[2]);
                       client.println(z[3]);
                       client.println(z[4]);
                       client.println(z[5]);
                       client.println();
                      
                       
                       client.println(y[1]); 
                       client.println(y[2]);
                       client.println(y[3]);
                       client.println(y[4]);
                       client.println(y[5]);
                       client.println();                                               
                  break;
                 }
             
             if (c == '\n') 
               {
                 currentLineIsBlank = true;
               }  
               else if (c != '\r') 
               {
                 currentLineIsBlank = false;
               }
         }
    } 
    delay(1000);
    client.stop();
    }   
}
void readpacket()
  {
  if (Serial.available() > 0) 
    {
    delayMax = millis()+50;
    int b = Serial.read();
    if (b == 0x7E) 
      {
        packet[0] = b;                           
        packet[1] = readByte();
        packet[2] = readByte();
        int dataLength = (packet[1] << 8) | packet[2];  
        for(int i=1;i<=dataLength;i++) 
          {
            packet[2+i] = readByte();               
          }
        int apiID = packet[3];                
        if (apiID == 0x83) 
            {

              
              moduleID[1] = (packet[4] << 8) | packet[5];
              if (moduleID[1]==0x01)
              {
                int SgnlPwr = packet[6];
                int SampleNumber = packet[8];                                                                                                                    
                int i;                                                                                                                                                                                                                                                                                                                                       
                if (SampleNumber >= 1)  
                  {                                                                                                        
                    analogSamples[1] = (packet[11] << 8) | packet[12];
                    analogSamples[2] = (packet[13] << 8) | packet[14];
                    analogSamples[3] = (packet[15] << 8) | packet[16];
                    analogSamples[4] = (packet[17] << 8) | packet[18];
                    delay(1);
                  } 
                   int reading = analogSamples[1];  
                   int reading_2 = analogSamples[2];
                   int reading_3 = analogSamples[3];
                   int reading_4 = analogSamples[4];
        // On converti la valeur lue  en millivolts
                   v[1] =((float) reading)*330/1024;  
                   v[2] =((float) reading_2)*330/1024;
                   v[3] =((float) reading_3)*330/1024;
                   v[4] =((float) reading_4)*330/1024;
                   delay(1);
              }
              else if (moduleID[1]==0x02)
              {
               int SgnlPwr = packet[6];
                int SampleNumber = packet[8];                                                                                                                    
                int i;                                                                                                                                                                                                                                                                                                                                       
                if (SampleNumber >= 1)  
                  {                                                                                                        
                    analogSamples[1] = (packet[11] << 8) | packet[12];
                    analogSamples[2] = (packet[13] << 8) | packet[14];
                    analogSamples[3] = (packet[15] << 8) | packet[16];
                    analogSamples[4] = (packet[17] << 8) | packet[18];
                    analogSamples[5] = (packet[19] << 8) | packet[20];
                    delay(1);
                    
                  } 
                   int reading_5 = analogSamples[1];  
                   int reading_6 = analogSamples[2];
                   int reading_7 = analogSamples[3];
                   int reading_8 = analogSamples[4];
                   int reading_9 = analogSamples[5];
        // On converti la valeur lue  en millivolts
                   z[1] =((float) reading_5)*330/1024;  
                   z[2] =((float) reading_6)*330/1024;
                   z[3] =((float) reading_7)*330/1024;
                   z[4] =((float) reading_8)*330/1024;
                   z[5] =((float) reading_9)*330/1024;
                   delay(1);
              } 
              else if (moduleID[1]==0x03)
              {
               int SgnlPwr = packet[6];
                int SampleNumber = packet[8];                                                                                                                    
                int i;                                                                                                                                                                                                                                                                                                                                       
                if (SampleNumber >= 1)  
                  {                                                                                                        
                    analogSamples[1] = (packet[11] << 8) | packet[12];
                    analogSamples[2] = (packet[13] << 8) | packet[14];
                    analogSamples[3] = (packet[15] << 8) | packet[16];
                    analogSamples[4] = (packet[17] << 8) | packet[18];
                    analogSamples[5] = (packet[19] << 8) | packet[20];
                    delay(1);
                    
                  } 
                   int reading_10 = analogSamples[1];  
                   int reading_11 = analogSamples[2];
                   int reading_12 = analogSamples[3];
                   int reading_13 = analogSamples[4];
                   int reading_14 = analogSamples[5];
        // On converti la valeur lue  en millivolts
                   y[1] =((float) reading_10)*330/1024;  
                   y[2] =((float) reading_11)*330/1024;
                   y[3] =((float) reading_12)*330/1024;
                   y[4] =((float) reading_13)*330/1024;
                   y[5] =((float) reading_14)*330/1024;
                   delay(1);
              } 
            }
              
      }
    }
  }
 uint8_t readByte() 
  {
    while (true) 
      {
	if(delayMax <= millis())
        {
            break;
        }
        if (Serial.available() > 0) 
        {
          return Serial.read();
        }
      }
    return 0;  
  }

Merci d'avance,

Salut mika

Je pense pas qu'il s'agisse d'un problème de mémoire mais il y a clairement dans ton code plusieurs endroit où le code peu se bloquer.

Essentiellement partout où tu lis des paquets sur la liaison série.
Il est probable que ton code se bloque quelque part là dedans.

Avant de modifier ton code je te propose de debugguer un peu pour essayer de confirmer cette hypothèse.
On ne peut pas utiliser la liaison série mais il existe de nombreuses solutions pour sortir de l'info afin de savoir ce qu'il se passe.

  1. Utiliser un SoftwareSerial associé à un adaptateur série pour relier au PC si tu as un port série ou USB/Serie sur ton C (attention il peut être nécessaire de mettre un peu de hard pour adapter si to port série est un vrai RS232)

  2. Utiliser des leds. Tu as surement plein de pin numérique dispo. Donc mettre des leds (+résistance) et utiliser des digitalWrite dans ton code pour savoir où tu es.
    2 possibilités :

  • dédier une led à chaque section de code : tu l'allume quand tu rentre, tu l'éteint quand tu sort.
  • sortir une valeur binaire sur plusieurs leds pour identifier des points dans ton code : avec 5 leds tu peux identifier 32 endroits différents
    Avec cela tu pourras avoir une idée d'ou ton code se bloque.
  1. Utilise ton afficheur LCD pour afficher l'endroit où tu passes.

Je pense qu'au final tu devrais/devra revoir ton code pour utiliser des timeout et plus de gestion de cas d'erreur.
N'oublie pas la loi de Murphy ; si quelque chose peut mal se passer, ca se passera forcement mal un jour o l'autre, généralement quand tu ne t'y attends pas.

Notamment regarde les fonctions avancées de Serial/Stream qui permettent de gérer les timeouts :
setTimeout()
readBytesUntil()

Salut Barbudor,

Le problème, c'est que j'ai déployé le réseau donc pour faire tout ses tests c'est délicat, je pense que si le système récupère des octets qui changent peu donc une température constante, il n'y a pas de soucis. Par contre dès que les températures commencent à grimper, j'ai l'impression que mon receveur a du mal à emmagasiner les infos du coup la page HTML ne se génère plus.

Dans mon code "void readpacket()", j'ai delayMax=millis()+50;
J'ai enlevé tous les delay(1) après mes analogSamples et à la fin de la fonction j'ai rajouté :

timerId = timer.setTimeout(1000, readpacket);

En fait j'avais lu ton code trop rapidement et je n'avais pas vu que readBytes gérait un timeout
Par contre tu ne teste pas son retour.

Donc dans :

packet[0] = b;                           
packet[1] = readByte();
packet[2] = readByte();

Si la liaison est rompue, tu attends 2 fois, tu conserve la valeur 0 et tu continue comme si de rien n'était.

Il faut que tu trouves un moyen de savoir où est ton code quand ca coince.

Pour ce qui est de la mémoire, tu peux aussi vérifier mais il faudrait avoir un moyen de sortir une trace texte pour afficher la mémoire disponible toutes les 2 secondes par exemple.

Oui parce que ce sont les deux paquets qui m'intéressent, le premier paquet c'est tout le temps 0 et l'autre octet c'est le nombre de xbee déployé pour le réseau.

La j'ai modifié et pareil même constat au bout de deux jours cette fois cela s'est coupé à 14h30.

Je n'arrive pas à comprendre ou trouver cette erreur. Je ne sais pas si ca vient de mon soft ou bien du serveur extérieur !

En faisant un reset automatique du ethernet shield ! ça pourrait le faire !

Je regarde comment je pourrais faire çà !

Dans ce programme, j'aimerai faire un reset logiciel c'est à dire mettre à l'état haut le reset quand ça serial.available est ok donc il récupère tous les paquets et les convertits s'il ne reçoit pas de trames je me le reset à l'état bas pour faire un reset du soft. Quand pensez vous?

en gros le code :

void setup()
{
  Ethernet.begin(mac, ip);
  pinMode(RESET,OUTPUT);
  server.begin();
  Serial.begin(9600);
  delay(1);
}

void loop()
{
........
}

void readpacket()
  {
  if (Serial.available() > 0)
    {
        digitalWrite(RESET, HIGH);
        .............
.......................
...............
...................
    }
else
{
digitalWrite(RESET, LOW);
}

Qu'en pensez vous?

Ca s'appelle un chien de garde (watchdog). Il y en a un intégré dans le chip ATmega qu'on doit pouvoir activer si tu le souhaites.

Sinon, tu peux effectivement faire un reset mais ton code est trop violent.
Il faut une tempo et si au bout de x minutes tu ne reçoit plus rien alors tu reset.

Mais j'ai peur que ça ne serve à rien car je pense que tu te bloques quelque part dans ton code donc tu ne viendras jamais activer ton reset.

Il faut que tu avances dans la compréhension du problème.
Si l'ethernet ne répond plus c'est probablement parce que ton code bloque quelque part.
Essaye de tracer plus finement.
Déjà si tu mets une LED a clignoter dans le loop, est-ce que çà clignote tout le temps ou bien est-ce que ca se bloque aussi au bout de quelques jours ?

Oui ms le watchdog ne dure pas au max 8s?? on ne peut pas plus je crois !

Oui je vais mettre une led oui...ca m'aidera peut être...

Cela peut aussi venir de ma sous fonction "readbyte"

Je suis désolé de relancer le sujet mais j'ai encore un soucis de connexion entre le serveur web ethernet shield et la génération de la page HTML. Je me suis aperçu qu'en appuyant sur le reset de l'arduino le système repartait donc j'en ai déduis que ca venait de mon soft... Voici mon code :

void setup()
{
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  digitalWrite(RESET, HIGH);
  pinMode(RESET, OUTPUT);
  server.begin();
  Serial.begin(9600);
  delay(1);
  //Serial.print("Starting.........."); 
  //Serial.println(); 
}
void loop()
{

  readpacket();
  EthernetClient client = server.available();
  
  if (client) 
    {
       boolean currentLineIsBlank = true; 
       while (client.connected()) 
         {
           if (client.available()) 
             {
               
               char c = client.read();
               if (c == '\n' && currentLineIsBlank) 
                 {    
                    client.println("HTTP/1.1 200 OK");
                    client.println("Content-Type: text/html");
                    client.println();
                   
                        
                        client.println(v[1]);
                        client.println(v[2]);
                        client.println(v[3]);
                        client.println(v[4]);
                        client.println();
                     
                       
                       client.println(z[1]); 
                       client.println(z[2]);
                       client.println(z[3]);
                       client.println(z[4]);
                       client.println(z[5]);
                       client.println();
                      
                       
                       client.println(y[1]); 
                       client.println(y[2]);
                       client.println(y[3]);
                       client.println(y[4]);
                       client.println(y[5]);
                       client.println();                                               
                  break;
                 }
             
             if (c == '\n') 
               {
                 currentLineIsBlank = true;
               }  
               else if (c != '\r') 
               {
                  // you've gotten a character on the current line
                  currentLineIsBlank = false;
               }
             }
         
    } 
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    //Serial.flush();
    digitalWrite(RESET, LOW);
    
    } 
 digitalWrite(RESET, LOW); 
}

Je ne sais plus ou me diriger...surtout que les coupures de connexion sont variables...
Merci d'avance

Bonjour Barbudor

Je viens à vous car j'ai toujours ce problème, je vais donc debugguer pas à pas en mettant des LEDS sur la transmission et la conversion et voir comment cela se comporte.
Ensuite, j'ai acheté un autre module ethernet chinois ENC28J60, avec une bibliothèque différente cela me fera reprendre le programme au complet mais cela peut être une solution.
Merci

void readpacket()
  {
  if (Serial.available() > 0) 
    {
digitalWrite(LED,HIGH);
delay(1000);
    delayMax = millis()+50;
    int b = Serial.read();
    if (b == 0x7E) 
      {
        packet[0] = b;                           
        packet[1] = readByte();
        packet[2] = readByte();
        int dataLength = (packet[1] << 8) | packet[2];  
        for(int i=1;i<=dataLength;i++) 
          {
            packet[2+i] = readByte();               
          }
        int apiID = packet[3];                
        if (apiID == 0x83) 
            {

              
              moduleID[1] = (packet[4] << 8) | packet[5];
              if (moduleID[1]==0x01)
              {
                int SgnlPwr = packet[6];
                int SampleNumber = packet[8];                                                                                                                    
                int i;                                                                                                                                                                                                                                                                                                                                       
                if (SampleNumber >= 1)  
                  {                                                                                                        
                    analogSamples[1] = (packet[11] << 8) | packet[12];
                    analogSamples[2] = (packet[13] << 8) | packet[14];
                    analogSamples[3] = (packet[15] << 8) | packet[16];
                    analogSamples[4] = (packet[17] << 8) | packet[18];
                    delay(1);
                  } 
                   int reading = analogSamples[1];  
                   int reading_2 = analogSamples[2];
                   int reading_3 = analogSamples[3];
                   int reading_4 = analogSamples[4];
        // On converti la valeur lue  en millivolts
                   v[1] =((float) reading)*330/1024;  
                   v[2] =((float) reading_2)*330/1024;
                   v[3] =((float) reading_3)*330/1024;
                   v[4] =((float) reading_4)*330/1024;
                   delay(1);
              }
              else if (moduleID[1]==0x02)
              {
               int SgnlPwr = packet[6];
                int SampleNumber = packet[8];                                                                                                                    
                int i;                                                                                                                                                                                                                                                                                                                                       
                if (SampleNumber >= 1)  
                  {                                                                                                        
                    analogSamples[1] = (packet[11] << 8) | packet[12];
                    analogSamples[2] = (packet[13] << 8) | packet[14];
                    analogSamples[3] = (packet[15] << 8) | packet[16];
                    analogSamples[4] = (packet[17] << 8) | packet[18];
                    analogSamples[5] = (packet[19] << 8) | packet[20];
                    delay(1);
                    
                  } 
                   int reading_5 = analogSamples[1];  
                   int reading_6 = analogSamples[2];
                   int reading_7 = analogSamples[3];
                   int reading_8 = analogSamples[4];
                   int reading_9 = analogSamples[5];
        // On converti la valeur lue  en millivolts
                   z[1] =((float) reading_5)*330/1024;  
                   z[2] =((float) reading_6)*330/1024;
                   z[3] =((float) reading_7)*330/1024;
                   z[4] =((float) reading_8)*330/1024;
                   z[5] =((float) reading_9)*330/1024;
                   delay(1);
              } 
              else if (moduleID[1]==0x03)
              {
               int SgnlPwr = packet[6];
                int SampleNumber = packet[8];                                                                                                                    
                int i;                                                                                                                                                                                                                                                                                                                                       
                if (SampleNumber >= 1)  
                  {                                                                                                        
                    analogSamples[1] = (packet[11] << 8) | packet[12];
                    analogSamples[2] = (packet[13] << 8) | packet[14];
                    analogSamples[3] = (packet[15] << 8) | packet[16];
                    analogSamples[4] = (packet[17] << 8) | packet[18];
                    analogSamples[5] = (packet[19] << 8) | packet[20];
                    delay(1);
                    
                  } 
                   int reading_10 = analogSamples[1];  
                   int reading_11 = analogSamples[2];
                   int reading_12 = analogSamples[3];
                   int reading_13 = analogSamples[4];
                   int reading_14 = analogSamples[5];
        // On converti la valeur lue  en millivolts
                   y[1] =((float) reading_10)*330/1024;  
                   y[2] =((float) reading_11)*330/1024;
                   y[3] =((float) reading_12)*330/1024;
                   y[4] =((float) reading_13)*330/1024;
                   y[5] =((float) reading_14)*330/1024;
                   delay(1);
              } 
            }
              
      }
    }
else
{
digitalWrite(LED,LOW);
}
  }
 uint8_t readByte() 
  {
    while (true) 
      {
	if(delayMax <= millis())
        {
            break;
        }
        if (Serial.available() > 0) 
        {
          return Serial.read();
        }
      }
    return 0;  
  }

J'ai mis la fonction LED pour savoir si la liaison série arrive je met à l'état haut sinon je mets à l'état bas mais cela ne veut pas fonctionner...

J'ai mis la fonction LED pour savoir si la liaison série arrive je met à l'état haut sinon je mets à l'état bas mais cela ne veut pas fonctionner...

Qu'est-ce qui ne veut pas fonctionner ?
Que fait la led ?

Tu donne un code mais tu n'es pas précis sur ce qui ne va pas.
Je ne sais pas ce que tu est sensé recevoir, a quel rythme, etc ...
Donc ma visibilité est nulle.

Quelle est la longueur des paquets reçus ?
Vu que tu utilises 2 octets je suppose qu'elle peut être longue.
Or le tampon mémoire de la liaison série Arduino est de 16 octets.

  if (Serial.available() > 0) 
    {
digitalWrite(LED,HIGH);
delay(1000);

Avec ce delay(1000); tu perd 1 seconde a rien faire alors que les données arrivent.
Une fois les 16 octets du tampon de réception rempli, le driver HardwareSerial jette les données qui continue a arriver.
Une fois que tu auras lu dataLength tu n'auras plus que 13 octets à récupérer.