Điều chỉnh độ sáng bóng đèn từ xa với Arduino
Điều khiển từ xa IR được sử dụng trong dự án này sử dụng giao thức truyền thông RC-5. Một dự án liên quan dưới đây cho thấy cách giải mã điều khiển từ xa RC-5. Lưu ý rằng chúng ta cần giải mã điều khiển từ xa IR của mình để biết mã IR của các nút mà chúng ta sẽ sử dụng trong code Arduino.
Phần cứng cần thiết:
Danh sách linh kiện cơ bản cần thiết cho dự án này bên dưới.
- Board Arduino
- BT136 Triac
- Đèn điện xoay chiều 220v
- bộ thu IR
- IC LM393 (hoặc LM339)
- Bộ ghép nối (MOC3020, MOC3021, MOC3022, MOC3023)
- 2 x Diode 1N4007 (hoặc 1N4001)
- 2 x Điện trở 220k ohm
- Điện trở 10k ohm
- Điện trở 470 ohm
- Điện trở 120 ohm
- Điện trở 100 ohm
- Tụ 47uF
- Tụ 0,01uF
- Breadboard
- Dây dẫn
Arduino điều khiển cường sáng từ xa:
Sơ đồ mạch được hiển thị dưới đây.
Tất cả các điểm mút nối đất được nối với nhau.
Nói chung, bộ thu IR có 3 chân: GND, VCC và đầu ra, trong ví dụ này, đầu ra được nối với chân Arduino 2 là chân ngắt ngoài (INT0). Cảm biến hồng ngoại cũng như IC LM393 được cung cấp nguồn 5V (đến từ board Arduino).
Thông tin thêm về IC LM393 tại đây.
CODE điều chỉnh ánh sáng điều khiển từ xa bằng Arduino:
Như được hiển thị trong sơ đồ mạch, đầu ra của bộ thu IR được kết nối với chân ngắt bên ngoài Arduino (chân số 2), có nghĩa là khi nhấn nút (từ điều khiển từ xa), Arduino bắt đầu đọc Tín hiệu hồng ngoại ngay lập tức.
Điều khiển từ xa được sử dụng trong ví dụ này sử dụng giao thức RC-5, thông báo mã RC-5 dài 14 bit:
2 bit start, 1 bit chuyển đổi, 5 bit địa chỉ và 6 bit lệnh. 2 bit (bit start) luôn là 1 và bit chuyển đổi có thể là 1 hoặc 0.
Trong dự án này, tôi đã không sử dụng 2 bit start và bit chuyển đổi vì chúng không có tác dụng (cũng để đơn giản hóa code). Tôi đã sử dụng một điều khiển từ xa TV có nghĩa là tất cả các bit địa chỉ là 0 (address = 0).
Những gì còn lại là phần quan trọng trong mã RC-5 là số lệnh, tôi đã sử dụng hai nút. nút đầu tiên có mã = 0x10, nó tăng cường độ ánh sáng và nút thứ hai có mã = 0x11 làm giảm cường độ ánh sáng. Các nút khác của điều khiển từ xa không có tác dụng đối với mạch này.
Tần số của nguồn AC của tôi là 50Hz, có nghĩa là khoảng thời gian là 20ms, vì vậy chu kỳ nửa sóng là 10ms = 10000 us.
CODE Arduino đầy đủ:
// Arduino light dimmer with IR remote control // Define number of Timer1 ticks (with a prescaler of 1/8) #define short_time 1400 // Used as a minimum time for short pulse or short space ( ==> 700 us) #define med_time 2400 // Used as a maximum time for short pulse or short space ( ==> 1200 us) #define long_time 4000 // Used as a maximum time for long pulse or long space ( ==> 2000 us) // define remote control button codes #define Button_up 0x10 #define Button_dn 0x11 #define ZC_input 3 #define triac_gate 8 bool ZC_previous = 0; byte rc5_state = 0, j, alpha = 100; unsigned int rc5_code; void setup(void) { pinMode(triac_gate, OUTPUT); digitalWrite(triac_gate, LOW); // Timer1 module configuration TCCR1A = 0; TCCR1B = 0; // Disable Timer1 module TCNT1 = 0; // Set Timer1 preload value to 0 (reset) TIMSK1 = 1; // enable Timer1 overflow interrupt attachInterrupt(0, RC5_Read, CHANGE); // Enable external interrupt (INT0) } void RC5_Read() { unsigned int timer_value; if(rc5_state != 0){ timer_value = TCNT1; // Store Timer1 value TCNT1 = 0; // Reset Timer1 } switch(rc5_state){ case 0 : // Start receiving IR data (initially we're at the beginning of mid1) TCNT1 = 0; // Reset Timer1 TCCR1B = 2; // Enable Timer1 module with 1/8 prescaler ( 2 ticks every 1 us) rc5_state = 1; // Next state: end of mid1 j = 0; return; case 1 : // End of mid1 ==> check if we're at the beginning of start1 or mid0 if((timer_value > long_time) || (timer_value < short_time)){ // Invalid interval ==> stop decoding and reset rc5_state = 0; // Reset decoding process TCCR1B = 0; // Disable Timer1 module return; } bitSet(rc5_code, 13 - j); j++; if(j > 13){ // If all bits are received rc5_state = 0; rc5_code &= 0x07FF; // Remove the two start bits and the toggle bit from the code message if( (rc5_code == Button_dn) && (alpha < 100) ) alpha++; if( (rc5_code == Button_up) && (alpha > 0) ) alpha--; return; } if(timer_value > med_time){ // We're at the beginning of mid0 rc5_state = 2; // Next state: end of mid0 if(j == 13){ // If we're at the LSB bit rc5_state = 0; bitClear(rc5_code, 0); // Clear the LSB bit rc5_code &= 0x07FF; if( (rc5_code == Button_dn) && (alpha < 100) ) alpha++; if( (rc5_code == Button_up) && (alpha > 0) ) alpha--; return; } } else // We're at the beginning of start1 rc5_state = 3; // Next state: end of start1 return; case 2 : // End of mid0 ==> check if we're at the beginning of start0 or mid1 if((timer_value > long_time) || (timer_value < short_time)){ rc5_state = 0; // Reset decoding process TCCR1B = 0; // Disable Timer1 module return; } bitClear(rc5_code, 13 - j); j++; if(timer_value > med_time) // We're at the beginning of mid1 rc5_state = 1; // Next state: end of mid1 else // We're at the beginning of start0 rc5_state = 4; // Next state: end of start0 return; case 3 : // End of start1 ==> check if we're at the beginning of mid1 if((timer_value > med_time) || (timer_value < short_time)){ // Time interval invalid ==> stop decoding TCCR1B = 0; // Disable Timer1 module rc5_state = 0; // Reset decoding process return; } else // We're at the beginning of mid1 rc5_state = 1; // Next state: end of mid1 return; case 4 : // End of start0 ==> check if we're at the beginning of mid0 if((timer_value > med_time) || (timer_value < short_time)){ // Time interval invalid ==> stop decoding TCCR1B = 0; // Disable Timer1 module rc5_state = 0; // Reset decoding process return; } else // We're at the beginning of mid0 rc5_state = 2; // Next state: end of mid0 if(j == 13){ // If we're at the LSB bit rc5_state = 0; bitClear(rc5_code, 0); // Clear the LSB bit rc5_code &= 0x07FF; if( (rc5_code == Button_dn) && (alpha < 100) ) alpha++; if( (rc5_code == Button_up) && (alpha > 0) ) alpha--; } } } ISR(TIMER1_OVF_vect) { // Timer1 interrupt service routine (ISR) rc5_state = 0; // Reset decoding process TCCR1B = 0; // Disable Timer1 module } void loop() { while(digitalRead(ZC_input) == ZC_previous) ; // Wait for zero crossing event ZC_previous = digitalRead(ZC_input); delayMicroseconds(alpha * 95); // Why 95? for max alpha=100 we get 9500µs (half wave period=10000µs) digitalWrite(triac_gate, HIGH); delayMicroseconds(200); digitalWrite(triac_gate, LOW); }
VIDEO demo: