Led'in yanıp sönmesini durdur

Benim kod:

// Pin 13 has a LED connected on most Arduino boards.
// give it a name:
int led = 13;
const int buttonPin = 2;

// the setup routine runs once when you press reset:
void setup() {
 //initialize the digital pin as an output.
  pinMode(led, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
}

// the loop routine runs over and over again forever:
void loop() 
{
  bool buttonState = digitalRead(buttonPin);
  while (buttonState == LOW)
  {
   digitalWrite(led, HIGH);  //turn the LED on (HIGH is the voltage level)
   delay(1000);              //wait for a second
   digitalWrite(led, LOW);   //turn the LED off by making the voltage LOW
   delay(1000);              //wait for a second
   }
 if (buttonState == HIGH){
   digitalWrite(led, LOW);}
  }

Son kod satırı:

if (buttonState == HIGH){
   digitalWrite(led, LOW);}

Led'i sürekli yanıp sönme durumundan çıkarmak için kullanmayı denedim. Dolayısıyla bu projenin amacı, ledin bir tuşla yanıp sönmesini sağlamak ve ardından aynı tuşla kapatmak. Bu beni saatlerce rahatsız ediyor ve bütün işi ben yaptım ama bu son kısmı yapamıyorum. Burada yanlış yapılan ne?

Açıklama için DÜZENLENİR:

Amaç, her düğmeye basıldığında LED'in yanıp sönen ve yanıp sönmeyen bir durum arasında değişmesidir. LED'in durumu, düğmenin seviyesi tarafından (itilmiş/basılmamış) değil, itme eyleminin kendisiyle sürülür.

2
Ne olmak istiyorsun Yanıp sönmeyi başlatmak için bir kez, yanıp sönmeyi durdurmak için tekrar mı basın? Düğmeye basıldığında yanıp sönüyor mu? Başka bir şey?
katma yazar af., kaynak
Evet ilk söylediğin şey. Yanıp sönmeyi başlatmak için bir kez, yanıp sönmeyi durdurmak için tekrar bir kez basın.
katma yazar Jon7, kaynak

5 cevap

Anahtar testinin göz kırpma kontrolünden oldukça bağımsız olması mantıklıdır. Bu, aşağıdaki kodda yapılır; bu, bir düğmeye her basıldığında yanıp sönen ışığı açar veya kapatır. Bu kodla, butona basıldığında LED yanar veya yaklaşık 2 Hz hızında yanıp söner.

enum { LED=13, ButtonPin=2, BounceMS=50, BlinkMS=256 };
unsigned long buttonAt;
bool blinky, bouncy, buttonState;

void setup() {
  pinMode(LED, OUTPUT);
  pinMode(ButtonPin, INPUT_PULLUP);
  blinky = bouncy = buttonState = false;
  buttonAt = millis();
}

void loop() {
 //Detect button changes
  if (bouncy) {
    if (millis() - buttonAt > BounceMS)
      bouncy = false;      //End of debounce period
  } else {
    if (digitalRead(ButtonPin) != buttonState) {
      buttonState = digitalRead(ButtonPin);
      buttonAt = millis();
      bouncy = true;       //Start debounce period
      if (buttonState) {   //Was button just pressed?
        blinky = !blinky;  //Toggle blink-state
      }
    }
  }
 //Control light-blinking
  if (blinky) {
   //Turn LED on for BlinkMS ms, then off for same 
    digitalWrite(LED, (millis() - buttonAt)%(2*BlinkMS) < BlinkMS);
  } else {
    digitalWrite(LED, LOW);
  }
}
2
katma

OP'nin bir yorumunda açıkladığı gibi, elde etmeye çalıştığı şey, led'i kapatmak için basılacak düğmeye sahip olmamak üzere, yanıp sönme ile sönme arasında değişen bir düğmeye sahip olmaktır.

Bu, bu şekilde yapılabilir:

bool prevButtonState;
bool ledBlinking;

void loop() 
{
    bool buttonState = digitalRead(buttonPin);

    if (prevButtonState && !buttonState)
    {//Pressing edge: there is a transition between high and low
        ledBlinking = !ledBlinking;
    }
    prevButtonState = buttonState;

    if (ledBlinking)
    {
        digitalWrite(led, HIGH);  //turn the LED on (HIGH is the voltage level)
        delay(1000);              //wait for a second
        digitalWrite(led, LOW);   //turn the LED off by making the voltage LOW
        delay(1000);              //wait for a second
    }
    else
    {
        digitalWrite(led, LOW);
    }
}

Bununla birlikte, bu, düğmenin art arda yapılan kontrolleri arasında çok uzun bir süreye yol açar (çünkü çevrimler arasında 2 saniyelik bir gecikme olur). Bunu millis işlevini kullanarak çözebilirsiniz:

bool prevButtonState;
bool ledBlinking;
unsigned long prevMillis;

void loop() 
{
    bool buttonState = digitalRead(buttonPin);

    if (prevButtonState && !buttonState)
    {//Pressing edge: there is a transition between high and low
        ledBlinking = !ledBlinking;

        prevMillis = millis() - 1000;//Force a check
    }
    prevButtonState = buttonState;

    if (ledBlinking)
    {
        if ((millis() - prevMillis) >= 1000)
        {
            prevMillis += 1000;
            digitalWrite(led, !digitalRead(led));
        }
    }
    else
    {
        digitalWrite(led, LOW);
    }
}

Daha sonra geri dönüş sorunu var, ama bu OT oluyor. Öneri: Sıçrama yaşıyorsanız düğmeyi yönetmek için Bounce2 kitaplığını kullanın

2
katma
bu yorumu istediğinizde söyleyin -> yanıp sönen led, başka bir itme -> söndü. Kodumun yaptığı şey bu. Kodunuz basılı tutuluyor -> led yanıp sönüyor, basılı değil -> kapalı
katma yazar Tom Collins, kaynak
Hayır, düğmeyi ledleri kapatmak için kullanmak istiyorum. Bir anahtar ve bir ampul gibi .. tek fark lighbulb'un yanıp sönmesidir.
katma yazar Jon7, kaynak

REDAKTE

Arduino loop() işlevi bu durumda döngüsünü gereksiz kılarken döngüsünü kullanır. Daha da kötüsü: iken döngüsünü uygulamanın yolu buttonState 'in güncellenmesini önler, böylece döngü içinde sıkışıp kaldığınızdan emin olun.

Gerçekte ihtiyacınız olan şey, LED'i yanıp sönmek için zamanlayıcılar ve YÜKSEK - DÜŞÜK düğmesi geçişleriyle sürülen 2 durumlu bir makine kullanmak.

Bunun yerine şunu deneyin:

#include "Timer.h"

// Pin 13 has a LED connected on most Arduino boards.
// give it a name:
const int led = 13;
const int buttonPin = 2;

// declare state variables as global
bool buttonState = LOW;
bool buttonState_prev = LOW;
bool toggleBlinking;
bool blinkState;

// declare a Timer object so blinking can be done without loosing button presses
Timer timer_b;
int blink_id;

// the setup routine runs once when you press reset:
void setup() {
 //initialize the digital pin as an output.
  pinMode(led, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);

 //initial state: toggle led each 1000 ms
  blink_id = timer_b.oscillate(led, 1000, HIGH);
  blinkState = true;
  toggleBlinking = false;
}

// the loop routine runs over and over again forever:
void loop() {
 //Update the timer (required)
  timer_b.update();

 //check if button has been pressed (HIGH to LOW),
 //then debounce it and raise toggle flag
  buttonState = digitalRead(buttonPin);
  if ((buttonState != buttonState_prev) && (buttonState_prev == HIGH)) {
   //simple button debounce (confirm press after some ms)
    delay (50);
    buttonState = digitalRead(buttonPin);
    if (buttonState != buttonState_prev) toggleBlinking = true;
  }

 //keep current LED state unless the button has been pushed
  switch (blinkState) {
    case true:
     //if button has been pushed, stop blinking and change LED state
      if (toggleBlinking == true) {
        timer_b.stop (blink_id);
        blinkState = false;
      }
      break;
    case false:
      digitalWrite(led, LOW);
     //if button has been pushed, start blinking and change LED state
      if (toggleBlinking == true) {
        blink_id = timer_b.oscillate(led, 1000, HIGH);
        blinkState = true;
      }
      break;
  }

  buttonState_prev = buttonState;
  toggleBlinking = false;
}

NOTE: You'll need to install the Timer.h library. I'VE TESTED MY CODE AND IT WORKS.

2
katma
Bu bir kilitlenme değil, aksi halde iyi :-)
katma yazar af., kaynak
Haklısın, teşekkürler. Cevabı düzenleyeceğim.
katma yazar Arperum, kaynak
Tamam, bir pull-up kullandığını göreceğim. Bunu kontrol edeceğim.
katma yazar Arperum, kaynak
Cevabı değiştirdim, bir göz at.
katma yazar Arperum, kaynak
Kodunuz sadece Led'in bir kez yanıp sönmesini sağlıyor ... Burada ne yapmaya çalıştığınızı anlıyorum ama düğmeye basıldığında ledin sürekli yanıp sönmesini istiyorum. Ancak, düğmeye tekrar basıldığında yanıp sönmeyi keser. Dediğim gibi, bu, ledin sadece bir kez yanıp sönmesini sağlıyor, sonra düğmeye basmadan yanıp sönmeyi bırakıyor ...
katma yazar Jon7, kaynak
Evet üzgünüm, daha fazla ayrıntı vermeliydim:
katma yazar Jon7, kaynak
@EnricBlanco herhangi bir güncelleme? üzgünüm ben sadece bu konuda sessiz bir süredir ve sorunları hakkında biraz açıklama gerekir ..
katma yazar Jon7, kaynak

