Problème variable remise à zéro par le programme

Bonjour,

J'ai un petit problème que je ne sais résoudre !!
J'ai un programme qui fonctionne et que je développe depuis 2 mois...
Tout allait bien jusqu'à aujourd'hui.
J'ai remplacé une constante INT en variable non constante pouvant être modifiée dans le programme.
Je l'initialise à une valeur de 40 dans le SetUp, et quand je la lis dans le programme elle est à "0" ! (Alors que si je la lis dans le setup, elle est bien à 40 !!) et je ne la touche nulle part ailleurs !!

Kezako ? Merci de votre aide...

Le bug est ligne 42...

enfin c'est ce que je vois

:slight_smile:

Blague à part... vous pensez nous avoir donné assez d'info?

si je devais prendre un pari, je dirais que vous avez déclaré une variable locale dans votre setup() et une autre globale du même nom. Dans le setup() vous initialisez la variable locale et quand le setup() est fini cette variable locale disparait et vous retrouvez la variable globale dans la loop() qui n'a pas été touchée et donc est à 0 puisque les variables globales sont initialisées par le compilateur à 0....

Si c'est cela, la punition (pour ne pas nous avoir montré votre code) c'est de lire quelques documents sur la portée etsur le scope des variables

Avant le setup :

int CoefProgres;

Dans le setup :

CoefProgres=60;
 Serial.print("coef:");
 Serial.println(CoefProgres);

Le moniteur affiche 60.

Dans le loop :

Serial.println(CoefProgres);

Le moniteur affiche 0.

J'utilise des dizaines d'autres variables de la même manière, et elles fonctionnent, il n'y a que celle-là qui me pose problème !!
J'ai essayé de la renommer, j'ai essayé de changer de type, rien n'y fait...
Et j'ai vérifié 10 fois, je ne change sa valeur nulle part dans le programme.
A la compilation, pas d'erreur et je suis à cette taille de programme :

Le croquis utilise 40 822 octets (16%) de l'espace de stockage de programmes. Le maximum est de 253 952 octets.
Les variables globales utilisent 3 513 octets (42%) de mémoire dynamique, ce qui laisse 4 679 octets pour les variables locales.

Là tout de suite, je dirais qu'il doit manquer des données. Et/ou que celles que vous nous donnez sont incomplètes. Vous ne voudriez pas tout simplement poster votre code?

hello
à vue de nez, tu redéclares ta variable dans la loop et ce n'est donc pas la même variable que tu affiches dans le setup et dans le loop

Le programme complet représente 2536 lignes.
De plus, je travaille sur un système que je voudrais commercialisé plus tard, je ne peux pas mettre le code en ligne !
Voilà les lignes concernées : j'ai testé avec 2 variables

Déclaration des variables, avant le setup :

int KoefProgres;
int LongFreinage;

Dans le setup:

KoefProgres=40;
  Serial.print("coef:");
  Serial.println(KoefProgres);
  LongFreinage=15;
  Serial.print("longfrei:");
  Serial.println(LongFreinage);

Le moniteur affiche :

coef:40
longfrei:15

Dans le loop :

Serial.print("facteur:");
    Serial.println(KoefProgres);
    Serial.print("longfrei:");
    Serial.println(LongFreinage);

Le moniteur affiche :

facteur:0
longfrei:15

Montrez nous le setup. vous nous garantissez que vous ne faites pas une double création de variable?

sinon si elle est à zéro c'est que vous avez un buffer overflow quelque part

J'ai utilisé la fonction "trouver" de l'éditeur, afin de vérifier s'il n'y a pas d'autres utilisation de la variable, et il n'y a rien.
Les deux variables que j'ai mis dans l'exemple sont utilisées exactement de la même manière.
Je viens d'en créer une 3eme pour voir:

int CoefProgres2;
int KoefProgres;
int LongFreinage;

Dans le setup :

KoefProgres=40;
  CoefProgres2=40;
  Serial.print("coef:");
  Serial.println(CoefProgres2);
  LongFreinage=15;
  Serial.print("longfrei:");
  Serial.println(LongFreinage);

Le moniteur affiche :

coef:40
longfrei:15

Dans le loop:

Serial.print("facteur:");
    Serial.println(CoefProgres2);
    Serial.print("longfrei:");
    Serial.println(LongFreinage);

Le moniteur affiche:

facteur:1
longfrei:15

C'est de mieux en mieux !!
J'utilise la variable "CoefProgres2" dans une multiplication, il a multiplié par 2 !!!

Comment puis-je détecter un buffer overflow ? Et pourquoi arriverait-il maintenant, alors que ce matin encore, ca fonctionnait...

OK et vous êtes sûr à 100% (je radote) qu'il n'y a pas le mot clé "int" devant votre variable dans le setup?

avez vous des chaînes de caractères ou des tableaux qui sont déclarés proche de vos variables?

utilisez vous des Strings? (la classe chaîne de caractères)

