Spegnimento led dopo tot secondi da pressione bottone continua

Buongiorno a tutti... Scrivo nella community (dopo anni passati a seguirla da esterno ma ad apprendere svariati trucchetti qua e là) perché ho un problema con la realizzazione di una cosa che per voi sarà del tutto banale...ma non riesco a venirne a capo.

SCOPO In sostanza devo fare in modo che un led rimanga acceso per un tot di secondi (che successivamente verrà deciso da un potenziometro...ma non per ora) durante la pressione di un pulsante... se il pulsante viene rilasciato ovviamente il led si spegne...ma fintanto che esso sarà premuto il led rimarrà acceso per tot secondi....

Ho pensato di usare la funzione millis() partendo dallo spunto presente nella guida ovvero:

const byte button=2;
const byte LED=10;

bool blinking = false;  //defines when blinking should occur
unsigned long blinkInterval = 250;  // number of milliseconds for blink
unsigned long currentMillis; // variables to track millis()
unsigned long previousMillis;

void setup() {
  pinMode(button, INPUT);
  pinMode(LED, OUTPUT);
}

void loop() {
  // this code blinks the LED
  if (blinking) {    
    currentMillis = millis();  // better to store in variable, for less jitter
    if ((unsigned long)(currentMillis - previousMillis) >= blinkInterval) {  // enough time passed yet?
      digitalWrite(LED, !digitalRead(LED));  // shortcut to toggle the LED
      previousMillis = currentMillis;  // sets the time we wait "from"
    }
  } else {
    digitalWrite(LED, LOW); // force LED off when not blinking
  }
  int reading = digitalRead(button);
  delay(50); // crude de-bouncing

  if (reading==LOW) // buttons with pull-up are pressed when LOW
    blinking=true; // start blinking
  else
    blinking=false; // stop blinking
}

ho modificato il codice in questa maniera

const byte button=2;
const byte LED=9;

bool ledon = false;  //defines when blinking should occur
unsigned long Interval = 2500;  // number of milliseconds led on
unsigned long currentmillis; 
void setup() {
  pinMode(button, INPUT);
  pinMode(LED, OUTPUT);
}

void loop() {
  // this code blinks the LED
  
  if (ledon) {    
      digitalWrite(LED, HIGH);
      currentmillis = millis();
    if ((unsigned long)(currentmillis >= Interval)) {  // enough time passed yet?
      digitalWrite(LED, LOW);  // shortcut to toggle the LED 
    }
  } else {
    digitalWrite(LED, LOW); // force LED off when not blinking
  }
  int reading = digitalRead(button);
  delay(50); // crude de-bouncing

  if (reading==HIGH) 
    ledon=true; 
  else
    ledon=false; 
}

L'idea del codice è dunque.,... Se il bottone è premuto (reading ==HIGH) la condizione di if(ledon) è vera e quindi prendi il valore di millis() e se questo supera il valore "interval" spegni il led....

Ovviamente non funziona niente.... ho provato anche altri tipi di codice ma niente da fare o si accende ma non si spegne mai... riesco a farlo funzionare solo se il comando di spegnimento è al di fuori della condizione di tasto premuto (ad esempio pigio il tasto e lo rilascio il led si spegne dopo tot tempo indicato da me...ma non è quello che voglio fare)....

Qualche dritta???

Grazie mille a tutti e complimenti per la community

Buongiorno, essendo il tuo primo post, nel rispetto del regolamento della sezione Italiana del forum (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD ([u]spiegando bene quali conoscenze hai di elettronica e di programmazione[/u] ... possibilmente [u]evitando[/u] di scrivere solo una riga di saluto) e di leggere con MOLTA attenzione il su citato REGOLAMENTO ... Grazie. :)

Guglielmo

P.S.: Ti ricordo che, fino a quando non sarà fatta la presentazione, nessuno ti potrà rispondere, quindi ti consiglio di farla al più presto. ;)

gpb01: Buongiorno, essendo il tuo primo post, nel rispetto del regolamento della sezione Italiana del forum (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD ([u]spiegando bene quali conoscenze hai di elettronica e di programmazione[/u] ... possibilmente [u]evitando[/u] di scrivere solo una riga di saluto) e di leggere con MOLTA attenzione il su citato REGOLAMENTO ... Grazie. :)

Guglielmo

P.S.: Ti ricordo che, fino a quando non sarà fatta la presentazione, nessuno ti potrà rispondere, quindi ti consiglio di farla al più presto. ;)

