Accendere e spegnere arduino con un pulsante

La funzione millis va chiamata (come ogni funzione) aggiungendo le due parentesi di chiamata, e la variabile temporale deve essere di tipo unsigned long.

Ok e funziona perfettamente, vorrei però inserirlo in un progetto già fatto senza aggiungere un pulsante, ma utilizzando i due pulsanti già esistenti, che fanno altro uno naviga nelle pagine uno seleziona, vorrei fare on- off premendoli insieme, secondo voi potrebbe essere possibile, grazie

È possibile, certo.

Però devi modificare il comportamento di ciascuno dei due pulsanti esistenti. Adesso alla pressione di uno dei due pulsanti si ottiene la funzione 'naviga' oppure la funzione 'seleziona'. Devi modificare ciascun pulsante in modo che, quando viene premuto, non vada subito ad eseguire la funzione assegnata 'naviga' oppure 'seleziona', ma per un tempo da te prefissato (100-200 ms) analizzi l'altro pulsante con una funzione non bloccante basata su millis(). Se l'altro pulsante non è già premuto o non viene premuto in quell'intervallo di tempo, il pulsante esplica la sua funzione di 'naviga' oppure 'seleziona', altrimenti viene eseguita la funzione 'spegni'.

Ciao,
P.

Non necessariamente bisogna attendere quei tempi tra azioni sui pulsanti, se ad esempio i comandi normali vengono modificati per essere sensibili al rilascio anziché alla pressione, allora basta riscontrare i due pulsanti premuti assieme e si sa subito che si vuole spegnere.

Occorre certamente una modifica al circuito per gestire in hardware l'and dei pulsanti per l'accensione:


98747684


Ma questa modifica è il meno. Il problema grosso potrebbe essere il resto del software se non è stato scritto in partenza con criteri ben precisi di codice non bloccante e letture ingressi ben disaccoppiate dalla logica esecutiva.

Se invece come vedo di solito tutte le letture degli ingressi sono embeddate dentro le condizioni if della logica, e magari questa è pure scritta in modo bloccante, significa dover riscrivere (e quindi ripensare da capo) un bel po' di roba.

Diciamo che almeno tutti gli ingressi dovrebbero essere letti in un punto solo, producendo delle variabili di comando chiamate magari 'click1' ecc, e nella logica si dovrebbero leggere queste variabili al posto degli ingressi diretti, allora se ne potrebbe uscire.

In quest'ottica la lettura/gestione dei due pulsanti potrebbe diventare la seguente (ammesso che quelli già presenti chiudano verso massa e quindi si possa realizzare il circuito di cui sopra):

#define PIN_RITENUTA ...
#define PIN_PULS1    ...
#define PIN_PULS2    ...

byte rilasciato = 0;
unsigned long t = 0;
byte prem1Prec = 0;
byte prem2Prec = 0;


void setup() 
{
    pinMode(PIN_PULS1, INPUT_PULLUP);
    pinMode(PIN_PULS2, INPUT_PULLUP);
    pinMode(PIN_RITENUTA, OUTPUT);
    digitalWrite(PIN_RITENUTA, 1);
}


void loop() 
{
    delay(40); // debounce barbaro minimo

    // letture ingressi con riconoscimento
    // click su rilascio

    byte prem1 = (digitalRead(PIN_PULS1) == 0);
    byte click1 = !prem1 && prem1Prec;
    prem1Prec = prem1;

    byte prem2 = (digitalRead(PIN_PULS2) == 0);
    byte click2 = !prem2 && prem2Prec;
    prem2Prec = prem2;


    // Gestione autoritenuta

    if (!rilasciato)
    {
        click1 = 0;  // nessun comando finche' non rilasciato
        click2 = 0;
        if (!prem1 && !prem2) { rilasciato = 1; }
    }

    if (rilasciato && prem1 && prem2)
    {
        if (millis()-t > 2000)  // se premuti per due secondi
        {
            digitalWrite(PIN_RITENUTA, 0);
            while (1);        // attesa rilascio
        }
    }
    else
    {
        t = millis(); 
    }


    // Resto della logica circa 25 cicli al secondo

    // ......................

}
1 Like

