Funzione Auto Manuale

Ciao a tutti
sto cercando un esempio o qualcuno che abbia fatto una funzione auto/manuale

Spiego meglio con un esempio quello che desidererei capire e studiare

Accendiamo un LED

Desidero scegliere se accendere il led in modo manuale tramite un pulsante o
se accendere il led tramite un timer (automatico)

Ovviamente se scelgo la funzione manuale, la funzione auto deve essere esclusa e disabilitata
e se scelgo auto la funzione manuale deve esser esclusa e disabilitata

Partirei da qui:

boolean manualModeEnable = 0; // se vero modalità manuale abilitata
boolean autoModeEnable = 0; //se vero modalità abilitata
boolean modeSelected; // mentre vero è possibile selezionare una modalità
int modeNumber; //numero della modalità (auto/manual)

Avete suggerimenti ???

Grazie in anticipo

Ciao Datalife,

di boolean ne basta una per decidere se MANUALE od AUTOMATICO…e la gestisci o con una if/else o con due if…uno che verifica se true l’altra se false.

poi…come passi lo switch tra AUTOMATICO e MANUALE?..pin in ingresso?..comando da seriale?..altro?

Innanzitutto GRAZIE
io pensavo a una cosa del genere, caricato funziona (manca selezione Auto Man) ma è solo un if
la cosa importante lo switch se è OK e fa la sua funzione di abilitare una scelta e disabilitare tutto il resto e si può ottimizzare ?

#include <LCD.h>
#include <LiquidCrystal.h>
#include <LiquidCrystal_I2C.h>

const int butUp = 8;
const int butDown = 9;
const int enter = 10;
const int butP = 11;
const int butM = 12;
boolean t_butUp, t_butDown, t_butP, t_butM, t_enter;

boolean manualModeEnable = 0; //if true the manual mode is enabled
boolean autoModeEnable = 0;  //if true the auto mode is enabled
boolean modeSelected; // while true you can select a mode
int modeNumber; //number of the mode

LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

void setup() {
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  lcd.begin(20, 4);
  t_butUp = 0x00;
  t_butDown = 0x00;
  t_butP = 0x00;
  t_butM = 0x00;
  t_enter = 0x00;
}

void homePosition()
{
 lcd.setCursor(4, 1);
 lcd.print("HELLO WORLD !");
}

void manualMode()
{
  lcd.clear();
  lcd.print("Modalita Manuale");
  while (manualModeEnable == 1)
  {
   lcd.setCursor(5, 2);
   lcd.print("Giu");
  if(!digitalRead(enter)) t_enter = 0x01;
  if(digitalRead(enter) && t_enter)
     { t_enter = 0x00;
   manualModeEnable = 0;
   lcd.clear();
   break;}
  }
 }

void autoMode()
{
  lcd.clear();
  lcd.print("Modalita Automatica");
  while (autoModeEnable == 1)
  {
   lcd.setCursor(3, 1);
   lcd.print("Velocita 1");
   lcd.setCursor(3, 2);
   lcd.print("Velocita 2");
  if(!digitalRead(enter)) t_enter = 0x01;
  if(digitalRead(enter) && t_enter)
     { t_enter = 0x00;
   manualModeEnable = 0;
   lcd.clear();
   break;
   }
  }
}

void loop() {
  homePosition();
  if(!digitalRead(enter)) t_enter = 0x01;
  if(digitalRead(enter) && t_enter)
     { t_enter = 0x00;
     lcd.clear();
  while (modeSelected == 0){
  modeSelected = 0;
  modeNumber = 0;
  lcd.setCursor(1, 0);
  lcd.print("Scegli la modalita");
  lcd.setCursor(0, 1); 
  lcd.print("> Automatico   ");
  lcd.setCursor(0, 2); 
  lcd.print("  Manuale      ");
  if(!digitalRead(enter)) t_enter = 0x01;
  if(digitalRead(enter) && t_enter)
     { t_enter = 0x00;
      modeNumber = 1;//manual mode
      }
  if(!digitalRead(butUp)) t_butUp = 0x01;
  if(digitalRead(butUp) && t_butUp)
     { t_butUp = 0x00;
      modeNumber = 2;//manual mode
      }

  switch(modeNumber) 
  {
    case 1:
      manualModeEnable = 1; //manual mode
      manualMode();
      break;
    case 2:
      autoModeEnable = 1; //auto mode
      autoMode();
      //homePosition();
      break;}
  }
 }
}

