Pages: [1]   Go Down
Author Topic: Fare più cose contemporaneamente?  (Read 1472 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Full Member
***
Karma: 0
Posts: 128
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao a tutti,
dalla domanda capirete che sono un newbie di questo mondo.... smiley-red
Quello che non riesco a capire è come fa arduino, che esegue un'istruzione alla volta a eseguire il codice esterno ad una funzione e contemporaneamente "essere in allerta" su eventuali input esterni.
Faccio un esempio: se devo far lampeggiare 2 led o più contemporaneamente so che devo usare millis(), mettiamo il caso però che se premo un pulsante entro in una funzione il programma dei due led lampeggianti deve continuare a funzionare e in più se avviene qualcosa (tipo la pressione di un altro pulsante) si devono fermare.

Si vede che sono un po' confuso?! smiley-grin
Logged

Riva del Garda, TN / Forlì
Offline Offline
Edison Member
*
Karma: 8
Posts: 2246
Il piu' modesto al mondo
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

usi sempre millis, fai uno diagramma a blocchi ti aiuterà molto smiley-wink
Logged

Il nuovo forum italiano sull'elettronica: http://www.electroit.tk/ <--- Nuovamente online!

0
Offline Offline
Full Member
***
Karma: 0
Posts: 128
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

innanzitutto ti ringrazio per la risposta...
immaginavo ma sinceramente non mi è chiaro! se sono dentro una funzione come fa a "leggere"il resto del programma?
Logged

Riva del Garda, TN / Forlì
Offline Offline
Edison Member
*
Karma: 8
Posts: 2246
Il piu' modesto al mondo
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

quando richiami una funzione una volta eseguita il programma esce. ti spiego:
Code:
void loop() {
parte di programma
funzione();
altra parte di programma
}

void funzione() {
programma nella funzione
}

è equivalente a scrivere
Code:
void loop() {
parte di programma
programma nella funzione
altra parte di programma
}
Logged

Il nuovo forum italiano sull'elettronica: http://www.electroit.tk/ <--- Nuovamente online!

0
Offline Offline
Full Member
***
Karma: 0
Posts: 128
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, il tuo esempio è chiarissimo.
Se posso, inserisco il codice di un meù per modificare la data e l'ora al quale ho aggiunto 2 led lampeggianti. Ecco, quando entro nel menù i led si bloccano smiley-confuse

Code:
#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h>
#include <LiquidCrystal.h>


LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int Sec, Min, Ore, Data, Mese,Anno;
int Puls_Set, Puls_Set_Old = LOW, Puls_Inc, Puls_Inc_Old = LOW, Puls_Dec, Puls_Dec_Old = LOW, Puls_Ok, Puls_Ok_Old = LOW;
int Set_HR = 0, Set_MIN = 0, Set_SEC, Set_DATA = 1, Set_MESE = 1, Set_ANNO = 10;
int Move_Set = 0;

const int led1 = 9;
const int led2 = 10;
long previousMillis = 0;
long previousMillis1 = 0;
int statoLed1 = LOW;
int statoLed2 = LOW;


void setup()
{
  Serial.begin(9600);
  lcd.begin(20,4);
  lcd.clear();
  pinMode(led1 , OUTPUT);
  pinMode(led2 , OUTPUT); 
  RTC.stop();  //inizializzo RTC
  RTC.set(DS1307_SEC,Set_SEC);
  RTC.set(DS1307_MIN,Set_MIN);
  RTC.set(DS1307_HR,Set_HR);
  RTC.set(DS1307_DATE,Set_DATA);
  RTC.set(DS1307_MTH,Set_MESE);
  RTC.set(DS1307_YR,Set_ANNO);
  RTC.start();
}



//-------------------------FUNZIONE PER MODIFICA ORA E DATA-----------------------------
void modifica_ora(){
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Imposta data e ora");

  while (true){

    Puls_Inc = digitalRead(51);
    Puls_Dec = digitalRead(49);
    Puls_Ok  = digitalRead(45);

    //-----------------------------INCREMENTA ORA--------------------------------   
    if (Puls_Inc == HIGH && Puls_Inc_Old == LOW && Move_Set == 0){
      Set_HR = Set_HR + 1;
      if (Set_HR >23){
        Set_HR = 0;
      }
      RTC.set(DS1307_HR,Set_HR); 
      Puls_Inc_Old = Puls_Inc;
    }   
    if (Puls_Inc == LOW && Puls_Inc_Old == HIGH){     
      Puls_Inc_Old = Puls_Inc;
    }

    //----------------------------DECREMENTA ORA-----------------------------------           
    if (Puls_Dec == HIGH && Puls_Dec_Old == LOW && Move_Set == 0){
      Set_HR = Set_HR - 1;
      if (Set_HR <0){
        Set_HR = 23;
      }
      RTC.set(DS1307_HR,Set_HR); 
      Puls_Dec_Old = Puls_Dec;
    }   
    if (Puls_Dec == LOW && Puls_Dec_Old == HIGH){     
      Puls_Dec_Old = Puls_Dec;
    }


    //-----------------------------INCREMENTA MINUTI--------------------------------   
    if (Puls_Inc == HIGH && Puls_Inc_Old == LOW && Move_Set == 1){
      Set_MIN = Set_MIN + 1;
      if (Set_MIN >59){
        Set_MIN = 0;
      }
      RTC.set(DS1307_MIN,Set_MIN); 
      Puls_Inc_Old = Puls_Inc;
    }   
    if (Puls_Inc == LOW && Puls_Inc_Old == HIGH){     
      Puls_Inc_Old = Puls_Inc;
    }

    //----------------------------DECREMENTA MINUTI-----------------------------------           
    if (Puls_Dec == HIGH && Puls_Dec_Old == LOW && Move_Set == 1){
      Set_MIN = Set_MIN - 1;
      if (Set_MIN <0){
        Set_MIN = 59;
      }
      RTC.set(DS1307_MIN,Set_MIN); 
      Puls_Dec_Old = Puls_Dec;
    }   
    if (Puls_Dec == LOW && Puls_Dec_Old == HIGH){     
      Puls_Dec_Old = Puls_Dec;
    }     

    //-----------------------------INCREMENTA DATA--------------------------------   
    if (Puls_Inc == HIGH && Puls_Inc_Old == LOW && Move_Set == 2){
      Set_DATA = Set_DATA + 1;
      if (Set_DATA >31){
        Set_DATA = 0;
      }
      RTC.set(DS1307_DATE,Set_DATA); 
      Puls_Inc_Old = Puls_Inc;
    }   
    if (Puls_Inc == LOW && Puls_Inc_Old == HIGH){     
      Puls_Inc_Old = Puls_Inc;
    }

    //----------------------------DECREMENTA DATA-----------------------------------           
    if (Puls_Dec == HIGH && Puls_Dec_Old == LOW && Move_Set == 2){
      Set_DATA = Set_DATA - 1;
      if (Set_DATA <0){
        Set_DATA = 31;
      }
      RTC.set(DS1307_DATE,Set_DATA); 
      Puls_Dec_Old = Puls_Dec;
    }   
    if (Puls_Dec == LOW && Puls_Dec_Old == HIGH){     
      Puls_Dec_Old = Puls_Dec;
    } 

    //-----------------------------INCREMENTA MESE--------------------------------   
    if (Puls_Inc == HIGH && Puls_Inc_Old == LOW && Move_Set == 3){
      Set_MESE = Set_MESE + 1;
      if (Set_MESE >12){
        Set_MESE = 0;
      }
      RTC.set(DS1307_MTH,Set_MESE); 
      Puls_Inc_Old = Puls_Inc;
    }   
    if (Puls_Inc == LOW && Puls_Inc_Old == HIGH){     
      Puls_Inc_Old = Puls_Inc;
    }

    //----------------------------DECREMENTA MESE-----------------------------------           
    if (Puls_Dec == HIGH && Puls_Dec_Old == LOW && Move_Set == 3){
      Set_MESE = Set_MESE - 1;
      if (Set_MESE <0){
        Set_MESE = 12;
      }
      RTC.set(DS1307_MTH,Set_MESE); 
      Puls_Dec_Old = Puls_Dec;
    }   
    if (Puls_Dec == LOW && Puls_Dec_Old == HIGH){     
      Puls_Dec_Old = Puls_Dec;
    }     

    //-----------------------------INCREMENTA ANNO--------------------------------   
    if (Puls_Inc == HIGH && Puls_Inc_Old == LOW && Move_Set == 4){
      Set_ANNO = Set_ANNO + 1;
      if (Set_ANNO >99){
        Set_ANNO = 0;
      }
      RTC.set(DS1307_YR,Set_ANNO); 
      Puls_Inc_Old = Puls_Inc;
    }   
    if (Puls_Inc == LOW && Puls_Inc_Old == HIGH){     
      Puls_Inc_Old = Puls_Inc;
    }

    //----------------------------DECREMENTA ANNO-----------------------------------           
    if (Puls_Dec == HIGH && Puls_Dec_Old == LOW && Move_Set == 4){
      Set_ANNO = Set_ANNO - 1;
      if (Set_ANNO <0){
        Set_ANNO = 99;
      }
      RTC.set(DS1307_YR,Set_ANNO); 
      Puls_Dec_Old = Puls_Dec;
    }   
    if (Puls_Dec == LOW && Puls_Dec_Old == HIGH){     
      Puls_Dec_Old = Puls_Dec;
    }     


    lcd.setCursor(0, 2);
    if (Set_HR < 10) {
      lcd.print("0");
    }

    lcd.print(Set_HR);

    if (Set_MIN < 10) {
      lcd.print(":0");
    }
    else {
      lcd.print(":");
    }
    lcd.print(Set_MIN);

    //----------------------------------------------------VISUALIZZO DATA-------------------------
    lcd.setCursor(10, 2); 
    if (Set_DATA < 10) {
      lcd.print("0");
    }

    lcd.print(Set_DATA);   

    if (Set_MESE < 10) {
      lcd.print("/0");
    }
    else {
      lcd.print("/");
    }

    lcd.print(Set_MESE);

    if (Set_ANNO < 10) {
      lcd.print("/200");
    }
    else {
      lcd.print("/20");
    }
    lcd.print(Set_ANNO);



    //--------------------------------------------------ESCO DA MODIFICA ORA------------------     
    if (Puls_Ok == HIGH && Puls_Ok_Old == LOW){
      Puls_Ok_Old = Puls_Ok;     
      Move_Set = Move_Set + 1;
      if (Move_Set > 4){
        lcd.clear();
        Move_Set = 0;
        break;
      }
    }

    if (Puls_Ok == LOW && Puls_Ok_Old == HIGH){     
      Puls_Ok_Old = Puls_Ok;
    }
  } 
  loop();
}

void loop()
{
  Ore = (RTC.get(DS1307_HR, true));
  Min = (RTC.get(DS1307_MIN,false));
  Sec = (RTC.get(DS1307_SEC,false));
  Data = (RTC.get(DS1307_DATE,false));
  Mese = (RTC.get(DS1307_MTH,false));
  Anno = (RTC.get(DS1307_YR,false));

  Puls_Set = digitalRead(53);

  if (Puls_Set == HIGH && Puls_Set_Old == LOW){
    Puls_Set == Puls_Set_Old; 
    modifica_ora();
  }
  if (Puls_Set == LOW && Puls_Set_Old == HIGH){
    Puls_Set == Puls_Set_Old;
  }

  lcd.setCursor (0, 0);
  Mostra_ora();
  lcd.setCursor (10, 0);
  Mostra_data();



  //----------------------LED------------------------
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > 1000)
  {
    previousMillis = currentMillis;

    if (statoLed1 == LOW)
      statoLed1 = HIGH;

    else

        statoLed1 = LOW;
    digitalWrite(led1, statoLed1);
  }
  unsigned long currentMillis1 = millis(); 
  if (currentMillis1 - previousMillis1 > 150)
  {
    previousMillis1 = currentMillis1;

    if (statoLed2 == LOW)
      statoLed2 = HIGH;

    else

        statoLed2 = LOW;
    digitalWrite(led2, statoLed2);
  }

}
Logged