bunu dene:

if (key_pressed()) digitalWrite(LED_PIN, (digitalRead(LED_PIN)==ON)?OFF:ON);
else digitalWrite(LED_PIN, OFF);

led bağlantınıza göre ON/OFF tanımlayın.

Düzenle.

Düğmenin de led yanıp sönme modunu değiştirmesini istiyorsanız, bunu deneyin.

    if (btn_pressed())                  //if btn falling edge detected
        btn_status ^= 1;                //flip the last bit. btn_status += 1; works as well
    if (btn_status & 0x01) led1_flp();  //flip led1
    else led1_off();                    //otherwise, turn off led1

    //flip led2
    IO_FLP(LED_PORT, LED2);

mantık oldukça basittir: eğer düğmeye basılırsa (aktif düşük), btn_status'u değiştirin. btn_status 1 ise led1'i yanıp söner.

temel olarak, düğmeye basın, led yanıp sönmeye başlar; düğmeye 2. kez basın, led yanıp sönmeyi keser;

led2 kodun eşzamanlılığını göstermek için her zaman yanıp söner.

burada harekete geçiyor.

enter image description here

Kod bir resim için yazılmıştır ancak temel olarak herhangi bir mcu üzerinde çalışır.

1
katma
while (buttonState == LOW)

bir kez buttonState == LOW 'ı sonsuz bir döngüde yakalarsınız.
Bundan kurtulmak istiyorsanız, bu döngüde buttonState içinde bu anketi kullanmanız gerekir.
Ancak bu amaç için yeterli değil. Gerçekte ihtiyacınız olan şey bir (boolean) değişken - diyelim ki yanıp sönüyor - örneğin, buttonState'te her bir düşme kenarı gördüğünüzde değerini değiştiriyor.
Ardından, bu değişkenin değerini şöyle bir if/else deyiminde kontrol edin:

