Arduino xử lý hàm chậm như thế nào

Tôi không phải là chuyên gia Arduino, mặc dù có tấm trong một thời gian dài tôi hầu như không điều tra. Những lần tôi sử dụng nó, nó giống như một công cụ sao chép và dán mã đã được tạo ra nhưng không quan tâm nhiều đến việc thực sự tìm hiểu cách thức hoạt động của nó mà chỉ đơn giản là với mục đích làm cho nó hoạt động và hữu ích cho tôi. Giáng sinh này, tôi đã điều chỉnh cảnh Chúa giáng sinh một chút bằng một số đèn LED và cảm biến siêu âm HC-SR04. Và tôi dừng lại để xem những gì phải làm.

Tôi chỉ muốn làm những điều khác nhau với hai đèn LED từ cùng một tín hiệu. Rất tiếc. Tôi nhanh chóng vấp phải những gì tôi nghĩ sẽ một trong những hạn chế đầu tiên bạn gặp phải khi bắt đầu sử dụng Arduino. Và bạn không cần phải làm cho nó quá phức tạp. Tôi chỉ nói về một số đèn LED, bạn nhận ra rằng bạn không thể làm những gì bạn muốn một cách chính xác.

Hãy làm rõ nó ngay từ đầu đa nhiệm không tồn tại trong Arduino, hai công việc không thể được xử lý song song. Nhưng có những kỹ thuật để thực hiện cuộc gọi nhanh đến mức chúng dường như hoạt động cùng một lúc.

Tôi kể vụ việc chi tiết hơn. Vào dịp Giáng sinh, tôi đã dựng một Khung cảnh Chúa giáng sinh và muốn một số đèn Chúa giáng sinh bật sáng khi con gái tôi đến gần. Không có gì phức tạp. Tôi chỉ muốn hai nhánh đèn led hoạt động khác với các giá trị của cảm biến khoảng cách.

Đăng ký kênh Youtube của chúng tôi

Tôi muốn khi ai đó tiến gần hơn 10 cm

  • Một trong những nhánh ánh sáng đi tới các vì sao sẽ sáng trong 10 giây
  • Rằng chiếc còn lại đi vào trong các ngôi nhà sẽ tồn tại trong 10 giây nhưng vì chúng tách khỏi hiện trường Chúa giáng sinh.

Đơn giản phải không? vì điều này có thể gây ra cho bạn những vấn đề lớn. Vì Arduino không có khả năng đa nhiệm, nó thực hiện hết lệnh này đến lệnh khác.

 

Arduino xử lý hàm chậm như thế nào

Tôi đã làm một gắn với cảm biến siêu âm HC-SR04 và 2 đèn LED, mỗi đèn sẽ bằng một nhánh của Bethlehem. Phần đầu tiên không vui lắm, vì nó là cấu hình thiết lập và hoạt động của cảm biến siêu âm trong LOOP, nhưng bạn có thể tìm thấy điều này ở hàng nghìn nơi. Giống như một ngày khác nếu tôi yêu cầu nhiều hơn, tôi tạo ra một đặc biệt, bây giờ bạn đang ở đây (xin lỗi không ghi các khoản tín dụng, nhưng tôi không nhớ tôi lấy nó từ đâu)

Mã HC-SR04 trên Arduino