Riva del Garda, TN / Forlì
Offline Offline
Edison Member
*
Karma: 8
Posts: 2246
Il piu' modesto al mondo
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

eh qui diventa dura, ma è perchè usi un while.

in effetti il multithreading esisterebbe sul micro ma processing non permette di utilizzarlo smiley-mad

dovresti eliminare i while e i controlli farli nel loop diretto..

è un po un casino qui rifare tutto senza modificare qualche decina di righe di codice.
Logged

Il nuovo forum italiano sull'elettronica: http://www.electroit.tk/ <--- Nuovamente online!

0
Offline Offline
Faraday Member
**
Karma: 31
Posts: 2908
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
eh qui diventa dura, ma è perchè usi un while.
Si un poco si, ma mica tanto.

Quote
in effetti il multithreading esisterebbe sul micro ma processing non permette di utilizzarlo smiley-mad

None, non c'èntra processing. Per implementare il multithreading o time shared, è necessario supporto nel microcontrollore o meglio microprocessore perchè io non conosco microcontrollori che supportano il multithreading. Leggi http://it.wikipedia.org/wiki/Multithreading.

Quote
dovresti eliminare i while e i controlli farli nel loop diretto..
Anche, oppure assicurarti che il while non monopolizzi il microcontrollore.

Poi tu fai una cosa che non si dovrebbe fare, mi stranizza che il codice da te postato lavori correttamente, quasi subito dovrebbe incasinarsi tutto. Se non ho visto male tu richiami il chiamante, cioè dalla funzione loop() fai una chiamata a funzione la quale chiama la funzione loop(), in pratica la funzione non ritorna mai. Non so se è permesso una tale tecnica sui microcontrollori, di sicuro sul PC non si fà.

