用开关打开和关闭LED


10

我正在尝试编写代码,以使LED在关闭时点亮,并在打开时使用触觉按钮开关关闭。我已经写好了connectionPicture库中正确的代码,但是我只能在关闭时打开它,然后再关闭它。在极少数情况下,在多次按下此键后,当我按下按钮时,LED会熄灭,但是我确定那不是应该的。

#include <wiringPi.h>
int main (void)
{
    wiringPiSetup ();
    pinMode (0, OUTPUT);
    pinMode (1, INPUT);
    digitalWrite (0, LOW);
    for(;;)
    {
        if(digitalRead (1) == LOW)
        {
            if(digitalRead (0) == HIGH)
                digitalWrite (0, LOW);
            else if(digitalRead (0) == LOW)
                digitalWrite (0, HIGH);
         }
     }
     return 0;
}

我已经附上了电路接线图。LEDciruit

c 

2
您的媒体库中是否包含此开关的去抖动功能?如果不是,您可能成功关闭了LED,然后立即将其重新打开。一旦检测到状态变化,请在短时间内忽略所有进一步的检测。

1
@MikeW我不这么认为。我将在处理if语句后尝试插入延迟。

6
@duskwuff这个问题肯定是关于编程的。

1
保持包含led(ON / OFF)当前状态(可能通过枚举)的局部变量不要尝试读取输出引脚的状态。而是检测输入状态的边沿从输入引脚的高到低变化。然后更新局部变量的当前状态:outputimagevar =(outputimagevar == HIGH)?低高; 然后digitalWrite(0,outputimagevar); 然后,当输入从LOW变为HIGH时,将HIGH复位为LOW检测逻辑。同样,确保“去抖动”输入状态,也许可以确保(例如)连续3次读取都显示相同状态。

我刚才所做的是在每个if语句的嵌套中插入半秒的延迟,这一次似乎正在正常工作。有人告诉我,这是一种蛮力方法,无法按预期运行,因为如果按下按钮的时间超过半秒,我可能会预料到它,并且在我的主项目中可能无法正常工作,因此我将研究其余的答案。我感谢大家的投入。

Answers:


4

接线看起来与代码正确。

问题在于代码处于非常紧密的循环中。理论上,当按下按钮时,回路主体会反复打开和关闭LED。从理论上讲,当释放按钮时,LED有50/50的机会保持打开或关闭状态。按下按钮时,您是否注意到亮度的变化?可能还不足以引起注意。

在实践中,导致LED保持点亮趋势的原因是您测试是否已点亮的方式。将0引脚写入高电平将向输出施加3.3 V电压。但是那条线连接到LED,并且该引脚配置为输出。LED可能会将电压降得足够低,以至于在读取时不会注册为HIGH,但有时这样做是因为它接近截止电压。

实际上,每次按下按钮来关闭和打开LED的代码都将使用下降沿触发的中断。如注释中所指出的那样,在这种情况下,您可能希望对中断进行反跳处理。您还可以通过记录按钮的先前状态并仅在按钮状态更改后才更改LED来做同样的事情而不会中断。现在在编写代码时进行反跳没有任何意义。

#include <wiringPi.h>
int main (void)
{
    wiringPiSetup ();
    pinMode (0, OUTPUT);
    pinMode (1, INPUT);
    digitalWrite (0, LOW);

    int prevButton = HIGH, LED = 0;

    for(;;)
    {
        if(prevButton == HIGH && digitalRead(1) == LOW)  // a falling edge
        {
            prevButton = LOW;

            if(LED)
            {
                LED = 0;
                digitalWrite(0, LOW);
            }
            else
            {
                LED = 1;
                digitalWrite(0, HIGH);
            }
        }
        else if(prevButton == LOW && digitalRead(1) == HIGH)  // a rising edge, do nothing
        {
            prevButton = HIGH;
        )

        // Add a delay here to debounce the button 

    }
    return 0;
}

0

在普通变量中维护“状态”可能比尝试从当前GPIO状态推断出状态更简单。

同样,“忙循环”将消耗OS允许该进程的每个CPU周期;对于这样一个简单的过程,您将看到您的CPU负载将上升到100%!例如,您应该允许进程通过usleep()调用将CPU放弃其他任务。延迟还可以消除开关的反弹。

#include <wiringPi.h>
#include <unistd.h>

int main (void)
{
  wiringPiSetup ();
  pinMode (0, OUTPUT);
  pinMode (1, INPUT);
  digitalWrite (0, LOW);

  // Initial state
  int led = LOW ;
  bool button_down = (digitalRead(1) == LOW) ;

  for(;;)
  {
    // If button-down event (Hi-lo transition)...
    if( !button_down && digitalRead(1) == LOW )
    { 
      // Keep button state
      button_down = true ;

      // Toggle LED state
      led = (led == LOW) ? HIGH : LOW ;
      digitalWrite( 0, led ) ;
    }
    // Button up event...
    else if( button_down && digitalRead(1) == HIGH ) 
    {
      // Keep button state
      button_down = false ;
    }

    usleep( 10000 ) ;
  }

  return 0;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.