be sicuramente diventa più leggibile se i vari boolean anziche valere 0x00 o 0x01 li fai diventare true o false :wink:

lo stesso vale per i vari pulsanti,

se hai scritto all’inizio

butUp = 8

perchè poi scrivi

pinMode (8,INPUT_PULLUP)

questo sarebbe comodo solo se scrivessi

for (byte x =8; x<=12 ;x++){
   pinMode(x,INPUT_PULLUP);
}

così con 3 righe imposti tutti i pulsanti

come ti diceva Orso prima
ti basta una sola variabile booleana per manuale/automatico
se la variabile vale true è (per esempio) automatico
se vale false è manuale
averne 2 ti complica la vita

OK
grazie ragazzi vado a modificare i tasti ed elimino la booleana manualMode

GRAZIE ancora

Desidero scegliere se accendere il led in modo manuale tramite un pulsante o
se accendere il led tramite un timer (automatico)

Ovviamente se scelgo la funzione manuale, la funzione auto deve essere esclusa e disabilitata
e se scelgo auto la funzione manuale deve esser esclusa e disabilitata

Ma per selezionare il modo usi un pulsante o un selettore?

Nel caso del pulsante, la situazione si complica.

Se usi un pulsante, che è monostabile, l'unico modo che mi viene in mente per rendere i due modi, manuale/automatico, mutualmente esclusivi è di commutarli a seguito della premuta/ripremuta del pulsante.
Quinsi si intercetta il fronte di salita della premuta e si cambia il modo per mezzo di un'operazione di inversione logica.

Qua sotto trovi uno pseudocodice che fa quello che richiedi, non ti rimane che adattarlo al "linguaggio di Arduino" ossia tradurlo in C.

Nello pseudocodice ipotizzo che il pulsante è normalmente aperto, se così non fosse bisogna invertire la logica.

Un altro svantaggio è che alla riaccensione della scheda perdi il modo che avevi scelto, a meno che non lo memorizzi nella EEPROM di Arduino, quindi la cosa più logica è settare il manuale come modo predefinito all'accensione. Inoltre la funzione antirimbalzo (debounce in inglese) diventa fondamentale, visto che un ingresso oscillante provocherebbe centinaia di cambi di modo a casaccio :D.

Se usassi un interruttore, che è bistabile, la gestione sarebbe molto più semplice. L'intercettazione del fronte di salita sarebbe superflua, la posizione dell'interruttore determinerebbe direttamente i modi manuale/automatico.

#define MAN 0
#define AUTO 1

bool pulsanteSelezioneModo = LOW;
bool fronteSalita = LOW; 
bool statoPrec = LOW

bool pulsanteLED = LOW;

bool modo = MAN; 

void setup() {	
		...
	}

void loop() {

pulsanteSelezioneModo = leggi(indirizzo_pin_pulsanteSelezioneModo)
pulsanteLED = leggi(indirizzo_pin_pulsanteLED) 
	
fronteSalita = pulsanteSelezioneModo AND NOT statoPrec

statoPrec = pulsanteSelezioneModo;

IF fronteSalita THEN modo = !modo

IF modo vale MAN THEN scrivi(indirizzo_pin_LED) = pulsanteLED
ELSE IF modo vale AUTO THEN accensione temporizzata del LED 

}

Come da codice uso i pulsanti standard di arduino, non uso un interruttore On/off

Ma scusate la mia ignoranza la funzione switch

"E’ come un interruttore nel corso del programma. Fa prendere al programma diverse direzioni in base al valore della variabile (il suo nome deve essere messo tra parentesi dopo switch). E’ utile perché può sostituire lunghe serie di if."

e continua a fare l'istruzione all'infinito fino a quando non c'è un break.

Se è cosi, entro nel menu scelta attivo la prima e resta attiva la seconda viene esclusa.
Nel caso rientro nel menu della scelta e seleziono la seconda la prima viene disabilitata e si abilita e resta attiva la seconda.

è corretto ?

lo switch è come un if, ma con lo switch il programma esegue quello che c'è all'interno del case e se metti il break alla fine di ogni case termini il controllo switch e continui senza troppi problemi. molto più semplice da interpretare rispetto agli if, ma a me risulta non annidabile con altri switch.

Come da codice uso i pulsanti standard di arduino, non uso un interruttore On/off

