2026-07-03 · 8 min read
IoT: Arduino LED và Nút Bấm
Thực hành nháy LED, dùng mảng LED, đọc nút với INPUT_PULLUP và viết nút bấm kiểu toggle.
Từ LED nhấp nháy đến nút bấm có trạng thái
LED và nút bấm là hai bài thực hành nhỏ nhưng rất đáng học kỹ. LED giúp ta hiểu output, còn nút bấm giúp ta hiểu input. Khi ghép hai phần này lại, ta có mô hình thu nhỏ của rất nhiều thiết bị IoT: đọc tín hiệu, xử lý, rồi phản hồi.
Bài này đi từ nháy LED cơ bản đến nút bấm kiểu toggle.
Bài 1: Hai LED nháy so le
Mục tiêu là cho hai LED đổi trạng thái luân phiên sau mỗi 500ms.
int led1 = 12;
int led2 = 13;
void setup() {
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
}
void loop() {
digitalWrite(led1, HIGH);
digitalWrite(led2, LOW);
delay(500);
digitalWrite(led1, LOW);
digitalWrite(led2, HIGH);
delay(500);
}
pinMode(..., OUTPUT) khai báo chân dùng để xuất tín hiệu. digitalWrite(..., HIGH) đưa chân lên mức cao, còn LOW đưa chân về mức thấp.
Với mạch LED mắc từ chân digital qua LED và điện trở về GND, mức HIGH làm LED sáng, mức LOW làm LED tắt.
Bài 2: Điều khiển nhiều LED bằng mảng
Khi số LED tăng lên, viết từng dòng digitalWrite sẽ khó bảo trì. Mảng giúp gom các chân LED vào một danh sách và xử lý bằng vòng lặp.
int led1 = 11;
int led2 = 12;
int led3 = 13;
int ledArr[] = {led1, led2, led3};
int ledCount = sizeof(ledArr) / sizeof(ledArr[0]);
void setup() {
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
digitalWrite(led1, HIGH);
digitalWrite(led2, HIGH);
digitalWrite(led3, HIGH);
}
void loop() {
for (int i = 0; i < ledCount; i++) {
delay(500);
digitalWrite(ledArr[i], LOW);
delay(500);
}
for (int i = ledCount - 1; i >= 0; i--) {
delay(500);
digitalWrite(ledArr[i], HIGH);
delay(500);
}
}
Dòng sizeof(ledArr) / sizeof(ledArr[0]) tính số phần tử trong mảng. Cách này giúp code linh hoạt hơn khi thêm hoặc bớt LED.
Bài 3: Đọc nút bấm với INPUT_PULLUP
INPUT_PULLUP dùng điện trở kéo lên bên trong Arduino. Nhờ vậy chân input có trạng thái ổn định khi nút chưa được nhấn, không bị “trôi” giữa LOW và HIGH.
Điểm cần nhớ là logic sẽ đảo:
Nhan nut -> LOW
Tha nut -> HIGH
Ví dụ bật LED khi nút được nhấn:
int btn = 3;
int led = 5;
void setup() {
pinMode(btn, INPUT_PULLUP);
pinMode(led, OUTPUT);
Serial.begin(9600);
}
void loop() {
int mode = digitalRead(btn);
Serial.println(mode);
if (mode == LOW) {
digitalWrite(led, HIGH);
} else {
digitalWrite(led, LOW);
}
}
Serial.begin(9600) mở Serial Monitor ở tốc độ 9600 baud. Khi debug nút bấm, in giá trị đọc được ra Serial là cách nhanh nhất để biết mạch và code có đang hiểu nhau không.
Bài 4: Nút bấm kiểu toggle
Với toggle, mỗi lần nhấn nút sẽ đổi trạng thái LED: đang tắt thì bật, đang bật thì tắt. Đây là hành vi gần hơn với công tắc thực tế.
int btn = 3;
int led = 4;
bool isLedOn = false;
bool lastBtn = LOW;
void setup() {
pinMode(btn, INPUT);
pinMode(led, OUTPUT);
}
void loop() {
bool currentBtn = digitalRead(btn);
if (currentBtn == HIGH && lastBtn == LOW) {
isLedOn = !isLedOn;
digitalWrite(led, isLedOn);
}
lastBtn = currentBtn;
}
Điều kiện currentBtn == HIGH && lastBtn == LOW phát hiện cạnh lên, tức khoảnh khắc nút vừa được nhấn. Nếu chỉ kiểm tra currentBtn == HIGH, vòng lặp chạy rất nhanh và LED có thể đổi trạng thái nhiều lần trong một lần nhấn.
Ghi chú thực tế
Nút bấm cơ khí thường có hiện tượng dội phím. Khi nhấn hoặc thả, tín hiệu có thể rung trong vài mili giây. Với bài đơn giản, code trên đủ để học nguyên lý. Với sản phẩm thật, nên thêm debounce bằng thời gian hoặc dùng thư viện hỗ trợ.