Các loại hàm khởi tạo (constructor) của lớp trong Java
1. Hàm khởi tạo (constructor) là gì? Hàm khởi tạo (constructor) trong Java là một hàm...
Kết quả sẽ mở trong tab mới, giới hạn trong website này.
Truy cập nhanh
Tìm kiếm gần đây
Hướng dẫn điều khiển LED RGB với button bằng Arduino Uno: mỗi lần nhấn đổi một màu, có chống dội phím và chỉnh độ sáng bằng PWM.
Bài này hướng dẫn điều khiển LED RGB với button bằng Arduino: mỗi lần nhấn nút, LED đổi sang một màu mới. Chỉ cần một nút nhấn, chúng ta có đủ 4 chế độ sáng. Nếu chưa biết cách sử dụng nút bấm với Arduino, bạn xem lại bài lập trình điều khiển led bằng nút bấm trước nhé.
Mục tiêu bài học:
LED RGB thực chất là 3 con LED đỏ (Red), xanh lá (Green) và xanh dương (Blue) gộp chung. Mỗi màu có một chân điều khiển riêng.
LED RGB có 4 chân. Chân dài nhất là chân chung, 3 chân còn lại là R, G, B. Có hai loại:
Bài này dùng loại cathode chung. Nếu bạn chỉ có loại anode chung, hãy nối chân chung lên 5V và đảo HIGH thành LOW trong code.
Linh kiện cần chuẩn bị:
Ba chân R, G, B nối vào chân 9, 10, 11. Đây đều là chân PWM (có dấu ~ trên board), nên sau này chỉnh được độ sáng. Nút nhấn một đầu lên 5V, đầu kia vào chân 2 và xuống GND qua điện trở 10kΩ.
| Linh kiện | Chân linh kiện | Arduino Uno |
|---|---|---|
| LED RGB | R (qua điện trở 220Ω) | 9 |
| LED RGB | Chân chung (dài nhất) | GND |
| LED RGB | G (qua điện trở 220Ω) | 10 |
| LED RGB | B (qua điện trở 220Ω) | 11 |
| Nút nhấn | Chân 1 | 5V |
| Nút nhấn | Chân 2 (kèm 10kΩ xuống GND) | 2 |
Lưu ý: Không nối thẳng chân R, G, B vào Arduino mà thiếu điện trở. Dòng quá lớn có thể làm hỏng LED và chân Arduino. Nếu bạn dùng module LED RGB đã hàn sẵn điện trở thì bỏ qua 3 điện trở này. Thứ tự chân có thể khác nhau tùy hãng, hãy xem datasheet của LED bạn đang có.
Yêu cầu bài toán như sau:
Đây là code đầy đủ, viết cho LED RGB cathode chung (chân chung nối GND, xuất HIGH là sáng):
// Code dành cho LED RGB cathode chung: HIGH = sáng, LOW = tắt
// Dùng LED anode chung thì phải đảo HIGH/LOW
// Chân nối với chân R của LED RGB
#define pinLedRed 9
// Chân nối với chân G của LED RGB
#define pinLedGreen 10
// Chân nối với chân B của LED RGB
#define pinLedBlue 11
// Chân nối với nút nhấn (có điện trở kéo xuống 10kΩ)
#define pinButton 2
// Trạng thái trước đó của nút nhấn
boolean lastPinButton = LOW;
// Trạng thái hiện tại của nút nhấn
boolean currentPinButton = LOW;
// Chế độ sáng hiện tại của LED (0 = tắt)
int ledMode = 0;
void setup() {
pinMode(pinLedRed, OUTPUT);
pinMode(pinLedGreen, OUTPUT);
pinMode(pinLedBlue, OUTPUT);
pinMode(pinButton, INPUT);
}
// Hàm chống dội phím: đọc lại nút sau 20 ms nếu trạng thái thay đổi
boolean debounce(boolean lastState) {
boolean currentState = digitalRead(pinButton);
if (lastState != currentState) {
delay(20);
currentState = digitalRead(pinButton);
}
return currentState;
}
// Hàm bật LED theo chế độ
void setMode(int mode) {
if (mode == 1) { // Nhấn lần 1: màu đỏ
digitalWrite(pinLedRed, HIGH);
digitalWrite(pinLedGreen, LOW);
digitalWrite(pinLedBlue, LOW);
} else if (mode == 2) { // Nhấn lần 2: màu xanh lá
digitalWrite(pinLedRed, LOW);
digitalWrite(pinLedGreen, HIGH);
digitalWrite(pinLedBlue, LOW);
} else if (mode == 3) { // Nhấn lần 3: màu xanh dương
digitalWrite(pinLedRed, LOW);
digitalWrite(pinLedGreen, LOW);
digitalWrite(pinLedBlue, HIGH);
} else if (mode == 4) { // Nhấn lần 4: cả 3 màu sáng dần rồi giữ sáng
for (int brightness = 0; brightness <= 255; brightness += 5) {
analogWrite(pinLedRed, brightness);
analogWrite(pinLedGreen, brightness);
analogWrite(pinLedBlue, brightness);
delay(20);
}
}
}
void loop() {
currentPinButton = debounce(lastPinButton);
// Nút vừa được thả ra (HIGH -> LOW) => tính là 1 lần nhấn
if (lastPinButton == HIGH && currentPinButton == LOW) {
ledMode++;
if (ledMode == 5) {
ledMode = 1; // Quay lại màu đỏ
}
setMode(ledMode); // Chỉ đổi màu ngay sau mỗi lần nhấn
}
lastPinButton = currentPinButton;
}Nút nhấn là tiếp điểm cơ khí. Lúc nhấn hoặc thả, hai lá kim loại không chạm nhau ngay mà nảy lên nảy xuống trong vài mili giây. Hiện tượng này gọi là dội phím (bounce).
Mắt chúng ta không thấy, nhưng Arduino thì thấy rõ. Hàm loop() lặp hàng nghìn lần mỗi giây. Mỗi lần tiếp điểm nảy đều bị đọc thành một lần nhấn.
Muốn tận mắt thấy dội phím, bạn nạp thử đoạn code đếm số lần nhấn dưới đây. Đoạn này chỉ so sánh trạng thái trước và sau, chưa chống dội.
#define pinButton 2
boolean lastState = LOW; // Trạng thái lần đọc trước
int count = 0; // Số lần nhấn đếm được
void setup() {
pinMode(pinButton, INPUT);
Serial.begin(9600);
}
void loop() {
boolean currentState = digitalRead(pinButton);
// LOW -> HIGH: nút vừa được nhấn xuống
if (lastState == LOW && currentState == HIGH) {
count++;
Serial.println(count);
}
lastState = currentState;
}Mở Serial Monitor rồi nhấn nút đúng 10 lần. Con số in ra lớn hơn 10 nghĩa là nút của bạn đang bị dội. Có nút rung nhiều, có nút gần như không, nên mỗi bạn sẽ thấy một kết quả khác nhau.
Code chạy đúng vài lần chưa chắc là đúng. Chỉ cần đổi sang nút cũ hơn, LED lại nhảy màu lung tung. Vì vậy chống dội là bước bắt buộc, không phải tùy chọn.
Ý tưởng rất đơn giản: thấy nút đổi trạng thái thì đừng tin ngay. Chờ một chút cho tiếp điểm hết rung rồi đọc lại.
currentState.lastState. Giống nhau thì nút không đổi, trả kết quả về luôn.delay(20).Mức 20 ms thường đủ cho nút nhấn nhỏ trong bộ kit Arduino. Nút cũ rung lâu hơn thì bạn tăng lên 50 ms. Đừng tăng quá nhiều, vì trong lúc delay() Arduino không làm được việc gì khác.
Mẹo: Ngoài cách dùng delay(), bạn có thể chống dội bằng millis() để chương trình không bị dừng. Một cách khác là mắc thêm tụ điện song song với nút để lọc nhiễu bằng phần cứng.
Trong loop(), biến ledMode tăng 1 khi nút chuyển từ HIGH sang LOW. Với mạch điện trở kéo xuống, nhấn nút là HIGH, thả ra là LOW. Vậy chương trình đếm một lần nhấn ở thời điểm bạn thả nút.
Việc so sánh trạng thái trước và sau chỉ giúp giữ nút lâu không bị đếm liên tục. Nó không lọc được dội phím, vì mỗi lần tiếp điểm nảy cũng tạo ra một cặp HIGH/LOW mới. Do đó hai bước phải đi cùng nhau: debounce() lọc nhiễu trước, sau đó mới so sánh để đếm.
Khi ledMode lên tới 5, ta gán lại về 1 để quay vòng. Lúc mới cấp điện, ledMode bằng 0 nên LED tắt. Hàm setMode() chỉ được gọi ngay sau mỗi lần nhấn, nên hiệu ứng sáng dần ở chế độ 4 chạy đúng một lần rồi giữ sáng.
Chế độ 1 đến 3 dùng digitalWrite(): bật đúng một màu, tắt hai màu còn lại. Chế độ 4 thì khác. Nó dùng analogWrite() để xuất xung PWM (Pulse Width Modulation – điều chế độ rộng xung).
Giá trị truyền vào từ 0 (tắt) đến 255 (sáng nhất). Vòng for tăng độ sáng mỗi bước 5 đơn vị, nghỉ 20 ms, đến 255 thì dừng và giữ sáng. Cả 3 màu cùng sáng nên LED sẽ ra màu gần trắng.
millis() đo thời gian giữ nút.delay() nên lúc LED đang sáng dần, nhấn nút có thể bị bỏ qua. Hãy viết lại bằng millis() để nút luôn phản hồi ngay.