Progetto azionamento servo ad ogni impulso

Ok, perdono. Quindi il problema è soltanto un modo per non ripetere il ciclo all'infinito? Allora si fa semplice. In primo luogo, per correggere i rimbalzi fai un buon anti rimbalzo hardware (googla un po per vedere come si fa). Inoltre per fare quanto ti serve ti conviene ripartire da capo

1)metti SEMPRE le graffe alle if e alle else
2) modifica la variabile pos in tipo bool (varrà soltanto 1 o 0)
3) aggiungi due variabili globali (sempre bool) "devomuovere" e "statoprec"
4) lascia la setup inalterata
in loop()
5) ultima riga di loop(), così è messa: statoprec=digitalRead (pulsante);
6) se sento pulsante e non sento statoprec devomuovere diventa 1
7) se (devomuovere && timer millis())...
A) pos=!pos; qui inverto il valore di pos (se 1 diventa 0 e viceversa)
B) servo.write (90*pos);
C) carico il timer
D) devomuovere=pos

Ad occhio e nove e mezzo di sera dovrebbe andare. Sai scriverlo?

Perdono?!Assolutamente figurati, anzi perdonatemi voi per la mia inesperienza!Ahah
Comunque si, domani provo a scriverlo così e vedere cosa succede, se va tutto a buon fine provo anche a aggiungere un debounce sul pulsante! Grazie!

Buongiorno, ho provato a buttare giù due righe, ovviamente c'è qualcosa che non va...qualcuno ha voglia di dare un occhio insieme? Ovviamente IDE non riesce nemmeno a compilarlo, non riesco a capire al meglio la riga 6 suggerita da Silente. Grazie Ragazzi! :slight_smile: :slight_smile:

#include<Servo.h>
Servo myservo;
unsigned long previousMillis=0; 
unsigned long interval=145; 
bool pos;
bool devomuovere;
bool statoprec; 
int button=7;  
void setup()
{myservo.attach(9);
myservo.write(0); 
pinMode(button,INPUT);}
void loop()
{statoprec=digitalRead(button);
{if(digitalRead(button)==HIGH) && statoprec=0;
{devomuovere=1;}}
{if(devomuovere==1) && (millis()-previousMillis>interval))
{previousMillis=millis();
pos=!pos;
myservo.write(90*pos);
devomuovere=pos;}}}/code]

Ti manca la parentesi di chiusura di un if() e non puoi compilare, poi fai un assegnazione con = e non un confronto di uguaglianza con ==

Leggi cosa significa indentare il codice e applicalo sempre nei tuoi programmi!

#include<Servo.h>
Servo myservo;
unsigned long previousMillis=0; 
unsigned long interval=145; 
bool pos=1;
bool devomuovere=0;
bool statoprec=0; 
int button=7; 
int movimenti=0; 
void setup(){
    myservo.attach(9);
    myservo.write(0); 
    pinMode(button,INPUT);
}
void loop(){
   
    if(digitalRead(button)==HIGH)){
        devomuovere=1;
        pos=0;
        delay(200); // Cosi hai il tempo di sollevare il dito e fa un unica lettura
        
    }
   if(devomuovere && (millis()-previousMillis>interval)){
        previousMillis=millis();
        myservo.write(90*pos);
        pos=!pos;
        movimenti++;
        if(movimenti==3){// Quando ho mosso 3 volte il servo
            devomuovere=0; 
            movimenti=0;
        }
   }


}

Ho aggiunto un delay(200) dopo la lettura del pulsante, in tal modo si ha il tempo di sollevare il dito e
quindi fare un unica lettura dello stato pulsante.

Ci sono anche molti altri errori di logica, di sintassi e ulteriori parentesi in eccesso.

Concordo su cominciare prima di tutto a indentare, se non si vuole fare a mano almeno usare la funzione formattazione automatica dell'IDE (CTRL+T).

NOTA:Secisonodubbisucosasialindentazionenepossia
moparlaremafondamentalmentelasuamancanzaèco
mescrivereinquestomodononsicapiscenien
teenonsitrovanoglierrori

Poi consiglierei di disegnare prima la logica su un foglio di carta (diagramma di flusso), e solo quando funziona provare a tradurla in istruzioni C. All'inizio è molto importante farsi uno schema mentale di corrispondenza tra sequenza di istruzioni e diagramma a blocchi, al punto che in molti corsi di programmazione si comincia prima a disegnare algoritmi solo su carta, scrivendosi anche il valore delle variabili in ogni momento. Poi con la pratica si riesce a scrivere direttamente le istruzioni, ma può comunque servire qualche diagramma generale dell'elaborazione o dei valori assunti dalle variabili in diverse situazioni.

Spesso la logica più semplice per descrivere il comportamento complessivo del programma è la stessa che useremmo in italiano per descrivere qualcosa da fare per noi, ad esempio questa (che è anche la più adatta quando si vuole usare millis per non bloccare il ciclo di loop con le delay):

quando sono in attesa:
    se pulsante premuto:
        annoto tempo attuale
        comando servo 90 gradi
        stato = pausa1

quando sono in pausa1:
    se scaduto il tempo:
        annoto tempo attuale
        comando servo 0 gradi
        stato = pausa2

quando sono in pausa2:
    se scaduto il tempo:
        stato = attesa

Avendo un problema specifico avevo pensato a una soluzione particolare che ho proposto!

Devo fare tre movimenti del servo zero-90-zero.

  1. Ho un timer, un contatore di tempo tramite funzione millis()

  2. Premendo un pulsante abilito il timer

  3. Allo scattare del timer eseguo il movimento, inverto i gradi e conto il movimento

  4. Eseguiti i tre movimenti disabilito il timer, azzero i movimenti, e tutta la sequenza
    può ricominciare a una nuova pressione del pulsante

Ciao ragazzi, i questi giorni seguendo i suggerimenti di tutti mi sono messo a scrivere qualcosa.
Il suggerimento di scrivermi su carta cosa voglio ottenere dal programma mi ha aiutato molto, probabilmente molti di voi mi diranno che mi sono complicato la vita nel scrivere il programma, però diciamo che funziona un pò come volevo io.
L'unico problema che ho è il seguente: nel momento in cui premo il pulsante e lo tengo premuto volutamente qualche secondo (per vedere se nonostante ciò il servo ritorni nella posizione 0°), nel momento del rilascio il servo compie ancora un ciclo 0° gradi (posizione nel quale si trova di partenza) a 90 ° gradi (dove sta in uno stato di pausa di 3 secondi come detto dalla funzione millis) per finire a ritornare a 0°.
Ho analizzato più di una volta il programma e penso che il problema stia nel primo else presente nel void loop, probabilmente un problema di rimbalzo del pulsante risolvibile con un debounce?
Grazie a tutti per i suggerimenti, inizio a ingranare la marcia giusta!!

#include<Servo.h>
Servo myservo;
unsigned long pushbutton = 0;
unsigned long pushdelay = 500; //tempo in ms del ritardo del pulsante
unsigned long servopen = 0;
unsigned long intclose = 3000; //tempo in ms di quanto il servo sta aperto
bool devoaprire;
bool chiudisubito;
bool devochiudere;
int button = 7;
void setup() {
  myservo.attach(9);
  myservo.write(0);
  pinMode(button, INPUT);
}
void loop() {
  if (digitalRead(button) == HIGH) {
    unsigned long pushbutton = millis();
    devoaprire = 1;
  }
  else
  { chiudisubito = 0;
  }
  if (devoaprire == 1 && chiudisubito == 0) {
    myservo.write(90);
    unsigned long servopen = millis();
    devoaprire = 0;
    if (millis() - pushbutton > pushdelay) {
      pushbutton = millis();
      chiudisubito = 1;
    }
    devochiudere = 1;
  }
  if (devochiudere == 1 && (millis() - servopen > intclose)) {
    servopen = millis();
    myservo.write(0);
  }
}

Si, la logica è decisamente incasinata.

Quello che non capisco è come facciano a funzionare le variabili tempo 'pushbutton' e 'servopen' che, essendo locali, dovrebbero essere ricreate nuove ad ogni giro di loop.

Per il resto le variabili booleane sono inizializzate a zero (false) in modo implicito nella dichiarazione, ma potrebbero anche non esserlo, per cui sempre meglio assegnare un valore di partenza esplicito.

Sorvoliamo sul fatto che essendo booleane sarebbe meglio impostarle a true/false invece che 1/0, ma tecnicamente è la stessa cosa.

La mancanza di un debounce potrebbe sicuramente causare la ripartenza al rilascio, ma in questo caso ci sono due condizioni concomitanti che farebbero ripartire comunque anche con il debounce: tenendo premuto il pulsante a lungo la variabile 'devoaprire' a un certo punto non viene più rimessa a 0, quindi quando si rilascia diventa subito vera la condizione di partenza.

Inoltre anche la variabile 'devochiudere' non viene più rimessa a 0.

Grazie Claudio_FF, effettivamente anche a me la logica sembra un tantino complicata, suggerimenti per migliorarla?
Proverò a riscriverlo tenendo conto di quanto mi hai detto, magari tenendo conto la funzione di debounce.