int ledPin1 = 8; int ledPin2 = 7; khoảng cách xa; thời gian dài; thời gian dài hiện tại; thời gian dài; void setup () {// khởi tạo pin kỹ thuật số LED_BUILTIN dưới dạng đầu ra. pinMode (ledPin1, OUTPUT); pinMode (ledPin2, OUTPUT); Serial.begin (9600); pinMode (3, OUTPUT); / * kích hoạt chân 9 làm đầu ra: cho xung siêu âm * / pinMode (2, INPUT); / * kích hoạt chân 8 làm đầu vào: thời gian trả về siêu âm * /} // hàm lặp chạy lặp đi lặp lại mãi mãi void loop () {digitalWrite (3, LOW); / * Do ổn định cảm biến * / delayMicroseconds (5); digitalWrite (3, CAO); / * gửi xung siêu âm * / delayMicroseconds (10); thời gian = xungIn (2, CAO); / * Chức năng đo độ dài của xung tới. Đo thời gian trôi qua từ khi gửi xung siêu âm đến khi cảm biến nhận được phản hồi, nghĩa là: từ khi chân 12 bắt đầu nhận được phản hồi, CAO, cho đến khi nó ngừng hoạt động, THẤP, độ dài của xung đến * / khoảng cách = int (0.017 * thời gian); / * công thức tính khoảng cách thu được giá trị nguyên * / / * Theo dõi tính bằng cm bằng màn hình nối tiếp * / Serial.println ("Khoảng cách"); Serial.println (khoảng cách); Serial.println ("cm"); chậm trễ (1000);

Với điều này, khoảng cách đo bằng cảm biến siêu âm sẽ được xem lại và lưu trữ

Giải pháp vận hành LEDS

Điều đầu tiên nghĩ đến là bắt đầu trì hoãn. Tôi không biết tại sao, nhưng tất cả những người mới bắt đầu đều nghĩ đến delay () và điều đó hạn chế rất nhiều các tùy chọn vì trong khi sử dụng delay (), bảng không tiếp tục hoạt động và do đó bạn không thể làm gì khác trong thời gian tạm ngưng đó. Giải pháp là sử dụng millis ()

Ở đây tôi đã tìm thấy một giải pháp, đơn giản dựa trên if và counter. Như một giáo viên của tôi đã từng nói, bất cứ thứ gì cũng có thể được lập trình với nhiều if liên tiếp. Nhưng tất nhiên sự thật không được thanh lịch cho lắm.

// nếu khoảng cách nhỏ hơn 10 thì ta bật hai đèn LED hoặc nhánh lên và bắt đầu đếm thời gian bằng mili () if (khoảng cách <10) {digitalWrite (ledPin1, HIGH); digitalWrite (ledPin2, CAO); currenttime = millis (); } // nếu khoảng cách lớn hơn 10, chúng tôi sẽ kiểm tra thời gian trôi qua kể từ khi nó được bật và nếu nó lớn hơn thời gian được chỉ định, chúng tôi sẽ tắt LED1 nếu (khoảng cách> 10) {timepast = millis () - currenttime ; digitalWrite (ledPin1, LOW); // nếu khoảng cách lớn hơn 10000 ta sẽ tắt LED2 if (timepast> 10000) {digitalWrite (ledPin2, LOW); }}}

Điều mà đoạn mã này dự định là Arduino liên tục thực thi ba lệnh if đó để nó đi qua chúng nhanh đến mức có vẻ như nó đang thực hiện nhiều việc cùng một lúc. Nhưng như chúng ta đã biết, nó tiếp tục thực hiện từng câu một.

Khi khoảng cách được đo và lưu trữ trong biến khoảng cách, ifs sẽ được đánh giá:

  • Lần đầu tiên kiểm tra xem khoảng cách có nhỏ hơn 10 cm mong muốn hay không. Nếu vậy, chúng tôi bật hai đèn LED và bắt đầu đếm thời gian bằng mili ()
  • và chúng tôi sẽ đi đến thứ hai nếu khoảng cách lớn hơn 10 cm. Nếu nó tuân thủ, chúng tôi tính toán thời gian đã trôi qua và hủy kích hoạt led 1, chỉ phụ thuộc vào khoảng cách.
  • Chúng tôi sẽ chuyển sang phần thứ ba nếu chúng tôi kiểm tra xem đã hơn 10 giây kể từ khi bộ đếm được kích hoạt hay chưa, và nếu có, hãy tắt pin 2
  • Và vì vậy vòng lặp tiếp tục. Và một lần nữa.

Cuối cùng, và mặc dù giải pháp đã hiệu quả, tôi thấy rõ rằng vấn đề này chắc hẳn đã có nhiều người trải qua và cần phải có một giải pháp chính thống hơn. Tôi bắt đầu tìm kiếm và tôi đã tìm thấy một cái hay (chắc chắn không phải là cái duy nhất) từ các chàng trai của Adafruit và lập trình hướng đối tượng. Nó bao gồm việc tạo các đối tượng với các lớp xác định để thực hiện các cuộc gọi nhanh chóng và không phải lặp lại mã hàng trăm lần trong chương trình của chúng tôi.

Cuối cùng thì giải pháp của tôi là "giống nhau" với bộ đếm if + nhưng thanh lịch hơn nhiều và cung cấp mã dễ đọc hơn và hiệu quả hơn nhiều.

Quản lý đa nhiệm chắc chắn dẫn đến quản lý thời gian trong Arduino. Lúc đầu điều này không được đưa vào bài báo nhưng tôi nghĩ nó rất thú vị.

Arduino và chức năng thời gian

Như tôi đã nhận xét Tôi nghĩ rằng có một sự phụ thuộc lớn với độ trễ () , có thể bởi vì những người mới bắt đầu nhìn thấy chức năng này trong tất cả các ví dụ thường được đặt từ nhấp nháy đến bất kỳ đèn giao thông nào hoặc bất kỳ thao tác bật và tắt đèn LEDS nào.

Độ trễ có một vấn đề rất lớn, đó là khi chúng ta gọi delay () trong một khoảng thời gian, mọi thứ sẽ dừng lại. Bảng không đọc bất kỳ cảm biến nào, cũng không tiếp tục thực hiện các câu, cũng không làm bất cứ điều gì cả, chỉ cần đợi thời gian mà chúng tôi đã nói với bạn để trôi qua và tất nhiên nếu chúng ta muốn sử dụng bảng cho nhiều hơn một việc. đồng thời, điều này không khả thi.

Chúng ta sẽ phải xem xét mili () thậm chí đến delayMicroseconds () Và chúng tôi cũng có micros () trả về số micro giây kể từ khi chương trình bắt đầu thực thi

Chớp mắt không chậm trễ

Một ví dụ thú vị để xem nó hoạt động như thế nào chạy Blink thần thoại nhưng không có độ trễ. Sự khác biệt chính là chúng ta quên đi hàm delay (), sử dụng millis () để có thể đếm thời gian giữa các hoạt động.