Go Down

Topic: Arduino MEGA qui se dégrade physiquement ? Erreur Timer ?WDT? Incompréhensible ! (Read 4897 times) previous topic - next topic

teji

Bonjour à tous,
C'est avec un problème vraiment étrange et INCROYABLE que j'arrive vers vous ! Cela fait quelques années que je programme avec arduino...
Pour faire court, dans un projet "domotique" personnel, j'ai fait un INO de gestion de l'alarme/caméra IP/lumières/interrupteurs/chauffage.
Rien de merveilleux, c'est assez "générique"...
Voici le problème : le projet a tourné plusieurs mois (au moins 3 mois) sans aucune erreur ni crash. Un jour, tout bloqué, mort.
Je me dis que le MEGA2560r3 est mort, je le change, ça redémarre.
Sauf que 1 mois après, rebelotte, mort, je change le mega, ca redemarre.
Jusque là, je pourrais avoir fait une erreur "hardware"... Mais ça va être pire.
Comme j'ai rapidement eu une 3eme fois le problème, je cherche. je reprends sur le bureau le mega 1 & 2, sensés être morts.
ce que je découvre dépasse toutes les bizareries que j'ai pu voir en 20 ans de microcontrolleurs.
Si je mets un programme d'exemple dans les méga morts, cela fonctionne.
ça pourrait laisser croire que mon programme est buggué. (mais pourquoi aurait-il tourné plusieurs mois sans problèmes ?)
Pire ! : Mon programme compilé fait actuellement +/- 63.000 octets. Si j'enlève n'importe quelle partie de programme pour que la version compilée soit plus petite (58.000 octets), cela fonctionne !!!!! peut importe ce que j'enlève. J'ai même enlevé des lignes inutiles (gestions de certaines pages dans le webserveur embarqué), et le soft démarre sans, mais pas avec. Peu importe le bloc que j'enlève, ça fonctionne !
Pire, au bout de plusieurs chipotages (programme complet/programme "coupé"), un des méga "mort" tourne avec le programme complet !!! incompréhensible !!!  :smiley-eek-blue:
je tourne fou. et je ne peux pas changer de mega tous les 2 mois, avec toute la maison qui s'arrete !
Bon... plus de détails :
- en gros, c'est un méga 2560R3 + ETH r3 connecté par I2C à un module RTC et une board I/O Velleman, connecté via RS485 à des modules DMX (dimmers digitaux), avec les entrées analog qui monitorent les détecteurs alarme, et qq sorties qui font du PWM pour des leds incrustées dans les murs. Via l'IP (qui controle la position des caméras IP en fct de l'alarme), on peut aussi monitorer et régler grossièrement le tout ou consulter les logs enregistrés sur la SD du shield ETH.
- j'utilise le WDT, ,donc je reflashe mes méga avec le bootloader 1.04 pour éviter les bugs d'upload et de WDT connus dans les versions antérieures des bootloader qu'on reçoit d'usine
-j'utilise bcp de libraires ajoutés : simpleDMX, DS1307rtc, memoryfree, Queue, et Time. Je me demande parfois s'il n'y a pas un problème d'utilisation d'un timer par plusieurs de ces librairies. Mais alors, ça devrait redémarrer après un reset (soft ou hard power off/on)
- je stocke dans l'eeprom interne certains valeurs "live" (secondes de chauffage par jour, valeurs des groupes de lampes...) ce qui doit représenter 200 écritures EEPROM / jour et peut-être autant de lectures... Est-ce que détériorerais le CPU sensé résister à 1.000.000 de cycles ? Je fais une pause de 2ms après chaque lecture/ecriture, par sécurité....
- J'utilise un ETH shield pour la connection réseau vers caméras IP et webserveur interne ainsi que pour stocker sur une microSD le log de tout ce qui se passe (chauffage, alarme, interrupteurs, lampes).... Quand un mega a l'air mort, j'ai des doutes sur :
        * L'usage simultané de SD&ETH : l'écriture lors du boot sur la SD semble etre refusée ou bloquée, ça varie...
        * le WDT : on dirait que ça boot, mais que mon WDT (8S) redémarre le systeme... mais alors, pourquoi cela fonctionne avec le même soft un peu plus court ???? et avec le soft long sur un mega neuf ?
- La librairie "Queue" qui permet de scheduler des jobs toutes les X millisecondes est très utile, au début, en désactivant des jobs, ça redémarrait, mais je me suis vite rendu compte que c'est juste la diminution de taille du programme compilé qui faisait accepter le projet, puisque quand j'enlève des lignes de codes liées à des pages web que je ne consulte pas, cela fonctionne aussi (balisées par un IF que je suis sûr qui reste FALSE tout le temps)... Mais c'est là que j'ai eu un doute sur l'usage des timers... SimpleDMX semble utiliser un timer, queue aussi, et si il y avait un double usage ? cela redémarrerais avec un reset...

Je suis complètement perplexe devant ces infos, et ces erreurs... Quelqu'un aurait-il une idée, une voir de recherche, une expérience similaire ?
D'avance un grand merci pour votre éventuelle réponse !
Long Live to Arduino Community ! ;-)

