Cilibiu Postat Martie 13, 2021 Partajează Postat Martie 13, 2021 (editat) 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(); } Editat Martie 13, 2021 de Cilibiu Link spre comentariu
mihaicozac Postat Martie 13, 2021 Partajează Postat Martie 13, 2021 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 spre comentariu
Cilibiu Postat Martie 13, 2021 Autor Partajează Postat Martie 13, 2021 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 spre comentariu
Mircea Postat Martie 13, 2021 Partajează Postat Martie 13, 2021 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 spre comentariu
Vizitator Postat Martie 13, 2021 Partajează Postat Martie 13, 2021 @Cilibiu Hai sa o luam incet. Ai idee ce face functia loop() ? Link spre comentariu
mihaicozac Postat Martie 13, 2021 Partajează Postat Martie 13, 2021 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 spre comentariu
Cilibiu Postat Martie 13, 2021 Autor Partajează Postat Martie 13, 2021 (editat) 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. Editat Martie 13, 2021 de Cilibiu Link spre comentariu
Vizitator Postat Martie 13, 2021 Partajează Postat Martie 13, 2021 @Cilibiu Nu cred ca esti pe calea cea buna daca faci programare prin incercari. Nu-i pescuit. Eu ce sa zic. Bafta! Link spre comentariu
Cilibiu Postat Martie 13, 2021 Autor Partajează Postat Martie 13, 2021 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 spre comentariu
Liviu M Postat Martie 13, 2021 Partajează Postat Martie 13, 2021 (editat) 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. Editat Martie 13, 2021 de Liviu M Link spre comentariu
mihaicozac Postat Martie 13, 2021 Partajează Postat Martie 13, 2021 (editat) 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. Editat Martie 13, 2021 de mihaicozac Link spre comentariu
Liviu M Postat Martie 13, 2021 Partajează Postat Martie 13, 2021 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 spre comentariu
Cilibiu Postat Martie 13, 2021 Autor Partajează Postat Martie 13, 2021 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 spre comentariu
Liviu M Postat Martie 13, 2021 Partajează Postat Martie 13, 2021 (editat) 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 Editat Martie 13, 2021 de Liviu M Link spre comentariu
Cilibiu Postat Martie 13, 2021 Autor Partajează Postat Martie 13, 2021 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 spre comentariu
Postări Recomandate
Creează un cont sau autentifică-te pentru a adăuga comentariu
Trebuie să fi un membru pentru a putea lăsa un comentariu.
Creează un cont
Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!
Înregistrează un nou contAutentificare
Ai deja un cont? Autentifică-te aici.
Autentifică-te acum