Jump to content
ELFORUM - Forumul electronistilor

Cum poate Arduino sa faca doua "treburi" in acelasi timp.


mani

Recommended Posts

Buna ziua la toata lumea.

Eu sunt un cititor al acestui forum de unde am invatat foarte multe lucruri ,sunt autodidact si doresc sa actulizez ceea ce am facut mai demult,asa ca va rog sa ma ajutati daca vreti

cu o automatizare pentru o centrala caruia i-am scris codul din recopilari de alte lucrari din internet.

Trebuie sa monitorizez doua temperaturi si o fotocelula sa le imprim intr-un Lcd si in functie de acesti parametri arduino comanda: un snec cu timp ciclic, cu diferiti timpi de on si off,

un ventilator la diferite turatii, o bujie  de aprindere a focului  , o pompa de circulare a apei.

Problema e ca atunci  cand chem functiile respective in" loop" arduino " ingheata" si  pe ecran parametrii monitorizati la fel si nu pot intra nici in meniu sa-i  reglez in timp real.

Doresc ca cineva sa ma ajute sa scap de a folosi  acest "WHILE" care i-mi da probleme .

Sunt un incepator cu arduino ,am incercat cu libraria <pt.h> si am reusit  doar snecul sa nu mai opreasca arduino atat timp cat merge la incarcare,celelate functii nu reusesc sa le adaptez la aceasta librarie.

Codul e lung si nu-l pot posta tot ca nu ma lasa ,am pus doar o parte unde am eu problema cu timpul.Am inceput sa studiez TimeOne dar nu inteleg cum pot aplica eu intreruperile in cazul meu pentru o fuctie, pentru o iesire digitala am inteles cum se face dar restul ma depaseste  si nu sunt capabil sa-i dau de capat. 

Va rog daca puteti sa ma indrumati cu un exemplu de cum pot solutiona problema.Invat mai repede din exemple aplicate la cod.

Va multumesc pentru rabdarea de a citi tot acest pomelnic . Atasez o parte din cod.

O zi buna va doresc.


 

  #include <Wire.h>
  #include <LiquidCrystal_I2C.h>
  #include <thermistorFun.h>
  #include <pt.h>
  //Inicializacion LCD
  LiquidCrystal_I2C lcd(0x38,20,4);  

  struct pt raspador; 
  struct pt relanti;
  struct pt lento;
  struct pt medio;
  struct pt rapido;
 
  //Temporales para conversion
  float Caldera;
  float Humos;
  int LDR;
  int termostat;

  #define sensorCaldera 1
  #define sensorHumos 2
  #define sensorLDR 3
  #define ventilador 5
  #define resistencia 6
  #define sinfin 9
   #define actuador_adelante 11
  #define actuador_atras 12
  #define thermostat 14

 //Variables temp caldera   
  byte prog_tc = 33;
  byte prog_th= 160;
  //Variables menu tiempos
  byte prog_TL = 5;
  byte prog_TC = 5;
  byte prog_TN1 = 10;
  //Variables menu relanti
  byte prog_dr = 2;
  byte prog_cr = 10;
  byte prog_vr = 32;
  //Variables menu nivel-1
  byte prog_d1 = 3;
  byte prog_c1 = 6;
  byte prog_v1 = 65;
  //Variables menu nivel-2
  byte prog_d2 = 3;
  byte prog_c2 = 4;
  byte prog_v2 = 127;
  //Variables menu nivel-3
  byte prog_d3 = 2;
  byte prog_c3 = 2;
  byte prog_v3 = 255;
  byte cheie; 
  //Variable para tiempos
  unsigned long periodStart, periodFinished, periodElapsed;
  
  char temp_str[10]; 
//////////////////////////////////////////////////////////////////////////////////////
 void setup() {
   
  lcd.init();                           //Iniciamos el LCD
  lcd.backlight();                      //Iniciamos la retroiluminacion
  PT_INIT(&raspador);
  PT_INIT(&relanti);
  PT_INIT(&lento);
  PT_INIT(&medio);
  PT_INIT(&rapido); 
  
  pinMode(actuador_adelante,OUTPUT);
  pinMode(actuador_atras,OUTPUT);
  pinMode(resistencia, OUTPUT); 
  pinMode(ventilador, OUTPUT);
  pinMode(sinfin, OUTPUT);
  pinMode(thermostat, INPUT_PULLUP);
  pinMode(LDR,INPUT);

  bool flag = HIGH;
  }