barbudor

Si je comprend bien,  nous ne sommes pas dans le cas d'un bug dans des lignes de code qui ne s'executent que les 29 février à  24h01.

Si tu reset ta carte, elle ne démarre plus du tout?
Elle n'arrive même pas dans le setup?

Il ne faut pas oublier que de nombreuses lib en C++ nous demande de créer des objets en variables globales. Dans ce cas, le code des constructeurs s'exécute _avant_ main/setup. Donc beaucoup de choses se passent avant même d'arriver dans setup.

Il faudrait trouver un moyen de tracer ce qui se passe au démarrage.

Par ailleurs je pense que tu fais un usage excessif de l'EEPROM. 1M de cycles c'est pour la flash il me semble. L'EEPROM devrait être plus faible. Mais je n'ai pas d'experience sur le sujet.
Pour un stockage récurrent,  je suggère de passer à un stockage externe I2C/SPI: mieux vaut cramer et changer un dip8 externe qu'une Atmega.

Christian_R


je stocke dans l'eeprom interne certains valeurs "live" (..) 200 écritures EEPROM / jour  (...) Est-ce que détériorerais le CPU sensé résister à 1.000.000 de cycles ?

A première vue je pense pourtant à une défaillance de l'EPROM.

L'utilisation quotidienne trop répétée de l'Eprom en lecture/écriture peut finir par planter la carte.
http://forum.arduino.cc/index.php?topic=116057.5

C'est pas plutôt 100 000 cycles la limite ?  http://forum.arduino.cc/index.php?topic=76982.0
Christian

Artouste

Bonjour je pense aussi à un probleme d'eeprom
il y a chez microchip un doc et soft permettant de determiner +/- le nb de cycles
meme si ça ne concerne pas les atmel , ça reste quand meme didactique sur l'impact des parametres.

le tuto
http://www.microchip.com/stellent/groups/SiteComm_sg/documents/Training_Tutorials/en532276.pdf

le soft+doc
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010003

Quelle quantité d'eeprom utilise tu pour tes sauvegarde 200 fois jours ?
comme tu utilise un ds1307 tu a aussi si c'est suffisant d'utiliser la ram de la RTC , il y a 56 byte dispo de ram sauvegardé par batterie

B@tto

A mon avis EEPROM aussi : c'est 100 000 écritures et pas 1 000 000 (et encore il faut voir ça comme la durée de vie annoncée des ampoules, des fois ça pète avant ...). Ce qui donne 500 jours de vie.

Essaye de relancer une MEGA morte en changeant tes adresses en EEPROM
Blog électronique : battomicro.wordpress.com
Photographie : www.interactive-celebration.fr
Fablab de Montpellier : www.labsud.org

fdufnews

La doc Atmel dit ça:
Write/Erase Cycles:10,000 Flash/100,000 EEPROM
Donc c'est bien 100000 cycles pour l'EEPROM

La technologie EEPROM n'est pas adaptée à ce genre de besoin. Elle est plutôt prévue pour du paramétrage. Donc nombre d'écriture réduit.
Pour un nombre important de cycles d'écritures, il est préférable de partir sur des techno comme la NVRAM qui utilise une RAM avec une Flash en cache. La lecture/écriture se fait dans la RAM et le transfert vers la Flash est automatique à la coupure de l'alimentation.

Si tu veux rester avec l'EEPROM de ton ATMega, il faut déplacer périodiquement le bloc dans lequel tu écris de façon à ne pas atteindre trop tôt le nombre de 100000 écritures.

Super_Cinci

il est clair que tu ustilises abusivement l'EEPROM. (n'utiliserais-tu pas par hasard la flash pour tes chaînes de caractères?)

On dit 100 000 cycles, mais si j'écris dans la même adresse toutes les millisecondes, je doute que ça tienne 1"40. il y a assez de ram dans la méga pour n'utiliser que la ram, et dans le même principe que la NVRAM, ne sauvegarder en EEPROM que lorce que c'est vraiment nécessaire ;)

