Beberapa pola LED independen

8

Saya memiliki masalah, yang pada awalnya (dan baru di Arduino) saya pikir itu adalah aplikasi yang sempurna untuk Arduino. Namun, setelah mencoba dan gagal menerapkannya, saya sendiri ragu!

Cukup - Saya perlu mengontrol banyak LED secara independen, banyak di antaranya akan memiliki pola tersendiri - misalnya "5 detik hidup - mati 5 detik". "flash berkelanjutan" - atau urutan seperti "2 berkedip, jeda, 1 flash". Jelas tanpa kemewahan utas saya menjadi sedikit macet. Lebih baik mendengar jika a) Arduino adalah pilihan terbaik dan b) jika itu - bagaimana saya bisa melakukan ini!

Terima kasih sebelumnya :)

Nickos
sumber
1
Sudahkah Anda melihat pada protothreads ? Ada beberapa perpustakaan Arduino yang memungkinkan Anda dengan mudah memasukkan protothreads dalam proyek Anda.
sachleen

Jawaban:

9

Menangani beberapa pola pada saat yang bersamaan tentu dimungkinkan dengan platform seperti Arduino, dan ada sejumlah cara untuk melakukannya.

Salah satu metode yang akan saya pertimbangkan adalah fungsi menulis yang secara efektif mewakili setiap pola secara matematis. Anda baru saja melewatkannya total waktu yang telah berlalu dalam program Anda sejauh ini, dan itu akan melakukan tindakan yang sesuai untuk momen spesifik waktu itu. Ini akan segera kembali setelah itu (tidak ada penundaan atau apa pun).

Untuk melakukan itu, pertama-tama Anda harus tahu berapa lama satu siklus pola berlangsung. Anda kemudian dapat menggunakan operator modulo untuk mengetahui seberapa jauh siklus Anda saat ini. Dari sana, yang perlu Anda lakukan adalah memiliki beberapa ifkondisi untuk menentukan apa yang harus dilakukan pada waktu tertentu.

Inilah yang mungkin terlihat untuk pola "5 detik aktif, 5 detik nonaktif" Anda:

function pattern5on5off(unsigned long totalTime)
{
  // Calculate how far through the current cycle we are
  const unsigned long cycleTime = totalTime % 10000;

  // If we're in the first 5 seconds of the cycle then turn the light on.
  // Otherwise, turn it off.
  if (cycleTime < 5000)
    digitalWrite(3, HIGH);
  else
    digitalWrite(3, LOW);
}

Memang, terus-menerus menelepon digitalWrite()ketika Anda tidak perlu secara teknis tidak terlalu efisien. Seharusnya tidak menyebabkan bahaya, dan cukup mudah untuk dioptimalkan jika perlu.

Untuk menggunakan contoh di atas dalam sketsa, Anda hanya perlu memanggilnya loop(), dan meneruskan nomor yang Anda dapatkan millis(); misalnya:

void loop()
{
  const unsigned long totalTime = millis();

  pattern5on5off(totalTime);

  // call other patterns here...
}

Pola lain akan lebih kompleks, tetapi mengikuti prinsip yang sama. Anda hanya perlu menggunakan ifpernyataan yang sesuai untuk mengekspresikan logika Anda.

Yang penting untuk diingat adalah bahwa fungsi tersebut mewakili momen tertentu dalam waktu. Seharusnya tidak pernah menghentikan atau menunda program, jika tidak maka pola lainnya tidak akan berjalan.

Sunting: Waktu pada siklus pertama
Seperti jfpoilpret mencatat dalam komentar, siklus pertama akan dimulai pada titik acak. Hal ini karena pertama kali Anda menelepon millis()di loop(), itu tidak akan dimulai dari 0 (perangkat akan sudah telah berjalan untuk waktu yang singkat sebelum loop()dipanggil). Sangat mudah untuk diselesaikan, jika perlu.

Anda akan melakukannya dengan mengimbangi totalTimenilai dengan nilai apa pun yang Anda dapatkan pada saat pertama kali loop(). Sebagai contoh:

unsigned long g_startTime = 0;

void loop()
{
  unsigned long totalTime = 0;

  if (g_startTime == 0) {
    // This is the first cycle.
    // Store the start time so we can compensate later.
    g_startTime = millis();

  } else {
    // This is not the first cycle.
    // Compensate for the start time.
    totalTime = millis() - g_startTime;
  }

  pattern5on5off(totalTime);
  // etc..
}
Peter Bloomfield
sumber
Terima kasih banyak - sangat masuk akal! Aku benar-benar telah membenturkan kepalaku ke dinding dengan pendekatan yang salah ... :)
Nickos
1
Masalah dengan %pendekatan ini adalah bahwa waktunya tidak akan benar pertama kali, karena itu hanya akan acak pada awalnya.
jfpoilpret
1
@ jfpoilpret Itu benar. Sangat mudah untuk memperbaikinya, jadi saya telah menambahkannya ke jawaban saya. :)
Peter Bloomfield
Pilihan lain adalah, alih-alih menjalankan millissatu kali dalam loop dan meneruskan nilainya sebagai parameter ke setiap fungsi yang dipimpin, untuk memiliki masing-masing fungsi sebagai yang tanpa parameter, dan menjalankan millis di dalam masing-masing. Itu akan memungkinkan setiap fungsi untuk mendapatkan nilai yang lebih tepat, yang mungkin atau mungkin tidak penting tergantung pada berapa banyak waktu yang dibutuhkan masing-masing fungsi dalam loop, dan juga persyaratan ketepatan waktu aplikasi.
heltonbiker
4

Arduino adalah pilihan yang bagus untuk tugas ini - mudah untuk memulai. Kuncinya adalah menulis kode yang tidak menghalangi. Anda dapat melihat contoh BlinkWithoutDelay.

Saya membuat saran untuk tugas Anda:

// Timing suquences for the LED's in milliseconds
// First value is on time, second value is off time,
// third value on time and so on (up to 10 values)
// One row for each LED
unsigned int led_timing[][10] = {
  {5000, 5000},
  {100, 1000},
  {100, 100, 100, 1500, 100, 1500}
};

// The pins the LED's are connected to
byte led_pins[] = {11, 12, 13};

// Keep track of timing sequence
// Array size taken from led_pins
unsigned long last_change[sizeof(led_pins)/sizeof(led_pins[0])];
byte timing_i[sizeof(led_pins)/sizeof(led_pins[0])];

void setup()
{
  // Initialize LED's as output
  for (byte i = 0; i < sizeof(led_pins)/sizeof(led_pins[0]); i++)
  {
    pinMode(led_pins[i], OUTPUT);
    digitalWrite(led_pins[i], HIGH);
  }
}


void loop()
{
  // Current timestamp
  unsigned long now = millis();

  // Keep track of sequence for each LED
  for (byte i = 0; i < sizeof(led_pins)/sizeof(led_pins[0]); i++)
  {
    if (now - last_change[i] >= led_timing[i][timing_i[i]])
    {
      digitalWrite(led_pins[i], !digitalRead(led_pins[i]));
      timing_i[i]++;

      // Start over at the end of timing sequence
      timing_i[i] %= sizeof(led_timing[i])/sizeof(led_timing[i][0]);

      last_change[i] = now;
    }
  }
}
user2973
sumber
0

Saya tahu posting sudah tua, tapi saya memeriksa contoh dengan pendekatan berbasis array dan menurut saya:

sizeof(led_timing[i])/sizeof(led_timing[i][0])

akan selalu menghasilkan ukuran yang dialokasikan (jumlah elemen) dari array - dalam kasus ini 10. Jadi waktunya tidak akan restart sampai Anda mencapai "akhir" array, menggunakan elemen yang tidak ditentukan. Untuk LED "0":

int led_timing[0][10]:
5000,5000, <undefined>, <undefined>, <undefined>, <undefined>, <undefined>, <undefined>, <undefined>, <undefined>

Salam Tommy

TommyL
sumber