当我按下切换按钮时,如何以不同的方式闪烁LED?

时间:2018-05-09 11:06:25

标签: c++ arduino

按下切换按钮,我试图使LED闪烁。如果我第一次按下第一个拨动开关,LED会以5 Hz的频率闪烁,当我第二次按下切换按钮时,LED以6 Hz的频率闪烁,当我第三次按下时,LED熄灭。

我尝试使用下面的程序,但它没有按我的意愿工作。

// constants won't change. They're used here to set pin numbers:
const int buttonPin = 7;     // the number of the pushbutton pin
const int ledPin =  6;      // the number of the LED pin
// variables will change:
int buttonState = 0;  

// variable for reading the pushbutton status
void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
   Serial.begin(9600); 
}

void loop() {
   int x=0; 
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);
  Serial.print(x);
  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (buttonState == HIGH &&  x==0) {
    // turn LED on:
    digitalWrite(ledPin, HIGH);
    delay(1000);
    digitalWrite(ledPin, LOW);
     delay(1000);
    Serial.print(x);
  } else {
    // turn LED off:
    x = x+1;
  }
  if (buttonState == HIGH && x==1) {
    // turn LED on:
    digitalWrite(ledPin, HIGH);
    delay(2000);
    digitalWrite(ledPin, LOW); 
    delay(2000);
     Serial.print(x);

  } else {
    // turn LED off:
    digitalWrite(ledPin, LOW);
    x = x+1;
  }
  if (buttonState == HIGH && x==2) {
    // turn LED on:
    digitalWrite(ledPin, HIGH);
    delay(3000);
    digitalWrite(ledPin, LOW);
    delay(3000);
     Serial.print(x);
  } else {
    // turn LED off:
    digitalWrite(ledPin, LOW);
    x = x+1;

  }
  if (buttonState == HIGH && x==3) {
    // turn LED off:
    digitalWrite(ledPin, LOW);
    x = 0;
  }
}

当我使用此代码时,它适用于第一种情况,即LED在1000毫秒延迟时闪烁,但如果我切换开关它再次适用于第一种情况。如何使其执行第二个条件,即在2000毫秒的延迟时闪烁?

4 个答案:

答案 0 :(得分:0)

您应该创建应用程序的全局状态。如果你以50hz / 60hz / off的速度闪烁,你可以记住这个状态。然后你可以使用开关来做正确的事情。

然后检查按钮是否被按下并更改应用程序状态。

请参阅下面的示例:

// constants won't change. They're used here to set pin numbers:
const int buttonPin = 7;     // the number of the pushbutton pin
const int ledPin =  6;      // the number of the LED pin
// variables will change:
int applicationState = 0;  
bool lightOn = true;

int currentDelay = 1000;

unsigned long currentMillis = 0;
unsigned long previousMillis = 0;

// variable for reading the pushbutton status
void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
}

void loop() {

    if (digitalRead(buttonPin) == HIGH) {
        applicationState++;
        if(applicationState >= 3) {
            applicationState = 0;
        }
        delay(100);
    }

    switch(applicationState){
        case 0:
            currentDelay = 1000;
            lightOn = true;
            break;
        case 1:
            currentDelay = 2000;
            lightOn = true;
            break;
        case 2:
            digitalWrite(ledPin, LOW);
            lightOn = false;
            break;
    }


    currentMillis = millis();
    if (currentMillis - previousMillis >= currentDelay && lightOn) {
        previousMillis = currentMillis;
        digitalWrite(ledPin, !digitalRead(ledPin));
    }      
}

我希望您能理解我尝试用示例代码说明和演示。

答案 1 :(得分:0)

现在你的逻辑在一个循环中检查x的值为3次。 当x大于零时,下面的代码会切换光。按下按钮时,x的值会改变。

但是这里存在一个很大的问题:如果在处理器中发生了其他事情或者正在休眠时按下按钮(例如您想要使用的长延迟),则可能会忽略该按钮。因此,您最好使用它们来研究中断并实现此行为。

if (x > 0)
{
    digitalWrite(ledPin, HIGH);
    delay(1000 * x);
    digitalWrite(ledPin, LOW);
}
if (buttonState == HIGH)
{
    x++;
    if (x > 3)
        x = 0;
}

答案 2 :(得分:0)

您的代码无效:

  1. 您需要检查按钮状态是否发生变化,检测是否存在边缘。并确保只检测一次边缘。

  2. 您必须重复循环闪烁直到按下按钮,然后才能更改频率。

  3. 您必须在睡觉时检查按钮,否则当您按下按钮时程序无法识别。

  4. 要使其正常工作,您必须更改完整的程序。

    #define BLINK_SLEEP_TIME <some value> // insert value for 16.6666ms
    
    //return 1 after a positive edge
    bool button_read(void)
    {
      static bool lastState=1; //set this to 1, so that a pressed button at startup does not trigger a instant reaction
      bool state = digitalRead(buttonPin);
      if(state != lastState)
        {
          state=lastState;
          return state;
        }
     return 0;
    }
    
    //Blink the LED with a given period, till button is pressed
    //Times are in x*16.666ms or x/60Hz
    //At least one time should be more than 0
    void blink(uint8_t ontime, uint8_t offtime) 
    {
      while(1)
      {
        for(uint8_t i=0;i<ontime;i++)
        {
          led_setOn();
          delay(BLINK_SLEEP_TIME);
          if(button_read())
          {
            return;
          }
        }
        for(uint8_t i=0;i<offtime;i++)
        {
          led_setOff();
          delay(BLINK_SLEEP_TIME);
          if(button_read())
          {
            return;
          }
        }
      }
    }
    
    const uint8_t time_table[][]=
    {
      {0,50},//LED is off
      {6,6}, //LED blinks with 5Hz, 60Hz/2/6=5Hz
      {5,5}, //LED blinks with 6Hz, 60Hz/2/5=6Hz
    }
    
    void endless(void)
    {
      uint8_t i=0;
      for(;;)
        {
          i++;
          if(i>2)
          {
            i=0;
          }
          blink(time_table[i][0],time_table[i][1]);
        }
    }
    

    更好的方法是使用硬件PWM模块并在按钮边缘后更改值。

答案 3 :(得分:0)

首先这是你的电路。我试过这个电路和代码并为我工作。我用中断检查按钮状态。毫安计算很简单。

频率= 1 /期间

期间= Ton + Toff

6Hz = 1000毫秒/ T => T = 166毫升

166 = Ton + Toff(对于%50占空比Ton = Toff)=&gt;吨= Toff = 83毫升

enter image description here

const int ledPin = 13;
const int buttonPin = 2;
int state = -1;
bool willLightOn = false;

unsigned long currentDelay = 0;
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(buttonPin), changeState, FALLING);
}

void loop() {
  if(state % 3 == 0) { //6Hz 
    currentDelay = 83;
    willLightOn = true;
  } else if (state % 3 == 1) { //5Hz
    currentDelay = 100;
    willLightOn = true;
  } else if (state % 3 == 2) { //LED off
    currentDelay = 0;
    willLightOn = false;
    digitalWrite(ledPin, LOW);
  }

  currentMillis = millis();
    if (currentMillis - previousMillis >= currentDelay && willLightOn) {
        previousMillis = currentMillis;
        digitalWrite(ledPin, !digitalRead(ledPin));
    } 
}

void changeState() {
  state++;
}