Bất lợi khi sử dụng hàm delay
Các bạn có thể quen với việc sử dụng hàm delay() để code Arduino. Kể từ ngày đầu tiên lập trình với Arduino, delay là một trong những hàm bạn sử dụng đầu tiên. Một phần bởi vì nó đơn giản, dễ sử dụng cho việc định thời (timming). Sử dụng hàm delay đơn giản là bạn muốn Arduino dừng hoạt động trong 1 khoản thời gian trước khi nó thực hiện câu lệnh kế tiếp. Đây chính là vấn đề chính của nó. Arduino sẽ không thể thực thi bất kỳ câu lệnh nào khác cho đến khi hàm delay được hoàn thành, kể cả việc người dùng thao tác với nút nhấn hoặc bất kỳ thứ gì hệ thống tương tác.
Lợi ích khi tránh việc sử dụng hàm delay
Arduino là vi điều khiển chỉ có 1 nhân xử lý nên tại 1 thời điểm chỉ có thể thực hiện 1 tác vụ. Nếu không sử dụng bất kỳ OS – hệ điều hành – nào chạy trên Arduino, bạn sẽ không thể chạy đa nhiệm trên Arduino.
Tuy nhiên có 1 cách giúp các bạn có thể xử lý nhiều tác vụ trên Arduino là sử dụng hàm millis(). Việc sử dụng hàm delay trong các chương trình đa nhiệm sẽ làm Arduino không xử lý được tác vụ khác trong một khoảng thời gian. Bạn nên tránh sử dụng đến hàm này.
Millis() có nhiệm vụ trả về một số – là thời gian (tính theo mili giây) kể từ lúc mạch Arduino bắt đầu chương trình của bạn. Nó sẽ tràn số và quay số 0 (sau đó tiếp tục tăng) sau 50 ngày.

Ví dụ về sử dụng hàm millis()
Ví dụ in ra giá trị hàm millis() qua Serial Monitor của Arduino IDE
unsigned long time;
void setup(){
Serial.begin(9600);
}
void loop(){
Serial.print("Time: ");
time = millis();
// in ra thời gian kể từ lúc chương trình được bắt đầu
Serial.println(time);
// đợi 1 giây trước khi tiếp tục in
delay(1000);
}
Ví dụ về nhấp nháy Led theo chu kỳ 1 giây
- Chớp nháy LED D2 trên board UnoX bằng sử dụng chân 13 tín hiệu điều khiển.
- Hiển thị trạng thái LED ON/OFF trên màn hình monitor trên trình biên dịch Arduino-IDE.
#define pinLed 13 // Định nghĩa pinLed là chân số 13
int ledState = LOW; // khai báo biến lưu trạng thái của LED
unsigned long previousMillis = 0; // Khai báo biến previousMillis = 0
const long interval = 1000; // Khái báo biến interval = 1000 mili giây = 1s
void setup()
{
Serial.begin(9600);
pinMode(pinLed, OUTPUT);
}
void loop()
{
unsigned long currentMillis = millis();
// Nếu hàm millis() đếm được 1000 milli giây = 1s thì sẽ thay đổi trạng thái LED
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
if(ledState == LOW) {
ledState = HIGH; // Đổi trạng thái
Serial.println("LED ON"); // Hiển thị trạng thái "LED ON" trên monitor
} else {
ledState = LOW; // Đổi trạng thái
Serial.println("LED OFF"); // Hiển thị trạng thái "LED OFF" trên monitor
}
digitalWrite(pinLed, ledState); // Xuất tín hiệu HIGH hoặc LOW để LED sáng hoặc tắt
}
}
Ví dụ nhấp nháy cùng lúc 2 đèn led, mỗi đèn có chu kì nháy sáng khác nhau
Đoạn chương trình dưới đây có chức năng kiểm tra các biến thời gian time1, time2 so với giá trị của hàm millis(). Nếu vượt quá thời gian quy định 1000ms với biến time1 và 300ms với biến time2 thì sẽ thay đổi trạng thái đèn led.
byte led1 = 5;
byte led2 = 6;
unsigned long time1 = 0;
unsigned long time2 = 0;
void setup()
{
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
}
void loop()
{
if ( (unsigned long) (millis() - time1) > 1000 )
{
if ( digitalRead(led1) == LOW )
{
digitalWrite(led1, HIGH);
} else {
digitalWrite(led1, LOW );
}
time1 = millis();
}
if ( (unsigned long) (millis() - time2) > 300 )
{
if ( digitalRead(led2) == LOW )
{
digitalWrite(led2, HIGH);
} else {
digitalWrite(led2, LOW );
}
time2 = millis();
}
}
Lưu ý quan trọng về hàm thời gian millis()
Các hàm về thời gian trong Arduino gồm millis() và micros() sẽ bị tràn số sau 1 thời gian sử dụng. Với hàm millis() là khoảng 50 ngày. Tuy nhiên, do là kiểu số nguyên không âm (unsigned long) nên ta dễ dàng khắc phục điều này bằng cách sử dụng hình thức ép kiểu.
unsigned long time; byte ledPin = 10; void setup() { // khởi tạo giá trị biến time là giá trị hiện tại // của hàm millis(); time = millis(); pinMode(ledPin, OUTPUT); digitalWrite(ledPin, LOW); } void loop() { // Lưu ý các dấu ngoặc khi ép kiểu // đoạn chương trình này có nghĩa là sau mỗi 1000 mili giây // đèn Led ở chân số 10 sẽ thay đổi trạng thái if ( (unsigned long) (millis() - time) > 1000) { // Thay đổi trạng thái đèn led if (digitalRead(ledPin) == LOW) { digitalWrite(ledPin, HIGH); } else { digitalWrite(ledPin, LOW); } // cập nhật lại biến time time = millis(); } }
Thông thường, nếu ta có 2 số A, B và B lớn hơn A ( B > A) thì phép trừ thu được A-B là một số âm. Nhưng khi ép kiểu unsigned long là kiểu số nguyên dương, không có số âm nên giá trị trả về là 1 số nguyên dương lớn.
Ví dụ: kết quả của phép trừ:
unsigned long ex = (unsigned long) (0 - 1);
là 4294967295, con số này chính là giá trị lớn nhất của kiểu số unsigned long.