Ma scusate la mia ignoranza la funzione switch

“E’ come un interruttore nel corso del programma. Fa prendere al programma diverse direzioni in base al valore della variabile (il suo nome deve essere messo tra parentesi dopo switch). E’ utile perché può sostituire lunghe serie di if.”

e continua a fare l’istruzione all’infinito fino a quando non c’è un break.

Se è cosi, entro nel menu scelta attivo la prima e resta attiva la seconda viene esclusa.
Nel caso rientro nel menu della scelta e seleziono la seconda la prima viene disabilitata e si abilita e resta attiva la seconda.

è corretto ?

La struttura switch-case, come hai giustamente citato, è un’istruzione di selezione. Ma tieni presente che la selezione avviene in funzione del valore di una variabile, che in questo caso proviene dal pulsante, e se il valore cambia allora viene selezionato un “case” diverso dal precedente. Il pulsante al momento del rilascio torna allo stato di riposo che equivale a uno 0 logico (nessun passaggio di corrente), se il pulsante è normalmente aperto. Poniamo che il pulsante premuto (passaggio di corrente) equivalga a modo automatico selezionato e che finché è premuto il modo automatico viene mantenuto (variabile =1), al momento del rilascio il valore cambia automaticamente perché il tasto fisicamente apre il suo contatto e si annulla il passaggio di corrente quindi si va a selezionare il modo manuale (variabile =0). In pratica, se non memorizzi l’evento della premuta, il valore a 1 della variabile perdura fintantoché tieni pigiato il tasto.

e continua a fare l’istruzione all’infinito fino a quando non c’è un break.

No, sbagliato non funziona così. A meno che nei case non ci sia un while, o altra istruzione ciclica, che fa ciclare le istruzioni contenute nel case all’infinito. Ad ogni modo il break dovrebbe stare fuori dal corpo dell’istruzione ciclica, sennò il ciclo verrebbe interrotto. I break servono per non eseguire le istruzioni del case successivo, se vengono omessi semplicemente saranno eseguite anche le istruzioni del o dei case che vengono dopo di quello selezionato. Vale a dire che un case non terminante con un’istruzione di break, fa sì che due o più case siano selezionati dallo stesso valore della variabile sottoposta allo switch.
In definitiva lo switch, se come ho detto prima non viene alterato da istruzioni esterne, di per sé esegue le istruzioni del case e SUBITO DOPO il break l’esecuzione del programma continua.
Ci sono istruzioni di selezione e iterazione (ciclo/ripetizione), lo switch è esclusivamente un’istruzione di selezione.

Diverso è il caso in cui selezioni il modo solo una volta ad inizio programma e poi non fai ciclare più la lettura dello stato del tasto. Non ho letto come hai strutturato il programma, comunque anche se fosse così per selezionare l’automatico dovresti avere un tasto di start programma separato, tenere premuto il tasto di selezione modo, e infine premere il tasto di start. Cioè tasti di start e selezione modo premuti contemporaneamente attivano il modo automatico una sola volta. Dopodiché, il tasto di selezione modo verrebbe ignorato fino a che non si verifichi una riaccensione della scheda oppure alla pressione di un eventuale tasto di stop programma che farebbe ripartire il programma dall’inizio.

Intanto grazie per la spiegazione
Ora la leggo e rileggo bene poi ci studio sopra e vedo che strada percorrere.

Una cosa però, ho notato che con il comando digitalWrite(Lamp1, HIGH);
mi rimangono accesi i led anche se esco dallo switch con analogWrite(Vch1Pin, 255) se esco dallo switch
si spengono.

se non gli dai una istruzione diversa non è possibile che si "spengano" da soli :slight_smile:

Patrick_M:
se non gli dai una istruzione diversa non è possibile che si "spengano" da soli :slight_smile:

Perdona la mia ignoranza ma questa non l'ho capita, chiedo venia!

Faccio un esempio pratico.
Dalla schermata principale dove visualizzo - temperatura/valore pH/data e ora -
se premo "Enter" entro nel menu principale
vado alla voce impostazioni premo "Enter" ed entro nel submenu
qui scelgo la voce "Accendi Spegni Neon" premo "Enter" e accedo al seguente codice.

Se premo pulsante "Piu" accendo e poi spengo il led1, se premo "Meno" accendo e spengo il led2.
Con "Enter" esco dal void luci e torno alla schermata principale temperatura/pH/data e ora
senza che i led si spengano

