Jump to content
ELFORUM - Forumul electronistilor
Cilibiu

Watch dog nu lucreaza corect

Recommended Posts

Salut tuturor.

Folosesc de foarte mult timp Arduino, dar in cea mai mare parte folosesc programare BASIC pentru ATMEL.

De ceva vreme am inceput sa fac proiecte care necesita sa fie "online" permanent.

In basic am folosit WD si nu am avut probleme.

In schimb cand folosesc WD la placile de arduino lucrurile se schimba.

Cel mai stabil WD gasit pe gogu si testat este cel de mai jos.

Totusi am probleme si cu acesta.

Ca sa fiu sigur ca WD reseteaza de fiecare data, am folosit codul de mai jos in BLINK LED, mai exact daca se blocheaza sa reseteze MCU, insa dupa cateva saptamani tot sa blocat MCU.

Am zis sa fac alt experiment, si am pus un delay de 6 secunde in cod-ul de blink led, WD setat la 2 secunde.

La fiecare 2 secunde se restarta MCU, asa ca lam lasat sa vad cand se blocheaza, am fost uimit cand am vazut ca dupa 7 ore sa blocat MCU.

Cum se poate asa ceva?

Cod WD folosit aici.

#include <avr/wdt.h> //Watch dog timer functions

// Pin 13 has an LED connected on most Arduino boards.
int led = 13;

void setup() {
  wdt_disable(); //Datasheet recommends disabling WDT right away in case of low probabibliy event
  pinMode(led, OUTPUT); //set up the LED pin to output
  pinMode(2,INPUT_PULLUP); //setup pin 2 for input since we will be using it with our button
  setWDT(0b00001000); //set for reset
}

void loop() {
  delay(500);
   digitalWrite(led, HIGH);    // turn the LED off by making the voltage LOW
    wdt_reset(); //Reset the WDT 
delay(6000);
}

//this function setups up and starts the watchdog timer
void setWDT(byte sWDT) {
   WDTCSR |= 0b00011000;
   WDTCSR = sWDT |  WDTO_2S; //Set WDT based user setting and for 2 second interval
   wdt_reset();
}

 

 

Edited by Cilibiu
Link to post
Share on other sites

delay() este o funcţie blocking, cât timp rulează nu mai merge nimic în fundal. Dacă ai nevoie de temporizări foloseşti millis() sau mai bine un contor separat bazat pe Timer1, millis() se dă peste cap la fiecare câteva săptămâni şi dacă ai ceva care merge non-stop se poate bloca la tranziţiile astea.

Link to post
Share on other sites

millis()

[Time]

Description

Returns the number of milliseconds passed since the Arduino board began running the current program. This number will overflow (go back to zero), after approximately 50 days.

 

Deci ar trebui sa folosesc: millis(1000) in loc de delay(1000) ?

Sunt curios, fac testul sa vad.

In foarte multe coduri folosesc delay, deci voi avea ceva de lucru sa inlocuiesc cu millis().

Totusi mai sus zice ca se reseteaza dupa aproximatic 50 zile!

Link to post
Share on other sites

Intreruperea WDT ar trebui sa actioneze in cazul in care e setata la 2s si ceva obliga programul sa ruleze 6s. 

 

Nu cunosc codul postat, asa ca nu ma pot pronunta daca e bine setata intreruperea WDT. 

Link to post
Share on other sites

millis() e un contor ce se incrementează permanent, temporizările se referă la comparaţii între valorile instantanee ale millis().

De ex. ai aşa

unsigned long now = millis(); // variabila now ia valoarea instantanee a lui millis()

după un tmp faci 

unsigned long then = millis() //variabila then primeşte altă valoare, mai mare

deci poţi face o comparaţie gen

if (millis() - now > 1000) ......  codul de executat 

deci dacă au trecut 1000ms se execută codul respectiv

Link to post
Share on other sites
Posted (edited)
Acum 28 minute, Liviu.Mihaiu a spus:

@Cilibiu
Hai sa o luam incet.
Ai idee ce face functia loop() ?

 

Aici se scrie programul ce va rula continuu! in basic ai DO>>LOOP.

Acum 23 minute, mihaicozac a spus:

millis() e un contor ce se incrementează permanent, temporizările se referă la comparaţii între valorile instantanee ale millis().

De ex. ai aşa

unsigned long now = millis(); // variabila now ia valoarea instantanee a lui millis()

după un tmp faci 

unsigned long then = millis() //variabila then primeşte altă valoare, mai mare

deci poţi face o comparaţie gen

if (millis() - now > 1000) ......  codul de executat 

deci dacă au trecut 1000ms se execută codul respectiv

Deci sa inteleg ca eu trebuie sa compar o valoare aleasa de mine cu mills().

 if (millis() > 3000) {
   wdt_reset(); //Reset the WDT 
   }

