Sử Dụng Watchdog Timer Trong Arduino - TAPIT

Tính ổn định là một trong những tiêu chí được đặt ra hàng đầu khi triển khai phát triển sản phẩm, hệ thống. Nhiều lý do xảy ra có khả năng làm treo hệ thống như nhiễu, tràn bộ nhớ, đợi dữ liệu từ ngoại vi hỏng… Để giải quyết những trường hợp này, một tính năng quan trọng không thể không được nhắc đến – Watchdog Timer. Trong bài viết này, TAPIT mong muốn sẽ giúp cho các bạn dễ hình dung được chức năng của Watchdog Timer và hướng dẫn cách sử dụng trong Arduino.

1. Watchdog Timer là gì? Sử dụng Watchdog Timer để làm gì?

Bản chất Watchdog Timer (WDT) là một bộ đếm thời gian với bộ dao động độc lập hoạt động liên tục. Nếu sau một khoảng thời gian, bộ đếm không được refresh về 0 thì WDT sẽ tự động thực thực hiện nhiệm vụ reset MCU.

Trong các project lớn thì WDT là một chức năng không thể thiếu. Giả sử hệ thống của bạn bị treo, chương trình sẽ bị dừng lại nhưng bộ đếm thời gian của WDT vẫn hoạt động và sẽ tiếp tục đếm cho tới giá trị đã được định trước. Khi đó hệ thống sẽ được khởi động lại từ đầu để tiếp tục hoạt động mà không cần tác động từ bên ngoài.

2. Cách sử dụng Watchdog Timer trong Arduino

Ở đây mình có 2 chương trình mẫu. Các bạn hãy thử rồi bật Serial Monitor lên và nhận xét nhé:

Chương trình mẫu thứ nhất

C #include <avr/wdt.h> int dem=0; void setup() {    //watchdog timer with 2 Seconds time out    Serial.begin(9600);    wdt_enable(WDTO_2S);    Serial.println("Hello World!"); } void loop() {   dem++;   Serial.println(dem);   delay(100); }
12345678910111213 #include <avr/wdt.h>intdem=0;voidsetup(){  //watchdog timer with 2 Seconds time out  Serial.begin(9600);  wdt_enable(WDTO_2S);  Serial.println("Hello World!");}voidloop(){ dem++; Serial.println(dem); delay(100);}

Chương trình mẫu thứ hai

C #include <avr/wdt.h> int dem=0; void setup() {    //watchdog timer with 2 Seconds time out    Serial.begin(9600);    wdt_enable(WDTO_2S);    Serial.println("Hello World!"); } void loop() {   dem++;   Serial.println(dem); delay(100); wdt_reset(); }
1234567891011121314 #include <avr/wdt.h>intdem=0;voidsetup(){  //watchdog timer with 2 Seconds time out  Serial.begin(9600);  wdt_enable(WDTO_2S);  Serial.println("Hello World!");}voidloop(){ dem++; Serial.println(dem);delay(100);wdt_reset();}

Các bạn đã nhận ra sự khác nhau của 2 chương trình chưa? Chương trình mẫu thứ nhất có thêm dòng lệnh wdt_reset(); trong hàm loop() đúng không?

Và kết quả của cả 2 chương trình  sẽ như sau:

  • Chương trình mẫu thứ nhất sẽ in ra chữ Hello World! một lần rồi sẽ tăng biến dem rồi in Serial Monitor ra giá trị khoảng 22 – 24 rồi sẽ quay lại in chữ Hello World!, khởi tạo lại biến dem ,…
  • Chương trình mẫu thứ hai sẽ chỉ in ra một lần chữ Hello World! sau đó sẽ tăng biến dem và in ra Serial Monitor liên tục.

=> Chứng tỏ tại chương trình 1 mạch đã bị reset sau khoảng 2s.

Mình sẽ giải thích những dòng lệnh về WDT trong Chương trình mẫu thứ hai như sau:

  • Thư viện cần thiết để sử dụng Watchdog Timer
#include <avr/wdt.h>
1 #include <avr/wdt.h>
  • Lệnh khởi tạo WDT với thời gian để reset là 2 giây với nhãn WDTO_2S
wdt_enable(WDTO_2S);
1 wdt_enable(WDTO_2S);

Ta có thể chỉnh với các mức thời gian với các mức thời gian với các nhãn như bảng sau

Mức thời gian Tên
15 ms WDTO_15MS
30 ms WDTO_30MS
60 ms WDTO_60MS
120 ms WDTO_120MS
250 ms WDTO_250MS
500 ms WDTO_500MS
1 s WDTO_1S
2 s WDTO_2S
4 s WDTO_4S
8 s WDTO_8S
  • Lệnh reset lại bộ đếm WDT
wdt_reset();
1 wdt_reset();

Lệnh wdt_reset() này cần phải cho vào đúng nơi trong chương trình của bạn.

Ví dụ như bạn cài đặt thời gian reset WDT là 2s với lệnh wdt_enable(WDTO_2S). Và trong chương trình của bạn có hàm có thời gian chạy hơn 2s thì tốt nhất bạn nên để trong hàm đó vài lệnh wdt_reset();

C void abcxyz() {   do something…;   wdt_reset();   do something…; ... }
123456 voidabcxyz(){ dosomething; wdt_reset(); dosomething;...}

Hoặc bạn không thể sử dụng delay hơn 2s mà bạn phải chia ra thành nhiều lệnh delay nhỏ hơn

//delay với thời gian 3s

C //delay với thời gian 3s delay(1000); wdt_reset(); delay(1000);. wdt_reset(); delay(1000);.
123456 //delay với thời gian 3sdelay(1000);wdt_reset();delay(1000);.wdt_reset();delay(1000);.
  • Lệnh vô hiệu hóa WDT
wdt_disable();
1 wdt_disable();

Nếu nữa thì bạn có thể tắt chức năng WDT bằng lệnh này nếu thấy không cần thiết nữa.

3. Tổng kết

Bài viết này chủ yếu nói về cách sử dụng chức năng reset lại hệ thống với Watchdog Timer trong Arduino. Ngoài ra, các bạn có thể tìm hiểu thêm tại datasheet để tạo ra một ra ngắt WDT hoặc đánh thức Arduino khi đang trong chế độ tiết kiệm năng lượng (Sleep Mode).

Chúc các bạn thành công!

Người thực hiện

Đậu Đức Thắng – Cố vấn tại Cộng đồng Kỹ thuật TAPIT

Từ khóa » Bộ đếm Thời Gian Arduino