////////////////////////////////////////////////////////////////////////////////////
 void loop() {
  monstrar_sensores();
  leer_sensores(); 
  //mmenu();
  termostat=digitalRead(thermostat);
  
  while(termostat==LOW)  {
 
  leer_sensores();   
  borrar(0,9,0);  
  borrar(0,9,1);  
  termostat=digitalRead(thermostat);
  
  limpiador();

  limpInit();
  
  cargaInit();
  
 // encendidoBujia();
    
  //quemado_inicial();
  
 // modulacion();
  
  //modulacion_inversaTC();

  //quemador_paradoTC();
  
  } 
 }
///////////////////////////////////////////////////////////////////////////////////
////////////////////Funcion borrado Caracteres////////////////////////
  void borrar(int first, int last, int row){
     
  for (first ; first < last+1 ; first++){
       lcd.setCursor(first,row);
       lcd.print(" ");
   }
  }  

void timeElapsed(){
     
  periodFinished= millis();
  periodElapsed = (periodFinished - periodStart);
  }
//////////////////////////////////////////////////////////////////// 

 void limpiador()  {
   
  lcd.setCursor(0,0);
  lcd.print("Limpieza");
  borrar(0,8,2);
  lcd.setCursor(0,3);
  lcd.print("Raspa");
   digitalWrite(actuador_adelante,HIGH);         //  motor limpiador hacia delante
   digitalWrite(actuador_atras, LOW);            //  pin rele desactivado 
   analogWrite(ventilador, 255);
       periodStart = millis();     
       timeElapsed();
       
 while(periodElapsed <5000) { 
       leer_sensores();
       timeElapsed();
       lcd.setCursor(1,2);
       lcd.print(">>>"); 
       digitalWrite(actuador_adelante,LOW );         //  motor limpiador hacia atras
       digitalWrite(actuador_atras,HIGH);            //  pin rele activado
  
      if(Humos>=prog_th) break;  
  }
   digitalWrite(actuador_adelante,LOW );         //  motor limpiador hacia atras
   digitalWrite(actuador_atras,HIGH);            //  pin rele activado
 }
   void limpiador_atras()  { 
    
       periodStart = millis();                                 
       //tiempo_limpiador= millis();
       timeElapsed();
 while(periodElapsed <5000) { 
       leer_sensores();
       //monstrar_sensores();
       lcd.setCursor(1,2);
       lcd.print("<<<");
       timeElapsed();
      // if(Humos>=prog_th) break;        
                                         
      digitalWrite(actuador_adelante,LOW );                //  motor limpiador hacia delante pero parado por 
      digitalWrite(actuador_atras, LOW);
   }   
     borrar(0,4,2);
     borrar(0,4,3);
 } 
 
//////////////////////////////////////////////////////////////////// 
  void limpInit () {                        //limpieza inicial
        
  lcd.setCursor(0,3);
  lcd.print("Aire");
  lcd.setCursor(1,2);
  lcd.write(7);
  lcd.write(8);  
  analogWrite(ventilador, 255);             //ventilator maximo
  periodStart = millis();
  timeElapsed();
  while(periodElapsed < prog_TL*1000){      //un timpo de 5 segundos
  //monstrar_sensores();
  leer_sensores();
  timeElapsed(); 
  if(Humos>=prog_th) break;   
  }
  analogWrite(ventilador, 0);               //aqui se para
  borrar(0,4,2);  
  borrar(0,4,3); 
  }
//////////////////////////////////////////////////////////
  void cargaInit () {                       //carga inicial peletts
  
  long counter=0;
  lcd.setCursor(0,0);
  lcd.print("Carga >>"); 
  lcd.setCursor(0,3);
  lcd.print("Pelet"); 
  lcd.setCursor(1,2);
  lcd.write(6);
  lcd.write(6);
  lcd.write(6);
  digitalWrite(sinfin, HIGH);               // motor sinfin  en marcha
  
  periodStart = millis();
        timeElapsed();
  while(periodElapsed < prog_TC*1000){      //un timpo de 5 segundos
        monstrar_sensores();
        timeElapsed();        
  LDR=analogRead(sensorLDR);
  if (LDR >= 200){          //  Alimentación parada Si se detecta una llama estable.
      delay(100);
      counter++;
  if (counter >= 60) {
      digitalWrite(sinfin, LOW);     
      break;
   } 
   } else {
            counter=0;
   }                                           
  //if (termostat==HIGH){
                     
  //    break;
   // }
  //if(Humos>=prog_th) break;   
  }       
      digitalWrite(sinfin, LOW);                 //aqui se para
      borrar(0,4,2); 
      borrar(0,4,3);
  }  
