Go Down

Topic: [Risolto] Attendere che sensore entri in regime stabile (Read 881 times) previous topic - next topic

fvlgnn

Apr 07, 2013, 04:17 pm Last Edit: Apr 08, 2013, 07:36 pm by fvlgnn Reason: 1
Ciao a tutti,
sto ottimizzando uno sketch che esegue una determinata funzione ogni volta che un input cambia di stato, con i pin digitali è facile dato che uso 0/1 ma con i pin analogici è più complesso per il loro variare sia all'accensione, che durante il funzionamento (esempio sensore gas, temperatura, ecc.) con il map ho fatto in maniera tale che queste variazioni siano meno frequenti.

Qualcuno di voi ha una soluzione o un comando che attualmente mi sfugge per:
1) attendere del tempo dopo all'accensione prima di leggere il valore dei sensori analogici per aspettare che gli hardware si stabilizzino prima di entrare in regime.
2) eseguire una determinata funzione quando il variare dei sensori analogici muta di una certa costante.

Per il primo problema mi è venuto in mente l'uso di millis ma non ho capito come si resetta ad ogni loop, nel reference dice che torna a 0 dopo circa 50gg e forse potrebbe essere la soluzione che cerco, secondo voi?

Per il secondo problema potrei usare un if in questa maniera if ((valore <= valore+x) || (valore >= valore+x))
secondo voi ad ogni loop rischio che questo caso non si verifichi mai???

Grazie a chiunque voglia discutere con me di questa soluzione.
Buona domenica a tutti!
Gianni
Il 99% dei problemi informatici si trovano tra la tastiera e la sedia!

leo72

1) l'attesa con millis mettila nel setup(), in modo che l'attesa venga eseguita solo 1 volta all'avvio dell'Arduino.
Code: [Select]
void setup() {
  .....
  while (millis() < 3600000) { //1 ora di attesa (1000*60*60)
    .....qui puoi fare qualcos'altro, ad esempio leggere un pulsante
  }
}

void loop() {
}


2) i controlli entro un certo range si fanno con l'and logico mettendo prima il limite inferiore e poi quello superiore:
Code: [Select]
if ((valore >= minimo) && (valore <= massimo)) {
  ....
}

Così solo se valore è compreso fra minimo e massimo il codice nell'if viene eseguito

fvlgnn

Grazie Leo72 Come sempre ti ringrazio della disponibilità e del lavoro che svolgi su questo forum!


1) l'attesa con millis mettila nel setup(), in modo che l'attesa venga eseguita solo 1 volta all'avvio dell'Arduino.

Non avevo mai pensato a mettere l'attesa nel setup ;) questa soluzione mi piace ... grazie!


2) i controlli entro un certo range si fanno con l'and logico mettendo prima il limite inferiore e poi quello superiore:
Code: [Select]
if ((valore >= minimo) && (valore <= massimo)) {
  ....
}

Così solo se valore è compreso fra minimo e massimo il codice nell'if viene eseguito

Questa soluzione l'avevo scartata perché non vorrei impostare una costante di massimo o minimo ma vorrei usare il valore letto sul pin analogico per fare il paragone/controllo, es.
Code: [Select]

// X è un numero intero
if ((valore >= valore+X) && (valore <= valore+X)) {
  ....
}

In questa maniera però il caso dell'if non si avvera mai dato che Arduino ha in memoria valore e se aumenta o diminuisce lo paragona con un valore che è già aumentato o dimuito ... dico male?
Il mio intento è quello di creare uno sketch dinamico e in parte ci sono riuscito facendo eseguire delle funzioni ad ogni loop. Questa feature che vorrei implementeare esegue le funzioni solo quando sono necessarie ... mi sto perdendo in un bicchier d'acqua  :~
Non riesco a trovare la soluzione ... forse con un while?
Grazie ancora,
Gianni
Il 99% dei problemi informatici si trovano tra la tastiera e la sedia!

leo72

Spiega per bene cosa vuoi fare, mica l'ho capito sai  :smiley-sweat:
1) tu vuoi leggere un valore da un pin analogico e controllare se quel valore sta all'interno di un certo intervallo oppure
2) tu vuoi leggere un valore da un pin analogico che corrisponda allo scostamento sopra e sotto concesso ad una variabile che tu hai?

fvlgnn


Spiega per bene cosa vuoi fare, mica l'ho capito sai  :smiley-sweat:
1) tu vuoi leggere un valore da un pin analogico e controllare se quel valore sta all'interno di un certo intervallo oppure
2) tu vuoi leggere un valore da un pin analogico che corrisponda allo scostamento sopra e sotto concesso ad una variabile che tu hai?

Hai ragione, mi sono spiegato malissimo!
Come accennato, vorrei creare uno sketch "dinamico", ovvero uno sketch che non ha bisogno di avere delle soglie impostate, a fare i controlli ci pensa PHP con MySQL o i Trigger Script di Google Drive. Supponiamo che il mio sketch invia un HTTP GET o POST ogni 3 secondi e giustamente i server dove mi appoggio o anche lo stesso Big G potrebbero infastidirsi di questa specie di BOT sui loro server. Pertanto il mio intento è quello di far inviare i dati solo quando ci sono variazioni rilevanti. Con i pin digitali usando 0/1 è facile ma con i pin analogici supponendo che sono mappati a 256 bit questa variazione dovrebbe stare intorno ai 10-15 bit qundi la soluzione che cerco è un mix delle 2 che hai segnalato ma che si avvicina più alla seconda. Lo sketch di elaborazione nel loop deve risultare standard per più utenze.
Credo che questa sia la soluzione ma il caso dell'if in questa maniera non si avvera mai ... o sbaglio?
Code: [Select]
if ((valore >= valore+10) && (valore <= valore+10)) {
  ....
}