In definitiva per risolvere devi fare tante funzioni quante necessarie e tutte queste sono rientranti sempre e comunque e sopratutto assicurati che ogni funzione svolga il proprio lavoro nel minore tempo possibile.
Es. La funzione per scrivere l'ora i minuti e i secondi spezzala in 3, solo ogni secondo devi aggiornare il display dei secondi, e così anche per i minuti e ore.

Ciao.

Spezzetta il programma in funzioni e richiamale in sequenza nel loop.

 
Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

0
Offline Offline
Full Member
***
Karma: 0
Posts: 128
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Vi tartasso con altre domande, scusatemi ma vorrei capire fino in fondo:
Quote
eh qui diventa dura, ma è perchè usi un while.
Quote
Si un poco si, ma mica tanto.
ah...per me è moooolto dura!!!

Quote
dovresti eliminare i while e i controlli farli nel loop diretto..
Quote
Anche, oppure assicurarti che il while non monopolizzi il microcontrollore.

ma una volta che entro nel ciclo non ha già "monopolizzato" il microcontrollore?
Quote
Poi tu fai una cosa che non si dovrebbe fare, mi stranizza che il codice da te postato lavori correttamente, quasi subito dovrebbe incasinarsi tutto. Se non ho visto male tu richiami il chiamante, cioè dalla funzione loop() fai una chiamata a funzione la quale chiama la funzione loop(), in pratica la funzione non ritorna mai. Non so se è permesso una tale tecnica sui microcontrollori, di sicuro sul PC non si fà.
Io richiamo la funzione loop() dalla funzione modifica_ora().E' sbagliato?