Chiedo venia, ho provveduto a fare la presentazione, grazie ancora.

Ragioniamo…(pseudo codice):

Verifica stato pulsante

Se pulsante premuto Se passaggio da pulsante non premuto a premuto Memorizzo millis memorizzo pulsante premuto

Se millis – millis memorizzato inferiore a tempoX LED acceso

Altrimenti LED spento

Altrimenti LED spento Pulsante non premuto

ORSO2001: Ragioniamo…(pseudo codice):

Verifica stato pulsante

Se pulsante premuto Se passaggio da pulsante non premuto a premuto Memorizzo millis memorizzo pulsante premuto

Se millis – millis memorizzato inferiore a tempoX LED acceso

Altrimenti LED spento

Altrimenti LED spento Pulsante non premuto

In primis ti ringrazio per la risposta... Dal tuo "pseudo-codice" dunque dovrei utilizzare dei flag per la verifica dello status del bottone giusto?

ma questo tuo passaggio non mi torna

Se pulsante premuto

Se passaggio da pulsante non premuto a premuto

Il secondo "if" non è automatico essendo all'interno di un "if" che si abilita solo se il pulsante è effettivamente premuto?... cosa non sto capendo?

Volendo c'è una logica ancora più semplice senza flag:

Se non è premuto

    LED spento
    memorizzo millis

Altrimenti se non trascorso periodo

    LED acceso

Altrimenti

    LED spento

Claudio_FF:
Volendo c’è una logica ancora più semplice senza flag:

Se non è premuto

LED spento
    memorizzo millis

Altrimenti se non trascorso periodo

LED acceso

Altrimenti

LED spento

interessante provo a girarla in questa maniera…
quindi sarebbe

Se bottone è LOW
il led sta spento
salvo il millis attuale (che sarà zero praticamente)
Altrimenti (else if) millis() - millis salvato <= tempochevoglio
led acceso
Altrimenti
led spento

mmmh…

Posso provare cosi

Claudio_FF:
Volendo c’è una logica ancora più semplice senza flag:

Se non è premuto

LED spento
    memorizzo millis

Altrimenti se non trascorso periodo

LED acceso

Altrimenti

LED spento

FUNZIONAA!!! ho provato questo codice

const byte button=2;
const byte LED=9;

unsigned long Interval = 3000;  // number of milliseconds led on
unsigned long prevmillis; 
int buttonState=0;


void setup() {
  pinMode(button, INPUT);
  pinMode(LED, OUTPUT);
}
 
void loop() 
{
  buttonState = digitalRead (button);
  if (buttonState == LOW)
  {
    digitalWrite (LED, LOW);
    prevmillis = millis();
  }
  else if (millis() - prevmillis <= Interval)
  {
    digitalWrite (LED, HIGH);
  }
  else
  digitalWrite (LED, LOW);
}

E funziona esattamente come volevo :wink:
Questo ragionamento inverso partendo dallo status di bottone spento non lo avevo pensato…! grazie per la dritta

Ora devo pensare a come assegnare a “interval” un valore che sia dato da un potenziometro…ipotizzando che il valore minore del potenziometro sia 0 e il massimo 10 secondi…(10000ms)

:wink:

Guarda la funzione map potrebbe tornarti utile ;)

nongio86: salvo il millis attuale (che sarà zero praticamente)

Non è zero, è il valore attuale del contatore letto da millis(). In pratica finché il pulsante non è premuto la variabile rincorre il contatore. Quando il pulsante è premuto la variabile resta fissa e il contatore avanza. Ed è proprio dalla differenza tra contatore e variabile che si calcola il tempo trascorso.

fabpolli:
Guarda la funzione map potrebbe tornarti utile :wink:

ci do un occhio grazie…

Banalmente facendo così

const byte button=2;
const byte LED=9;

unsigned long Interval = 0;  // number of milliseconds led on
unsigned long prevmillis; 
int buttonState=0;
int pot = 0;
int valuepot = 0;


void setup() {
  pinMode(button, INPUT);
  pinMode(LED, OUTPUT);
  Serial.begin(9600);
}
 
void loop() 
{
  valuepot = analogRead(pot);
  Interval = (valuepot * 10);
  buttonState = digitalRead (button);
  if (buttonState == LOW)
  {
    digitalWrite (LED, LOW);
    prevmillis = millis();
  }
  else if (millis() - prevmillis <= Interval)
  {
    digitalWrite (LED, HIGH);
  }
  else
  digitalWrite (LED, LOW);
}

Quindi andando a leggere il valore del potenziometro, ed assegnandolo a “Interval” moltiplicato per 10 (cos’ dovrei arrivare a circa 10 secondi se non erro, devo controllare di preciso) sembra funzionare come voglio :wink:

Claudio_FF:
Non è zero, è il valore attuale del contatore letto da millis(). In pratica finché il pulsante non è premuto la variabile rincorre il contatore. Quando il pulsante è premuto la variabile resta fissa e il contatore avanza. Ed è proprio dalla differenza tra contatore e variabile che si calcola il tempo trascorso.

Sisi certo perdonami… sarà il “ground zero” per il delta tra quel millis e quello che si cattura in fase di controllo di quanto tempo è passato… mi son spiegato male

const byte button=2;
const byte LED=9;

float Interval = 0;  // number of milliseconds led on
unsigned long prevmillis; 
int buttonState=0;
int pot = 0;
int valuepot = 0;


void setup() {
  pinMode(button, INPUT);
  pinMode(LED, OUTPUT);
  Serial.begin(9600);
}
 
void loop() 
{
  valuepot = analogRead(pot);
  Interval = (valuepot * 14.67);
  buttonState = digitalRead (button);
  if (buttonState == LOW)
  {
    digitalWrite (LED, LOW);
    prevmillis = millis();
  }
  else if (millis() - prevmillis <= Interval)
  {
    digitalWrite (LED, HIGH);
  }
  else
  digitalWrite (LED, LOW);
}

ok…il bottone rimane acceso da un minimo do 0 secondi a 15 secondi (in base a quanto si gira il potenziometro) :wink:

nongio86:
sarà il “ground zero” per il delta tra quel millis e quello che si cattura in fase di controllo di quanto tempo è passato…

Perfetto

int pot = 0;


valuepot = analogRead(pot);

Questo non mi quadra, è una lettura analogica dal pin 0… ma di che Arduino stiamo parlando? Su ArduinoUNO (e altri derivati dall’ATMEGA328) il pin 0 è la ricezione seriale e in ogni caso non funziona come ingresso analogico.

Per il resto ok, funziona, eventualmente si potrebbe fare un po’ di “ordine” nel senso di stile consistente e codice autodocumentante: variabili in minuscolo e costanti/etichette in maiuscolo, conversioni tra tipi esplicite tramite cast, eliminazione dal codice dei riferimenti hardware (numeri di pin e valori HIGH/LOW), eliminazione variabili globali non indispensabili, uso dei tipi dati base indipendenti dall’architettura:

//-------------pulsante

#define BUTTON     2
#define NOTPRESSED LOW

//-------------LED

#define LED        9
#define OFFLEVEL   LOW
#define ONLEVEL    HIGH

//-------------Ingresso analogico

#define POT        ??????

//----------------------------------------------

void setup() 
{
    pinMode(BUTTON, INPUT);
    pinMode(LED, OUTPUT);
}

//----------------------------------------------

void loop()
{
    uint32_t static prevmillis = 0;
    int16_t         valuepot = analogRead(POT);
    float           interval = (float)valuepot * 14.67;

    if (digitalRead(BUTTON) == NOTPRESSED)
    {
        digitalWrite (LED, OFFLEVEL);
        prevmillis = millis();
    }
    else if ((millis() - prevmillis) <= (uint32_t)interval)
    {
        digitalWrite (LED, ONLEVEL);
    }
    else
    {
        digitalWrite (LED, OFFLEVEL);
    }
}

//----------------------------------------------

uhmmm sono un secondo bloccato…

Allora la funzione che il led si spegne dopo tot secondi in base al potenziometro sempre col tasto premuto funziona bene… ma ho un problema che non avevo calcolato…

devo inserire anche degli altri led che si spengono solo al rilascio del bottone (e quindi se ne fregano del potenziometro e del millis() )…però col codice che ho ora non so come fare…

const byte button=2; //pin bottone
const byte led7 = 7; //led pin 7 che si spegne in base al pot
const byte led8 = 8; //led pin 8 che si spegne in base al pot
const byte led9 = 9; //led pin 9 che si spegne in base al pot
const byte led10 = 10; //led pin 10 che si spegne col tasto
const byte led11 = 11; //led pin 11 che si spegne col tasto
const byte led12 = 12; //led pin 12 che si spegne col tasto
const byte led13 = 13; //led pin 13 che si spegne col tasto

