Zpožděné vypnutí blikání s millis

Wiring, C++, C, Java, ...
Pravidla fóra
Toto subfórum slouží k řešení obecných otázek kolem programování (konstrukce, knihovny, alokace paměti, ...)
Odpovědět
johnyhol
Příspěvky: 33
Registrován: 07 pro 2017, 21:17
Reputation: 0

Zpožděné vypnutí blikání s millis

Příspěvek od johnyhol » 19 dub 2021, 08:34

Zdravím všechny. Potřeboval bych poradit jak upravit (nebo poradit nějaký jiný kód bez delay) kód níže, aby po sepnutí tlačítka blikala LED a po uvolnění tlačítka po nastavené době blikání přestalo. Nyní je to tak, že LED po sepnutí pořád svítí a po uvolnění po nastaveném čase vypne.

Kód: Vybrat vše

 

//Global Variables
const byte BUTTON=5; // our button pin
const byte LED=3; // LED (built-in on Uno)
unsigned long buttonPushedMillis; // when button was released
unsigned long ledTurnedOnAt; // when led was turned on
unsigned long turnOnDelay = 500; // wait to turn on LED
unsigned long turnOffDelay = 5000; // turn off LED after this time
bool ledReady = false; // flag for when button is let go
bool ledState = false; // for LED is on or not.

void setup() {
pinMode(BUTTON, INPUT);
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW);
}
void loop() {
// get the time at the start of this loop()
unsigned long currentMillis = millis(); 
 
 // check the button
if (digitalRead(BUTTON) == LOW) {
  // update the time when button was pushed
  buttonPushedMillis = currentMillis;
  ledReady = true;
}
  
 // make sure this code isn't checked until after button has been let go
if (ledReady) {
   //this is typical millis code here:
   if ((unsigned long)(currentMillis - buttonPushedMillis) >= turnOnDelay) {
     // okay, enough time has passed since the button was let go.
     digitalWrite(LED, HIGH);
     // setup our next "state"
     ledState = true;
     // save when the LED turned on
     ledTurnedOnAt = currentMillis;
     // wait for next button press
     //ledReady = false;
   }
}
  
 // see if we are watching for the time to turn off LED
if (ledState) {
   // okay, led on, check for now long
   if ((unsigned long)(currentMillis - ledTurnedOnAt) >= turnOffDelay) {
     ledState = false;
     digitalWrite(LED, LOW);
   }
}
}
Díky

KamilV
Příspěvky: 479
Registrován: 03 dub 2018, 15:27
Reputation: 0
Bydliště: Olomouc

Re: Zpožděné vypnutí blikání s millis

Příspěvek od KamilV » 19 dub 2021, 08:51

Podobně, jako si počítáš čas vypnutí LEDky a porovnáváš s millis(), poznamenávej si "čas" posledního bliknutí a když je od něj millis() větší třeba než 500, změň stav LEDky a čas si přepiš. Celé to dělej ve větvi, kdy LEDka svítí...

johnyhol
Příspěvky: 33
Registrován: 07 pro 2017, 21:17
Reputation: 0

Re: Zpožděné vypnutí blikání s millis

Příspěvek od johnyhol » 19 dub 2021, 11:26

Trápil jsem se s tím celý víkend, ale na nic jsem nepřišel. Zkoušel jsem i různé příklady (asi 10 různých způsobů), ale pořád bez výsledku. Buď mi to blikalo a nefungovalo vypnutí, nebo to zase vypínalo, ale nefungovalo blikání. Neměl bys prosím nějaký příklad podle kterého bych mohl postupovat?
Díky

Uživatelský avatar
gilhad
Příspěvky: 778
Registrován: 07 bře 2018, 11:22
Reputation: 0

Re: Zpožděné vypnutí blikání s millis

Příspěvek od gilhad » 19 dub 2021, 14:41

Myslim, ze tohle by mohlo fungovat (a resit i pomerne rychle mackani tlacitka "nejak")

Kód: Vybrat vše


const byte BUTTON=5; // our button pin
const byte LED=3; // LED (built-in on Uno - should not be 13 ??)

bool wait_for_blinking = False; // LED should start blinking sometime later
bool wait_for_stop = False; // LED should stop blinking sometime later
bool start_after_stop = False; // (BUTTON pressed after released, last action of BUTTON was press it for start)
bool blinking = False; // LED should be blinking
bool status = False; // LED is ON
bool debouncing = False; // BUTTON changed status recently, we should wait untill it is settled


// times for millis() comparation, initialized to zero at start
unsigned long blinking_wait_from;  // requested start of blinking
unsigned long stop_wait_from;  // requested stop of blinking
unsigned long debounce_wait_from; // BUTTON changed at this time, we should wait a moment untill it debounces
unsigned long changed_last; // last change of LED

// just constants
const unsigned long blinking_delay = 250; // time of ON or OFF (speed of blinking)
const unsigned long blinking_start_delay = 1000; // time of delay before start blinking
const unsigned long blinking_stop_delay = 1000; // time of delay before stop blinking
const unsigned long debounce_delay = 100; // time of delay before button is considered debounced

