Go Down

Topic: neofita, come utilizzare un valore compreso tra due massime (Read 10041 times) previous topic - next topic

Goretto

Domanda da pieno neofita di programmazione così come di elettronica.

Come è possibile far compiere un azione ad Arduino SE percepisce un valore compreso tra due massime?
Cioè io voglio che compia un'azione SE la lettura del pin X è compresa tra 900 e 950 e che ignori eventuali oscillazioni oltre tali limiti.
Vediamo se mi spiego meglio.... io voglio che compia un'azione quando al pin X rileva un valore <900.
Il problema si presenta quando il valore letto oscilla tra 900 e 901 oppure tra 900 e 899... l'azione viene attuata e arrestata rapidamene, cosa non ammissibile sul progetto che sto realizzando.

Spero di essermi spiegato.

Perdonate la novellaggine!

uwefed

#1
Aug 10, 2013, 07:49 am Last Edit: Aug 10, 2013, 09:56 pm by uwefed Reason: 1
Code: [Select]
if (start ==0 && x>=900 && x<=950) start = 1;else start=0;
if(start ==1 && x>=890 && x<=960) start = 0;else start=1;

if(start==1) esegui codice


Parte se il valore é tra 900 e 950 e si arresta se il valore é tra 890 e 960. Puó variare di 10 punti.

Ciao Uwe

[EDIT] corretto i = in ==. Errore da pricipiantissimo[/EDIT]

leo72

Altra soluzione è registrare l'istante in cui inizi l'operazione e poi, quando controlli se i parametri sono usciti dai valori di attivazione, verificare che sia passato un certo lasso di tempo prima di terminare l'azione, così da lasciargli il tempo per essere portata a conclusione.

Riprendendo l'esempio di Uwe:
Code: [Select]
//attivazione
if ((start == 0) && (lettura >= 900 && lettura <= 950)) {
  start = 1;
  avvio = millis();
}
//disattivazione
if ((start == 1) && (lettura < 900 || lettura > 950)) {
  //stacca solo se è passato "intervallo"
  if ((millis() - avvio) > intervallo) {
    start = 0;
  }
}

Goretto

#3
Aug 10, 2013, 12:02 pm Last Edit: Aug 10, 2013, 12:14 pm by Goretto Reason: 1
Fantastico amici! (posso chiamarvi amici?)
La sintassi di LEO72 la conosco a parte ovviamente la parte di "tolleranza"
La sintassi di UWE invece non l'avevo mai vista ma è molto più diretta!
A quanto pare ci sono diversi "stili" di scrivere il medesimo codice! mamma mia ancora più difficile da ricordarsi!  :smiley-red:

Oggi mi rimetto all'opera e provo!


PS. ragionando attentamente però LEO72 il tuo codice prevede una tolleranza di un solo punto mentre quello di UWE prevede una tolleranza di 10 punti. Siccome l'azione sarebbe l'avvio e l'arresto di un motore elettrico non va bene altrimenti avrei un avvio e arresto rapido di esso quando il valore oscilla di un paio di punti sulla soglia minima o massima bruciando il motore o comunque consumando troppa corrente a causa dello spunto.

menniti

Intervengo da ignorante. La soluzione di Leo risolve il tuo problema, quella di UWE lo fa solo parzialmente, in quanto non fa altro che spostare il range. Tu vuoi che succeda qualcosa tra 900 e 950, con la soluzione di Uwe il qualcosa succede tra 890 e 960, ma il problema che lamenti si ripresenta quando avrai 889-890 e 960-961. La soluzione di Leo invece fa in modo da ignorare per un certo lasso di tempo quella variazione di ±1, in pratica è la corretta applicazione del meccanismo detto di isteresi.
Questo capisco io leggendo quei due codici, poi magari non ho capito nemmeno la problematica ed allora ignoratemi :)
Manuale "Arduino e le tecniche di programmazione dei microcontrollori ATMEL"
http://www.michelemenniti.it/manuale_di_programmazione.html
http://www.michelemenniti.it/offerta.html
Articoli ElettronicaIN
http://www.michelemenniti.it/elettronica_in.html

Goretto

no un attimo non ci ho capito nulla sul codice di LEO... :smiley-roll-sweat:



if ((start == 0) && (lettura >= 900 && lettura <= 950)) {
  start = 1;
  avvio = millis(); <---- questo cosa sarebbe? una variabile?
}
//disattivazione
if ((start == 1) && (lettura < 900 || lettura > 950)) {
  //stacca solo se è passato "intervallo"
  if ((millis() - avvio) > intervallo) { <---- intervallo è un'altra variabile da dichiarare? e avvio?
    start = 0;
  }
}

oh se preferite, rinuncio eh! non voglio rompere le scatole. :smiley-zipper:

Etemenanki

Sto andando a logica, perche' di programmazione me ne intendo molto poco, ma se lo scopo e' di avere l'attivazione fra 900 e 950, e non essere disattivato "a saltelli" se oscilla ad esempio a 899 o a 951, non sarebbe sufficente modificare i parametri della sezione "disattivazione" in, ad esempio, 890 e 960 ?

Tipo, ad esempio:

//disattivazione
if ((start == 1) && (lettura < 890 || lettura > 960)) ... ecc ...