float Interval = 0;  // inizializzazione tempo led acceso
unsigned long prevmillis; //inizializzazione contatore millis iniziali
int buttonState=0;//inizializzazione stato bottone iniziale
int pot = 0; // inizializzazione potenziometro
int valuepot = 0; // inizializzazione valore potenziomentro


void setup() {
  pinMode(button, INPUT); //inizializzazione bottone
  pinMode(led7, OUTPUT); //inizializzazione tutti led --->
  pinMode(led8, OUTPUT);
  pinMode(led9, OUTPUT);
  pinMode(led10, OUTPUT);
  pinMode(led11, OUTPUT);
  pinMode(led12, OUTPUT);
  pinMode(led13, OUTPUT); // <---fine
  Serial.begin(9600); //inizializzazione porta seriale
}
 
void loop() 
{
  valuepot = analogRead(pot);
  Interval = (valuepot * 14.66);
  buttonState = digitalRead (button);
  if (buttonState == LOW)
  {
    digitalWrite (led7, LOW);
    digitalWrite (led8, LOW);
    digitalWrite (led9, LOW);
    digitalWrite (led10, LOW);
    digitalWrite (led11, LOW);
    digitalWrite (led12, LOW);
    digitalWrite (led13, LOW);
    prevmillis = millis();
  }
  else if (millis() - prevmillis <= Interval)
    {
    digitalWrite (led7, HIGH);
    digitalWrite (led8, HIGH);  
    digitalWrite (led9, HIGH);
     } 

  else
  digitalWrite (led9, LOW);
  digitalWrite (led13, LOW);
}

se aggiungo l’accensione dei led 10/11/12/13 nell’else prima dell’“if (millis() - prevmillis <= Interval)” poi non funziona più il led a tempo con il potenziometro…

mmmmh… devo pensare come sistemare

@Claudio_FF ho arduino Duemilanove… dici di cambiare pin e andare su uno digitale?

nongio86:
@Claudio_FF ho arduino Duemilanove… dici di cambiare pin e andare su uno digitale?

Allora ipotizzo che ti sei collegato su A0, non sapevo che il compilatore fosse così “intelligente” da trasformare una analogRead(0) in analogRead(A0). Io avrei assegnato a pot il valore A0, o, in alternativa, 14 (A0 è un etichetta che “vale” 14).

Per il resto non mi sembra ci siano difficoltà, tutti i LED spenti se non premuto, tutti i LED accesi durante il conteggio tempo, e solo quelli che si vogliono spegnere allo scadere si comandano OFF nell’else finale.

mi sento di intervenire

innanzitutto ti sta ardimentando in 2 delle cose più difficili da capire per un hobbysta e questo ti fà onore.

Millis() è un cronometro..... Lo stato di un pulsante...prima adesso...è piu difficile di quel che immagini.

Se riesci ad comprenderli entrambi avrai fatto un passo in avanti....altrimenti sei bloccato.

In bocca al lupo.

Se l'unica parte non Chiara è l'aggiunta dei "Led che si devono spegnere al rilascio del pulsante" Allora farei due passi: In primo luogo modificherei la richiesta. Credo che la richiesta possa essere tradotta come "io voglio aggiungere dei led il cui stato sia uguale a quello del pulsante". Se le due richieste soddisfano entrambe il tuo bisogno, allora sei pronto per fare il secondo passo per il quale ti do una dritta: Leggi la prima delle 3 frasi sotto questo post, Quella in cui parla delle variabili. E ricordati che HIGH e LOW sono numeri, più precisamente 1 e 0. E che quindi se sono numeri... E sapendo che funzioni mi serve per comandare i LED...

Claudio_FF: A0 è un etichetta che "vale" 14

In realtà, 14 viene trasformato in 14-14=0, in quanto è il bit 0 della porta C.

Hai risolto?

Datman:
In realtà, 14 viene trasformato in 14-14=0, in quanto è il bit 0 della porta C.

No, la porta C è la porta digitale, 0, in questo caso, è il canale del multiplexer del ADC (ADC0) ... che poi, entrambe le cose (il pin 0 della porta digitale C ed il canale 0 del multiplexer del ADC) siano collegate allo stesso piedino fisico ha poca importanza.


Guglielmo