Nyalakan dan matikan LED dengan sakelar


10

Saya mencoba menulis kode untuk menyalakan LED saat mati dan mematikan ketika menggunakan sakelar tombol tekan taktil. Saya telah menulis apa yang saya yakini sebagai kode yang tepat dengan pustaka wiringPi, tetapi saya hanya bisa mengaktifkannya ketika dimatikan dan tidak bisa mematikannya setelah itu. Pada contoh yang sangat jarang dan setelah banyak penekanan berulang kali LED akan mati ketika dinyalakan dan saya menekan tombol, tapi saya yakin bukan itu cara kerjanya.

#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;
}

Saya telah memasang gambar tentang bagaimana rangkaian ini dihubungkan.LEDciruit

c 

2
Apakah perpustakaan Anda menyertakan debounce untuk switch? Jika tidak, Anda mungkin mematikan LED dengan sukses dan kemudian segera menyalakannya kembali. Setelah Anda mendeteksi perubahan status, abaikan deteksi lebih lanjut untuk periode singkat.

1
@ MikeW saya tidak percaya begitu. Saya akan mencoba memasukkan penundaan setelah pernyataan if diproses.

6
@duskwuff Pertanyaan ini jelas tentang pemrograman.

1
menjaga variabel lokal yang berisi keadaan saat ini dari led (ON / OFF) (mungkin melalui enum) jangan mencoba untuk membaca keadaan pin output. Alih-alih mendeteksi tepi input berubah dari tinggi ke rendah dari pin input. kemudian perbarui status arus variabel lokal: outputimagevar = (outputimagevar == TINGGI)? RENDAH: TINGGI; kemudian digitalWrite (0, outputimagevar); kemudian, ketika input berubah dari RENDAH ke TINGGI, setel ulang logika deteksi TINGGI ke RENDAH. Juga, pastikan untuk 'debounce' keadaan input, mungkin dengan memastikan (katakanlah) 3 kali dibaca berturut-turut semua menunjukkan kondisi yang sama.

Apa yang baru saja saya lakukan adalah memasukkan penundaan setengah detik di dalam sarang masing-masing jika pernyataan dan tampaknya berfungsi saat ini. Sesuatu mengatakan kepada saya bahwa ini adalah semacam metode bruteforce yang tidak akan selalu berfungsi seperti yang saya perkirakan jika tombol ditekan lebih cepat dari setengah detik, dan mungkin tidak akan berfungsi seperti itu di proyek utama saya, jadi saya akan melihat ke dalam sisa jawabannya. Saya menghargai masukan semua orang.

Jawaban:


4

Kabel terlihat benar untuk kode.

Masalahnya adalah bahwa kode tersebut berada dalam loop yang sangat ketat. Secara teori, ketika tombol ditekan, loop body berulang kali menyalakan dan mematikan LED. Secara teori, akan ada kemungkinan 50/50 LED dibiarkan hidup (atau mati) ketika tombol dilepaskan. Apakah Anda melihat perubahan kecerahan ketika tombol ditekan. Mungkin tidak cukup untuk diperhatikan.

Dalam praktiknya, alasan kecenderungan membiarkan LED menyala adalah cara Anda menguji apakah sudah menyala. Penulisan pin 0 TINGGI berlaku 3,3 V ke output. Tapi kabel itu terhubung ke LED dan pin dikonfigurasi untuk menjadi output. LED mungkin menjatuhkan voltase cukup rendah untuk tidak mendaftar sebagai TINGGI ketika dibaca, tetapi kadang-kadang itu terjadi karena dekat dengan cutoff.

Dalam praktiknya, kode untuk mematikan dan menghidupkan LED dengan setiap tombol tekan akan menggunakan interupsi yang dipicu oleh jatuh. Seperti yang ditunjukkan dalam komentar, Anda ingin menghilangkan interupsi dalam kasus itu. Anda juga dapat melakukan hal yang sama tanpa menyela dengan merekam keadaan tombol sebelumnya dan hanya mengubah LED ketika keadaan tombol telah berubah. Debouncing saat kode ditulis sekarang tidak masuk akal.

#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

Mungkin lebih mudah untuk mempertahankan "keadaan" dalam variabel normal daripada mencoba menyimpulkannya dari keadaan GPIO saat ini.

Juga "loop sibuk" akan mengkonsumsi setiap siklus CPU OS akan memungkinkan proses; untuk proses yang begitu sederhana, Anda akan melihat bahwa beban CPU Anda akan naik hingga 100%! Anda harus mengizinkan proses untuk melepaskan CPU ke tugas lain dengan usleep()panggilan misalnya. Penundaan juga akan berfungsi untuk menonaktifkan sakelar.

#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;
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.