[Debutant] plantage sur manip string

Bonjour à tous, je bloque sur un truc bête :frowning:

Je cherche la présence d'une string dans une autre (message UDP) et bien ca soit basique ca fait planter mon programme qui reboot dés que j'essaye de manipuler les strings.
Au début je pensais que cela venait de caractères spéciaux présents mais je m'aperçois que non et qu'en sortant la ligne de commande d'une condition donnée ca marche :~

Ci dessous mon code modifié avec un exemple (j'ai fait un copier/coller de ce bout de code test sur les string) :

//test string
                                 String stringOne = "/1/push1/z";
                                 int firstClosingBracket = stringOne.indexOf("push1");
                                 Serial.println("The index of > in the string " + stringOne + " is " + firstClosingBracket);
                               //fin de test

Quand il est dans dans la condition :

if (buf[IP_PROTO_P]==IP_PROTO_UDP_V){
}

ca fait planter mon code, par contre si je le sors de la condition ca passe très bien !?

Help .... je suis à court d'idée là =(

Le code avec le commentaire :

#include "EtherShield.h"

uint8_t mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x25};
uint8_t myip[4] = {192,168,1,25};
uint16_t MYWWWPORT = 80;
uint16_t outgoingport = 12345;

#define BUFFER_SIZE 750
static uint8_t buf[BUFFER_SIZE+1];

char reply[]="00000000";
String UDPMsg;
char c;
EtherShield es=EtherShield();

uint16_t plen, dat_p;
static uint8_t udp_length;
static uint8_t udp_buffer[50];

///----------------------------------------------------------
void setup(){
  
  Serial.begin(9600);
  Setup_Pins();
  es.ES_enc28j60Init(mymac);
  es.ES_init_ip_arp_udp_tcp(mymac,myip, MYWWWPORT);
  Serial.println("Start");
} // end setup
///----------------------------------------------------------
void loop(){
  
              // read packet, handle ping and wait for a tcp packet:
              dat_p=es.ES_packetloop_icmp_tcp(buf,es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf));
              
              if (buf[IP_PROTO_P]==IP_PROTO_UDP_V){ 
                 //Serial.println(buf[IP_PROTO_P]);
                
                
                               udp_length=buf[39]-16; // calculate UDP data lenght
                             // udp_length=buf[39]-8; // calculate UDP data lenght
                               
                               for (int i = 0; i < udp_length; i++)
                               {
                                     //Serial.write(buf[42+i]);
                                      c = buf[42+i];
                                      UDPMsg += c;
                               }//end for
                               
                               Serial.println(UDPMsg);
                                 
                                                              
                               //test string -> ca fait planter mon code
                                 String stringOne = "/1/push1/z";
                                 int firstClosingBracket = stringOne.indexOf("push1");
                                 Serial.println("The index of > in the string " + stringOne + " is " + firstClosingBracket);
                               //fin de test
                               
                               //Relay_Control();
                               //Status_Reply();
                               //es.ES_make_udp_reply_from_request(buf,reply,8,outgoingport); 
                               buf[IP_PROTO_P]=0;
                               UDPMsg="";
              } //end if
  //test string -> ca marche 
  String stringOne = "/1/push1/z";
  int firstClosingBracket = stringOne.indexOf("push1");
  Serial.println("The index of > in the string " + stringOne + " is " + firstClosingBracket);
  //fin de test
  
} // end loop

bonjour, si tu met autre chose dans ce if sa passe? genre un delay un serial.print ou coi ca passe? moi je pense que c'est dans tes condition que une variable doit déconné :s

Quel micro sur ta carte? car tu utilises pas mal de RAM déjà et donc lors de la création de stringOne peut être as-tu un débordement.

Bonjour,

fdufnews:
Quel micro sur ta carte? car tu utilises pas mal de RAM déjà et donc lors de la création de stringOne peut être as-tu un débordement.