bricoleau

Quelques idées, au cas où cela puisse t'aider :

Si c'est un pb d'EEPROM cramée il me semble que tu dois pouvoir le vérifier sur ta première MEGA, via un script spécifique de tests de lecture / ecriture.

Après, tes symptômes de taille de code proche de 64k (2^16) me font penser à un problème d'adressage de la mémoire flash.
Tes 63000 octets de code ne sont peut-être pas les seuls à occuper de la flash, et du coup tu te retrouves avec certaines instructions ou données présentes au delà de 64k, qui nécessitent en théorie un adressage sur plus de 16 bits.
Mais là je ne suis pas assez calé en arduino pour creuser les hypothèses d'explication (compilo, PROGMEM, gestion des adresses flash..)

Enfin, ton symptôme "plusieurs mois OK puis boum" ne pourrait-il pas être lié au roll over de millis(), 49 jours et 17h après le boot, qui fait dérailler le code quelquepart au niveau de ton scheduler ? Suivi par exemple d'un code qui boucle sur des écritures en EEPROM.

bricoleau

Petit complément sur l'adressage flash : le bootloader occupe lui-même une partie de la flash (8 ko indiqués dans la doc arduino pour une MEGA2560 & le bootloader standard).
Donc je sens bien un problème lié à de l'adressage long (> 64k).
Est-ce que tu utilises pgmspace/PROGMEM ? Si oui, il y a peut-être des subtilités à prendre en compte dans les adressages.


teji

Bonjour à tous, et merci pour vos réponses, que je décortique les unes après les autres, ... je vous répond ci dessous à chacun, en vous remerciant encore d'ailleurs...
- Barbudor : Si, la carte démarre encore, mais j'ai des crashs. Deux types de crash : soit la carte SD qui ne s'initialise pas (le begin qui fail) suivi d'un reboot, soit un arret net du code (j'ai des point de passage visibles dans l'init, mais c'est après, et la boucle étant rapide c'est difficile à monitorer) qui provoque un WDT reset ....
- Artouste : J'utilise beaucoup de données dans l'EEPROM : sans vous saouler de détails, j'ai 24 canaux de dimmers. 14 groupes de lamps. chacun des groupes de lampe peut avoir une "position" représentant une mémorisation des états des lampes du groupe. (6 mémoires). chaque mémoire de chaque canal doit mémoriser la valeur du canal, le canal et la vitesse de variation. ce qui nous donne 14groupes x 9 canaux x 6 memoires x 3 octets = 2268 octets ;-) Ces configurations sot visibles/modifiables via l'interface web. A chaque changement de mémoire, on lit les valeurs à assigner au groupe (et donc aux canaux)... le nombre de lecture n'est pas limité je pense... Puis on écrit la nouvelle valeur de la mémoire du groupe qu'on vient de changer (EX GR1=mem3). Comme sans, en cas de reboot (wdt, parasite, panne de courant...), le systeme recharge de l'EEPROM la valeur de chaque groupe, et les lampes sont remise à leur valeur avant la panne. très pratique à en juger par les RESET que je retrouve de temps à autre sur les logs dans la SD ;-)  L'autre type d'écriture concerne 4 bytes, toujours les meme, qui sont un compteur de secondes de feu de ma chaudière (puisque injection constante, le nombre de seconde de feu reflète la consommation). quanc ça brule, je mets ce compteur à jour toutes les 10 secondes. ayant max 1h de feu par jour actuellement, cela représente 360 write de 4 octets.  par jour. plus les changements d'interrupteur, je dirais 50 par jour, donc 50 ecritures de 1 octet. même à 100.000 cycles, ça devrait tenir ... ça dépend comment on compte... si 1 octet est un cycle, sans tenir compte de ""100.000 fois le meme octet"... on a 100.000 / ((360x4)+50) = 67 jours, ... ça c'est plaisible.... Je pourrais néanmoins stocker les 14 octets de valeur de groupe et les  octets du compteur de feu dans le module 1307 et ses 56 bytes de ram. si je perds les groupes, pas trop trop grave, et si je perd le compteurs (ce ui arrive quand je dois changer de mega), l'interface web me permet de ré-ecrire une valeur, et je prends la dernière venant de la dernière ligne des log files de la SD (je log tout dans des fichiers nommé en date du jour, consultables via interface web)
-fdufnews : ça serait une bonne solution une NV ram i2c qui sauvegarde en flash quand il y a une coupure ! tu conseille une référence particulière (min 4ko) ?
-SuperCinci : oui, ce serait aussi une idée : laisser mes tableaux de config en EEPROM (ça ne change jamais, ou presque), et garder mes valeurs de groupes et de compteur de feu en RAM. il faudrait pouvoir détecter une coupure et sauvegarder...  Mais dans ce cas, un crash, un WDT reset, et ma maison se retrouve dans le noir ! ;-) la solution de la NV ram backupée me séduit plus...
-bricoleau : j'y ai pensé, c'est pour cela que je tenais au WDT + sauvegarde. en me doutant qu'un jour ou l'autre, il y aurait un problème liée à la durée de run et à un débordement ou l'autre... mais ça doit redémarrer dans ce cas ! et ici, ça redémarre, et lors du boot (visible avec les détails de débug sur l'usb/serial) ça plante, alors qu'il n'y a aucun EEPROM.write lors du boot (mais bien des EEPROM.read)... ceci dir, si l'eeprom pose problème, peut-être que ça crashe lors de la lacture une fois qu'elle est "abîmée".... J'ai un code qui write le tableau de config (valeurs des memoires/groupes...) "par défaut" pour mes nouveaux MEGA... je vais effectivement l'essayer sur un mega mort. mais ce code fait plus que 63.000 octets... je devrais peut-être faire un validateur de eeprom (qui lit/write 4x chaque octet des 4K) et voir si ça bloque, et où (les octets souvent écrits ?) ou quand (x lectures...)... et pas de PROGMEM utilisé... par contre bcp de print(F("xxxx")) qui stockent le texte en flash plutot que ram... mais ce n'est que des accès read... qui ne sont pas comptés....