Quote
In definitiva per risolvere devi fare tante funzioni quante necessarie e tutte queste sono rientranti sempre e comunque e sopratutto assicurati che ogni funzione svolga il proprio lavoro nel minore tempo possibile.
Es. La funzione per scrivere l'ora i minuti e i secondi spezzala in 3, solo ogni secondo devi aggiornare il display dei secondi, e così anche per i minuti e ore.

Ciao.

Spezzetta il programma in funzioni e richiamale in sequenza nel loop.

E qui mi perdo.Se faccio come dici non ho lo stesso problema (il blocco dei led)?
Grazie mille di nuovo....soprattutto per la pazienza smiley

Logged

Milano, Italy
Offline Offline
Faraday Member
**
Karma: 11
Posts: 3091
Sideralis Arduino!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Io richiamo la funzione loop() dalla funzione modifica_ora().E' sbagliato?

Io credo proprio di si, non credo che nessuno abbia mai pensato di scrivere un abominio simile :-)
E' loop che fa girare il tuo codice, non il contrario!
F
Logged

Federico - Sideralis
Arduino &C: http://www.sideralis.org
Foto: http://blackman.amicofigo.com

0
Offline Offline
Full Member
***
Karma: 0
Posts: 128
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Io richiamo la funzione loop() dalla funzione modifica_ora().E' sbagliato?

Io credo proprio di si, non credo che nessuno abbia mai pensato di scrivere un abominio simile :-)
E' loop che fa girare il tuo codice, non il contrario!
F

addirittura....però vi avevo avvisato all'inizio del topic :-)
 
Corretto!

Logged

Milano, Italy
Offline Offline
Faraday Member
**
Karma: 11
Posts: 3091
Sideralis Arduino!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Chiaramente si dice per ridere  smiley-twist
Fede
Logged

Federico - Sideralis
Arduino &C: http://www.sideralis.org
Foto: http://blackman.amicofigo.com

0
Offline Offline
Faraday Member
**
Karma: 31
Posts: 2908
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
addirittura....però vi avevo avvisato all'inizio del topic :-)
Si avevi avvisato ma quello rimane un'abominio. Prendi le risposte con spirito

Diamo per scontato che ogni funzione ha una entrata ed una uscita. Quando viene eseguita una chiamata a funzione viene salvato il punto di chiamata, poi si passa ad eseguire il codice dentro la funzione, quando questa termina, l'esecuzione ritorna nel punto seguente a quello salvato prima della chiamata. In programmazione è possibile creare algoritmi ricorsivi, dove una funzione chiama se stessa, poi però tutte le chiamate alla fine ritornano sempre e la cosa funziona se non si supera il limite di ricorsione.

