Pages: [1] 2   Go Down
Author Topic: [débutant]Détection et correction des bug système  (Read 1490 times)
0 Members and 1 Guest are viewing this topic.
Region ile de france.
Offline Offline
Sr. Member
****
Karma: 3
Posts: 402
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour a tous,
 voila perso je n'ai j'amais apris a l'ecole (he oui en chimie a par des truc rigolo, dans la vie de tout les jour on peut pas faire grand chose avec) ou avec quelqu'un l'electronique n'y la programation je me debrouille par moi meme avec bouquin et forum et votre agréable participation. smiley

Pour un débutant comme moi certaine subtilité sont parfois difficile(pour ne pas dire très) a saisir c'est pourquoi je souhaite ouvrir ce topic pour tout ceux qui comme moi ne comprenne pas tout et on des plantages système, afin de permettre a chacun de les corriger.

dans mon cas, mon système de gestion de ma pièce d’élevage (reptile), ce produit un plantage total plus rien ne fonction au bout d'un certain temps (de quelque minute jusqu’à 2H), ce bug semble être apparue avec la mise en place du shiel ethernet.

dans mon système son pressent les élément suivant:
niveau hardware:
-carte arduino mega 2560
-shield ethernet
-carte RTC DS1307
-des sonde dallas DS18B20
-un ecran LCD tactile TFT MI0283QT2
-une carte 8relais a commande TTL

les librairie utiliser sont les suivante:
Code:
#include <MI0283QT2.h> // librairie de l'afficheur TFT MI0283QT2
#include <ADS7846.h> // inclusion de la librairie pour le touchpad
#include <Wire.h>
#include <DS1307.h>//librairie pour la RTC
#include <SD.h>//librairie pour la carte SD
#include <SDcard.h>//librairie pour la carte SD
#include <OneWire.h>
#include <DallasTemperature.h>//librairie pour les sonde DS18B20
#include <SPI.h>
#include <Ethernet.h>
#include <WebServer.h>


pour le moment ma seul technique si je puis dire consiste a regarder ce qui se passe visuellement sur mon écran LCD ou a l'aide du serial
parfois j'essai de bidouiller le code et voir ce qu'il ce passe , mais je n'ai pas trop de technique pour m'en sortire!

si vous avez des méthodologie particulière ou des astuces ou des idées(dite pas non vue ce que je voi sur le forum ça ne manque pas les idées) et que vous voulez bien les partager merci a vous!


une des premier question que je vous pose est que faut il surveillé ? (exemple memoire flash , debordement dans les declaration des variable ...)

Logged


Offline Offline
Full Member
***
Karma: 0
Posts: 101
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Utiliser le plus possible le renvoie de variable (état, température, compteur, etc) sur serial via une fonction c'est plus facile à activer et désactiver avec un bool avant le setup.

Vérifier si tu n'as pas de fuite mémoire qui fini par saturer et planter la machine (toujours avec renvoie sur le serial http://arduino.cc/playground/Code/AvailableMemory)

Logged

- 1 mega 2560
- 1 Raspeberry Pi (en pré-commande)
- Quarante douze PC
- beaucoup de volonté, pas beaucoup de temps.
- Ma religion : OpenSour

Region ile de france.
Offline Offline
Sr. Member
****
Karma: 3
Posts: 402
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Pas mal le teste de mémoire je vais tester cela ce soir pour voir un peut ce que sa donne !
Logged


Rennes
Offline Offline
Sr. Member
****
Karma: 1
Posts: 313
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Utiliser le plus possible le renvoie de variable (état, température, compteur, etc) sur serial via une fonction c'est plus facile à activer et désactiver avec un bool avant le setup.
Pour économiser en ressources mémoire et processeur il vaut mieux procéder via la compilation conditionnelle (#define) pour activer/désactiver le debug via Serial.println()
Ainsi lors de la compilation, si le #define n'est pas présent (ou en commentaire) ce code n'est pas inclus dans le code compilé.

Code:
En début de sketch:
#define DEBUG_SERIAL //commenter cette ligne pour désactiver tout log sur le port série

dans setup():
#ifdef DEBUG_SERIAL //ce qui entre cette ligne et le #endif n'est compilé que si DEBUG_SERIAL est défini
Serial.begin(9600);
#endif  

et partout où j'envoie des logs:
#ifdef DEBUG_SERIAL
Serial.println("une trace");
#endif

J'ai aussi d'autres defines pour activer/désactiver des infos de log spécifiques selon les composants de mon sketch que je veux tracer
« Last Edit: July 06, 2012, 04:47:25 am by patg_ » Logged


France
Offline Offline
Newbie
*
Karma: 0
Posts: 33
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Comme patg_ je dirais faire un LOG (sur carte SD ou via Série) avec un TimeStamp à chaque ligne. Ça permet de voir si c'est logiciel (plantage systématique sur une action) ou matériel (plantage n'importe quand)
Logged