J'avais eu une sale impression avec la cohabitation SD/eth au départ... puique cela semblait vloquer lors d'écriture d'un log txt ou lors du BEGIN sd ... mais pourquoi après X temps ? j'ai essaye les méga morts en changeant de SD, c'est pas lié. j'ai mis un autre ETH shield sur un mega mort, sans succès non plus.... le seul truc qui "pase" est un prog plus petit.... dingue.
Maintenant, effectivement, si l'EEPROM est abimée, peutêtre que la structure interne du cpu foire, donnant des résutlats imprévisibles sur l'addressage en général ...
je voudrais m'orienter sur la solution NVram externe sauvegardée, ou sur la solution tableau de config en eeprom, valeurs souvent modifiées (18 octets) en ram du DS1307.... avec un mega neuf, et puis "attendre" pour voir !


Artouste



je voudrais m'orienter sur la solution NVram externe sauvegardée, ou sur la solution tableau de config en eeprom, valeurs souvent modifiées (18 octets) en ram du DS1307.... avec un mega neuf, et puis "attendre" pour voir !



tu a 56 byte dispo sur  le DS1307 a partir de l'adresse 08H , , tu n'a rien à ajouter modifier en hard, juste un peu de soft à tripoter

barbudor

Quand tu reflashes le programme complet, il repart normalement ou bien il replante à l'identique ?
Je pense a des corruptions de la flash qui pourrait venir de problèmes d'alim (des pics sur l'alims pourraient veroler la flash).

fdufnews

Quote
-fdufnews : ça serait une bonne solution une NV ram i2c qui sauvegarde en flash quand il y a une coupure ! tu conseille une référence particulière (min 4ko) ?


http://www.cypress.com/?id=3489

Super_Cinci

Je vois mieux maintenant ton besoin : sauvegarder le plus souvent possible pour ne rien perdre en cas de crash.

Donc la solution NVRAM, en effet, serait bien simple. Il y a une autre solution (même principe que la NVRAM) que j'ai prévue de mettre en place (un jour), pour une électronique embarquée dans mon automobile : il y a une batterie, donc une alim permanente. Je ne travaillerais qu'avec la RAM, et quand on coupe le contact, je balance tout dans l'EEPROM en utilisant l'alim permanente, puis je coupe l'alimentation du proc (l'arduino gère lui-même son alimentation en gros, via un relais et une détection de coupure de l'alim "contact"). Tu pourrais utiliser une batterie ou un énorme condensateur pour te permettre d'avoir le temps de sauvegarder... C'est aussi compatible avec le WDT, au lieu de faire un reset, il lance la void de sauvegarde puis fait un reset...

B@tto

Ca marchera sans problème avec un petit accu. En plus avec une Arduino et un mosfet, on peut facilement piloter la recharge pour faire durer l'accu très longtemps.
Blog électronique : battomicro.wordpress.com
Photographie : www.interactive-celebration.fr
Fablab de Montpellier : www.labsud.org

Go Up