Вмикайте та вимикайте світлодіод за допомогою перемикача


10

Я намагаюся написати код, щоб отримати світлодіод, щоб увімкнути, коли він вимкнений, і вимкнути його, коли він увімкнений, використовуючи тактильний кнопковий перемикач. Я написав, що, на мою думку, це правильний код з бібліотекою wiringPi, але я можу змусити його вмикатись лише тоді, коли він вимкнений, і не можу змусити його вимкнутись після цього. У дуже рідкісних випадках і після багатьох повторних натискань світлодіод вимикається, коли він увімкнений, і я натискаю кнопку, але я впевнений, що це не так, як це повинно працювати.

#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
Чи містить у вашій бібліотеці дебюти за комутатор? Якщо ні, ви, ймовірно, успішно вимикаєте світлодіод, а потім негайно вмикаєте його. Після виявлення зміни стану ігноруйте подальші виявлення протягом короткого періоду.

1
@MikeW Я не вірю в це. Я спробую вставити затримку після того, як оператор if буде оброблений.

6
@duskwuff Це питання, безумовно, стосується програмування.

1
зберігайте локальну змінну, що містить поточний стан світлодіода (ON / OFF) (можливо, через enum), не намагайтеся прочитати стан вихідного штифта. Замість цього виявіть зміну краю вхідного стану від високого до низького вхідного штифта. потім оновіть локальний змінний поточний стан: outputimagevar = (outputimagevar == ВИСОКИЙ)? НИЗЬКИЙ: ВИСОКИЙ; потім digitalWrite (0, вихіднемаджевар); потім, коли вхід змінюється з НИЗКОГО на ВИСОК, скидайте логіку виявлення ВИСОКИЙ НА ВИСОК. Крім того, не забудьте "зняти" стан введення, можливо, запевнивши (скажімо), що 3 послідовні читання показують, що всі показують однаковий стан.

Що я тільки що зробив, це вставити на півсекунди затримку всередині гнізда кожного if оператора, і, здається, на цей раз він працює правильно. Щось підказує мені, що це такий спосіб грубої сили, який не завжди буде працювати, як я міг би передбачити, якщо натиснути кнопку швидше, ніж за півсекунди, і, мабуть, це не спрацює так у моєму головному проекті, тому я буду розглядати решта відповідей. Я вдячний всім внескам.

Відповіді:


4

Проводка виглядає правильно для коду.

Проблема полягає в тому, що код знаходиться в дуже тісному циклі. Теоретично при натисканні кнопки корпус петлі кілька разів вмикає та вимикає світлодіод. Теоретично існує ймовірність 50/50, коли світлодіод буде увімкненим (або вимкненим) при відпуску кнопки. Ви помічаєте зміну яскравості при натисканні кнопки. Може бути недостатньо, щоб помітити.

На практиці причиною тенденції залишати світлодіод у тому, як ви протестуєте, щоб перевірити, чи він уже включений. Пишучий штифт 0 HIGH застосовує 3,3 В до виходу. Але цей провід підключений до світлодіода і штифт налаштований на вихід. Світлодіод може знижувати напругу досить низьку, щоб не реєструватись як ВИСОКИЙ при зчитуванні, але іноді це відбувається, оскільки він знаходиться поблизу відсічення.

На практиці код для вимкнення та ввімкнення світлодіода при кожному натисканні кнопки використовує переривання, викликане краєм. Як зазначалося в коментарях, ви хочете викрити переривання в цій справі. Ви можете зробити те ж саме без перерв, записавши попередній стан кнопки та змінивши світлодіод лише тоді, коли стан кнопки змінився. Відмовлятися від написання коду зараз немає сенсу.

#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.

Також "цикл зайнятості" буде споживати кожен цикл процесора, що ОС дозволить процес; для такого простого процесу ви побачите, що завантаження вашого процесора зросте до 100%! Ви повинні дозволити процесу відмовитись процесору від інших завдань, наприклад, за допомогою usleep()виклику. Затримка також буде служити для відмови від вимикача.

#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;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.