스위치로 LED 켜고 끄기


10

촉각 푸시 버튼 스위치를 사용하여 LED가 꺼져있을 때 켜고 끄는 코드를 작성하려고합니다. 내가 생각하는 것은 wirePi 라이브러리를 사용하여 올바른 코드라고 썼지 만 꺼져있을 때만 켜고 그 후에 끌 수는 없습니다. 매우 드문 경우에 여러 번 반복해서 누르면 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;
}

회로가 어떻게 배선되어 있는지에 대한 이미지를 첨부했습니다.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 문의 둥지 안에 0.5 초 지연을 삽입하는 것입니다. 이번에는 제대로 작동하는 것으로 보입니다. 뭔가 버튼이 0.5 초보다 빨리 눌려지면 예상대로 항상 작동하지 않는 일종의 무차별 방법이라고 말하며, 주요 프로젝트에서 그렇게 작동하지 않을 것입니다. 나머지 답변. 모두의 의견에 감사드립니다.

답변:


4

배선이 코드에 맞게 보입니다.

문제는 코드가 매우 타이트한 루프에 있다는 것입니다. 이론적으로 버튼을 누르면 루프 본체가 반복적으로 LED를 켜고 끕니다. 이론적으로, 버튼에서 손을 떼면 LED가 켜져 있거나 꺼져있을 가능성이 50/50입니다. 버튼을 누를 때 밝기가 변하는 것을 알 수 있습니다. 눈에 띄지 않을 수 있습니다.

실제로, LED를 켜두는 경향이있는 이유는 이미 켜져 있는지 테스트하는 방법입니다. 쓰기 핀 0 HIGH는 출력에 3.3V를 적용합니다. 그러나 해당 와이어는 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 상태에서 추론하지 않고 일반 변수에서 "상태"를 유지하는 것이 더 간단합니다.

또한 "busy-loop"는 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.