Cosi, sarebbe attivo da 900 a 950, ma non si disattiverebbe finche' non scende di nuovo oltre 890 o sale oltre 960, dando un'isteresi di 10 punti in piu o in meno ... lo stesso per gli altri valori ... ovviamente, cambiando 890 e 960 con un'altro numero, cambi l'isteresi della quantita' che vuoi tu ...

... o sto dicendo ca**ate ?  :smiley-roll-blue:

"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

lucaleo


Sto andando a logica, perche' di programmazione me ne intendo molto poco, ma se lo scopo e' di avere l'attivazione fra 900 e 950, e non essere disattivato "a saltelli" se oscilla ad esempio a 899 o a 951, non sarebbe sufficente modificare i parametri della sezione "disattivazione" in, ad esempio, 890 e 960 ?

Tipo, ad esempio:

//disattivazione
if ((start == 1) && (lettura < 890 || lettura > 960)) ... ecc ...

Cosi, sarebbe attivo da 900 a 950, ma non si disattiverebbe finche' non scende di nuovo oltre 890 o sale oltre 960, dando un'isteresi di 10 punti in piu o in meno ... lo stesso per gli altri valori ... ovviamente, cambiando 890 e 960 con un'altro numero, cambi l'isteresi della quantita' che vuoi tu ...

... o sto dicendo ca**ate ?  :smiley-roll-blue:




anche a me sembra un'ottima soluzione... se invece la lettura non è stabile userei il metodo di leo

nid69ita

#8
Aug 10, 2013, 03:25 pm Last Edit: Aug 10, 2013, 03:28 pm by nid69ita Reason: 1

Code: [Select]
if (start ==0 && x>=900 && x<=950) start = 1;else start=0;
if(start==1 && x>=890 && x<=960) start = 0;else start=1;
if(start==1) esegui codice

Parte se il valore é tra 900 e 950 e si arresta se il valore é tra 890 e 960. Puó variare di 10 punti.
Ciao Uwe


@uwe intendevi test non assegnazione nei vari if?

Ma sbaglio o non funziona?  
@goretto chiede: "compia un'azione SE la lettura del pin X è compresa tra 900 e 950"
Per il valore ad esempio di 910, il primo if (partendo con start==0) è vero perciò start diventa 1
ma il secondo if è di nuovo vero ma start diventa 0 e perciò non esegue niente.

Oppure tra i due if devi rileggere il pin?
my name is IGOR, not AIGOR

PaoloP


no un attimo non ci ho capito nulla sul codice di LEO... :smiley-roll-sweat:

Code: [Select]
if ((start == 0) && (lettura >= 900 && lettura <= 950)) {
  start = 1;
  avvio = millis(); [b]<---- questo cosa sarebbe? una variabile? [/b]
}
//disattivazione
if ((start == 1) && (lettura < 900 || lettura > 950)) {
  //stacca solo se è passato "intervallo"
  if ((millis() - avvio) > intervallo) { [b]<---- intervallo è un'altra variabile da dichiarare? e avvio?[/b]
    start = 0;
  }
}


Al codice di Leo mancano alcune inizializzazzioni
Code: [Select]
unsigned long avvio;
const unsigned long intervallo = 1000; // ad esempio 1 secondo


Fatto questo avrai che:
Se start è uguale a 0 e contemporaneamente la lettura è compresa tra 900 e 950 o anche uguale agli estremi, allora imposta start uguale ad 1 e registra nella variabile avvio il valore attuale di millis. (millis è un contatore che parte da zero all'accensione di Arduino e viene incrementato ogni millisecondo)
Per la disattivazione controlla se start sia uguale ad uno e conteporaneamente se la lettura è estrena all'intervallo, estremi esclusi.
Se vero allora controlla se è passato 1 secondo dall'ultima volta. se è passato 1 secondo (intervallo = 1000) allora imposta start a zero.

come fa a calcolrare un secondo?
Semplice, fa la differenza tra il millis al momento dell'esecusione del codice, quindi millis(), e quello precedentemente registratio, ovvero la variabile avvio.
Se la differenza è maggiore di 1000 è passato 1 secondo, la condizione è vera ed esegue il codice abbiano all'IF.

Goretto

problemino stupido... sto cercando di capire ma ho un problema col monitor seriale ovvero mi legge il valore che mi serve, il problema è che lo ripete in orizzontale invece che in verticale rendendo di fatto impossibile capire il valore scritto... come faccio?

ratto93

invece di serial.print()
usa         serial.println() 
;)
Se corri veloce come un fulmine, ti schianterai come un tuono.


leo72

Era ovvio che nel mio codice mancassere alcune inizializzazioni di variabili, l'ho scritto di getto ma era comprensibilissimo cosa mancasse, grazie Paolo per le aggiunte  ;)

Tornando al problema, rispondo prima a Etemenanki: Goretto chiedeva che una volta che l'operazione fosse partita, non venisse interrotta neanche se la lettura usciva dai parametri. Fare come dici tu comporta che se si ha una discesa o una salita improvvisa della lettura, si può andare fuori range e bloccare l'operazione. Con la mia soluzione, come ha intuito Michele, si ha che, una volta iniziata l'operazione da attivare, questa non sia più interrotta anche se la lettura esce dal range di attivazione.

Etemenanki


... non venisse interrotta neanche se la lettura usciva dai parametri. ...


Errore mio, scusa, quello non l'avevo considerato  :smiley-roll-sweat:
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

Go Up