Accendere e spegnere Arduino con un pulsante con led di stato

Buongiorno a tutti,
anni fa ho fatto questa domanda sul forum e grazie a @Claudio_FF e altri avevo anche risolto il problema, ora però avevo bisogno di implementare la cosa, volevo aggiungere due cosa, e non so come fare, premetto accendo e spengo con ritardo per evitare accensioni e spegnimenti accidentali, vorrei inserire un led bicolore che quando premo il pulsante si accende rosso e diventa verde ad accensione avvenuta, stessa cosa quando premo il pulsante per spegnere diventa rosso fino a spegnersi a spegnimento avvenuto, intanto questo poi l'altra cosa, aiutatemi una cosa per volta grazie
698256526

#define pin_pulsante 6
#define pin_mosfet 7

int rilasciato = 0;
unsigned long t;

void setup() {
pinMode(pin_pulsante, INPUT_PULLUP);
pinMode(pin_mosfet, OUTPUT);
delay(1000); //tempo ritardo in accensione
digitalWrite(pin_mosfet, 1);

}

void loop() {
if (digitalRead(pin_pulsante) == 1) rilasciato = 1;
if ((digitalRead(pin_pulsante) == 0)  && rilasciato) 
{
  if(millis() - t > 1000) digitalWrite(pin_mosfet, 0); //tempo ritardo in spegnimento
}else{
  t = millis();
}

}

Led bicolore? Io aggiungerei semplicemente un led rosso da collegare ad un altro pin.
E per il codice quindi io farei così:

#define P_PULSANTE 10
#define P_MOSFET 13
#define P_ROSSO 12

unsigned long t = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("START");

  pinMode(P_PULSANTE, INPUT_PULLUP);
  pinMode(P_MOSFET, OUTPUT);
  digitalWrite(P_MOSFET, LOW);
  pinMode(P_ROSSO, OUTPUT);

  // Accendo led rosso
  digitalWrite(P_ROSSO, HIGH);
  delay(1000); //tempo ritardo in accensione
  digitalWrite(P_MOSFET, HIGH);
  //Spengo led rosso
  digitalWrite(P_ROSSO, LOW);
  Serial.println("STARTED!");
}

void loop() {
  if (digitalRead(P_PULSANTE) == LOW && t == 0) {
    t = millis();
    // Debounce software...
    delay(50);
    // Accendo led rosso
    digitalWrite(P_ROSSO, HIGH);
    Serial.println("Inizio sequenza ");
    Serial.print(t); Serial.println("...");
  }
  if (digitalRead(P_PULSANTE) == HIGH && t > 0) {
    //Spengo led rosso
    digitalWrite(P_ROSSO, LOW);
    t = 0;
    Serial.println(" (annullata)");
  }
  //tempo ritardo in spegnimento
  if(t > 0 && millis() - t > 1000) {
    digitalWrite(P_MOSFET, LOW); //tempo ritardo in spegnimento      

    // Simulo lo spegnimento....
    digitalWrite(P_ROSSO, LOW);
    Serial.println("*** SPENTO ***");
    while (1) { };

  }
}

NOTE
Per prima cosa ovviamente ho adeguato i pin a quelli che avevo nel simulatore, devi rimettere i tuoi. E per simulare lo spegnimento ho fatto un loop che ovviamente puoi togliere.
Nota comunque come ho cambiato la struttura del tuo codice, ad esempio gli stati dei pin meglio indicarli sempre con LOW e HIGH che sono più leggibili e soprattutto standard. Poi la variabile "rilasciato" oltre ad averla usata come un bool, è inutile, basta usare la variabile "t" che se diversa da zero significa che il tasto è stato premuto.

1 Like

@docdoc grazie infinite,
la seconda cosa che vorrei aggiungere è lo spegnimento automatico se la batteria è scarica, come alimentazione uso un pacco batterie 2s e pensavo di mettere un partitore di tre resistenze da 10K, cose ne pensi?

Un partitore per leggere la tensione di una batteria è possibile, prova a leggere questo articolo dove puoi trovare anche i calcoli da effettuare (parli di batterie LiPo, vero? Tra l'altro hanno una curva di scarica abbastanza lineare quindi dovrebbe andare bene):

Ovviamente significa che nel loop() misuri periodicamente la tensione (non serve farlo continuamente, io lo farei una volta al minuto quindi usando sempre millis()) e se la tensione scende sotto al livello che avrai stabilito, dovrà fare la stessa cosa che fai per spegnere il Mosfet.

Avevo già letto quell'articolo ma non capisco come inserirlo dentro allo sketc

Fai il contrario, prendi i codici di quell'articolo e una volta che la comunicazione funziona aggiungi quello che a te serve (ossia la comunicazione e la visualizzazione sull'LCD).

