Impianto d'Irrigazione Interrato gestito da Arduino

utilizzare 6 pulsanti collegati tutti tra loro all'A0, 5V e GNDutilizzare 6 pulsanti collegati tutti tra loro all'A0, 5V e GND

Spero che tu intenda dire " 6 pulsanti collegati attraverso resistenze "

un qualcosa del genere

Ryan0497:
... bisognerebbe creare un insieme di valori compresi tra un valore minimo e uno massimo. Come posso fare?

... map ? ... :wink:

brunello22:
Spero che tu intenda dire " 6 pulsanti collegati attraverso resistenze "

un qualcosa del genere

Si esatto... già che mi trovo, volevo sapere se ci fosse un modo per rendere i valori più costanti e meno variabili, qualcuno mi ha consigliato di utilizzare un condensatore collegato all'inizio del collegamento tra la 5V e il Pin A0. Dato che non sono tanto pratico con i condensatori mi confermate che in questo modo funzionerà meglio?

Etemenanki:
... map ? ... :wink:

L'ho vista più volte utilizzare questa "map"... oggi quando torno a casa vedrò di fare due prove qua e la e vi faccio sapere se tutto va bene.

"map" non e' altro che una funzione che ti converte una scala in un'altra, o per essere piu esatti, un'estensione di valore complessivo in un'altra proporzionale ma con scala differente ... esempio, hai una digitalRead che ti da valori da 0 a 1023, ma ti serve avere meno valori, diciamo 6 ... se fai map 0, 1023, 0, 5 (perche' 6 valori sono da 0 a 5, compreso lo zero), la variabile associata alla map ti restituira' 0 per valori fra 0 e 171 (circa, e' 170.unsaccodi6, ma io arrotondo :D)1 fra 172 e 341, 2 fra 342 e 512, e cosi via ... la stessa cosa che potresti fare a mano con una serie di if consecutivi, pero' con una sola operazione :wink:

EDIT: e si, un condensatorino da 100n fra il pin analogico e massa aiuta a stabilizzare la lettura (ricordandosi sempre che la prima lettura dell'ADC andrebbe sempre scartata)

Etemenanki:
"map" non e' altro che una funzione che ti converte una scala in un'altra, o per essere piu esatti, un'estensione di valore complessivo in un'altra proporzionale ma con scala differente ... esempio, hai una digitalRead che ti da valori da 0 a 1023, ma ti serve avere meno valori, diciamo 6 ... se fai map 0, 1023, 0, 5 (perche' 6 valori sono da 0 a 5, compreso lo zero), la variabile associata alla map ti restituira' 0 per valori fra 0 e 171 (circa, e' 170.unsaccodi6, ma io arrotondo :D)1 fra 172 e 341, 2 fra 342 e 512, e cosi via ... la stessa cosa che potresti fare a mano con una serie di if consecutivi, pero' con una sola operazione :wink:

EDIT: e si, un condensatorino da 100n fra il pin analogico e massa aiuta a stabilizzare la lettura (ricordandosi sempre che la prima lettura dell'ADC andrebbe sempre scartata)

Grazie mille... ho capito benissimo la funzione del "map". Oggi ci proverò e vedrò cosa succederà.

Non vedo l'utilizzo della map() in una lettura di un valore analogico......

Tu hai una qualcosa del genere

int Read_Buttons()
{
  ButtonsRead = analogRead(0);
  if (ButtonsRead > 900) return btnNONE;
  if (ButtonsRead < 110)   return btnRIGHT;
  if (ButtonsRead < 250)  return btnUP;
  if (ButtonsRead < 450)  return btnDOWN;
  if (ButtonsRead < 650)  return btnLEFT;
  if (ButtonsRead < 850)  return btnSELECT;
  return btnNONE;  // when all others fail, return this
}

Basta che tu sostituisca i valori che ottieni e rispettando l'ordine crescente

Mh... ci ho provato ma alla pressione dei tasti non andava. Comunque ci riproverò appena posso

brunello22:
Non vedo l'utilizzo della map() in una lettura di un valore analogico......

Invece e' proprio li che viene comodo :wink:

Tu hai valori che non necessariamente sono stabili e sempre gli stessi, per cui una map ti semplifica un po la vita ... metti ad esempio di avere valori che variano da 0 a 500 a passi di 100 (solo come esempio, 0 nessun pulsante premuto, da 100 a 500 per i 5 pulsanti) ma che possono anche sballare di 20 o 30 a causa di disturbi, falsi contatti, alimentazione non stabile, quello che vuoi, per cui dovresti fare una serie di controlli condizionali maggiore E minore ... invece di fare

SE minore di 50 ... - else SE maggiore di 50 E minore di 150 ... - else SE maggiore di 150 E minore di 250 ... - else ... eccetera

fai un solo if<30 {codice} else map variabile 30, 500, 1, 5, avrai che a zero (e fino a 30) hai nessun pulsante premuto (vera la condizione dell'if, che quindi salta il map nell'else, e dove puoi anche mettere variabile=0 o altro codice da eseguire se non e' premuto nulla), mentre in caso di un pulsante premuto il primo if viene saltato (perche' il valore sara' maggiore di 30) e la tua lettura, fra 30 e 500, viene divisa proporzionalmente in 5 "fette" (abbastanza larghe da comprendere disturbi e fluttuazioni, o almeno cosi si spera), ognuna delle quali ti restituisce "variabile" con un solo valore intero da 1 a 5, che potrai usare con altri if, con uno switch case, come vuoi ...

Non e' piu semplice che fare una sequenza di if/else a doppio controllo ? ... o sbaglio ? :wink:

EDIT: inoltre mi sa che il codice di prima non e' corretto ... sono if indipendenti, non e' una catena di if/else, inoltre i valori sono in ordine crescente ma con confronto "minore di", per cui se non ho letto male, se ad esempio il valore fosse 450 (quarto if), sarebbero eseguiti comunque anche il secondo ed il terzo, perche' sia 110 che 250 sono comunque minori di 450 (con gli if indipendenti succederebbe comunque, anche in ordine decrescente) ... questo non succederebbe con una sequenza di if/else con valori decrescenti, se non sbaglio, perche' la prima condizione vera interrompe la sequenza saltando i successivi else ... o almeno cosi dovrebbe essere ...

Ethem...

cosa c'è di più semplice della funzione proposta

int Read_Buttons()
{
  ButtonsRead = analogRead(0);
  if (ButtonsRead > 900) return btnNONE;
  if (ButtonsRead < 110)   return btnRIGHT;
  if (ButtonsRead < 250)  return btnUP;
  if (ButtonsRead < 450)  return btnDOWN;
  if (ButtonsRead < 650)  return btnLEFT;
  if (ButtonsRead < 850)  return btnSELECT;
  return btnNONE;  // when all others fail, return this }

Sotto a 110 c'è un pulsante
tra 111 e 249 un'altro e via dicendo
Ora, a meno che due valori non si accavallino, un modo più semplice io non lo vedo

Etemenanki:
EDIT: inoltre mi sa che il codice di prima non e' corretto ... sono if, non e' una catena di if/else, inoltre i valori sono in ordine crescente ma con confronto "minore di", per cui se non ho letto male, se ad esempio il valore fosse 450 (quarto if), sarebbero eseguiti comunque anche il secondo ed il terzo, perche' sia 110 che 250 sono comunque minori di 450 ...

Esatto... ecco perchè forse sembrava impazzire quando premevo un pulsante. Proprio per questo motivo cercavo un modo per creare un insieme di valori compresi tra...

Quando premevo un pulsante, questo mi faceva circa la funzione degli altri 3 pulsanti ( proprio perchè comprendeva i valori degli altri pulsanti)

brunello22:
Ethem...

cosa c'è di più semplice della funzione proposta
...

... un map ... :stuck_out_tongue:

No, seriamente, se non ci metti una sequenza di else con i valori decrescenti non ti funzionera' mai correttamente ... ad esempio, forse potrebbe funzionare cosi ... (da provare, comunque)

int Read_Buttons()
{
  ButtonsRead = analogRead(0);
  if (ButtonsRead > 900)
  {
    return btnNONE;
  }
  else if (ButtonsRead < 120)
  {
    return btnUP;
  }
  else if (ButtonsRead < 250)
  {
    return btnDOWN;
  }
  else if (ButtonsRead < 350)
  {
    return btnLEFT;
  }
  else if (ButtonsRead < 800)
  {
    return btnSELECT;
  }
}

(ma continua a sembrarmi piu semplice la map ;))

EDIT: l'ultimo else non serviva
RIEDIT: corretta con i tuoi valori, si puo fare anche decrescente, ma con gli else, senza non va bene

RAGAZZI.....

Ovvio che i valori devono essere in ordine crescente, altrimenti come fa' a funzionare

Quindi, prima di tutto leggere i valori che danno ogni pulsante premuto e poi assegnarli alla funzione

es

btnSELECT = 95
btnLEFT = 750
btnRIGHT = 300
btnUP = 200

diventa

int Read_Buttons()
{
  ButtonsRead = analogRead(0);
  if (ButtonsRead > 900) return btnNONE;
  if (ButtonsRead < 120)   return btnSELECT;
  if (ButtonsRead < 250)  return btnUP;
  if (ButtonsRead < 350)  return btnRIGHT;
  if (ButtonsRead < 800)  return btnLEFT;
  return btnNONE;  // when all others fail, return this }

brunello22:
RAGAZZI.....
Ovvio che i valori devono essere in ordine crescente, altrimenti come fa' a funzionare ...

Ehm ... scusa, ma ... premo UP, quindi valore minore di 250 ... nel tuo esempio ...

if (ButtonsRead > 900) return btnNONE; non viene eseguita, perche' valore minore di 250 ...
if (ButtonsRead < 120) return btnSELECT; non viene eseguita, perche' 250 e' maggiore di 120 ...
if (ButtonsRead < 250) return btnUP; VIENE eseguita, perche' il valore e' 250 (o minore) ...
if (ButtonsRead < 350) return btnRIGHT; VIENE eseguita, perche' 250 e' minore di 350 ...
if (ButtonsRead < 800) return btnLEFT; VIENE eseguita perche' 250 e' minore di 800 ...

... capisci cosa intendo ?

Guarda che il return chiude la funzione, quindi quando trova la prima condizione come vera, torna da chi l'aveva chiamata

Pero' a me a questo punto viene un'altro dubbio ... Ryan, cosa hai usato per evitare che la routine di lettura venga continuamente eseguita ad ogni ciclo del loop per tutto il tempo che il pulsante rimane premuto ? ... perche' con la velocita' di esecuzione del loop, anche premere un pulsante per un decimo di secondo, il micro lo legge decine di volte ... quindi per lui e' come se in quel periodo di tempo tu lo premessi decine di volte a ripetizione, se non usi un sistema per dire al micro di leggere una sola volta alla pressione e poi ignorare finche' non viene rilasciato ...

... non e' che stiamo cercando il problema nel posto sbagliato ? ...

Etemenanki:
per evitare che la routine di lettura venga continuamente eseguita ad ogni ciclo del loop per tutto il tempo che il pulsante rimane premuto ?

Si stava provando ad usare la logica del post #31: lettura pulsanti -> scancode -> rilevamento istante di pressione in base alla lettura precedente, con tanto di blocco ulteriori pressioni finché il tasto non viene rilasciato. Il loop, in quella versione, per semplicità ha un delay 50 che fa da antirimbalzo.

La lettura da un pin analogico non cambia niente, basta modificare la sola funzione leggiScanCode per leggere da pin analogico invece che da 4 digitali.

E' corretto sostituire il codice così? (dal post #38)

Il vero problema è la filosofia di utilizzo della "libreria" citata (Simple universal LCD menu code - #2 by system - Displays - Arduino Forum), che ha un loop interno bloccante, per cui il loop principale smette di essere eseguito, nessun pulsante viene più letto ecc ecc ecc.

In sostanza non basta mettere assieme due sketch sperando che funzionino, bisogna anche sapere esattamente quali vincoli prevedono: ordine di esecuzione, eventuali temporizzazioni, esecuzione bloccante/non bloccante, chi chiama chi e in che ordine.

Banalmente basta mettere la chiamata alla funzione 'letturaPulsanti();' del post #31 dentro il loop della libreria, dove c'è appositamente scritto:

IF YOU WANT OTHER CODE GOING ON IN THE BACKGROUND
WHILE WAITING FOR THE USER TO DO SOMETHING, PUT IT HERE

Ma, siccome i nostri pulsanti funzionavano bene solo grazie al delay 50 (che ci permetteva di non occuparci di rimbalzi meccanici), allora anche questo va spostato dentro il loop della libreria, in alternativa bisogna completare l'hardware con appositi filtri di debounce (che nel caso di lettura analogica porta a qualche complicazione in più perché i valori possono variare "lentamente" in tutto il range creando false letture).

E se invece dedicassi un pin analogico per ogni pulsante?

A0 -> Invio
A1 -> Indietro
A2 -> Sopra
A3 -> Sotto

Così poi con un codice si esegue la logica:
"Se Invio=1..." questo per ogni pin usato così come si fa per accendere/spegnere un semplice led alla pressione di un pulsante collegato a uno dei pin.

Che ne pensate? Voi con la vostra esperienza dite che in questo modo potrei aver trovato una soluzione? Purtroppo oggi non posso provare proprio nulla... mi sono sorti degli imprevisti che non mi permettono di dedicarmi all'hobbystica.

Posso soltanto pensare a modi che appena potrò dovrò testare e farvi sapere quale ha funzionato

interessante questa funzione "map"...prima o poi la voglio capire

Ryan0497:
E se invece dedicassi un pin analogico per ogni pulsante?

A0 -> Invio
A1 -> Indietro
A2 -> Sopra
A3 -> Sotto

e se invece trattasti ogni pulsante come un pezzo unico....magari ricordando in che condizione era precedentemente?????

ed in che condizione sono gli altri pulsanti????

ES

il pulsante 1 è premuto adesso, ma prima era già premuto oppure non era premuto???
gli altri pulsanti in che condizione sono???

Puso:
interessante questa funzione "map"...prima o poi la voglio capire

io la sto per testare... se non ho capito male

void loop()
{
  int val = analogRead(0);
  val = map(val, 0, 1023, 0, 3);
}

avendo la schedina dei 4 pulsanti, con questo sketch, alla pressionedi ogni tasto, avrò 0 per il tasto Indietro, 1 per l'Invio, 2 per Su e 3 per Giù cosìda poter richiamare immediatamente i pulsanti con una variabile ben definita e costante al posto di richiamarla con valori poco precisi compresi in un insieme che ha un valore minimo e un valore massimo. Ovviamente che Etemenanki mi corregga se ho sbagliato qualcosa in ciò che ho detto