/////////////////////////////////////////////////////////////
  void monstrar_sensores(){
  
     //lcd.setCursor(0,3);
     //lcd.print("Nivel"); 
     lcd.setCursor(11,0);
     lcd.print("Ldr:");
     lcd.setCursor(15,0);
     lcd.print(LDR,1);
     lcd.setCursor(11,1);
     lcd.print("Fum:");
     lcd.setCursor(15,1);
     lcd.print(Humos,1);
     lcd.setCursor(11,2); 
     lcd.print("Tur:");
     lcd.setCursor(15,2);
     lcd.print(Caldera,1);
 }
////////////////////////////////////////////////////////////////
 void leer_sensores() {
 
  LDR=analogRead(sensorLDR);
  String dataString = "sensor1,";
  dataString += temp_str;
  Caldera = thermistorRead(1);
  dtostrf(Caldera,6,2,temp_str);
  dataString += "\nsensor2,";
  dataString += temp_str;
  Humos = thermistorRead(2);
  dtostrf(Humos,6,2,temp_str);
  dataString += "\nsensor3,";
  dataString += temp_str; 
 }

 

//  Va multumesc mult.

Edited by nico_2010
Link to comment
  • Replies 30
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Posted Images

Incearca daca mai ai timp sa reeditezi postul, si sa postezi codul folosind buttonul Cod.

printCod.png.e958db95fb67d16eb8da46b7de60c113.png

 

Nici eu nu sunt programator, dar am folosit functia millis() pentru temperaturi sau timer1.

 

 

Edited by Guest
Link to comment

Buna ,prea tarziu nu pot sa-l mai reeditez postul 

Am incercat si cu functia millis() dar nu-mi iese,sunt multe solutii dar pentru cei care sunt in domeniu  ,eu invat programare la 49 de ani si ma poticnesc un pic 

de aceea am rugat sa mi se dea un ajutor pe baza de exemplu .

Codul merge dar se poate face mult mai bun decat am putut eu sa-l gandesc .

Multumesc mult.

 

Link to comment

Doar i-mi dau cu parerea - si in final nu vreau decat sa te incurajez sa nu abandonezi.

 

Metoda de a invata programare prin "compilare" cod din diverse surse fara sa intelegi conceptual modul de functionare nu-i cel mai recomandat  ...

 

Probabil o idee ar fi sa "rupi" aplicatia in mici module pe care sa le dezvolti (si sa le intelegi) separat  ...
 
Deduc din postarea ta:

Input:
 - Temp1 
 - Temp2 
 - Foto-cell

 

Out:
 - sneck t1->ON|OFF, t2->ON|OFF, ...
 - ventilator -> turatie variabila 
 - bujie 
 - pompa -> ON|OFF


Idei:
 - am putea sa ne facem un pic ordine "in minte" folosind o diagrama de stari (state machine) - acele etape prin care trece mica noastra automatizare.
 - Timer.h -> probabil fiecare actiune ai putea sa o implementezi intr-o functie si cu ajutorul clasei Timer sa le apelezi la intervalele sau pe perioada dorita

   

Succes
 
 

Link to comment

Inteleg fiecare lucru din codul care l-am scris si stiu fiecare parte cum functioneaza ,problema e ca nu am lucrat cu timers pana acum .

Am cerut un exemplu de cum se aplica un timer la o functie , pentru o iesire digitala stiu sa o fac.

Codul nu l-am putut posta tot ca are vreo 7000 de linii si e impartit tot in rutine si subrutine .

Multumesc oricum de initiativa.

 

 

Link to comment

Buna dimineata ,cred ca nu ma exprim corect in ceea ce priveste limbajul de programator si atunci am sa postez din nou o parte din cod in romana

cu ce as vrea eu sa faca in timpii respectivi fara sa-mi "paralizeze" arduino.

Eu pot intra in meniu si sa reglez parametrii doar cand contactele termostatului sunt deschise prin miscare encoderului,

cat timp se deruleaza programul nu am acces la meniu si nici senzorii nu se actualizeaza.

Sper sa nu deranjez pe nimeni ca pun iarasi o bucata de cod .