e allora a questo punto chiedo anche il resto, perche pensavo di riuscirci invece niente, vorrei avere questa funzione su un Attiny85 dove ho due pulsanti che pilotano l'accensione di una luce con due mosfet,
il pulsante 1 accende e spegne il mosfet 1 con debounce (per evitare accensioni accidentali)
il pulsante 2 accende e spegne il mosfet 2 con debounce (per evitare accensioni accidentali)
l'attiny85 è alimentato da un 7805 e due condensatori,
se premo i due pulsanti insieme e per un tempo X accendo o spengo il tutto
si può fare questo, grazie

... mi spiace dover sepre ricordare il REGOLAMENTO, punto 16.1 ... qui noi NON scriviamo codici per voi, al massimo vi diamo dei piccoli esempi o dei diagrammi di flusso, ma il codice lo DOVETE scrivere voi, poi noi vi aiutiamo a correggerlo :wink: Grazie.

Guglielmo

Mi sembra ci sia già tutto nel codice del post #20, basta solo aggiungere le inversioni dei mos quando si riscontrano le variabili click1 e click2 a 1.

E ripensandoci non serve neppure lo schema ampliato del post #20, si possono comunque leggere due pulsanti, di cui uno solo che comanda direttamente il mos.

987762348765674

In questo caso però la logica di gestione dell'autoritenuta è più complessa. Si parte da uno stato di funzionamento S zero che vuole vedere entrambi i pulsanti P premuti per due secondi. Allora si attiva l'autoritenuta (pwr-on) e si passa allo stato 1, che vuole vedere entrambi i pulsanti rilasciati. Solo a quel punto si passa allo stato 2 di funzionamento normale. In questo stato se si riscontrano entrambi i pulsanti premuti per due secondi si toglie l'autoritenuta (pwr-off).

2 Likes

Allora ho fatto il circuito come spiegato da @Claudio_FF ma usando un Attiny85, ho inserito il codice su quello che avevo io ma mi succede questo, quando alimento è tutto spento, OK, se premo anche solo un pulsante si accende subito e i due pulsanti accendono e spengono indipendentemete il loro led con il debounce che gli ho dato, però poi non riesco a spegnere, cosa posso cambiare, a me piacerebbe che per accendere e spegnere il tutto (autoritegno) si usasse la pressione dei due pulsanti assieme e per un tempo variabile che poi posso tarare
Questo è il mio codice

#define PIN_RITENUTA 4
const int led1 = 0;
const int led2 = 2;
const int PIN_PULS1 = 1;
const int PIN_PULS2 = 3;
int led1_state = LOW;
int led2_state = LOW;

byte rilasciato = 0;
unsigned long t = 0;
byte prem1Prec = 0;
byte prem2Prec = 0;

// Button states and debounce
int buttonState1 = 0;
int buttonState2 = 0;
int lastButtonState1 = HIGH;
int lastButtonState2 = HIGH;
unsigned long lastDebounceTime1 = 0;
unsigned long lastDebounceTime2 = 0;

void setup() {
  pinMode(PIN_RITENUTA, OUTPUT);
  digitalWrite(PIN_RITENUTA, 1);
  
  pinMode(led1, OUTPUT);
  pinMode(PIN_PULS1, INPUT_PULLUP);
  pinMode(led2, OUTPUT);
  pinMode(PIN_PULS2, INPUT_PULLUP);
}