if (blinking == true)
{
   digitalWrite(led, HIGH);  //turn the LED on (HIGH is the voltage level)
   delay(1000);              //wait for a second
   digitalWrite(led, LOW);   //turn the LED off by making the voltage LOW
   delay(1000);              //wait for a second
}
else
{
   digitalWrite(led, LOW);}
}

Ancak bununla yakında bir sonraki sorunla karşılaşacaksınız: Düğmenizin yoklama hızı çok düşük, çünkü sizi if yan tümcesinde yaklaşık 2 saniye tutan gecikmelerden dolayı çok düşük. Bir PWM kullanarak yanıp sönme döngüsünü ayarlamayı deneyin; burayı Ardından, PWM görevini% 50 olarak ayarlamak için yukarıdaki if yan tümcesini ve% 0 olarak ayarlamak için else yan tümcesini kullanın.

1
katma
Bu cevap biraz yanıltıcıdır. Yoklama buttonState , bir içindeyken (buttonState == LOW) döngüsü hiçbir şey yapmaz.
katma yazar af., kaynak
@Usav no, buttonState'i güncellemek, yeni bir tane oluşturmak değil diğerini kapsam dışından gölgelemek istiyorsunuz.
katma yazar Hailwood, kaynak
@Utsav Bu yardımcı olmaz. buttonState , iğnenin mevcut durumunu yansıtmaz. digitalRead yapar.
katma yazar Hailwood, kaynak
@KIIV böylelikle while döngüsüne başka bir bool buttonState = digitalRead (buttonPin); koydum ve ardından while döngüsünün içine If deyimini kesip yapıştırdım. Hala sonuç çıkarmıyorlar: Üzgünüm, istediğinizi gerçekten uygulayamadım ...
katma yazar Jon7, kaynak
'Yanıp sönen' adlı bu yeni bool değişkenini oluştururken, değişkeni bir sayı ile ayarlayabilir miyim? gibi: bool yanıp sönüyor = 0; veya başka bir şey mi yapıyorsunuz? Kafam çok karışık ..
katma yazar Jon7, kaynak
Yani süre döngüsünün içine If (buttonState == HIGH) koymamı mı istiyorsunuz?
katma yazar Jon7, kaynak