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.
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:
#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 ...)
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 Arduino Playground - AvailableMemory)
OLIVIERC67:
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é.
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
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)
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.
Heloderma-kris:
c'est quoi timestamp?
c'est le temps de la RTC par exemple ou une librairie particulière?
C'est effectivement un marquage temporel.
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.
fdufnews:
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 :
Marc56:
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).
OLIVIERC67:
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é.
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 ?
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 :
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 :
// 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 :
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é :
// 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 );
}
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!
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 :
/*
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 :
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!!
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!!!
Il doit bien y avoir une centaine de post sur le sujet. Lorsqu'on utilise une alim 12V le régulateur chauffe un maximum. Il est de loin préférable de se limiter à la plage 7 à 9V pour l'alimentation externe. Maintenant si tu es obligé d'utiliser du 12V rien ne t'empêche de placer un petit dissipateur sur le régulateur.
oui je vais regardez sur l'idée du dissipateur car a priori j'ai pas trouver d'alimentation 9V pour le moment qui coresponde a mes critére!
de toute magniere j'ai besoin de 12V pour la carte a relais.
bonsoir
en complément de la réponse de barbudor
tu mets un 7808 genre ça
tu reste en bas de gamme de regul pour l'arduino et un peu au dessus de la limite basse du régulateur embarqué , (moins de dissipation thermique à gerer pour l'arduino).
ne pas oublier que l'arduino est une base de prototypage, et comme tout le monde il a besoin d'air
tu peu aussi en plus , penser à une voie de convection naturelle pour optimiser passivement le refroidissement
bon j'ai tester hier soir et cette nuit ce n'est pas le fait que mon régulateur chauffe qui fait planter mon système j'en déduit que c'est mon serial qui sen charge !
pour barbudor : oui j'ai besoins du 12v pour alimenter la carte a relais et sinon le 5v me sert pour les shields et l'ecrant qui me semble et aussi en 5V
pour artouste : merci pour le régulateur , mais la va falloir que je vois avec le paternel car l’électronique pour l'instant ce limite a utiliser des résistance et des led pour pour moi , mais je vais voir pour mètre des entre toise pour sur élever la carte dans un premier temps