+1 l'hypothèse du débordement semble la plus probable.

Une bonne façon de savoir si c'est ça :
http://arduino.cc/playground/Code/AvailableMemory

Merci pour vos réponses.

C est une carte chinoise avec 4 relais et le Shields ethernet intègr?.
Les caractéristiques :

• Flash Memory 32 KB (ATmega328) of which 2 KB used by bootloader
• SRAM 2 KB (ATmega328)
• EEPROM1 KB (ATmega328)
• Clock Speed 16 MHz

Je fais un test des demain avec une fonction de test mémoire et vous tiens au courant.!

teste autre chose dans ce if déjà pour en avoir le coeur net c'est simple et ça mettra une partie hors de cause !

Bon je deterre mon post car je reprend mon petit projet et j'ai tjs mon probleme :slight_smile:

j'ai testé des println et ca passe, et j'ai donc testé une mesure de ram.

Voici la derniere version du code en 3 parties :

le main :

#include "EtherShield.h"

uint8_t mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x25};
uint8_t myip[4] = {192,168,1,25};
uint16_t MYWWWPORT = 80;
uint16_t outgoingport = 12345;

#define BUFFER_SIZE 750


static uint8_t buf[BUFFER_SIZE+1];
int thisByte = 33; 
char reply[]="/1/label1 ok";
String UDPMsg;
char c;
EtherShield es=EtherShield();

uint16_t plen, dat_p;
//static uint8_t udp_length;
//static uint8_t udp_buffer[50];
uint8_t udp_length;
uint8_t udp_buffer[50];

///----------------------------------------------------------
void setup(){
  
  Serial.begin(9600);
  Setup_Pins();
  es.ES_enc28j60Init(mymac);
  es.ES_init_ip_arp_udp_tcp(mymac,myip, MYWWWPORT);
  //Serial.println();
  Serial.println("Start");
  Serial.println(freeRam()); 
 
} // end setup
///----------------------------------------------------------
void loop(){
              
              // read packet, handle ping and wait for a tcp packet:
              dat_p=es.ES_packetloop_icmp_tcp(buf,es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf));
         
              if (buf[IP_PROTO_P]==IP_PROTO_UDP_V){
                
                               udp_length=buf[39]-16; // calculate UDP data lenght
                             
                               for (int i = 0; i < udp_length; i++)
                               {
                                     //Serial.write(buf[42+i]);
                                      c = buf[42+i];
                                      UDPMsg += c;
                               }//end for
               delay(500); 
               Serial.println(UDPMsg.indexOf("push1/z"));
               delay(500);
                                     
   
                               buf[IP_PROTO_P]=0;
                               UDPMsg="";
              } //end if

  
} // end loopThe ram test function :

la page de fonction reduite pour le moment a la mesure de la memoire :

///----------------------------------------------------------

int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

///----------------------------------------------------------

et pour finir un petite page de config des sorties :

///----------------------------------------------------------
void Setup_Pins(){
  
  pinMode(5, OUTPUT); digitalWrite(5, 0);
  pinMode(6, OUTPUT); digitalWrite(6, 0);
  pinMode(7, OUTPUT); digitalWrite(7, 0);
  pinMode(8, OUTPUT); digitalWrite(8, 0);
  
} // end Setup_Pins

Quand je lance tout çà :

sans envoyer de trame :
j'obtiens sur le port serie :

Start
993
Start
993
Start
993
Start
993

les reboot arrivent generalement toutes les 2-3 minutes
le test de mémoire retourne "993" je ne vois pas ce que ca peut representer ! c est suffisant ? à noter que j'ai aussi un test en baissant la taille du buffer (
#define BUFFER_SIZE xxx) et j'avait en resultat 1200 environ et ca continuait à rebooter...

Ensuite quand j'envois des trames OSC :

Start
993
3
Start
993
-1
Start
993
Start
993

Là on voit que à part les reboot ca marche j'obtiens "3" à la premiere trame qui correspond à la position du caractere recherché et -1 au deuxieme car la trame ne contenait pas ce que je cherche par contre ca reboot immédiatement apres le resultat, apres ca continu a rebooter toutes les 2-3 minutes.

Etant à court d'idée j'ai aussi posé la question à l'editeur de la carte on verra bien ....

Question bete liée au fait que je comprend pas encore tout le code :

void loop(){
  
              // read packet, handle ping and wait for a tcp packet:
              dat_p=es.ES_packetloop_icmp_tcp(buf,es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf));

J'ai du mal à visualiser le fonctionnement imbriqué du loop et de l'evenement de lecture du buffer, ya pas de risque que le contenu de dat_p change plus vite que le traintement complet de mon loop (pas facile à decrire l'idée là :D)

Merci de votre aide !

for (int i = 0; i < udp_length; i++)
                               {
                                     //Serial.write(buf[42+i]);
                                      c = buf[42+i];
                                      UDPMsg += c;
                               }//end fo

Je me demande si cette partie ne pourrait pas te jouer un mauvais tour.
Ta mesure de la mémoire disponible est réalisée à la fin du setup(). Toutes les variables sont créées à leur taille finale sauf UDPMsg la chaîne n'est pas initialisée donc sa longueur est nulle.
Lorsque tu la construis en ajoutant un caractère il est possible que quelque fois elle grossisse trop et bouffe le stack.

Pour vérifier ça, tu pourrais créer une variable longueur que tu mettes à zéro à l'initialisation et quand tu réinitialises la chaîne

buf[IP_PROTO_P]=0;
UDPMsg="";
longueur = 0;

Et tu l'incrémenterais lorsque tu ajoutes un caractère à la chaine

for (int i = 0; i < udp_length; i++)
                               {
                                     //Serial.write(buf[42+i]);
                                      c = buf[42+i];
                                      UDPMsg += c;
                                      longueur++;
                               }//end fo

Il faudrait l'envoyer par la console pour voir si elle ne devient pas plus grande que la place libre en mémoire. Sans perdre de vue qu'il y a en plus des variables locales créées dans les fonctions appelées dans la librairie Ethershield.

hello merci de t'intéresser à mon sujet :wink:

Ce que tu propose de serveiller je peux aussi le recupérer dans "udp_length" logiquement ?

Je vais de ce pas faire quelques tests pour vérifier :slight_smile:

Edit :

Donc voilà les resultats :

Le code modifié avec quelques traçages supplémentaires de la RAM, en mettant quelques commentaires et en ajoutant quelques delay :

#include "EtherShield.h"

uint8_t mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x25};
uint8_t myip[4] = {192,168,1,25};
uint16_t MYWWWPORT = 80;
uint16_t outgoingport = 12345;

#define BUFFER_SIZE 750


static uint8_t buf[BUFFER_SIZE+1];
int thisByte = 33; 
char reply[]="/1/label1 ok";
String UDPMsg;
char c;
EtherShield es=EtherShield();

uint16_t plen, dat_p;
uint8_t udp_length;
uint8_t udp_buffer[50];

///----------------------------------------------------------
void setup(){
  
  Serial.begin(9600);
  Setup_Pins();
  es.ES_enc28j60Init(mymac);
  es.ES_init_ip_arp_udp_tcp(mymac,myip, MYWWWPORT);
  
  Serial.println(" ");
  Serial.print("Start RAM ");
  Serial.println(freeRam() );
   
} // end setup
///----------------------------------------------------------
void loop(){
              
              // read packet, handle ping and wait for a tcp packet:
              dat_p=es.ES_packetloop_icmp_tcp(buf,es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf));
         
              if (buf[IP_PROTO_P]==IP_PROTO_UDP_V){
                
                               udp_length=buf[39]-18; // calculate UDP data lenght
                               Serial.print("udp_length ");
                               Serial.println(udp_length);
                               Serial.print("RAM ");
                               Serial.println(freeRam());
                                
                               for (int i = 0; i < udp_length; i++)
                               {
                                     //Serial.write(buf[42+i]);
                                      c = buf[42+i];
                                      UDPMsg += c;
                                      delay(10); 
                               }//end for
               Serial.print("RAM aprés traitement ");
               Serial.println(freeRam());                
               delay(100); 
               Serial.println(UDPMsg); 
               Serial.println(UDPMsg.indexOf("push1/z"));
               delay(100);
                                     
   
                               buf[IP_PROTO_P]=0;
                               UDPMsg="";
              } //end if

  
} // end loop

