Sari la conținut
ELFORUM - Forumul electronistilor

Subrutina in loop (senzor IR)


norad

Postări Recomandate

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
  • Răspunsuri 6
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

Top autori în acest subiect

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

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 de mihaicozac
Link spre comentariu

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

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 de mars01
Link spre comentariu

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 de norad
Link spre comentariu

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 cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări