neofita, come utilizzare un valore compreso tra due massime

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!

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]

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:

//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;
  }
}

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! :blush:

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.

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 :slight_smile:

no un attimo non ci ho capito nulla sul codice di LEO... :cold_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. :zipper_mouth_face:

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 ? :roll_eyes:

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 ? :roll_eyes:

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

uwefed:

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?

Goretto:
no un attimo non ci ho capito nulla sul codice di LEO... :cold_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;
  }
}

Al codice di Leo mancano alcune inizializzazzioni

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.

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?

invece di serial.print()
usa serial.println()
:wink:

capito!

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 :wink:

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.

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

Errore mio, scusa, quello non l'avevo considerato :cold_sweat:

Goretto:
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.

La tolleranza usato é un numero a caso e il codice (sia mio che di Leo) é di esempio. Devi decidere Tu quale valore di tolleranza é opportuno usare per il Tuo circuito. Non avendo informazioni sul circuito e sui componenti usati ne Leo ne io possiamo dire quale valore é buono da usare.

Sí nid69ita ho fatto un errore. Il codice corretto:

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

Se si vuole avere un range di tolleranza minore basta modificare i numero nel secondo controllo:
if(start==1 && (x<=890||& x>=960) start = 0;else start=1;

avvio = millis(); <---- questo cosa sarebbe? una variabile?

millis() é una funzione che da come valore i millisecondi trascorsi dall'acensione di Arduino. Ha come formato del valore un unsigned long e ritorna a 0 (overflow) dopo ca 49,5 giorni. Con un controllo del intervallo opportuno un overflow non pregiudica la correttezza del intervallo. Solo se l' intervallo deve essere piú lungo di 49 Giorni hai problemi.

Ciao Uwe

Io vi ringrazio di cuore davvero tutti! finalmente a mente fredda ho capito quasi tutto il codice! Cmq si il problema era non avere il fenomeno de "attacca-stacca" quando il valore iniziava a varcare la soglia minima o massima. Con voi (se non vi stuferete) credo che non sarà troppo difficile imparare bene le basi. grazie ancora, è meraviglioso!

PS. appena tiro giù lo sketch dal pc a carbonella che ho usato per programmare ve lo mostro. Oltretutto mi stavo complicando la vita ma mi è servito moltissimo a capire una cosa in più!

Uwe la tua ultima precisazione è musica! pari un docente! :grin:

@uwe ok, ora mi sono sintonizzato :grin:
Con il primo codice non capivo

Goretto:
Uwe la tua ultima precisazione è musica! pari un docente! :grin:

Devo deluderti; non sono docente; sono un tecnico per manutenzione.

Ciao Uwe