Multumesc ,o zi buna va doresc.

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  imprima_senzori();       //arata senzorii 
  citeste_senzori();       //
  meniu();                 //se intra in meniu prin rotirea encoderului
  termostat=digitalRead(thermostat);
  
  while(termostat==LOW)  {  //cat timp  contactul este inchis la termostat
                            //se deruleaza programul
  citeste_senzori();   
  sterge(0,9,0);  
  sterge(0,9,1); 
   
  termostat=digitalRead(thermostat);
  
  actuador_in_fata();  //aici trebuie ca acesta functie sa ruleze 5 secunde si sa se opreasca 

  actuador_in_spate(); //si sa inceapa aceasta sa ruleze 5 secunde si sa se opreasca

  curatire_cu_aer();   // urmand sa inceapa aceasta sa ruleze 7 secunde si sa se opreasca
  
  prima_incarcare();   //la randul ei acesta functie sa ruleze un timp reglabil intre 5 si 10 secunde
   
 }
}
void actuador_in_fata()  {
   
  lcd.setCursor(0,0);
  lcd.print("Limpieza");
  sterge(0,8,2);
  lcd.setCursor(0,3);
  lcd.print("Raspa");             
  lcd.setCursor(1,2);
  lcd.print(">>>"); 
  analogWrite(ventilador, 255); 
  digitalWrite(actuador_inainte,HIGH);        
  digitalWrite(actuador_inapoi,LOW);            
  }

void actuador_in_spate()  {
   
  lcd.setCursor(0,0);
  lcd.print("Limpieza");
  sterge(0,8,2);
  lcd.setCursor(0,3);
  lcd.print("Raspa");             
  lcd.setCursor(1,2);
  lcd.print("<<<"); 
  analogWrite(ventilador, 255); 
  digitalWrite(actuador_inainte,LOW);        
  digitalWrite(actuador_inapoi,HIGH);            
  }

void curatire_cu_aer() {                        
        
  lcd.setCursor(0,3);
  lcd.print("Aire");
  lcd.setCursor(1,2);
  lcd.write(7);    //caracter ventilator
  lcd.write(8);    //caracter ventilator
  analogWrite(ventilador, 255);             
  sterge(0,4,2);  
  sterge(0,4,3); 
  }
void prima_incarcare() {                      
  
  lcd.setCursor(0,0);
  lcd.print("Carga >>"); 
  lcd.setCursor(0,3);
  lcd.print("Pelet"); 
  lcd.setCursor(1,2);
  lcd.write(6);           //caracter snec
  lcd.write(6);           //caracter snec
  lcd.write(6);           //caracter snec
  digitalWrite(sinfin, HIGH);      
}

 void imprima_senzori(){
  
     lcd.setCursor(11,0);
     lcd.print("Ldr:");
     lcd.setCursor(15,0);
     lcd.print(LDR,1);
     lcd.setCursor(11,1);
     lcd.print("Fum:");
     lcd.setCursor(15,1);
     lcd.print(Humos,1);
     lcd.setCursor(11,2); 
     lcd.print("Tur:");
     lcd.setCursor(15,2);
     lcd.print(Caldera,1);
 }

void citeste_senzori() {
 
  LDR=analogRead(sensorLDR);
  String dataString = "sensor1,";
  dataString += temp_str;
  Caldera = thermistorRead(1);
  dtostrf(Caldera,6,2,temp_str);
  dataString += "\nsensor2,";
  dataString += temp_str;
  Humos = thermistorRead(2);
  dtostrf(Humos,6,2,temp_str);
  dataString += "\nsensor3,";
  dataString += temp_str; 
 }

void sterge(int first, int last, int row){
     
  for (first ; first < last+1 ; first++){
       lcd.setCursor(first,row);
       lcd.print(" ");
   }
  }


  

 

Link to comment

Ca s-o spunem pe a dreapta, Arduino nu poate face 2 lucruri in acelasi timp... :).

Dar, din ce inteleg eu, tu vrei ca indiferent UNDE in program esti sa vezi daca de ex. utilizatorul vrea sa faca ceva... de ex. sa intre in meniu sau orice altceva.

Primul lucru pe care ai nevoie sa-l stii este CE FACE USERUL atunci cand vrea ce vrea... de ex. poate apasa un buton....

Pasul urmator este sa te uiti la acel buton, daca a fost apasat sau nu, de peste tot... asta faci setand o intrerupere de timer.

In felul asta, din X in X micro/mili/secunde, "programul se uita" daca a fost apasat butonul iar in caz ca da, face vreo actiune.

Un exemplu de setare a timerului este asta si-l pui in setup :

 