Serve per distinguere la seconda pressione da una prima pressione indefinitamente lunga.

Non se se ho capito cosa intendi, ma per me non serve, perché io uso comunque la variabile "t", che riporto a zero quando rilascio prima che sia passato il tempo, e se tengo premuto il tasto per un tempo maggiore del tempo previsto per lo spegnimento di Arduino, la cosa non è più rilevante perché, appunto, Arduino si sarà nel frattempo spento.

Grazie intanto, datemi un aiuto, voglio inserire questo codice, su uno sketch che va su un wemos d1 mini, il problema è che ho solo un pin libero e i pin TX e RX, posso usare questi pin, lo sketch che uso ha un pulsante che mi cambia le pagine una volta acceso, come faccio a integrare sullo stesso pulsante anche l'accensione e lo spegnimento, ho veramente bisogno se potete aiutare, Grazie ancora

Dipende da come viene attualmente usato quel pulsante di selezione e da come è strutturato il programma.

Per usare un solo pulsante probabilmente basta riconoscere un click (selezione) da una pressione lunga (spegnimento).

Ho recentemente usato anche io vari D1 Mini, ma vorrei capire meglio: anche se possibile cerco sempre di evitare TX/RX, per curiosità, intanto, devi quindi ancora collegare sia il pulsante sia il LED rosso (per questo ti servono 2 GPIO)? E, per capire se si possa trovare una alternativa, cosa hai attualmente connesso agli altri pin? Ad esempio se hai altri 2 (ma anche più) pulsanti, potresti sfruttare il solo A0 per leggere lo stato dei pulsanti tramite partitore...

Ok cerco di spiegarmi allora, al D1 Mini ho collegato un display ST7789, un ADS1115,
ST7789 è così collegato al D1 Mini
GND - GND
Vcc - 3.3v
SCL - D5
SDA - D7
RES - D4
DC - D3

poi c'è un ADS1115 collegato
VDD
GND
SCL - D1
SDA - D2

Pulsante D0
Buzzer D6
Controllo Batteria A0

rimangono liberi solo D8 - RST - RX - TX, sempre che non si possa fare che SCL e SDA del display e del ADS non possono essere collegati assieme, poi non so come configurarli, allora guadagnerei due pin

Se il pulsante è quello di selezione allora è vorretto, ti manca quello di accensione/spegnimento ed il LED rosso, ossia 2 pin. E l'unico pin analogico già lo usi per la lettura della tensione della batteria.

Beh, intanto anche se non ho mai avuto a che fare con quel display e quel convertitore insieme, ma se sono entrambi con bus I2C, credo proprio che puoi usare SDA ed SCL per entrambi (a patto che abbiano indirizzi diversi). Per consigli sul codice però dovresti postarlo.

A parte questo, sinceramente visto che hai già un circuito per lo spegnimento io penserei ad implementare via hardware il controllo della tensione della batteria (non so darti uno schema per cui lascio la parola ad altri, ma credo che basti un operazionale per "spegnere" il Mosfet)

Ciao premesso che quello che mi avete indicato funziona alla grande, come faccio ad aggiungere che se non viene toccato il pulsante dopo 15minuti si spegne da solo
Grazie

"si spegne da solo" cosa?

Se guardi all'inizio tu mi avevi fatto un codice che che faceva On_Off di arduino , volvevo che si spegnesse da solo se uno se lo dimentica acceso

Se intendi contare 15 minuti dall'accensione di Arduino, ti basta verificare quando millis() ha un valore pari (o superiore) a 15*60*1000=900.000 millisecondi:

...
// Tempo di inattività (in secondi)
#define INATTIVITA 900
...
  //tempo ritardo in spegnimento
  // Verifico anche il tempo totale
  if((t > 0 && millis() - t > 1000) || millis() > INATTIVITA*1000 ) {
    digitalWrite(P_MOSFET, LOW);
    // Simulo lo spegnimento....
    digitalWrite(P_ROSSO, LOW);
    Serial.println("*** SPENTO ***");
    while (1) { };
  }
}

Altrimenti c'è lo sleep:
https://www.google.com/search?&q=arduino+sleep+mode

Si ma non è quello che chiede: so che il thread è vecchio e sono passati 3 mesi, anche io ho dovuto rifare mente locale, ma vedi la descrizione iniziale. Lui già spegne fisicamente Arduino.

Bisogna fare la differenza con un tempo preso ogni volta che si fa qualcosa per contare il tempo di inattività:

if (faccio qualcosa) {t_ultimo_uso=millis();}
if (millis()-t_ultimo_uso>900000UL) {spegni();}