void setup() {
	pinMode(BUTTON, INPUT_PULLUP);
	pinMode(LED, OUTPUT);
	digitalWrite(LED, LOW);
}

void loop() {

	unsigned long now=millis();

	// BUTTON
	if (debouncing && ((now - debounce_wait_from) > debounce_delay)) { 
		debouncing=False;
	};

	if (! debouncing) { 
		bool ButtonUp = digitalRead(BUTTON) == HIGH;
	
		if ( (!start_after_stop) && (! wait_for_blinking) && ( ! ButtonUp)  ) { // BUTTON pressed now and not managed yet (start_after_stop) and blinking not reguested yet
			start_after_stop = True;
			
			wait_for_blinking = True;
			blinking_wait_from = now;
			
			debounce_wait_from = now;
			debouncing=True;
		};
		
		if ( (start_after_stop) && ( ! wait_for_stop) && (ButtonUp) ) { // New request for stop and none pending
			start_after_stop = False;

			wait_for_stop = True;
			stop_wait_from = now;
			
			debounce_wait_from = now;
			debouncing=True;
		};
	};
	
	// LED
	
	if ( wait_for_blinking && (now - blinking_wait_from) >= blinking_start_delay ) {
		blinking = True;
		wait_for_blinking = False;
		
		if (start_after_stop) { // ignore waiting for stop
			wait_for_stop = False; 
		};
	};
	
	if (( ! status) && wait_for_stop && (now - stop_wait_from) >= blinking_stop_delay ) { // stop only when LED is OFF
		blinking = False;
		wait_for_stop = False;
		
		if ( ! start_after_stop) {
			wait_for_start = False;
		};
	};
	
	if ( blinking && ( (now - changed_last) >= blinking_delay ) ) { // Change LED if it should blink
		status = ! status;
		digitalWrite(LED,status);
		changed_last = now;
	};
}


johnyhol
Příspěvky: 33
Registrován: 07 pro 2017, 21:17
Reputation: 0

Re: Zpožděné vypnutí blikání s millis

Příspěvek od johnyhol » 19 dub 2021, 21:37

Díky moc, to je přesně to co jsem potřeboval. Musel jsem jen trochu upravit kód, chyběla tam jedna proměnná (bool wait_for_start = false;) a u false a true byly začáteční písmena velká. Přepsal jsem ještě nastavení vstupu (tlačítka) na obyčejný INPUT (mám zapojené s externím odporem) a hodnotu čtení na LOW. Ještě by mě zajímalo proč jsou za složenými závorkami středníky, má to nějaký speciální důvod?

Přikládám upravený funkční kód:

Kód: Vybrat vše

const byte tlacitko=4; // tlacitko pin
const byte LED=3; // LED pin

bool wait_for_blinking = false; // LED should start blinking sometime later
bool wait_for_stop = false; // LED should stop blinking sometime later
bool wait_for_start = false; // LED should start blinking sometime later
bool start_after_stop = false; // (tlacitko pressed after released, last action of tlacitko was press it for start)
bool blinking = false; // LED should be blinking
bool status = false; // LED is ON
bool debouncing = false; // tlacitko changed status recently, we should wait untill it is settled


// times for millis() comparation, initialized to zero at start
unsigned long blinking_wait_from;  // requested start of blinking
unsigned long stop_wait_from;  // requested stop of blinking
unsigned long debounce_wait_from; // tlacitko changed at this time, we should wait a moment untill it debounces
unsigned long changed_last; // last change of LED

// just constants
const unsigned long blinking_delay = 1000; // time of ON or OFF (speed of blinking)
const unsigned long blinking_start_delay = 100; // time of delay before start blinking
const unsigned long blinking_stop_delay = 20000; // time of delay before stop blinking
const unsigned long debounce_delay = 100; // time of delay before tlacitko is considered debounced

void setup() {
  pinMode(tlacitko, INPUT);
  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);
}

void loop() {

  unsigned long now=millis();

  // tlacitko
  if (debouncing && ((now - debounce_wait_from) > debounce_delay)) { 
    debouncing=false;
  };

  if (! debouncing) { 
    bool tlacitkoUp = digitalRead(tlacitko) == LOW;
  
    if ( (!start_after_stop) && (! wait_for_blinking) && ( ! tlacitkoUp)  ) { // tlacitko pressed now and not managed yet (start_after_stop) and blinking not reguested yet
      start_after_stop = true;
      
      wait_for_blinking = true;
      blinking_wait_from = now;
      
      debounce_wait_from = now;
      debouncing=true;
    };
    
    if ( (start_after_stop) && ( ! wait_for_stop) && (tlacitkoUp) ) { // New request for stop and none pending
      start_after_stop = false;

      wait_for_stop = true;
      stop_wait_from = now;
      
      debounce_wait_from = now;
      debouncing=true;
    };
  };
  
  // LED
  
  if ( wait_for_blinking && (now - blinking_wait_from) >= blinking_start_delay ) {
    blinking = true;
    wait_for_blinking = false;
    
    if (start_after_stop) { // ignore waiting for stop
      wait_for_stop = false; 
    };
  };
  
  if (( ! status) && wait_for_stop && (now - stop_wait_from) >= blinking_stop_delay ) { // stop only when LED is OFF
    blinking = false;
    wait_for_stop = false;
    
    if ( ! start_after_stop) {
      wait_for_start = false;
    };
  };
  
  if ( blinking && ( (now - changed_last) >= blinking_delay ) ) { // Change LED if it should blink
    status = ! status;
    digitalWrite(LED,status);
    changed_last = now;
  };
}

         

