norad Postat Martie 16, 2017 Partajează Postat Martie 16, 2017 Va salut, Am atasat la un Arduino Uno un senzor infrarosu MLX90614 si un shield keypad cu LCD. Am scris codul de mai jos (Atentie! nu e tot codul caci ocupa mult - am eliminat partea cu butoanele) ce face urmatoarele: -se seteaza temperatura (de ex. 30 grade) si histerezisul (de ex. 2 grade); -citeste temperatura de 4 ori pe secunta si o afiseaza pe LCD; -daca temperatura este mai mare decat 32 grade, afiseaza pe ecran "ALARM" si se aprinde ledul de pe placa; -daca temperatura e mai mica decat 28 grade, nu mai afiseaza "ALARM" si ledul de pe placa se stinge. Merge fara probleme. Doresc sa fac o subrutina in loop si anume, ledul de pe placa sa se aprinda si sa se stinga la fiecare 30 de secunde (sau alt numar de secunde, reglabil) daca temperatura detectata se mentine peste 32 grade. Vreau ca temperatura sa fie citita si afisata in continuare de 4 ori pe secunda. Am citit ceva cu "millis" ca sa evit "delay", dar nu stiu daca se aplica aici. Multumesc. #include <Wire.h> #include <Adafruit_MLX90614.h> //Sample using LiquidCrystal library #include <LiquidCrystal.h> // select the pins used on the LCD panel LiquidCrystal lcd(8, 9, 4, 5, 6, 7); Adafruit_MLX90614 mlx = Adafruit_MLX90614(); int Tempset = 30; int Hysteresis = 2; void setup() { pinMode(LED_BUILTIN, OUTPUT); mlx.begin(); // start the MLX sensor library lcd.begin(16, 2); // start the LCD library } void loop() { lcd.setCursor(5,0); lcd.print(Tempset); // print a simple message delay(250); lcd.setCursor(6,1); // move cursor to column "6" and line "1" lcd.print(mlx.readObjectTempC()); // display on LCD the object temperature in degree Celsius lcd.setCursor(5,0); lcd.print(Tempset); // display on LCD the object temperature in degree Celsius if (mlx.readObjectTempC() > (Tempset + Hysteresis)){ digitalWrite(LED_BUILTIN, HIGH); lcd.setCursor(9,0); // move cursor to column "9" and line "0" lcd.print("ALARM"); // print a simple message } if (mlx.readObjectTempC() < (Tempset - Hysteresis)){ lcd.setCursor(9,0); // move cursor to column "9" and line "0" lcd.print(" "); // print a simple message digitalWrite(LED_BUILTIN, LOW); } Foloseste butonul <> pentru postarea codului. Este singura data cand editez postul. Dupa, voi sterge postarea. Link spre comentariu
mars01 Postat Martie 16, 2017 Partajează Postat Martie 16, 2017 if (mlx.readObjectTempC() > (Tempset + Hysteresis)) { digitalWrite(LED_BUILTIN, HIGH); lcd.setCursor(9,0); // move cursor to column "9" and line "0" lcd.print("ALARM"); // print a simple message } devine ceva de genul: //astea apar undeva la inceputul programului //atentie ca daca programul merge mai mult de 50 si ceva de zile pot aparea probleme dar se pot face //corectii #define DELAY_INTERVAL 30000 // 30000ms = 30sec unsigned long millis_now = 0; bool state = LOW; if (mlx.readObjectTempC() > (Tempset + Hysteresis)) { if (millis() >= (millis_now + DELAY_INTERVAL)) { digitalWrite(LED_BUILTIN, !state); millis_now = millis(); } lcd.setCursor(9,0); // move cursor to column "9" and line "0" lcd.print("ALARM"); // print a simple message } Poti implementa si un mecanism ca sa numai tiparesti ALARM la fiecare trecere prin bucla, ci doar la schimbarea de stare. Link spre comentariu
mihaicozac Postat Martie 17, 2017 Partajează Postat Martie 17, 2017 (editat) Poţi folosi delay împreună cu un numărător/contor activat de condiţie, gen if(temp > 32) {counter++}; apoi if(counter > valoare oarecare) {aprinde ledul};. Dacă ai 4 citiri pe secundă ai nevoie de o valoare de declanşare de 1200. Avantajul este că variabila contor se poate reseta în orice moment când condiţia nu se mai îndeplineşte, de ex. dacă după 20 de secunde se coboară sub prag contorul revine la zero. Editat Martie 17, 2017 de mihaicozac Link spre comentariu
mihaicozac Postat Martie 17, 2017 Partajează Postat Martie 17, 2017 Am băgat un zero în plus şi nu mai pot edita, e clar că valoarea de declanşare a alarmei e de 120 nu 1200. Link spre comentariu
norad Postat Martie 17, 2017 Autor Partajează Postat Martie 17, 2017 Multumesc pentru cod si pentru editarea postului. Scuze pentru postarea fara <>.Am implementat rutina sugerata, insa vad ca e un fel de counter separat.Probabil nici eu nu am explicat prea bine ce vreau.Asadar, daca Tobject depaseste Tset sa se aprinda led-ul.Daca Tobject < Tset, ledul sa se stinga.Inainte de a implementa codul din postarea #2, asta se intampla.Dupa rutina cu millis (multumesc mars01), daca Tobject > Tset ledul se aprinde. Daca, dupa 2 secunde, de exemplu, Tobject < Tset, ledul se stinge. Insa, daca dupa alte 2 secunde Tobject > Tset, ledul nu se mai aprinde, ci trebuie sa astept pana ce trec 30 de secunde de la momentul zero.Or, mie imi este necesar ca acest counter de 30 de secunde sa fie resetat odata cu Tobject < Tset.Concret, cand Tobject > Tset, sa fie generat un semnal dreptunghiular la unul dintre pinii digitali (eu am ales pentru a fi mai simplu ledul de pe placa), semnal dreptunghiulat care sa porneasca intotdeauna cu nivel logic 1 si sa plece din origine, adica tzero=0, iar frecventa si factorul de umplere reglabile. Link spre comentariu
mars01 Postat Martie 17, 2017 Partajează Postat Martie 17, 2017 (editat) Daca se intra in alarma (temp mare), in afara de afisarea alarmei si a LED-ului, programul mai face altceva? Cu alte cuvinte, se poate schimba din "if" in while"? Adica: atata timp cat temperatura este mai mare decat cea prag, stai in bucla si afiseaza Alarma, iar in plus blink-uieste un LED. Sau ceva de genul: //astea apar undeva la inceputul programului //atentie ca daca programul merge mai mult de 50 si ceva de zile pot aparea probleme dar se pot face //corectii #define DELAY_INTERVAL 30000 // 30000ms = 30sec unsigned long millis_now = 0; bool state = LOW; if (mlx.readObjectTempC() > (Tempset + Hysteresis)) { if (millis() >= (millis_now + DELAY_INTERVAL)) { digitalWrite(LED_BUILTIN, !state); millis_now = millis(); } lcd.setCursor(9,0); // move cursor to column "9" and line "0" lcd.print("ALARM"); // print a simple message } else { millis_now = millis(); state = LOW; digitalWrite(LED_BUILTIN, state); } Editat Martie 17, 2017 de mars01 Link spre comentariu
norad Postat Martie 17, 2017 Autor Partajează Postat Martie 17, 2017 (editat) Ati intuit bine. Rutina se afla de fapt in Tobject < Tset. Am scris-o pe forum in Tobject > Tset pentru ca e mai intuitiv. In fine, programul mai face si altceva. In locul ledului care blink-uieste este un releu ce comanda o unitate de incalzire (un fel de cuptor cu microunde) - digestor ii zice. Lichidul (sau amestecul de lichide) apos se afla intr-o capsula de teflon etansa. Incinta este plasata in cuptor si lichidul se incalzeste sub actiunea microundelor. Temperatura lichidului nu poate fi citita direct (nu poate fi bagata o sonda metalica in cuptorul cu microunde) si nici sonda infrarosu in capsula de teflon. Prin urmare citirea temperatului trebuie sa se faca indirect si anume se citeste temperatura capsulei (cu un senzor IR de la distanta). Cum capsula se incalzeste mai greu decat lichidul din interior, incalzirea trebuie sa se faca cu precautie: 30 secunde incalzire, dupa care 30 secunde pauza (sau poate alte valori determinate empiric). In felul acesta controlez inertia termica a capsulei. Daca ar fi lasat cuptorul sa mearga continuu, lichidul s-ar incalzi mult mai rapid decat citeste senzorul infrarosu temperatura pe capsula si ar genera niste presiuni uriase, cu pericol de explozie. Ar fi varianta cu PID, dar eu vreau sa controlez riguros timpii de incalzire. Sunt excluse modificari aduse modularii magnetronului. Editat Martie 17, 2017 de norad 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