Se sostituisco digitalWrite(Lamp1, HIGH); con il comando per accendere un led rgb
analogWrite(Vch1Pin, 255);
analogWrite(Vch2Pin, 255);
analogWrite(Vch3Pin, 255);

i tre pin sono rosso/verde/blu, il led rgb si accende correttamente ma se premo "Enter" torno alla schermata principale ma il led rgb si spegne.

Ho variato solo questo

void luci() //Accendi Spegni Luci Neon//
{
  lcd.clear();
  while(1){
  lcd.setCursor(0, 0);
  lcd.print("ACCENDI SPEGNI NEON");
  lcd.setCursor(0, 1);
  lcd.print("Premi ENTER. Accendi");
  lcd.setCursor(0, 2);
  lcd.print("e Spegni Linea 1 e 2");
  lcd.setCursor(0, 3);
  lcd.print("premi Tasti DX e SX");
  if(!digitalRead(enter)) t_enter = 0x01;
  if(digitalRead(enter) && t_enter)
     { t_enter = 0x00;
       lcd.clear();
  while(1){
  lcd.setCursor(0, 0);
  lcd.print("ACCENDI SPEGNI NEON");
  lcd.setCursor(2, 1);
  lcd.print("Stato LUCE1 ");
  lcd.setCursor(2, 2);
  lcd.print("Stato LUCE2 ");
  if(!digitalRead(butP)) t_butP = 0x01;
  if(!digitalRead(butM)) t_butM = 0x01;
  if(digitalRead(butP) && t_butP)
  {
     t_butP = 0x00;
     set1++;
     if(set1 > 2) set1 = 0x01;
     switch(set1)
     {
         case 0x01:
               lcd.setCursor(2, 1);
               lcd.print("Stato LUCE1 On ");
               digitalWrite(Lamp1, HIGH);
               break;
         case 0x02:
               lcd.setCursor(2, 1);
               lcd.print("Stato LUCE1 Off");
               digitalWrite(Lamp1, LOW);
               break;
     }
  }
  if(digitalRead(butM) && t_butM)
  {
     t_butM = 0x00;
     set2++;
     if(set2 > 2) set2 = 0x01;
     switch(set2)
     {
         case 0x01:
               lcd.setCursor(2, 2);
               lcd.print("Stato LUCE2 On ");
               digitalWrite(Lamp2, HIGH);
               break;
         case 0x02:
               lcd.setCursor(2, 2);
               lcd.print("Stato LUCE2 Off");
               digitalWrite(Lamp2, LOW);
               break;
     }
 }
  if(!digitalRead(enter)) t_enter = 0x01;
  if(digitalRead(enter) && t_enter)
     { t_enter = 0x00;
       lcd.clear();
       break;
       avanza = 3 ;}
  }
break;}
 }
}

Puoi farmi capire una cosa: ma tutto questo che cosa dovrebbe comandare? Sei partito dall'esempio di un led e mo " temoeratura, ph..." giusto per capire di che parliamo.
Inoltre quanto tempo hai per farlo?

Perdona la mia ignoranza ma questa non l'ho capita, chiedo venia!

intendo dire che se da qualche parte hai scritto

analogWrite(Vch1Pin, 255)

l'unico modo perchè questo led (che nel pezzo di programma che hai postato non esiste, quindi è difficile capire a cosa ti riferisci), l'unico modo dicevo, perchè questo led si spenga è che da qualche altra parte del programma ci sia o questa istruzione

analogWrite(Vch1Pin, 0)

o questa

digitalWrite(Vch1Pin,LOW)

o questa...

digitalWrite(5,LOW)  //supponendo che Vch1Pin corrisponda al pin 5

o infine questa

pinMode(Vch1Pin,INPUT)

cioè se in qualche modo non modifichi lo stato del pin Vch1Pin quello continuerà fino alla fine dei giorni a rimanere come l'avevi lasciato l'ultima volta ed in questo caso tu l'hai lasciato con un PWM 255 quindi praticamente a +5V continui, quindi acceso alla max intensità

Silente:
Inoltre quanto tempo hai per farlo?

finchè i pesci restano vivi :smiley:

Grazie ragazzi
ora mi leggo le vostre riposte, chiedo scusa ma sono sono stato in vacanza per un paio di settimane
Ora si torna a sgobbare e poi vi aggiorno
GRAZIE !!!