void setup() {
//......................

//set timer1 interrupt every 10ms
  cli();
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;
  OCR1A = 2499;                        //(16.000.000MHz * 10ms) / 64 -1
  TCCR1B |= (1 << WGM12);              //CTC mode 
  TCCR1B |= (1 << CS11) | (1 << CS10); //prescaler 64  
  TIMSK1 |= (1 << OCIE1A);             // enable timer compare interrupt 
  sei();  

//.......................

}

Asta va avea ca efect ca la fiecare 10ms o sa se execute functia de mai jos:

 

ISR(TIMER1_COMPA_vect) {  
  //aici pui codul pe care vrei sa-l execute periodic
  //...........
}

 

Link to comment

trebuie sa renunti la buclele cu while(), sunt ceea ce se numeste blocking functions.

incearca sa rescrii programul astfel incat, de exemplu, in loc de

 while(termostat==LOW)  {  //cat timp  contactul este inchis la termostat
                            //se deruleaza programul
  citeste_senzori();   
  sterge(0,9,0);  
  sterge(0,9,1); 
  /*
  restul functiilor
  */
     
   }

sa scrii ceva de genul

 if(termostat==LOW && meniuActiv == false)  {  //cat timp  contactul este inchis la termostat si NU esti in meniu, defineste o variabila care sa tina cont de asta ...
                            //se deruleaza programul
  citeste_senzori();   
  sterge(0,9,0);  
  sterge(0,9,1); 
  /*
  retul functiilor
  */
 }

rezultatul final ar fi cam acelasi, cu diferenta ca acum nu mai ramai blocat in while() ...

 

relativ la lcd, poti incerca sa-ti definesti un buffer de 2 string-uri x 16 caractere pe care sa-l modifici pe parcursul codului si sa-l scrii o singura data la finalul buclei in lcd.

ar scurta semnificativ durata de executie a codului

Link to comment

Asta cu crearea buferului pentru lcd nu o prea inteleg ,daca esti amabil sa postezi un exemplu.

Cum fac sa temporizez o functie 5 secunde de exemplu si sa se opreasca si apoi sa temporizez alta si sa se opreasca .

Poate plictisesc cu insistenta mea , asa ca ma scuzati.

Link to comment
31 minutes ago, mani said:

Cum fac sa temporizez o functie 5 secunde de exemplu si sa se opreasca si apoi sa temporizez alta si sa se opreasca .

Poate plictisesc cu insistenta mea , asa ca ma scuzati.

In ideea anterioara cu intreruperile, sa zicem ca generezi una la fiecare 100ms.

Creezi o variabila pe care o denumesti de ex. timeCounter si pe care o incrementezi la fiecare intrerupere... adica de 10 ori pe secunda pt. exemplul ales.

Cand intri in functie aduci la zero contorul (timeCounter = 0) dupa care incepi sa executi ce ai de executat dar te mai uiti din cand in cand la contor in bucla aia de executie... cand asta ajunge la 50, termini functia.

La a 2-a functie, reiei procedura... s.a.m.d.

Link to comment

Dacă nu vrei să foloseşti funcţia millis() care e cel mai simplu de folosit, cum au spus colegii foloseşti o variabilă contor care se incrementează la fiecare tură de loop. Dar pt. asta ai nevoie ca acea variabilă să fie iniţializată în funcţia setup(). De ex. ai în setup()   counter1 = 0; apoi în loop() counter1++; asta creşte valoarea variabilei cu 1 la fiecare reiterare, iar dacă scrii o condiţie if (counter1) > 100 {......}, după 101 de ture loop() se creeaza condiţia şi se execută ce vrei tu.după care poţi reseta contorul în funcţia condiţiei, de ex. counter1 = 0; şi procesul se reia.

Uite de ex. cum am rezolvat eu o funcţie multiplă ca apăsarea unui buton, o apăsare scurtă opreşte un program, una lungă schimbă conţinutul unui display:

 

 

if (a_6 < 300) {                           // BUTON STOP
    stop_prog = true;
    start_timer = 0;
    standby_timer = 0;
    display_timer++;
    if (display_timer == 10 && stop_prog) {
      display_status++;                      //LA APASAREA PRELUNGITA PE STOP SE SCHIMBA CONTINUTUL AFISAJULUI
    }
    if (display_timer > 10) {
      display_timer = 0;
    }
  }
  else {
    display_timer = 0;
  }

În acest caz variabila contorizată este display_timer.

Edited by mihaicozac
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now



×
×
  • 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