Grazie,
Gianni
Il 99% dei problemi informatici si trovano tra la tastiera e la sedia!

leo72

Ora ho capito. Devi usare un'altra variabile e salvarci la precedente lettura del pin analogico. Facendo quindi la differenza fra la lettura attuale e la precedente, puoi impostare lo scostamento oltre il quale far inviare l'avvertimento.

Esempio:
Code: [Select]
const int range = 50; //imposto il max range
void setup() {
  prevValue = analogRead(pin); //lettura iniziale
  ...
}

void loop() {
  value = analogRead(pin);
  if (abs(prevValue - value) > range) {
    ....faccio qualcosa...
  }
  prevValue = value; // salvo la lettura
}

Ogni volta che viene fatta la comparazione, controllo se il valore assoluto della differenza fra prevValue e value sia maggiore del range impostato. Uso abs() affinché non debba fare 2 confronti, uno sullo sforamento verso il basso ed uno sullo sforamento verso l'alto.

fvlgnn

Limpido e cristallino ... grazie mille Leo72!
Attendo ad aggiungere il tag [Risolto], vorrei postare alla community parte del codice una volta che lo avrò testato.
Ciao e grazie ancora,
Gianni
Il 99% dei problemi informatici si trovano tra la tastiera e la sedia!

fvlgnn

#7
Apr 08, 2013, 07:35 pm Last Edit: Apr 08, 2013, 09:58 pm by fvlgnn Reason: 1
Come promesso scrivo il codice provato e testato che grazie a Leo72 sono riuscito ad integrare sul mio sketch "dinamico".
Lo sketch attende una calibrazione dei sensori analogici di tot tempo ed esegue delle funzioni solo quando ci sono delle variazioni significative dei sensori analogici e delle variazioni degli I/O digitali.
I valori temporali di while e delay sono esagerati ma permettono di capire meglio il funzionamento.
Code: [Select]
//init sensori analogici
int a0; // imposto il valore di a0 come intero
int prevA0; // imposto valore precedente di a0 come intero

const int range = 15; //imposto il range massimo permesso di variazione da usare per i sensori analogici

//init sensori digitali
int d7; // imposto il valore di d7 come intero
int ind7 = 7; // imposto il pin digitale 7 per la lettura
int prevD7; // imposto valore precedente di d7 come intero

boolean run = false; // imposto run come falsa

// la mia funzione da eseguire solo se ci sono variazioni significative dei pin
void funzione () {
 Serial.println("*** *** *** *** *** ***");
 Serial.println(".::ESEGUO FUNZIONE::.");
 Serial.println("*** *** *** *** *** ***");
}

void setup(){
 pinMode(ind7, INPUT); // inizializzo pin digitale 3 come ingresso

 // calibrazione per i primi 150000 millisecondi = 2' e 30''
 while (millis() < 150000) { // attendi 2,5 min  
   //attendi
 }
 //lettura iniziale di prevA0 con conversione da 1024 a 256 bit del pin analogico 0
 prevA0 = map(analogRead(A0), 0, 1023, 0, 255);

 //lettura iniziale di prevD7
 prevD7 = digitalRead(ind7);

 Serial.begin(9600);
 Serial.println("partito");
}

void loop(){  

 Serial.println("inzio loop");

 //leggo il pin analogico 0 e lo converto a 256 bit
 a0 = map(analogRead(A0), 0, 1023, 0, 255);

 //leggo lo stato del pin digitale 7
 d7 = digitalRead(ind7);

 //scrivo un report ad ogni loop
 Serial.print("valore A0 precedente:");
 Serial.print(prevA0);
 Serial.print(" - valore A0 attuale:");
 Serial.println(a0);
 Serial.print("valore D7 precedente:");
 Serial.print(prevD7);
 Serial.print(" - valore D7 attuale:");
 Serial.println(d7);

 //controllo che il valore a0 non abbia superato il range stabilito o il d7 non sia cambiato di stato
 // e come dice Leo72 per il primo controllo if si usa abs() affinché non debba fare 2 confronti
 if ((abs(prevA0 - a0) > range) || (d7 != prevD7)) {
   run = true; // imposto il booleano come vero per eseguire la funzione
   Serial.println(".:: OVERFLOW ::."); // scrivo che c'è un cambio stato
 }
 else {
   run = false; // imposto il booleano come falso e non eseguo niente
   Serial.println("valori nel range"); // scrivo che tutto è ok
 }
 prevA0 = a0; // salvo la lettura di prevA0 per il loop successivo
 prevD7 = d7; // salvo la lettura di prevD7 per il loop successivo

 if (run){ // se run è vera eseguo la funzione
   delay(1000); //attendo un secondo prima di eseguire la funzione
   funzione();
 }

 delay(2500);
 Serial.println("fine loop");
} //loop

Si possono aggiungere tutti i pin che volete controllare ;)
Per chi volesse consultare l'articolo sul mio blog personale, con la descrizione dettagliata dello sketch e i possibili utilizzi può visitare il segunte indirizzo Arduino: attendere calibrazione di sensori ed eseguire funzioni solo con variazioni significative dei valori
Grazie ancora a Leo72!
Enjoy,
Gianni
Il 99% dei problemi informatici si trovano tra la tastiera e la sedia!

leo72


Go Up