Resultat :

Start RAM 945

Start RAM 945

Start RAM 945

Start RAM 945

Start RAM 945
udp_length 10
RAM 700
RAM aprés traitement 691
/1/push1/z
3

Start RAM 945

On constate encore 4 plantages à sans trame UDP (environ 1 plantage à la minute) :roll_eyes:
Et visiblement pas de débordement de la RAM et UDP_Lenght qui est de 10 caracteres

Maintenant le meme code avec suppression des delay :

Start RAM 945

Start RAM 945

Start RAM 945

Start RAM 945

Start RAM 945

Start RAM 945

Plantage à vide au depart, et ensuite plantage complet avec retour de caractères incohérents à l'envoi de trames.... :disappointed_relieved:

Alors quand même précision importante sur la trame utilisée :

Exemple de trame UDP quand j'appuie sur le bouton 1 de mon emeteur (touchOSC iphone)

/1/push1/z
/1/push1
/1/push1
/1/push1/z

Les deux premières lignes sont envoyées lorsque qu'on appuie sur le bouton, les deux dernières quand on relache, ca fait donc 4 trames à la suite, constant que je ne trappais qu'une ligne à chaque fois sur la console, j'ai augmenté la vitesse du port serie à 115200 bauds.

Nouveau test de code en laissant tout sauf la commande de manip string :

#include "EtherShield.h"

uint8_t mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x25};
uint8_t myip[4] = {192,168,1,25};
uint16_t MYWWWPORT = 80;
uint16_t outgoingport = 12345;

#define BUFFER_SIZE 750


static uint8_t buf[BUFFER_SIZE+1];
int thisByte = 33; 
char reply[]="/1/label1 ok";
String UDPMsg;
char c;
EtherShield es=EtherShield();

uint16_t plen, dat_p;
uint8_t udp_length;
uint8_t udp_buffer[50];

///----------------------------------------------------------
void setup(){
  
  Serial.begin(115200);
  Setup_Pins();
  es.ES_enc28j60Init(mymac);
  es.ES_init_ip_arp_udp_tcp(mymac,myip, MYWWWPORT);
  
  Serial.println(" ");
  Serial.print("Start RAM ");
  Serial.println(freeRam() );
   
} // end setup
///----------------------------------------------------------
void loop(){
              
              // read packet, handle ping and wait for a tcp packet:
              dat_p=es.ES_packetloop_icmp_tcp(buf,es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf));
         
              if (buf[IP_PROTO_P]==IP_PROTO_UDP_V){
                                
                               udp_length=buf[39]-18; // calculate UDP data lenght
                               Serial.print("udp_length ");
                              Serial.println(udp_length);
                               Serial.print("RAM ");
                               Serial.println(freeRam());
                                
                               for (int i = 0; i < udp_length; i++)
                               {
                                     //Serial.write(buf[42+i]);
                                      c = buf[42+i];
                                      UDPMsg += c;                                     
                               }//end for
               Serial.print("RAM aprés traitement ");
               Serial.println(freeRam());                
 
              Serial.println(UDPMsg); 
//              Serial.println(UDPMsg.indexOf("push1/z")); -> **************manip string en commentaire ***************

//                                     
//   
                               buf[IP_PROTO_P]=0;
                               UDPMsg="";
              } //end if

  
} // end loop