Je suis sûr que la variable est bien déclarée en globale, nulle part ailleurs !!
Je ne l'utilise qu'aux endroits précédemment cités !!
Elle n'est pas utilisée dans aucune condition, ni aucun tableau !
Je viens de changer d'Arduino pour vérifier, cela fait strictement la même chose...
J'utilise beaucoup de String, mais je ne vois pas en quoi elles influenceraient...

J'ai un autre problème qui survient aussi, aléatoirement, j'ai des problèmes de communications Série...
Ce qui fait que l'Arduino redémarre... sur un simple Serial3.print(une_chaine);
J'ai baissé la vitesse de transmission, mais ça ne change rien. J'ai donc mis en commentaires cette partie du programme pour l'instant... afin de trouver d'abord la panne de cette variable !

Je sèche vraiment sur ce problème !!!!!!!
Pour l'utilisation, je suis à 16% de l'espace stockage de programme et 43% de mémoire dynamique...

J'utilise beaucoup de String, mais je ne vois pas en quoi elles influenceraient...

si vous lisez l'anglais : The Evils of Arduino Strings

éventuellement ce que vous pouvez faire pour voir si c'est un pb de débordement mémoire, changez la place de déclaration de votre variable globale; mettez là au début ou à la fin de toutes les déclarations - le plus loin possible de sa déclaration actuelle et regardez s'il se passe la même chose

Entre le moment où ça fonctionnait et le moment où ça n'a plus fonctionnait, j'avais ajouté 10 lignes de code, dans des fonctions qui ne sont pas appelées dans mes tests.
Je viens de les mettre en commentaire et ça remarche.
Je ne comprends pas pourquoi, car ces lignes n'ont rien à voir avec ces variables.
Y'a-t-il un nombre de lignes maximum pour le code ??????????
Je suis à 16% de l'espace !!!! 43% de mémoire dynamique ?
Peut-on dans le programme, lorsqu'il tourne, connaitre à quel pourcentage la mémoire est utilisée ????
JE suis vraiment surpris de ce qui se passe....

Une image vaut 100 mots

mais bon vous pouvez en lire plus ici

et voir comment utiliser freeRam()

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

vous pouvez aussi aller voir la librairie MemoryFree (un peu documentée ici, avec le code ci dessous)

MemoryFree.h:

// MemoryFree library based on code posted here:
// http://forum.arduino.cc/index.php?topic=27536.msg204024#msg204024
// Extended by Matthew Murdoch to include walking of the free list.

#ifndef MEMORY_FREE_H
#define MEMORY_FREE_H

#ifdef __cplusplus
extern "C" {
#endif

int freeMemory();

#ifdef  __cplusplus
}
#endif

#endif

MemoryFree.cpp:

#if (ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#endif

extern unsigned int __heap_start;
extern void *__brkval;

/*
 * The free list structure as maintained by the 
 * avr-libc memory allocation routines.
 */
struct __freelist {
  size_t sz;
  struct __freelist *nx;
};

/* The head of the free list structure */
extern struct __freelist *__flp;

#include "MemoryFree.h"

/* Calculates the size of the free list */
int freeListSize() {
  struct __freelist* current;
  int total = 0;
  for (current = __flp; current; current = current->nx) {
    total += 2; /* Add two bytes for the memory block's header  */
    total += (int) current->sz;
  }
  return total;
}

int freeMemory() {
  int free_memory;
  if ((int)__brkval == 0) {
    free_memory = ((int)&free_memory) - ((int)&__heap_start);
  } else {
    free_memory = ((int)&free_memory) - ((int)__brkval);
    free_memory += freeListSize();
  }
  return free_memory;
}

De plus, je travaille sur un système que je voudrais commercialisé plus tard, je ne peux pas mettre le code en ligne !

Moi j'aimerai savoir de quel produit il s'agit pour ne pas acheter par hasard quelque chose qui a été développé en utilisant la classe String

:slight_smile:

Je lis ce que vous m'envoyez
Mon problème n'a rien de mystérieux, puisqu'il s'agit d'une variable qui est initialisée alors qu'elle ne le devrait pas, j'ai mis les lignes de code correspondantes.
Utiliser une liaison série sans la classe String, c'est compliqué...dans Arduino je parle...
Le programme que je développe fait partie d'un tout, ce tout ne contient pas que l'arduino et le programme, il a d'autres choses autour. S'il faut prendre uniquement le processeur pour ne pas avoir à donner le code, je le ferai, mais je ne vois pas bien comment un outil "libre" ne devrait pas être intégré à quelque chose de commercial...
Bref.
Le problème est toujours là, sauf quand j'enlève une partie du programme qui se trouve dans une sous-fonction qui n'est pas appelée par le programme lors des tests. Donc je penche pour un dépassement de capacité, mais je ne sais pas lequel, et pourquoi...
Si, vous ne voulez plus m'aider, tant pis, je chercherai ailleurs...
Je trouve dommage ces réactions.
Mon programme, c'est mon travail, je n'ai pas envie de le laisser partir dans les méandres d'internet...

j'ai mis les lignes de code correspondantes.