Adica doar dupa 3 secunde va reseta WD. (dar nu va apuca) si WD va reseta MCU.

 

L.E

Am pus 2 coduri pe doua placi arduino sa vedem care se blocheaza si dupa cat timp.

Primul arduino are codul acesta:

#include <avr/wdt.h> //Watch dog timer functions

// Pin 13 has an LED connected on most Arduino boards.
int led = 13;

void setup() {
  wdt_disable(); //Datasheet recommends disabling WDT right away in case of low probabibliy event
  pinMode(led, OUTPUT); //set up the LED pin to output
  pinMode(2,INPUT_PULLUP); //setup pin 2 for input since we will be using it with our button
  setWDT(0b00001000); //set for reset
}

void loop() {
  digitalWrite(led, HIGH);    // turn the LED off by making the voltage LOW
   
   if (millis() > 3000) {
   wdt_reset(); //Reset the WDT 
   }
   
}

//this function setups up and starts the watchdog timer
void setWDT(byte sWDT) {
   WDTCSR |= 0b00011000;
   WDTCSR = sWDT |  WDTO_2S; //Set WDT based user setting and for 2 second interval
   wdt_reset();
}

Iar al doi-lea are codul acesta:

#include <avr/wdt.h> //Watch dog timer functions

// Pin 13 has an LED connected on most Arduino boards.
int led = 13;

void setup() {
  wdt_disable(); //Datasheet recommends disabling WDT right away in case of low probabibliy event
  pinMode(led, OUTPUT); //set up the LED pin to output
  pinMode(2,INPUT_PULLUP); //setup pin 2 for input since we will be using it with our button
  setWDT(0b00001000); //set for reset
}

void loop() {
   delay(1500);
   wdt_reset(); //Reset the WDT 
   digitalWrite(led, HIGH);    // turn the LED off by making the voltage LOW
   delay(500);
   wdt_reset(); //Reset the WDT 
   digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
   delay(500);
   wdt_reset(); //Reset the WDT 
   digitalWrite(led, HIGH);    // turn the LED off by making the voltage LOW
   delay(500);
   wdt_reset(); //Reset the WDT 
   digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
   delay(500);
   wdt_reset(); //Reset the WDT 
   delay(1500);
   wdt_reset(); //Reset the WDT 
delay(3000);
}

//this function setups up and starts the watchdog timer
void setWDT(byte sWDT) {
   WDTCSR |= 0b00011000;
   WDTCSR = sWDT |  WDTO_2S; //Set WDT based user setting and for 2 second interval
   wdt_reset();
}

Le-am pus pe aceasi sursa si le-am dat drumul sa functioneze.

Sunt curios care se blocheaza si dupa cat timp.

 

Edited by Cilibiu
Link to post
Share on other sites

Programare nu fac prin incercari.

Am zeci de proiecte cu MCU atmega scrise in BASCOM.

Am cateva zeci de proiecte scrise in ARDUINO IDE dar nu sunt expert in programare C++, logica o am de la BASIC si PLC, C++ cunosc elementele de baza si ceva peste, dar nu avansat.

Toate proiectele mele au ca si baza "functionarea pentru perioade scurte (gen cateva ore) " la care nu am avut probleme cu proiectele cu arduino.

Mai dau cate un restart la interfonul de scara o data la 1-3 luni care lam facut cu arduino, cu acces cu tag cu scriere/citire in EEPROM nu dupa ID.

Proiecte cu ATMEGA scrise in BASCOM de lunga durata a fost la o alarma si monitorizare usa/miscare (proiect propriu) , la care se bloca programul o data sau de 2 ori in cel mai rau caz intr-un an. Chiar am avut aproape 2 ani fara nici un restart la MCU si memoria a fost ocupata 96% din ce imi aduc aminte (proiect facut in 2007 parca).

Acum lucrez la automatizare casa (propria casa), ca CPU folosesc PLC nu arduino sau atmega (din cauza posibilitati de FREZZE).

Programul PLC (scris in TIA15.1) ruleaza fara intrerupere de 8 luni fara nici un restart de PLC.

PLC comunica via TCP IP cu arduino+ethernet shield de unde preiau foarte multe informati de la mai multi senzori si dau comenzi catre diferite device-uri ( 2 luni a functionat ARDUINO fara restart), acum lucrez la inlocuirea ARDUINO cu NODEMCU_ESP8266 ca sa inlocuiesc tot ce am arduino cu ethernet shield, dar vreau sa imbunatatesc stabilitatea sau resetarea MCU daca se blocheaza, programul fiind facut sa trimita si sa citeasca date din PLC dar in asa fel ca daca se blocheaza sa nu observi ca se opreste centrala....apa....luminile....se deschid portile....sau alarma pe sitemul de supraveghere......etc.

Program e gandit ca tot ce folosesc sa aibe self switch, la lipsa de date sa nu o ia razna, iar daca se depaseste un anumit timp (in care ar fi trebuit sa reseteze WD si sa apara LIVE BIT)sa afisez alarma si sa trimit mesaj SMS catre OWNER  cu textul (ESP_exterior nu raspunde la comunicatie)!

Doar ca trebuie sa pun la punct WD, tinand cont ca ESP il programez cu arduino IDE.....trebuie sa fie ceva sigur!

 

Link to post
Share on other sites
Acum 4 ore, Cilibiu a spus:

Am zis sa fac alt experiment, si am pus un delay de 6 secunde in cod-ul de blink led, WD setat la 2 secunde.

La fiecare 2 secunde se restarta MCU, asa ca lam lasat sa vad cand se blocheaza, am fost uimit cand am vazut ca dupa 7 ore sa blocat MCU.

De unde stii ca s-a blocat? Ce nu face?

 

PS Poti face poza de la semnatura mai mica? Ocupa juma' de pagina.

Edited by Liviu M
Link to post
Share on other sites

Citeşte puţin documentaţia aferentă.

Millis() este o contor incrementat la fiecare milisecundă şi care porneşte de la zero după resetare. Deci după 1 secundă are valoarea 1000, după 2 secunde 2000 şi tot aşa. Fiind variabilă tip unsigned long adică 32 de biţi după 50 de zile se dă peste cap şi o ia din nou de la zero. De aceea temporizările sunt relative la valoarea instantanee a funcţiei.

 

Le din ce am citit în documentaţia Arduino un delay() resetează orice watchdog în derulare.

 

 

Edited by mihaicozac
Link to post
Share on other sites

Ai si un link la documentatia respectiva? La arduino.cc, de delay zic chiar ca lasa intreruperile in pace, da' nu zic nimic de watchdog.

 

Citat

Certain things do go on while the delay() function is controlling the Atmega chip, however, because the delay function does not disable interrupts. Serial communication that appears at the RX pin is recorded, PWM (analogWrite) values and pin states are maintained, and interrupts will work as they should.

 

Link to post
Share on other sites
Acum 27 minute, Liviu M a spus:

De unde stii ca s-a blocat? Ce nu face?

 

PS Poti face poza de la semnatura mai mica? Ocupa juma' de pagina.

1.Nu sa mai aprins led-ul.

Dupa ce am apasat butonul de reset al arduino-ului si-a revenit.

2.As face-o daca as sti si cum.

Semnatura a fost modificata in 2018, stiu ca era mica pe vremea aia, acum nu stiu de ce e asa mare.....

 

Link to post
Share on other sites

Si in ce parte din codul tau stingi LED-ul? Dupa cum descrii, watchdogul functioneaza prea bine.

Singurul lucru la care-mi vine sa ma gandesc dupa ce am aruncat un ochi in foaia de catalog a lui ATMega328, e paragraful:

Citat

Bit 4 - WDCE: Watchdog Change EnableThis bit is used in timed sequences for changing WDE and prescaler bits. To clear the WDE bit, and/or change the prescaler bits, WDCE must be set.Once written to one, hardware will clear WDCE after four clock cycles.

Dupa ce am mai citit si implementarea lui wdt in biblioteca arduino. as incerca sa modific putin functia setup:

 

#include <avr/wdt.h> //Watch dog timer functions

// Pin 13 has an LED connected on most Arduino boards.
int led = 13;

void setup() {
  wdt_disable(); //Datasheet recommends disabling WDT right away in case of low probabibliy event
  pinMode(led, OUTPUT); //set up the LED pin to output
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  pinMode(2,INPUT_PULLUP); //setup pin 2 for input since we will be using it with our button
//  setWDT(0b00001000); //set for reset
   wdt_enable(WDTO_2S);
   wdt_reset();

}

void loop() {
  delay(500);
   digitalWrite(led, HIGH);    // turn the LED on by making the voltage HIGH
    wdt_reset(); //Reset the WDT 
delay(6000);
}

 

PS Am adaugat si led = LOW in setup. Si am corectat comentariul

 

 

Edited by Liviu M
Link to post
Share on other sites

Led-ul se stinge la resetare MCU.

Motiv ca resetul avea loc, deci WD lucreaza, dar nu mai functioneaza programul.

Din ce vad eu ai comentat linia asta: 

setWDT(0b00001000); //set for reset

Am uitat sa sterg comentariile, eu nu le folosesc, de aceea nu erau corecte.

Stau acum si incerc sa gasesc logica ,ce se intampla in momentul cand se bloca MCU? cum afecta linia de cod incarcarea programului sau rularea lui?

 

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.Terms of Use si Guidelines