Region ile de france.
Offline Offline
Sr. Member
****
Karma: 3
Posts: 402
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

c'est quoi timestamp?
c'est le temps de la RTC par example ou une librairie particuliaire?
Logged


France
Online Online
Faraday Member
**
Karma: 39
Posts: 3565
There is an Arduino for that
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Si j'en crois le nombre de librairies que tu utilises, tu ne dois utiliser beaucoup de mémoire.
La gestion de l'afficheur, du shield Ethernet et de la SDcard mets une forte pression sur la RAM. Il ne doit pas falloir grand chose pour avoir un débordement.

Il faut privilégier les variables locales. Et faire très attention aux chaînes de caractères et aux tableaux (utilisés dans l'Ethernet et la SDcard). Il faut être très attentif à la taille des tampons utilisés pour communiquer avec l'Ethernet et à la taille des tableaux définis pour manipuler les chaînes de caractères. Une chaîne de caractères  qui déborde d'un tampon peut passer 10 fois et faire planter la 11ème parce qu'il y a une variable critique qui a été écrasée.
Logged

France
Offline Offline
Newbie
*
Karma: 0
Posts: 33
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

c'est quoi timestamp?
c'est le temps de la RTC par exemple ou une librairie particulière?

C'est effectivement un marquage temporel.
http://fr.wikipedia.org/wiki/Timestamp

Indispensable dans tout fichier de log. Pour ne pas envahir la carte, tu créé un fichier de log par jour et tu ne garde que les 3 derniers par exemple. On utilise souvent le formatage  AAAAMMJJ-HHMMSS ce qui permet ensuite de trier facilement le fichier de log (car ordre alpha = ordre temporel) Il faut avoir une composant d'horloge (c'est le cas ici car il y a le DS1307) mais inutile de charger une lib supplémentaire (tout ce qu'il faut est déjà dans Wire.h). Quand on utilise que quelques fonctions d'un composant, il est préférable de reprendre la fraction de code intéressante que de charger toute la lib (c'est long, mais on sait exactement ce que fait la fonction)
 
Note que puisque tu utilises l'écran MI0283QT2 (excellent choix) qui est tactile, tu pourrais soulager la conso de ton système en le mettant OFF (affichage et calcul de toutes les fonctions) au bout de quelques secondes d'inactivité et en le réactivant au premier toucher.
« Last Edit: July 06, 2012, 06:24:58 am by Marc56 » Logged

Region ile de france.
Offline Offline
Sr. Member
****
Karma: 3
Posts: 402
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Si j'en crois le nombre de librairies que tu utilises, tu ne dois utiliser beaucoup de mémoire.
La gestion de l'afficheur, du shield Ethernet et de la SDcard mets une forte pression sur la RAM. Il ne doit pas falloir grand chose pour avoir un débordement.

Il faut privilégier les variables locales. Et faire très attention aux chaînes de caractères et aux tableaux (utilisés dans l'Ethernet et la SDcard). Il faut être très attentif à la taille des tampons utilisés pour communiquer avec l'Ethernet et à la taille des tableaux définis pour manipuler les chaînes de caractères. Une chaîne de caractères  qui déborde d'un tampon peut passer 10 fois et faire planter la 11ème parce qu'il y a une variable critique qui a été écrasée.

heureusement ma SD car ne me sert qu'a sauvegarder des variable de réglage genre temperature de consigne donc je ne la solicite que trés peut.

pour le shield ethernet , j'uttilise une macro (enfin je croi que c'est comme sa que l'on dit ) qui permet d'aprés ce que j'ai compris de stocker en ROM plutot qu'en RAM du type :
Code:
P(messagesModE) =
      "<h1>Modulation eclairage</h1>"
      "<form action=' http://x/x' method='POST'>"
      "<p><button name='ModE' value='1'>ON </button><button name='ModE' value='2'>auto</button><button name='ModE' value='0'>OFF</button></p></form>";

server.printP(messagesModE);

mais sinon mon sketch fait pour le moment 93000 octets pour 3194 lignes je sait pas si sa fait beaucoup !
Logged


Region ile de france.
Offline Offline
Sr. Member
****
Karma: 3
Posts: 402
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


Quand on utilise que quelques fonctions d'un composant, il est préférable de reprendre la fraction de code intéressante que de charger toute la lib (c'est long, mais on sait exactement ce que fait la fonction)
 
Note que puisque tu utilises l'écran MI0283QT2 (excellent choix) qui est tactile, tu pourrais soulager la conso de ton système en le mettant OFF (affichage et calcul de toutes les fonctions) au bout de quelques secondes d'inactivité et en le réactivant au premier toucher.

j'imagine q'effectivement je pourrait juste prendre une partie du code des librairie mais je ne maîtrise pas encore asser le sujet pour me lancer a vrai dire! et pour le moment comme j'utilise la mega j'ai encore de la place en mémoire , mais il faudra que je face sa car sa me permettra de mieux comprendre en retouchant juste certaine partie!

pour l’écran j'y avais penser mais je ne l'ai pas encore mis en pratique (je n'ai  pas encore réfléchie a la mise off).
Logged


Offline Offline
Full Member
***
Karma: 0
Posts: 101
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Utiliser le plus possible le renvoie de variable (état, température, compteur, etc) sur serial via une fonction c'est plus facile à activer et désactiver avec un bool avant le setup.
Pour économiser en ressources mémoire et processeur il vaut mieux procéder via la compilation conditionnelle (#define) pour activer/désactiver le debug via Serial.println()
Ainsi lors de la compilation, si le #define n'est pas présent (ou en commentaire) ce code n'est pas inclus dans le code compilé.

Code:
En début de sketch:
#define DEBUG_SERIAL //commenter cette ligne pour désactiver tout log sur le port série

dans setup():
#ifdef DEBUG_SERIAL //ce qui entre cette ligne et le #endif n'est compilé que si DEBUG_SERIAL est défini
Serial.begin(9600);
#endif  

et partout où j'envoie des logs:
#ifdef DEBUG_SERIAL
Serial.println("une trace");
#endif

J'ai aussi d'autres defines pour activer/désactiver des infos de log spécifiques selon les composants de mon sketch que je veux tracer

Merci pour le truc.

Mais je trouve que cela fait beaucoup de parasitage pour la lecture du code.
Ne vaut il pas mieux mettre ça dans une fonction et de l'appeler à chaque fois ?

(Ne pas tenir comptes des erreurs de syntaxe)
Code:
MafonctionDbg (MaTrace) {
#ifdef DEBUG_SERIAL
Serial.println(MaTrace);
#endif
}



Logged

- 1 mega 2560
- 1 Raspeberry Pi (en pré-commande)
- Quarante douze PC
- beaucoup de volonté, pas beaucoup de temps.
- Ma religion : OpenSour

Ile-de-France (92 sud), France
Offline Offline
Edison Member
*
Karma: 24
Posts: 2055
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Serial.print() prend beaucoup de type de variable différent en paramètre.
C'est une fonctionnalité du C++ qu'on appelle la surcharge qui permet de créer plusieurs fonctions qui ont le même nom mais dont les paramètres sont différents.
Ainsi si tu veut aller dans le sens que tu indique il va te falloir créer :

Code:
MafonctionDbg ( int MaTraceInt )
{
#ifdef DEBUG_SERIAL
Serial.println(MaTraceInt);
#endif
}

MafonctionDbg ( unsigned int MaTraceUnisgnedInt )
{
#ifdef DEBUG_SERIAL
Serial.println(MaTraceUnisgnedInt);
#endif
}

etc ... pour chaque type possible afin de recréer la même possibilités que Serial.print()
Important car en C/C++ les paramètres d'une fonctions sont impérativement typée.

Ensuite un des inconvénients de ta méthode c'est que quand tu désactive le debug, tu continue a appeler ta fonction. Même si celle-ci ne fait plus rien, le fait d'appeller la fonction, de ne rien faire et de ressortir va prendre du temps pour rien.

Une autre possibilité c'est de faire par exemple :

Code:
// Mettre le commentaire devant la 1ere ligne pour désactiver le code de debug ou devant la 2nde ligne pour activer
#define DEBUG(a) ##a
//#define DEBUG(a) {}


void QuelQuePart( int val )
{
 //....
  DEBUG( Serial.println("Bonjour ceci est une trace de debug..." ) );
  DEBUG( Serial.print("val = " ) );
  DEBUG( Serial.println( val ) );
}

Intérêt : tu peux aussi mettre dans DEBUG des instructions autres que Serial :

Code:
void Ailleurs( )
{
  DEBUG( int comptageErreurs = 0 );
  for ( int i = 0 ; i < 10 ; i++ )
  {
     int data = digitalRead( PIN );
     DEBUG( if ( data = LOW ) ++comptageErreurs );
  }
  DEBUG( Serial.print( "Nombre d'erreurs : " ) );
  DEBUG( Serial.println( comptageErreurs ) );
}

Encore une autre possibilité :

Code:
// Mettre 0 pour le mode normal et 1 pour le mode debug
#if 1
#define  DEBUGPRINT(a)        Serial.print(##a)
#define  DEBUGPRINTLN(a)    Serial.println(##a)
#else
#define  DEBUGPRINT(a)        {}
#define  DEBUGPRINTLN(a)    {}
#endif

void LaBas( int ici )
{
  DEBUGPRINT( "On est " );
  DEBUGPRINT( ici );
}

A+

« Last Edit: July 06, 2012, 04:49:49 pm by barbudor » Logged

Barbuduino: Arduino sur Breadboard & VinciDuino: Clone Leonardo // WR703: Mini-routeur hacké // LauchPad MSP430 et Stellaris // Panda II Arduino-like .NetMF sous VisualC#
RTFC: Read That F.....g Code / RTFD: Read That F.....g Doc / RTFDS: Read That F.....g DataSheet / RTFS: Read That F.....g Schematic / Wot da ya wanna D.I.Y. today ?

Region ile de france.
Offline Offline
Sr. Member
****
Karma: 3
Posts: 402
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

j' pour le moment opter pour #ifdefine debug qu e je ne conaisait pas est sa marche nikel j'essairai ta méthode aussi barbudor ,
sinon j'ai tester la mémoire avec freememory() et il m'indique 1560 j'imagine que se sont les octets donc sa va il m'en reste pas mal puisqu'il y en a 2000 si je ne m'abuse!

malgré avoir fait tourner mon soft toute la nuit la mémoire dispo reste inchanger , par contre mon serial semble c'etre bloqué a 21h40 la dernier ligne et constituer sur le serial de rectangle les un a coté des autre puis plus rien!!
et mon lcd a 00h36 (moment ou tout reste figer après , complètement planter).

je refait tourner mon programme avec le debug désactiver pour voir!
Logged


Offline Offline
Full Member
***
Karma: 0
Posts: 224
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Salut,

Personnellement je suis adepte des assertions. Elles permettent de vérifier qu'une condition est bien remplie. Dans le cas contraire, le programme s'arrête. Cela permet de tester qu'une valeur est bien comprise entre deux bornes, qu'un pointeur n'est pas nul, qu'une fonction est bien initialisée, etc...

Par défaut avec AVR-GCC (et donc Arduino), si la condition n'est pas remplie le programme s'arrête sans donner plus d'informations. Mais il est possible de redéfinir le comportement de l'assertion pour récupérer des informations capitales pour déboguer : fichier, fonction, ligne.

Si par exemple on utilise le sketch ci-dessous, la led va clignoter 3 fois puis l'instruction assert(false); va provoquer l'arrêt du programme :
Code:
/*
    Blink

    Turns on an LED on for one second, then off for one second, repeatedly.

    This example code is in the public domain.
 */
 
#define __ASSERT_USE_STDERR
 
#include <assert.h>
 
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;

// the setup routine runs once when you press reset:
void setup() {               
    // initialize the digital pin as an output.
    pinMode(led, OUTPUT); 

    Serial.begin(9600);
}

// the loop routine runs over and over again forever:
void loop() {
    for (uint8_t i = 0; i < 3; i++)
    {
        digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
        delay(1000);               // wait for a second
        digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
        delay(1000);               // wait for a second
    }
   
    assert(false);
}

//
void __assert(const char *__func, const char *__file, int __lineno, const char *__sexp){
    Serial.println(__func);
    Serial.println(__file);
    Serial.println(__lineno, DEC);
    Serial.println(__sexp);
    Serial.flush();
    abort();
}

Et quelques informations sont envoyées sur la liaison série :
Quote
loop
C:\Users\Julien\AppData\Local\Temp\build2705207067362707197.tmp\Blink.cpp
38
false

On peut voir que le programme s'est arrêté dans la fonction loop, ligne 38 du fichier blink.cpp (pas le fichier blink.ino !).
Logged


Region ile de france.
Offline Offline
Sr. Member
****
Karma: 3
Posts: 402
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Dans mon cas j'ai peut-être trouvé la source de mon problème : c'est soit le serial qui plante au bout d'un certain temps soit l'arduino a trop chaud en tout cas la partie régulateur de tension a l'entré de la carte devient bouillant , pourtant j'ai acheter une petite alimentation a découpage calibré a 12V je pensait que sa irais mais si je pose le doit dessus ouch sa brûle!!!

la mon système tourne en continu depuis samedi midi sans aucun bug, pour cela j'ai surélever la carte arduino et j'ai commenter la ligne de
# define SERIAL DEBUG
donc ce soir je tente de le faire planter en de-commentant le serial debug!!
Logged


Pages: [1] 2   Go Up
Jump to: