Salve a tutti!
Sono una newbie e sono sicura che questa domanda sia stata già posta molte volte, ma pur avendo spulciato decine di post e metodi non ne sono venuta a capo.
Il problema è semplice:
In un determinato caso di uno switch case, devo trovare un modo con cui il programma continui in loop a verificare se tre condizioni sono tutte soddisfatte in contemporanea, prima di stampare una cosa nel monitor seriale e uscire dal caso. Ora come ora la condizione viene verificata una volta sola. Se quando il programma entra nel caso e tutte e tre le condizioni sono soddisfatte, stampa quello che deve stampare. Altrimenti, ovviamente, no.
Ho provato con while(1){//cose da fare in loop} ma in questo caso non è possibile uscire dal loop. Ho provato anche con il do/while e ovviamente non ha funzionato.
Come posso risolvere o aggirare il problema?
void loop() {
if (Serial.available() > 0) {
int mode = Serial.read();
switch (mode) {
case '1':
Serial.println("In Case 1");
if (digitalRead(magneticPin1) == 1 && digitalRead(magneticPin2) == 1 && digitalRead(magneticPin3) == 1) {
Serial.println("<GO>");
} else {continua a controllare finchè le condizioni in if diventano vere}
break;
case '2':
Serial.println(digitalRead(magneticPin1));
}
}
}
nid69ita:
Perciò... come puoi stare dentro al case '1' di continuo se ad ogni giro di loop() rileggi da seriale ??
Di continuo spedisci '1' ??
Grazie per la risposta!
Io, appunto, vorrei evitare di spedire di continuo '1'.
Quello che chiedo è un modo per fare un loop dentro uno dei casi di switch case in pratica
La condizione che interrompe il loop che vuoi creare va inserita nelle parentesi del while.
Io però eviterei a prescindere un approccio di questo tipo. Ogni while che inserisci, se non ben gestito, può diventare un buco nero dal quale l'esecuzione del programma non esce più oltre ad essere bloccante.
cotestatnt:
Io però eviterei a prescindere un approccio di questo tipo. Ogni while che inserisci, se non ben gestito, può diventare un buco nero dal quale l’esecuzione del programma non esce più oltre ad essere bloccante.
Grazie per la risposta!
Che approccio consiglieresti, volendo evitare lo switch…case e while?
Io ho praticamente tre casi, diciamo “modalità di funzionamento” che cambiano in base ad un comando ricevuto dal monitor seriale. Ogni modalità deve essere un loop a sè, che verifica continuamente se determinate condizioni sono soddisfatte
Infatti, per adesso,ho risolto così, anche se mi sembra un modo molto rozzo
while (x == '1') {
Serial.println("In Case 1");
if (digitalRead(magneticPin1) == 1 && digitalRead(magneticPin2) == 1 && digitalRead(magneticPin3) == 1) {
Serial.println("<GO>");
break;
}
}
Mancano alcune specifiche per poter rispondere in modo accurato, comunque è un problema che solitamente si risolve con una macchina a stati finiti (cerca sul forum per maggiori dettagli ci sono molte discussioni a riguardo usando anche MSF o FSM)
in linea di massima potresti fare una cosa del tipo (ma è un esempio fatto senza test):
if (Serial.available() > 0) {
int mode = Serial.read();
bool newState = true;
}
switch(mode)
{
case 0:
if(newState)
{
serial.print(F("mode zero"));
newState = false;
}
...cose da fare finché non cambia lo stato...
break;
case 1:
if(newState)
{
serial.print(F("mode one"));
newState = false;
}
...cose da fare finché non cambia lo stato...
Sara_kon:
Che approccio consiglieresti, volendo evitare lo switch...case e while?
L'approccio che ti ha già suggerito fabpolli, anche se organizzato in maniera leggermente diversa.
Le tre modalità di funzionamento le "incapsuli" in 3 funzioni distinte che richiami nello switch/case e da quanto ho capito hai bisogno che vengano eseguite di continuo quindi la variabile newState non è necessaria.
Inoltre in questi casi io uso sempre delle enumerazioni (enum{}) per avere un'idea immediata dei diversi stati.
void funzione1(){ cose da fare nello stato 1 }
void funzione2(){ cose da fare nello stato 2 }
void funzione3(){ cose da fare nello stato 3 }
enum states {NODEF, STATE1, STATE2, STATE3};
int actualState = NODEF;
void loop(){
if (Serial.available() > 0) {
// Cosi va bene per provare rapidamente, ma meglio prevedere un minimo di controllo su quanto ricevuto
actualState = Serial.read();
}
switch(actualState)
{
case STATE1:
funzione1();
break;
case STATE2:
funzione2();
break;
case STATE3:
funzione3();
break;
default:
break;
}
}
La variabile newState l'ho inserita perché mi pareva di aver capito che volsse stampare su monitor seriale qualcosa solo una volta al cambio di stato, se non è così concordo che sia superflua
Standardoil:
Per tanti, tantissimi casi
Array di puntatori a funzione
Una mia curiosità che esula un po' dall'argomento: perché ritieni che l'array di puntatori a funzioni sia da preferire solo se le condizioni sono molte?
Io la trovo una soluzione elegantissima e cosi a naso direi che è più "prestante" in ogni caso a prescindere dal numero delle condizioni.
L'unico dubbio che ho, è possibile passare eventuali parametri alle funzioni ed in che modo?
Io ho capito che non ho capito come si deve comportare il programma, per cui ne scrivo un’altra versione magari ci prendo.
Ok, mi sono perso questo commento:
Io, appunto, vorrei evitare di spedire di continuo ‘1’.
Il codice seguente fa quello che desideri.
int mode;
void loop() {
if (Serial.available() > 0) {
mode = Serial.read();
}
switch (mode) {
case '1':
Serial.println("In Case 1");
if (digitalRead(magneticPin1) == 1 && digitalRead(magneticPin2) == 1 && digitalRead(magneticPin3) == 1) {
Serial.println("<GO>");
} else {continua a controllare finchè le condizioni in if diventano vere}
break;
case '2':
Serial.println(digitalRead(magneticPin1));
}
}
In questo modo dopo avere premuto 1 viene eseguito in loop il case 1, premendo 2 viene eseguito il case 2 in loop e premendo un altro numero nessuno dei case viene eseguito.
Sara_kon:
Grazie per la risposta!
Infatti, per adesso,ho risolto così, anche se mi sembra un modo molto rozzo
while (x == '1') {
@Sara, come ti hanno detto sopra, non cercare di forzare cicli all'interno della loop().
La loop() è già un ciclo. Devi ragionare in maniera diversa. Non come se la loop() fosse un programma che inizia e finisce.
Quindi con delle if ed anche eventuali variabili di stato (che accendi/spegni quando serve) eviti o forzi ingresso in certi rami di if.
nid69ita:
Si, puoi passare i parametri, ma le funzioni devo avere la stessa “impronta” ovvero stesso numero e tipo di parametri.
Almeno in C.
Se i parametri sono diversi immagino che una possibile soluzione potrebbe essere raggrupparli in delle struct{} e poi passare alle n-funzioni un puntatore a struct.
Che ne dici?
Edit:
Standardoil:
Lo consiglio solo per tanti casi solo perché è leggermente meno intuitivo
Si in effetti potrebbe “intimorire” se si è poco pratici con puntatori e affini
Maurotec:
Io ho capito che non ho capito come si deve comportare il programma, per cui ne scrivo un'altra versione magari ci prendo.
Hey, grazie mille!
Ho provato sia con il primo suggerimento che mi hai dato, ma in quel caso mi stampava il "Go" anche al di fuori del case '1', mentre questo è quello che ho provato a fare e poi ho aggirato preferendo il while, perchè non saprei come trascrivere quel "continua a controllare" in else.
Ora proverò la soluzione proposta da Contestatnt che mi pare quella più alla mia portata (forse), e sicuramente mi vado a vedere la programmazione a stati, visto che, da brava ignorantella, non ne avevo mai sentito parlare
è sempre molto bello confrontarsi qui, grazie a tutti!
>Sara_kon: Quando si quota un post, NON è necessario riportarlo (inutilmente) tutto; bastano poche righe per far capire di cosa si parla ed a cosa ci si riferisce, inoltre, se si risponde al post immediatamente precedente, normalmente NON è necessario alcun “quote” dato che è sottinteso.
Gli utenti da device “mobile” (piccoli schermi) ringrazieranno per la cortesia
Guglielmo
P.S.: Ho troncato io il “quote” del tuo post qui sopra