Ještě jednou moc díky!

Uživatelský avatar
gilhad
Příspěvky: 778
Registrován: 07 bře 2018, 11:22
Reputation: 0

Re: Zpožděné vypnutí blikání s millis

Příspěvek od gilhad » 20 dub 2021, 04:39

Protoze jsem to psal z hlavy (a tim externim odporem jsem si nebyl jisty) a ta pismena ma velka vlastne Python ... hlavne, ze to pomohlo :)

Strednik je nekdy potreba a nekdy ne a ja jsem liny si pamatovat kdy presne je v kterem jazyce nutny. Ale prazdny strednik navic je jen oddelovac prikazu, takze je tam jeden prazdny prikaz navic a rozumny prekladac ho vyhodi, takze jde jen o estetiku a me se to takhle libi vic, ze ten strednik znamena fakt konec.

Cili ano, jsou tam naprosto zbytecne. A stejne tak jsem mohl odsazovat treba na 2 mezery, misto na tab (ale zase tab mi prijde uhlednejsi, ze jedno odsazeni = jeden znak = velka mezera a ve VIMu se mi taby ukazujou hezky), nebo jiny z tisice drobnych detailu. Proste to pisu, jak se mi to libi, pak mi prekladac bud vynada (ty False/True a nedeklarovane promenne), nebo nevynada a pak je to bud spravne, nebo je tam logicka chyba.

Taky ta odsazeni prazdnyma radkama mela naznacit myslenkove celky, taky nejsou nutna, ale IMHO to zprehledni a pokud tam nejaka chyba je, tak se snaz najde. Stejne tak ty komentare, kdyz by kod delal neco jineho, nez co rika komentar, je to chyba, pak je potreba opravit kod a/nebo komentar - ale aspon je nejaka myslenka, ceho se chytit :) Stejne tak to rozdeleni na relativne male samostatne bloky - zase je snazsi rict, zda se to chova spravne.

A ty promenne jsem taky mohl pojmenovat jeste trochu konzistentneji, ale i tak kdyz jsou popisne, zase je to dalsi kontrola, ze asi delam to, co jsem chtel delat :) A kdyz pak nejaka vypadne, tak se da snaz usoudit, kde asi mela byt a co asi mela delat :)

ondraN
Příspěvky: 932
Registrován: 08 srp 2019, 20:01
Reputation: 0

Re: Zpožděné vypnutí blikání s millis

Příspěvek od ondraN » 20 dub 2021, 07:08

gilhad píše:
20 dub 2021, 04:39
Protoze jsem to psal z hlavy (a tim externim odporem jsem si nebyl jisty) a ta pismena ma velka vlastne Python ... hlavne, ze to pomohlo :)

Strednik je nekdy potreba a nekdy ne a ja jsem liny si pamatovat kdy presne je v kterem jazyce nutny. Ale prazdny strednik navic je jen oddelovac prikazu, takze je tam jeden prazdny prikaz navic a rozumny prekladac ho vyhodi, takze jde jen o estetiku a me se to takhle libi vic, ze ten strednik znamena fakt konec.

Cili ano, jsou tam naprosto zbytecne. A stejne tak jsem mohl odsazovat treba na 2 mezery, misto na tab (ale zase tab mi prijde uhlednejsi, ze jedno odsazeni = jeden znak = velka mezera a ve VIMu se mi taby ukazujou hezky), nebo jiny z tisice drobnych detailu. Proste to pisu, jak se mi to libi, pak mi prekladac bud vynada (ty False/True a nedeklarovane promenne), nebo nevynada a pak je to bud spravne, nebo je tam logicka chyba.

Taky ta odsazeni prazdnyma radkama mela naznacit myslenkove celky, taky nejsou nutna, ale IMHO to zprehledni a pokud tam nejaka chyba je, tak se snaz najde. Stejne tak ty komentare, kdyz by kod delal neco jineho, nez co rika komentar, je to chyba, pak je potreba opravit kod a/nebo komentar - ale aspon je nejaka myslenka, ceho se chytit :) Stejne tak to rozdeleni na relativne male samostatne bloky - zase je snazsi rict, zda se to chova spravne.

A ty promenne jsem taky mohl pojmenovat jeste trochu konzistentneji, ale i tak kdyz jsou popisne, zase je to dalsi kontrola, ze asi delam to, co jsem chtel delat :) A kdyz pak nejaka vypadne, tak se da snaz usoudit, kde asi mela byt a co asi mela delat :)
Amen.

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 16 hostů