Ciao a tutti, sto cercando di eseguire un azione che dovrebbe essere semplicissima, ma a cui non ho trovato soluzione non capisco dove sbaglio.
Il mio obbiettivo consiste nel controllare un servo motore 360, in modo tale da farlo girare in un verso per un certo intervallo di tempo per poi rimanere fermo, il tutto dovrebbe accadere solo quando tramite il telecomando viene premuto un certo pulsante. I collegamenti sono corretti, il ricevitore IR funziona e il comando viene eseguito, l'unico grande problema è che il servo gira una volta per ad esempio 4secondi, ma poi ripete l'azione all'infinito, non riesco ad uscire dal loop o quantomeno a ritornare alle condizioni iniziali prima che io ad esempio prema un altro pulsante del telecomando. Scusate la spiegazione banale e lunga, ma non so più che fare. Grazie in anticipo.
#include <Servo.h>
#include "IRremote.h"
Servo servo;
int receiver = 2;
int i = 0;
bool a;
IRrecv irrecv(receiver);
decode_results results;
void setup()
{
Serial.begin(9600);
servo.attach(12);
irrecv.enableIRIn();
}
void loop() {
if (irrecv.decode(&results))
{ if (a == true) {
switch (results.value)
{
case 0xFF30CF:
servo.write(0);
delay(2000);
servo.write(90);
delay(100);
a = false;
break;
}
}
}
}
Prima di copiare il codice, premi CTRL+T per abilitare la formattazione automatica. Al posto di delay() usa la funzione millis().
La funzione delay(2000) ferma per 2 secondi l'esecuzione delle altre istruzioni. Temporizzare porzioni di codice con millis() per il principiante è risultato essere complesso, ma è l'unica soluzione pratica per non impegnare la CPU e lasciare che questa possa eseguire le altre istruzioni presenti nel loop().
Grazie mille gentilissimo, quindi se ho capito bene utilizzare la funzione millis mi permetterà di eseguire l'azione del case per un certo intervallo e poi non si ripeterà, giusto?
No, usare millis per calcolare i tempi trascorsi serve, assieme a una corretta struttura logica, per poter gestire più cose contemporaneamente, ad esempio reagire alla pressione di un pulsante di stop mentre è in corso un'azione lunga diversi secondi, cosa che usando lunghi delay non sarebbe possibile (escluderei in questo momento discorsi legati a interrupt che andrebbero a creare un ulteriore livello di complicazione).
Il problema non è quale istruzione usare, ma come impostare una logica prima funzionante su carta e poi traducibile in istruzioni. E inevitabilmente si arriva alla macchina a stati, che è il modo più semplice per pensare e descrivere qualsiasi processo sequenziale e qualsiasi compito di automazione.
Occhio che con questa riga dentro il case stai dichiarando una nuova variabile locale diversa da quella che avevi dichiarato all'inizio.
Togli il bool e lascia solo a=false;
La mia risposta sarebbe identica a quella di @Claudio_FF .
Direi di iniziare a sistemare il tuo primo posto.
Clicca sull'icona della matita per editare il tuo primo post.
In arduino IDE carica il tuo programma e premi CTRL+T. Copia ed incolla lo sketch nel tuo primo post sostituendo quello presente.
Poi nell'IDE, correggi gli errori:
Ok grazie a tutti, ho sistemato gli errori e la formattazione dello sketch, in questo modo una volta eseguito il case, si dovrebbe interrompere il ciclo oppure serve un altro modo per fare in modo che venga eseguito una volta sola?
Se premi la prima volta il pulsante nel telecomando 0xFF30CF esegue:
servo.write(0);
delay(2000); // cpu impegnata per 2 secondi
servo.write(90);
delay(100); // cpu impegnata per 0.1 secondi
a = false; // non entra più in if (a == true)
Quindi se premi nuovamente non esegue più ciò che ha eseguito la prima volta. Ma occhio che non esegue neanche altri comandi poiché non entra proprio nello switch.
Si grazie mille ho provato e in effetti funziona così adesso. Per accedere nuovamente allo switch dovrei usare una funzione diversa da if, o altri metodi?
Di nuovo non si tratta di quale istruzione usare, ma di quale logica impostare (che poi si traduce in istruzioni). Visto che hai usato una variabile 'a' da mettere a false per disabilitare l'esecuzione, la logica è rimetterla a true quando vuoi che l'esecuzione sia di nuovo abilitata.