Résultat :

Start RAM 953
udp_length 10
RAM 708
RAM aprés traitement 699
/1/push1/z
udp_length 10
RAM 699
RAM aprés traitement 699
/1/push1##
udp_length 10
RAM 699
RAM aprés traitement 699
/1/push1##
udp_length 10
RAM 699
RAM aprés traitement 699
/1/push1/z

On constate :

-Pas de plantage sans trame UDP
-les 4 trames sont bien trappées

Je ne comprend meme pas pourquoi ca plante à vide, c'est pas un probleme de memoire et l'evenement n'est pas censé se produire sans trame UDP =(

On continu sur le meme theme :roll_eyes:

Tests intéressant :

Test 1 :

Je sors le test de string de la boucle "evenement udp" en passant le contenu de UDPMSG dans uns string UDPMSG2

void loop(){
              
patati patata de code que je ne remet pas
                        
               Serial.println(UDPMsg); 
//              Serial.println(UDPMsg.indexOf("push1/z"));
                               buf[IP_PROTO_P]=0;
                               UDPMsg2 =UDPMsg;                               
                               UDPMsg="";
              } //end if
            
if (UDPMsg2 != ""){
  Serial.println(UDPMsg2.indexOf("push1/z"));
   UDPMsg2="";
} //end if 
} // end loop

Le résultat est le même plantage sur le indexof

Test 2 :

//              Serial.println(UDPMsg.indexOf("push1/z"));
                               buf[IP_PROTO_P]=0;                            
                               UDPMsg="";
              } //end if
UDPMsg2 = "/1/test/push1/z";             
if (UDPMsg2 != ""){
  Serial.println(UDPMsg2.indexOf("push1/z"));
   UDPMsg2="";
} //end if 
} // end loop

là le résultat est intéressant :

8
8
8
8
8
8
8
8
8
8
ud°
Start RAM 918
8
8

On constate que le test indexof fonctionne bien et ne fait pas planter le code, sauf quand j'envois une trame UDP en plus, qui pourtant n'est pas traitée par la cherche de caractère ...

Ca serait peut etre un problème de format de variables ? mais le comportement ressemble plus à un problème de boucle ou d'événement imbriqués ayant des vitesse d''exécution différentes ...

Exemple le temps que l'indexof aboutisse le contenu de UDPMSG a deja changé ... a votre avis ?

A force de creuser ....

J'ai externalisé la fonction d'analyse de string :

Le code :

void loop(){
              
              // read packet, handle ping and wait for a tcp packet:
              dat_p=es.ES_packetloop_icmp_tcp(buf,es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf));
         
              if (buf[IP_PROTO_P]==IP_PROTO_UDP_V){
                                                            
                               udp_length=buf[39]-18; // calculate UDP data lenght
                             
                               for (int i = 0; i < udp_length; i++)
                               {
                                     //Serial.write(buf[42+i]);
                                      c = buf[42+i];
                                      UDPMsg += c;                                     
                               }//end for

                 search();
                 buf[IP_PROTO_P]=0;

              } //end if
         

} // end loop

et la fonction :

void search(){

if (UDPMsg != ""){
if (UDPMsg.indexOf("push1/z") > 1 )
{
Serial.println("Bouton1");
flag1 = flag1 + 1;
if (flag1 == 2 )
{
digitalWrite(5, 1);
delay(2000);
digitalWrite(5, 0);
flag1 = 0;
}
}
else if (UDPMsg.indexOf("push2/z") > 1 )
{
Serial.println("Bouton2");
flag2 = flag2 + 1;
if (flag2 == 2 )
{
digitalWrite(6, 1);
delay(2000);
digitalWrite(6, 0);
flag2 = 0;
}

} //end if

UDPMsg="";
} //end if

} // end Search

et là ca fonctionne :smiley: