Timer per dispenser con pulsante erogazione da premere una tantum

Salve, ho costruito un distributore di croccantini per gatti azionato da un pulsante (come svariati altri sul web hanno già fatto) vorrei convertirlo in un dispositivo che eroghi il cibo a tempo, ma conservare allostesso tempo la possibilità di erogare alla pressione del pulsante.

ho cercato una soluzione ovunque ma non riesco a venirne a capo perchè si crea sempre una sorta di conflitto tra i due comandii ( timer / pulsante) che in sostanza devono fare la stessa azione.

posto il mio orrendo codice iniziale ma funzionante!

#include <Servo.h>

Servo servo;

const int buttonPin = 2;

int buttonState = 0;
int ledPin = 6;


void setup() {
  // put your setup code here, to run once:
  servo.attach(9);
  pinMode(buttonPin, INPUT);
  pinMode(ledPin,OUTPUT);

}
void loop() {
  // put your main code here, to run repeatedly:
  buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH) {
    digitalWrite(ledPin,HIGH);
    servo.write(180);
    delay(1750);
  } else {
    digitalWrite(ledPin,LOW);
    servo.write(10);
                         
    
  }
}

Beh, semplice ma funzionale

Cosa intendi "a tempo" ?
Che deve erogare a delle determinate ore ?

Si, che si apra ogni 12 h ad esempio.
Ho provato a usare millis ma il delay che comunque devo inserire per lasciare aperto il servo per 1750 MS da qualche problema

Se vuoi precisione delle 12 ore nel tempo devi dotare il tuo progetto di un RTC, in tal modo preservi la funzionalità del pulsante ma aggiungi i controlli che ad una data ora eroghi il cibo

Vi ringrazio intanto per avermi risposto.
Prossimamente acquisteró questo modulo, allora.
Nel frattempo mi piacerebbe peró provare qualche soluzione basata sul software (ormai è una sfida tra me e l'ide).
Spero in qualche vostro altro suggerimento
Grazie!

dexter8D:
... Nel frattempo mi piacerebbe peró provare qualche soluzione basata sul software (ormai è una sfida tra me e l'ide).

la precisione dell'oscillatore di Arduino NON è sufficiente per avere un orologio affidabile, quindi, nell'arco di 24 ore ti potresti trovare l'orologio avanti o indietro di svariati minuti.

Per avere la precisione richiesta, ovvero esattamente ogni 12 ore (... o altro intervallo a tua scelta), DEVI avere necessariamente un modulo RTC e ti consiglio caldamente un modulo basato su DS3231 e NON su DS1307 che dcisamente meno preciso.

Guglielmo

Ho provato a usare millis ma il delay che comunque devo inserire per lasciare aperto il servo per 1750 MS da qualche problema

Perchè dici questo ?
Sono due cose diverse, con la millis() controlli che il tempo sia scaduto, quindi inserisci all'interno quello che devi fare

 if (millis() - oldmillis > ritardo )
  {
    digitalWrite(ledPin, HIGH);
    servo.write(180);
    delay(1750);
    digitalWrite(ledPin, LOW);
    servo.write(10);
    oldmillis = millis();
  }

e all'inizio devi dichiarare

unsigned long oldmillis = millis();
unsigned long ritardo = 12 * 3600UL * 1000 ; // 12 ore * 3600 secondi * 1000 millisecondi

E' chiaro che non c'è assoluta precisione, visto che la millis() nei tempi lunghi sballa un pò e in questo modo, senza un RTC esterno, le 12 ore partono dal momento in cui Arduino si accende

funziona!, grazie a tutti quanti.
il mio errore forse era mettere nel loop unsigned long currentMillis = millis().
Ora, la precisione non mi interessa tanto(i gattacci possono aspettare 2 minuti di scarto), l'ultima cosa che vorrei aggiungere è il lampeggio del led durante la funzione timer(un fatto puramente estetico, nientedimeno), che attualmente si accende solo quando viene premuto il pulsante.
provo a unire blink al codice e vi faccio sapere.
p.s.
(prossimamente vorrei aggiugere anche delle funzioni legate a una doppia pressione o una pressione prolungata del pulsante ma ancora non è il momento)

Questo è il codice attuale : timer + erogazione manuale
(ho portato il ritardo a 60000 ms per non dover aspettare 12 h :slight_smile: )

#include <Servo.h>

Servo servo;

const int buttonPin = 2;
unsigned long oldmillis = millis();
unsigned long ritardo = 60000 ;
int buttonState = 0;
int ledPin = 6;


void setup() {
  // put your setup code here, to run once:
  servo.attach(9);
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);

}
void loop() {
  // put your main code here, to run repeatedly:
  buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH) {
    digitalWrite(ledPin, HIGH);
    servo.write(180);
    delay(1750);
  } else {
    digitalWrite(ledPin, LOW);
    servo.write(10);

    if (millis() - oldmillis > ritardo )
    {
      digitalWrite(ledPin, HIGH);
      servo.write(180);
      delay(1750);
      digitalWrite(ledPin, LOW);
      servo.write(10);
      oldmillis = millis();
    }
  }
}