スイッチでLEDをオンまたはオフにする


10

触覚のプッシュボタンスイッチを使用して、LEDがオフのときに点灯し、オンのときに消灯するコードを記述しようとしています。私は、wiringPiライブラリを使用して適切なコードであると確信しているものを記述しましたが、オフにしたときにのみオンになり、その後オフにできません。非常にまれな状況で、何度も繰り返し押すと、LEDがオンになっているときに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;
}

回路の配線方法の画像を添付しました。LED回路

c 

2
ライブラリにスイッチのデバウンスが含まれていますか?そうでない場合は、おそらくLEDを正常にオフにしてから、すぐに再びオンにします。状態の変化を検出したら、それ以上の検出を短時間無視してください。

1
@MikeW私はそうは思わない。ifステートメントが処理された後に遅延を挿入してみます。

6
@duskwuffこの質問は間違いなくプログラミングについてです。

1
LEDの現在の状態(おそらく列挙型を介して)を含むローカル変数を保持して、出力ピンの状態を読み取ろうとしないでください。代わりに、入力ピンのハイからローへの入力状態変化のエッジを検出します。次に、ローカル変数の現在の状態を更新します。outputimagevar=(outputimagevar == HIGH)?低:高。次にdigitalWrite(0、outputimagevar); 次に、入力がLOWからHIGHに変化したときに、HIGHからLOWの検出ロジックをリセットします。また、おそらく3つの連続した読み取りがすべて同じ状態を示すことを保証するなどして、入力状態を必ず「デバウンス」してください。

私が今行ったのは、各ifステートメントのネスト内に0.5秒の遅延を挿入することで、今回は正しく機能しているようです。これは、ボタンが0.5秒より速く押された場合に予想されるように常に機能するとは限らない、ブルートフォースメソッドの一種であり、おそらくメインプロジェクトではそのように機能しないため、残りの答え。皆様のご意見に感謝いたします。

回答:


4

配線はコードに対して正しく見えます。

問題は、コードが非常にタイトなループにあることです。理論的には、ボタンを押すと、ループ本体がLEDのオンとオフを繰り返します。理論的には、ボタンを離したときにLEDがオン(またはオフ)のままになる可能性は50/50です。ボタンを押すと明るさが変化します。気づかれるほどではないかもしれません。

実際には、LEDをオンのままにする傾向がある理由は、LEDがすでにオンになっているかどうかをテストする方法です。ピン0をHIGHに書き込むと、出力に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;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.