Nhiều mẫu LED độc lập


8

Tôi có một vấn đề, mà lúc đầu tôi nghĩ (và là người mới đối với Arduino) Tôi mặc dù là một ứng dụng hoàn hảo cho Arduino. Tuy nhiên, sau khi thử và thất bại trong việc thực hiện nó, tôi đang nghi ngờ chính mình!

Đơn giản - Tôi cần điều khiển nhiều đèn LED một cách độc lập, nhiều trong số chúng sẽ có các mẫu riêng - ví dụ "5 giây bật - tắt 5 giây". "nhấp nháy liên tục" - hoặc các chuỗi như "2 lần nhấp, tạm dừng, 1 lần chớp". Rõ ràng là không có sự sang trọng của các chủ đề, tôi đang trở nên một chút không ổn định. Thật tuyệt khi nghe nếu a) Arduino là sự lựa chọn tốt nhất và b) nếu có - làm thế nào tôi có thể đi về điều này!

Cảm ơn trước :)


1
Bạn đã nhìn vào protothreads ? Có một vài thư viện Arduino cho phép bạn dễ dàng kết hợp các protothreads trong dự án của bạn.
sachleen

Câu trả lời:


9

Xử lý nhiều mẫu cùng một lúc chắc chắn là có thể với một nền tảng như Arduino, và có một số cách bạn có thể đi về nó.

Một phương pháp tôi sẽ xem xét là viết các hàm đại diện hiệu quả cho từng mẫu theo toán học. Cho đến nay, bạn chỉ cần vượt qua tổng thời gian đã trôi qua trong chương trình của mình và nó sẽ thực hiện hành động thích hợp cho thời điểm cụ thể đó. Nó sẽ trở lại ngay lập tức sau đó (không chậm trễ hoặc bất cứ điều gì).

Để làm điều đó, trước tiên bạn cần biết một chu kỳ của mẫu sẽ kéo dài bao lâu. Sau đó, bạn có thể sử dụng toán tử modulo để tìm hiểu xem bạn đang ở đâu trong chu kỳ hiện tại. Từ đó, tất cả những gì bạn cần làm là có một số ifđiều kiện để xác định những việc cần làm tại bất kỳ thời điểm nào.

Đây là giao diện của mẫu "5 giây bật, tắt 5 giây" của bạn:

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

Phải thừa nhận rằng, liên tục gọi điện digitalWrite()khi bạn không cần kỹ thuật là không hiệu quả. Nó không gây ra bất kỳ tác hại nào, và khá dễ dàng để tối ưu hóa nếu cần thiết.

Để sử dụng ví dụ trên trong một bản phác thảo, bạn chỉ cần gọi nó vào loop()và chuyển số bạn nhận được từ millis(); ví dụ:

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

  pattern5on5off(totalTime);

  // call other patterns here...
}

Các mẫu khác sẽ phức tạp hơn, nhưng theo cùng một nguyên tắc. Bạn chỉ cần sử dụng các iftuyên bố thích hợp để thể hiện logic của bạn.

Điều quan trọng cần nhớ là chức năng đại diện cho một thời điểm cụ thể. Nó không bao giờ nên tạm dừng hoặc trì hoãn chương trình, nếu không nó sẽ ngăn các mẫu khác chạy.

Chỉnh sửa: Thời gian trên chu kỳ đầu tiên
Như jfpoilpret đã lưu ý trong các nhận xét, chu kỳ đầu tiên sẽ bắt đầu tại một điểm ngẫu nhiên. Điều này là do lần đầu tiên bạn gọi millis()đến loop(), nó sẽ không bắt đầu từ 0 (thiết bị sẽ chạy trong một thời gian ngắn trước khi loop()được gọi). Thật dễ dàng để giải quyết, nếu cần thiết.

Bạn sẽ làm điều đó bằng cách bù đắp totalTimegiá trị bằng bất kỳ giá trị nào bạn nhận được trong lần đầu tiên loop(). Ví dụ:

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

Cảm ơn bạn rất nhiều - làm cho ý nghĩa hoàn hảo! Ive chắc chắn đã đập đầu vào tường với cách tiếp cận sai ... :)
Nickos

1
Vấn đề với %cách tiếp cận là lần đầu tiên sẽ không chính xác, vì nó sẽ chỉ là ngẫu nhiên lúc đầu.
jfpoilpret

1
@jfpoilpret Đó là sự thật. Thật dễ dàng để sửa chữa, vì vậy tôi đã thêm nó vào câu trả lời của mình. :)
Peter Bloomfield

Một tùy chọn khác là, thay vì chạy millismột lần trong vòng lặp và truyền giá trị của nó dưới dạng tham số cho mọi hàm led, để có mỗi hàm là một tham số không tham số và chạy millis bên trong mỗi hàm. Điều đó sẽ cho phép mỗi chức năng có được một giá trị chính xác hơn, điều này có thể hoặc không quan trọng tùy thuộc vào thời gian mỗi chức năng trong vòng lặp chạy, và yêu cầu về tính chính xác về thời gian của ứng dụng.
heltonbiker

4

Arduino là một lựa chọn tốt cho nhiệm vụ - dễ dàng để bắt đầu. Điều quan trọng là viết mã không chặn. Bạn có thể xem ví dụ về BlinkWithoutDelay.

Tôi đã đưa ra một đề nghị cho nhiệm vụ của bạn:

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

0

Tôi biết bài viết đã cũ, nhưng tôi đã kiểm tra ví dụ với cách tiếp cận dựa trên mảng và theo ý kiến ​​của tôi:

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

sẽ luôn mang lại kích thước được phân bổ (số phần tử) của mảng - trong trường hợp này 10. Vì vậy, thời gian sẽ không khởi động lại cho đến khi bạn đạt đến "kết thúc" của mảng, sử dụng các phần tử không xác định. Đối với đèn LED "0":

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

Chúc mừng Tommy

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.