void loop() {
  delay(40); // debounce barbaro minimo

    // letture ingressi con riconoscimento
    // click su rilascio

    byte prem1 = (digitalRead(PIN_PULS1) == 0);
    byte click1 = !prem1 && prem1Prec;
    prem1Prec = prem1;

    byte prem2 = (digitalRead(PIN_PULS2) == 0);
    byte click2 = !prem2 && prem2Prec;
    prem2Prec = prem2;


    // Gestione autoritenuta

    if (!rilasciato)
    {
        click1 = 0;  // nessun comando finche' non rilasciato
        click2 = 0;
        if (!prem1 && !prem2) { rilasciato = 1; }
    }

    if (rilasciato && prem1 && prem2)
    {
        if (millis-t > 2000)  // se premuti per due secondi
        {
            digitalWrite(PIN_RITENUTA, 0);
            while (1);        // attesa rilascio
        }
    }
    else
    {
        t = millis; 
    }


    // Resto della logica circa 25 cicli al secondo

    // ......................

  
  int reading1 = digitalRead(PIN_PULS1);
  if (reading1 != lastButtonState1)
    lastDebounceTime1 = millis();

  if ((millis() - lastDebounceTime1) > 500) {
    if (reading1 != buttonState1) {
      buttonState1 = reading1;
      if (buttonState1 == LOW) {
        led1_state = !led1_state;
      }
    }
  }

  lastButtonState1 = reading1;

  digitalWrite(led1, led1_state);

  int reading2 = digitalRead(PIN_PULS2);
  if (reading2 != lastButtonState2)
    lastDebounceTime2 = millis();

  if ((millis() - lastDebounceTime2) > 500) {
    if (reading2 != buttonState2) {
      buttonState2 = reading2;
      if (buttonState2 == LOW) {
        led2_state = !led2_state;
      }
    }
  }

  lastButtonState2 = reading2;

  digitalWrite(led2, led2_state);
}

Per favore qualcuno riesce ad aiutarmi e dirmi dove sbaglio grazie

Aggiungi qualche print
Così sai in quale ramo if entri

Da lì si capisce cosa accade

ATtiny85, 5 pin disponibili, 4 già impegnati, la vedo dura farci uscire anche la seriale... :wink:
(Oddio, è anche vero che ti serve solo il TX...)

Ciao, Ale.

Tieni ragione

Quindi magari mettere un led ausiliario e modularne i lampeggi

Altro non saprei...

Ah..

Mostrare schema e codice attuali

SE parliamo dello schema del post #20, E si accende con un solo pulsante, allora c'è un problema hardware, montaggio errato, o correnti disperse (???) dai PNP che vanno ad attivare la base del transistor gemello all'autoritenuta, magari con una R da 2,2 kΩ tra la sua base e massa si risolve.

Per lo spegnimento mi sembra strano, a meno che non dipenda dal punto precedente.

No come schema ho fatto l’ultimo quello del post 23, ho sbagliato io a capire forse ditemelo

Io direi che tentare di leggere e capire il codice che si copiaincolla sarebbe molto utile

L'errore è leggermente meno che chiarissimo da vedere, basta veramente leggere il codice con attenzione

Oppure in alternativa fare un minimo di debug facendo lampeggiare un led in maniera differente per ogni ramo if che si incontra

Non c'è nulla di difficile
Basta farlo

Ho parlato

Eh, ma anche se chi lo ha scritto lo avesse riletto con attenzione non sarebbe male :rofl: E lo avevo pure spiegato nel post #17 :roll_eyes: L'ho corretto :roll_eyes: È l'abitudine a usare una variabile temporale globale per contenere il tempo del ciclo attuale, letto con millis() una sola volta a inizio loop.

Comunque adesso è chiaro che l'accensione anche con un solo pulsante non si riferisce a uno qualsiasi dei due, ma solo a quello collegato al mos. Ed infatti come spiegato nel post #23 serve la nuova logica descritta.

È chiaro anche che lo scopo delle variabili 'click1' e 'click2' è sfuggito completamente e quindi tanto valeva eliminarle proprio.

Beh, che dire...

Piuttosto una domanda:

Cosa usi per quei begli schemini?

editato per evitare "flames". T'ho gia segnalato di evitare certe cose - gpb01

A me dispiace che vi arrabbiate ma non sono un genio come voi, se scrivo su un forum è per cercare un aiuto e magari capire qualche cosa, posso rileggere mille volta ma a questo punto non ho ancora capito quale è il circuito giusto, comunque grazie infinite

Ma non è così semplice

Tu puoi anche dire che cerchi aiuto e che leggi ma non capisci

Ma il vero problema è che non rispondi
Hai messo lo schema che usi? No
Hai messo il codice? No

E quindi?

Cosa ti aspetti? Che lo scopriamo per magia quali problemi hai?

Non sperarci

Guarda che ti sbagli ho messo il codice che uso sul post 24 e lo schema sto provando quello che mi ha consigliato Claudio_FF nel post 23
non ho capito se è meglio lo schema del post 20