le problème n'est pas dans ces lignes de code... il est ailleurs.. http://snippets-r-us.com

Si, vous ne voulez plus m'aider, tant pis, je chercherai ailleurs...
Je trouve dommage ces réactions.

Je vous ai donné des liens et du code pour tester à l'exécution la mémoire dispo. l'avez vous utilsé? qu'est-ce que ça vous dit ?

Je vous ai suggéré de déplacer la déclaration de la variable pour voir si elle était modifiée ou pas (sa place en mémoire dépend de l'ordre de déclaration des variables globales). l'avez vous fait? qu'est-ce que ça vous dit ?

On n'a aucune réponse à nos propositions.... Que voulez vous qu'on fasse sans code? le compilateur fonctionne, ce genre de bug n'arrive pas par hasard, c'est donc votre code qui est fautif... si on ne peut pas voir le code, c'est votre choix, mais on ne peut pas vous aider bcp si ce n'est qu'émettre des idées, ce qui n'est pas très scientifique ni gratifiant et en plus vous ne ne répondez pas aux propositions d'analyse...

Utiliser une liaison série sans la classe String, c'est compliqué...dans Arduino je parle...

absolument pas... et si ça vous cause des problèmes impossible à débogguer, votre solution apparente de simplicité ne l'est donc pas.

Quelques liens utiles pour se passer de la classe String

les fonctions C de base:
stdlib.h
string.h

Un "tuto" sur les bonnes pratiques pour gérer le port série
Serial Input Basics

je ne vois pas bien comment un outil "libre" ne devrait pas être intégré à quelque chose de commercial...

parce que libre ne veut pas dire qu'il est à vous... les librairies que de généreux contributeurs vous permettent d'utiliser sans vous casser la tête ont des conditions, suivant le type de licence retenu par l'auteur, si vous l'utilisez vous pouvez être obligé de donner TOUT le code source de votre produit avec votre produit. C'est un peu le principe du donnant-donnant. (une seule ligne de code provenant d'une telle licence et c'est en gros l'intégralité de votre projet que vous devez partager pour que quelqu'un qui chercherait à rebâtir ou modifier votre produit puisse le faire)

vous pouvez en lire plus ici par exemple (mais la GPL v3 n'est pas seule)

J'ai mis la fonction permettant de lire la mémoire libre (freeram)
J'ai 4319 en valeur affichée lors de l'appel de cette fonction.

J'ai déplacé la déclaration de la variable, à plusieurs endroits (début, milieu, fin) sans résultat.

Mon utilisation des String se limite aux échanges Série. J'ai essayé de faire le plus propre possible pour éviter les problèmes.
Tout fonctionnait très bien jusqu'à ce que j'ajoute ces quelques lignes, dans une fonction tierce...
Si je mets ces lignes en commentaire, ça fonctionne, si je les remets, la variable repasse à zéro...

Code appel freeRam, et lecture variable (appelé dans Loop()):

Serial.print("memoire:");
    Serial.println(freeRam());
    Serial.print("facteur:");
    Serial.println(FacteurProgression);

Voilà le code de la sous-fonction, dans laquelle, en commentaire, la ligne qui pose problème.
Quand j'active cette ligne, ma variable "FacteurProgression" est à "0" alors que je l'ai initialisée à 40.

void miseajour_suppression(int numconsigne, int num){
  for(int i=0;i<NbCantons;i++){
    if(numero[i]==num){
      numero[i]=0;
      liberation(i);
      //effacerLedsCanton(i);
      if(occupation[num]==1){
        occupation[num]=0;
        ConsiA[num]=0;
        ConsiN[num]=0;
        RalenA[num]=70;
        LimiA[num]=45;
        NbTrains--;
        lcd.setCursor(0,3);
        lcd.print("                    ");
        lcd.setCursor(0,3);
        String text="";
        if(num<10){
          text="0";
        }
        text=text+String(num);
        lcd.print("Train N"+String((char)223)+text+" supprime");
      }
      Serial.print("nb de trains : ");
      Serial.println(NbTrains);
      envoi_occupation(NbTrains, num, 0);
    }
  }
  if(occupation[num]==1){
    envoi_consigne(numconsigne,num,0);
  }
}

Et la fonction :

void effacerLedsCanton(int numero){
  registersK[numero*4+2]=LOW;
  registersK[numero*4+3]=LOW;
  registersK[numero*4]=LOW;
  registersK[numero*4+1]=LOW;
  writeRegistersK();
}

Pour l'utilisation d'Arduino, si je vends mon système, je donnerai le code avec, bien-sûr.
Mais, ici, je ne l'ai pas vendu... :wink:

Transformez tous vos Serial.print("xxxx"); en Serial.print(F("xxxx"));
ça va mettre toutes vos chaînes de caractères directement en mémoire programme et donc libérer de la RAM. essayez pour voir si ça change quelque chose

J'ai remplacé tous les Serial.print en ajoutant (F("xxx")), la mémoire est montée à 4997, mais la variable reste à "0".