Hotline/Zalo: 0919.890.938 (Mr Hơn)
Bài 4. Bộ đếm thời gian và ngắt timer trên ESP32
Trong thế giới của các thiết bị IoT (Internet of Things), việc điều khiển các thiết bị theo thời gian là một yêu cầu phổ biến. Để thực hiện điều này, chúng ta cần đến bộ đếm thời gian và ngắt timer. Bài viết này Điện thông minh E-smart sẽ hướng dẫn bạn cách sử dụng bộ đếm thời gian và ngắt timer trên ESP32 để tạo ra những dự án IoT thông minh và hiệu quả.
Bộ đếm thời gian trên ESP32
Bộ đếm thời gian trên ESP32 là một chức năng quan trọng, cho phép bạn đo đạc thời gian và thực hiện các tác vụ theo chu kỳ. Nó thường được sử dụng để:
- Đọc dữ liệu từ cảm biến: Đọc giá trị cảm biến nhiệt độ, độ ẩm, ánh sáng,… theo khoảng thời gian nhất định.
- Hiển thị màn hình: Hiển thị thông tin giá trị của cảm biến hoặc trạng thái thiết bị ra màn hình.
- Điều khiển các thiết bị: hẹn giờ Bật/tắt đèn, động cơ, hoặc các thiết bị khác theo lịch trình.
- Đọc ghi và ghi dữ liệu lên server: Định thời đọc và ghi dữ liệu với cloud server.
Các hàm đếm thời gian trong Arduino IDE
Hàm millis( )
Hàm millis()
trả về số mili giây đã trôi qua kể từ khi chương trình bắt đầu chạy. Nó rất hữu ích cho các tác vụ cần theo dõi thời gian dài hơn, như đèn nhấp nháy, đo thời gian giữa các sự kiện, hoặc tạo các khoảng thời gian chờ không chặn (non-blocking delays).
Ví dụ:
unsigned long previousMillis = 0;
const long interval = 1000; // 1 giây
void setup() {
Serial.begin(115200);
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
Serial.println("1 giây đã trôi qua");
}
}
Hàm micros( )
Hàm micros()
trả về số micro giây đã trôi qua kể từ khi chương trình bắt đầu chạy. Nó hữu ích cho các tác vụ cần độ chính xác cao hơn, như đo thời gian xung, hoặc các ứng dụng yêu cầu thời gian phản hồi nhanh.
Ví dụ:
unsigned long previousMicros = 0;
const long interval = 1000000; // 1 giây
void setup() {
Serial.begin(115200);
}
void loop() {
unsigned long currentMicros = micros();
if (currentMicros - previousMicros >= interval) {
previousMicros = currentMicros;
Serial.println("1 giây đã trôi qua");
}
}
Ưu và nhược điểm của hàm đếm thời gian
Ưu điểm
- Không chặn: Các hàm này không chặn chương trình, cho phép bạn thực hiện các tác vụ khác trong khi chờ đợi.
- Dễ sử dụng: Chỉ cần gọi hàm và so sánh giá trị trả về với thời gian mong muốn.
- Độ chính xác:
millis()
có độ chính xác đến mili giây, cònmicros()
có độ chính xác đến micro giây.
Nhược điểm
- Giới hạn thời gian:
millis()
sẽ tràn (overflow) sau khoảng 50 ngày, vàmicros()
sẽ tràn sau khoảng 70 phút. Tuy nhiên, bạn có thể xử lý tràn bằng cách sử dụng phép toán modulo.
Bộ đếm thời gian dùng thư viện Ticker
Sử dụng thư viện Ticker trên ESP32 giúp bạn dễ dàng thiết lập các tác vụ định kỳ mà không chặn chương trình chính. Thư viện này sử dụng bộ đếm thời gian phần mềm, đảm bảo tiết kiệm tài nguyên hệ thống và cho phép quản lý nhiều tác vụ khác nhau một cách hiệu quả. Thêm vào đó, Ticker đã được tích hợp sẵn khi cài đặt board ESP32, giúp bạn tiết kiệm thời gian và công sức.
1. Khai báo thư viện và biến:
Trong phần khai báo của chương trình, bạn cần khai báo thư viện Ticker và tạo một đối tượng Ticker. Ví dụ:
- Khai báo thư viện:
#include <Ticker.h>
- Tạo đối tượng Ticker:
Ticker ticker;
2. Thiết lập hàm callback:
Tạo một hàm callback để thực hiện tác vụ khi bộ đếm thời gian hết hạn. Ví dụ, nếu bạn muốn nhấp nháy đèn LED:
Tạo hàm callback:
void blink() {
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
3. Cấu hình Ticker trong setup( ):
Trong hàm setup()
, cấu hình Ticker để gọi hàm callback sau một khoảng thời gian nhất định. Ví dụ, để nhấp nháy đèn LED mỗi giây:
Cấu hình Ticker: ticker.attach(1.0, blink);
4. Hàm loop( ):
Trong hàm loop()
, bạn không cần làm gì đặc biệt vì Ticker sẽ tự động gọi hàm callback theo lịch trình đã thiết lập.
Code mẫu:
#include <Ticker.h>
Ticker ticker;
#define LED_BUILTIN 2
void blink() {
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
ticker.attach(1.0, blink); // Gọi hàm blink mỗi 1 giây
}
void loop() {
// Không cần làm gì trong loop
}
Ngắt timer trên ESP32
Ngắt timer trên ESP32 là một cơ chế đặc biệt, cho phép chương trình của bạn tạm dừng thực hiện một tác vụ để thực hiện một tác vụ khác khi bộ đếm thời gian đạt đến một giá trị nhất định. Dùng ngắt timer trên ESP32 giúp tiết kiệm tài nguyên và tăng hiệu suất của hệ thống.
ESP32 có 4 bộ đếm thời gian phần cứng (hardware timers), mỗi bộ đếm thời gian có thể được cấu hình độc lập. Các bộ đếm thời gian này là 64-bit và có thể đếm lên hoặc đếm xuống, với khả năng tự động tải lại giá trị ban đầu. Nhờ những bộ đếm này mà chúng ta có thể thiết lập ngắt timer trên ESP32 một cách linh hoạt.
Các bước thiết lập ngắt Timer trên ESP32
1. Khởi tạo bộ đếm thời gian
Trước khi tạo ngắt timer trên ESP32, bạn cần khởi tạo một bộ đếm thời gian. Bạn có thể chọn bộ đếm thời gian bằng cách chỉ định số thứ tự của nó (từ 0 đến 3). Bạn cũng cần thiết lập giá trị prescaler để xác định tốc độ đếm và chọn chế độ đếm lên hoặc đếm xuống. Ví dụ, để khởi tạo bộ đếm thời gian số 0 với prescaler là 80 và chế độ đếm lên, bạn sử dụng lệnh timerBegin(0, 80, true)
.
2. Thiết lập giá trị đếm
Sau khi khởi tạo, bạn cần thiết lập giá trị đếm ban đầu cho bộ đếm thời gian. Điều này giúp xác định điểm bắt đầu của quá trình đếm. Bạn có thể đặt giá trị đếm về 0 bằng lệnh timerWrite(timer, 0)
.
3. Gắn hàm ngắt
Tiếp theo, bạn cần gắn một hàm ngắt để xử lý sự kiện khi bộ đếm thời gian đạt đến giá trị xác định. Hàm ngắt này sẽ được gọi mỗi khi ngắt xảy ra. Bạn có thể gắn hàm ngắt bằng lệnh timerAttachInterrupt(timer, &onTimer, true)
.
4. Thiết lập ngắt timer trên ESP32
Bạn cần thiết lập giá trị ngắt cho bộ đếm thời gian. Điều này xác định khoảng thời gian sau đó ngắt sẽ được kích hoạt. Bạn cũng cần kích hoạt ngắt để đảm bảo nó hoạt động. Ví dụ, để thiết lập ngắt mỗi giây, bạn sử dụng lệnh timerAlarmWrite(timer, 1000000, true)
và kích hoạt ngắt bằng lệnh timerAlarmEnable(timer)
.
5. Hàm phục vụ ngắt timer trên ESP32
Hàm ngắt là nơi bạn đặt mã xử lý khi ngắt xảy ra. Ví dụ, bạn có thể in ra một thông báo trên Serial Monitor để kiểm tra xem ngắt có hoạt động hay không. Hàm ngắt có thể được định nghĩa như sau:
void IRAM_ATTR onTimer() {
Serial.println("Timer interrupt triggered");
}
Cách xác định các giá trị khi dùng ngắt timer trên ESP32
Ví dụ: Yêu cầu thiết lập ngắt timer trên ESP32 hoạt động với chu kỳ 1 giây.
Tần số xung nhịp cơ bản của Timer trên ESP32 là 80Mhz nên mình chọn bộ chia tỷ lệ là 80, từ đó suy ra giá trị đếm cần thiết lập để so sánh là 1.000.000
Code sử dụng ngắt timer trên ESP32:
hw_timer_t *timer = NULL;
void IRAM_ATTR onTimer() {
// Mã xử lý ngắt
Serial.println("Timer interrupt triggered");
}
void setup() {
Serial.begin(115200);
// Khởi tạo bộ đếm thời gian
timer = timerBegin(0, 80, true);//Bộ chia tỷ lệ là 80
// Đặt giá trị đếm về 0
timerWrite(timer, 0);
// Gắn hàm ngắt
timerAttachInterrupt(timer, &onTimer, true);
// Thiết lập giá trị đếm và bắt đầu bộ đếm thời gian
timerAlarmWrite(timer, 1000000, true); // 1 giây(giá trị đếm 1.000.000)
timerAlarmEnable(timer);
}
void loop() {
// Mã chính
}
Kết luận
Bộ đếm thời gian và ngắt timer trên ESP32 là những công cụ vô cùng hữu ích trong lập trình ESP32, giúp bạn tạo ra các dự án IoT thông minh và tự động. Bằng cách hiểu rõ cách hoạt động của chúng, bạn có thể xây dựng những hệ thống điều khiển với độ chính xác cao.