Quote
ah...per me è moooolto dura!!!
Posso immaginare, considera che si tratta di costringere il proprio cervello a raggionare come non è abituato.

Quote
ma una volta che entro nel ciclo non ha già "monopolizzato" il microcontrollore?

Appunto ti dicevo di fare in modo che nel while ci devi stare il minimo indispensabile a compiere una operazione.
Quantifichiamo il tempo, se il tuo led deve lampeggiare con una frequenza di un secondo, il while e tutte le altre parti del codice devono impiegare un tempo minore di 1 secondo.

Quote
E qui mi perdo.Se faccio come dici non ho lo stesso problema (il blocco dei led)?
Grazie mille di nuovo....soprattutto per la pazienza smiley

Non hai lo stesso problema sempre che ti assicuri di non impegnare il micro per più di un secondo.

Un esempio di pseudo codice spero ti possa servire di aiuto, io purtroppo non ho un display e mi viene difficile scrivere codice funzionante.

Pseudo Code:

loop()
{
1
2
3
}
Dopo l'esecuzione della riga 3 il micro riparte dalla riga 1, e così fino all'infinito.
nel setup chiama func_salva_ora_min_sec()

func_salva_ora_min_sec()
{
      legge i dati dall'rtc e li salva in variabili globali
      globale global_ora; global_min; global_sec;
}

func_controller()
{
      salva i dati ora ecc. in variabili locali
      ora_salvata;
      min_salvata;
      sec_salvata;
      chiama func_salva_ora_min_sec()
      potresti fare {
          confronta sec_salvata con global_sec, se diversi controlla che sec = 00 se lo è devi aggionare anche i minuti,
          ma prima controlla se min = 00 in tal caso devi aggiornare anche le ore.}
      oppure {
          confronta sec_salvata con global_sec, se diversi chiama funzione per aggiornare i secondi.
          confronta min_salvata con global_min, se diversi chiama funzione per aggiornare i minuti.
          confronta ore_salvata con global_ora, se diversi chiama funzione per aggiornare i ore.
      }
}
loop()
{
      chiama func_controller()
      leggi stato pin pulsanti o pulsati analogici
      if pulsante_premuto fai qualcosa es  chiama  funzione_flah_led();
      if pulsante1_premuto fai altro....
      if pulsa.....ecc.
}

Se vuoi una pulsantiera analogica che ti permette di leggere lo stato di più pulsanti premuti (quasi) contemporaneamente, guarda il forum di gioblu, c'è un mio post con del codice, se non lo capisci posta pure li o qui aprendo un nuovo post "ho trovato questo codice come funziona?".

Ok ciao.
 
« Last Edit: July 05, 2011, 05:28:02 am by MauroTec » Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

Riva del Garda, TN / Forlì
Offline Offline
Edison Member
*
Karma: 8
Posts: 2246
Il piu' modesto al mondo
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

io ocnsiglio di fare un diagramma a blocchi con un solo ritorno, intendo prima della programmazione andrebbe preso un foglio e fatto ogni singolo passaggio senza mai entrare in un loop, così sarebbe perfetto per la logica di arduino.
Logged

Il nuovo forum italiano sull'elettronica: http://www.electroit.tk/ <--- Nuovamente online!

BZ (I)
Offline Offline
Brattain Member
*****
Karma: 260
Posts: 21566
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ciao acron
I microcontroller non possono fare cose in contemporanea ma possono fare cose uno dopo l' altra e se programmate bene questo funziona bene senza che una cosa blocchi l' altra.

Chiamare la funziione loop() da una funzione che é chiamata da loop() é sbagliato perché intasi lo stack. A ogni chiamata di una funzione nella RAM viene memorizzato dove deve essere ritornato al termine della funzione. Se chiami da una funzione se stessa direttamente o nel Tuo caso indirettamente si accumulano questi indirizzi di ritorno al punto di ocupare tutta la RAM siservata per questo scopo.

soluzione semplice:
Puoi mettere la parte di programma che aggiorna i led in una funzione e chiamare quella sia nel funzionamento normale dal loop() che nel impostazione ora dalla funzione di setaggio ora "modifica_ora()" dentro il while().
Questo dovrebbe risolverti semplicemente il problma.

Ciao Uwe
« Last Edit: July 05, 2011, 05:41:01 am by uwefed » Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 128
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Grazie mille a tutti....farò qualche prova!
Mi sa che mi rivedrete presto smiley-grin
Logged

Pages: [1]   Go Up
Jump to: