Gilbert Sparios Postat Aprilie 17, 2022 Partajează Postat Aprilie 17, 2022 (editat) Am intr-o aplicatie, un Attiny85 printr-un NPN un releu (+flyback). Pentru alimentare, dintr-o sursa in comutatie de 12V alimentare pentru releu, si pentru 5V o alta sursa in comutatie reglata pe 5.01V. uC are in apropiere de alimentare 100nF+1000uF 16V, pe pinul de reset pull-up cu 10K. Softul este: /* Program: Controler ventilator baie, cu LDR uC Attiny85 8MHz, Optiboot */ #include <avr/io.h> #include <avr/wdt.h> #define LDR_PIN A2 #ifdef __AVR_ATtiny85__ #define RELAY_PIN 3 #else #define RELAY_PIN 13 #endif #define DELAYON 120*1000 // 2 minute delay on #define MAXIMUMRUN 3600000 uint32_t cMs = 0; uint32_t userStartTime = 0; uint32_t userTotalTime = 0; void setup() { pinMode(LDR_PIN, INPUT); pinMode(RELAY_PIN, OUTPUT); #ifdef __AVR_ATmega328P__ Serial.begin(9600); #endif #ifdef __AVR_ATtiny85__ if(MCUSR & _BV(WDRF)){ MCUSR &= ~_BV(WDRF); WDTCR |= (_BV(WDCE) | _BV(WDE)); WDTCR = 0x00; } wdt_enable (WDTO_2S); #endif } /*--------------------------------------------------------------------------------------------*/ byte readLDR(uint32_t interval, uint16_t cntRead, uint16_t triggerOn = 500, uint16_t histerizis = 50){ static uint32_t lstRdLDR = 0; static uint16_t cntReadLDR = 0; static uint16_t readLDRSum = 0; static byte result = 0; static byte old_result = 0; if((cMs-lstRdLDR)>interval){ if (cntReadLDR < cntRead) { readLDRSum += map(analogRead(LDR_PIN),1023,0,0,1023); cntReadLDR++; } else { readLDRSum = (uint16_t)(readLDRSum / cntReadLDR); if ((readLDRSum+histerizis) >= triggerOn) result = 1; if ((readLDRSum-histerizis) <= triggerOn) result = 0; #ifdef __AVR_ATmega328P__ Serial.print(F("cMs: ")); Serial.print(cMs); Serial.print(F(", readLDRSum: ")); Serial.print(readLDRSum); Serial.print(F(", userStartTime: ")); Serial.print(userStartTime); Serial.print(F(", userTotalTime: ")); Serial.println(userTotalTime); #endif readLDRSum = 0; cntReadLDR = 0; } lstRdLDR = cMs; } if (old_result != result) { if (result) userStartTime = cMs; if (!result) { userTotalTime = (cMs-userStartTime)+cMs; if (userTotalTime > (uint32_t)MAXIMUMRUN) userTotalTime = (uint32_t)MAXIMUMRUN; // do not run over 1hour } old_result = result; } return result; } /*--------------------------------------------------------------------------------------------*/ void loop() { #ifdef __AVR_ATtiny85__ wdt_reset (); //wathdog ! #endif cMs = millis(); byte presence = readLDR(50UL, 10,500,50); byte relState = 0; if (((presence) && ((cMs-userStartTime)>= (uint32_t)DELAYON)) || (cMs<=userTotalTime)) relState = 1; else relState = 0; digitalWrite(RELAY_PIN, relState); } Problema este ca se blocheaza adesea uC. Ce v-as ruga este sa va dati o parere referitor la soft, daca ar putea genera o eroare din soft sau se intampla ceva pe cablaj... Editat Aprilie 17, 2022 de Gilbert Sparios Link spre comentariu
Mircea Postat Aprilie 18, 2022 Partajează Postat Aprilie 18, 2022 Despre hardware e greu sa imi dau cu parerea. Insa, in soft se pare ce RESET-ul nu se face de catre WDT. Uite aici ceva despre WDIE, setare care lipseste din codul tau. Secventa asta: // Reset the watchdog reset flag MCUSR &= ~(1<<WDRF); // Start timed sequence WDTCR |= (1<<WDCE) | (1<<WDE); // Set new watchdog timeout value WDTCR = bb; // Enable interrupts instead of reset WDTCR |= _BV(WDIE); Daca ma insel, neintelegand codul tau, scuze. Link spre comentariu
nico_2010 Postat Aprilie 18, 2022 Partajează Postat Aprilie 18, 2022 Daca ai Optiboot pe ATTiny85 s-ar putea sa apara conflicte intre program si bootloader in ce priveste utilizare Watchdog! Parerea mea: scrie programul in C si verifica functionarea lui fara bootloader. Link spre comentariu
Liviu M Postat Aprilie 18, 2022 Partajează Postat Aprilie 18, 2022 Dacă pui un LED în loc de releu, se mai resetează? Am avut un montaj cu comportament asemănător și s-a potolit după ce am schimbat releul cu un triac. Link spre comentariu
Gilbert Sparios Postat Aprilie 18, 2022 Autor Partajează Postat Aprilie 18, 2022 (editat) O sa dau jos cutia din tavanul fals sa fac experimente. Cel mai probabil e situatia cu conflictul intre optiboot sau ventilatorul de la baie care e dupa releu dar alimentat din acelasi punct cu sursa principala face un emi ceva.. Trebuie cautat... Un proiect asa banal..din pacate face figuri... Editat Aprilie 18, 2022 de Gilbert Sparios Link spre comentariu
Gilbert Sparios Postat Aprilie 18, 2022 Autor Partajează Postat Aprilie 18, 2022 Am revenit cu un update. Am impresia ca uC nu este blocat sau aparent nu este blocat. Pentru ca citirea LDR o face, si dupa expirarea timpului de 2 minute (<DELAYON>) porneste ventilatorul, insa nu ramane cuplat timpul definit de <userTotalTime> dupa stingerea becului in baie. Nu vad eroarea dar pare o eroare in cod totusi... sau Timer0 pentru millis() pateste ceva...?.. Dupa re-alimentare montaj-ul se comporta normal...o vreme.. Link spre comentariu
Bandi Szasz Postat Aprilie 18, 2022 Partajează Postat Aprilie 18, 2022 if (userTotalTime > (uint32_t)MAXIMUMRUN) userTotalTime = (uint32_t)MAXIMUMRUN; // do not run over 1hour Si if (((presence) && ((cMs-userStartTime)>= (uint32_t)DELAYON)) || (cMs<=userTotalTime)) relState = 1; else relState = 0; Nu prea se impaca as zice eu. In anumite cazuri tu compari valaorea de "MAXIMUMRUN" care este 1 ora cu current millis() ? Pai daca montajul ala odata alimentat functioneaza o ora si currentMillis ajunge peste valoarea 3600000 oare ce se intampla ? In ce conditii poate fi acel " (cMs<=userTotalTime)" adevarat daca tie "millis()" o sa returneze tot timpul valori peste 3600000 ? Ai niste probleme de logica pe acolo... Link spre comentariu
Gilbert Sparios Postat Aprilie 18, 2022 Autor Partajează Postat Aprilie 18, 2022 (editat) Aparent ai gasit eroarea mea. Astfel ca if (userTotalTime > (uint32_t)MAXIMUMRUN) userTotalTime = (uint32_t)MAXIMUMRUN; // do not run over 1hour devine if (userTotalTime > ((uint32_t)MAXIMUMRUN)+cMs) userTotalTime = ((uint32_t)MAXIMUMRUN+cMs); // do not run over 1hour Multumesc @Bandi Szasz Editat Aprilie 18, 2022 de Gilbert Sparios Link spre comentariu
Vizitator Postat Aprilie 18, 2022 Partajează Postat Aprilie 18, 2022 Destul de greu de urmarit si depanat programul tau. Daca tot ai numit functia "ReadLDR()" eu zic ca o lasi sa faca numai asta. Sa citeasca de un anumit numar de ori pinul analog si sa returneze valoarea , eventual mapata in interval. Si sa faci comparatii si decizii in loop() sau in alte functii. 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