DIY - สวิทช์ควบคุมไฟหัวเตียงด้วยไมโครคอนโทรลเลอร์
ติดตั้งไฟหัวเตียงสำหรับอ่านหนังสือเป็นแผงหลอดแอลอีซึ่งใช้ไฟ 12 โวลต์ 360 มิลลิแอมป์ หรือ 4.3 วัตต์ 2 ข้างๆ ละแผง ไฟกลางคืน 12 โวลต์ 220 มิลลิแอมป์ หรือ 2.6 วัตต์ แต่มีวัสดุลดแสงคลุมไว้เพื่อเปลี่ยนสีให้เป็นเหลืองด้วย แต่เดิมทีผมใช้สวิทช์เลื่อนถูกๆ ธรรมดาทำให้เกิดปัญหาการคลอน แสงไฟจะไม่นิ่ง มีการกระพริบ (flickering effect) ทำให้ไม่สบายตาอย่างมาก
แนวทางที่น่าเลือกมี 2 อย่าง คือ เป็นวงจรดิจิตอลอิเล็กทรอนิกส์ หรือ ใช้ MCU (ไมโครคอนโทรลเลอร์ควบคุม) จึงตัดสินใจเลือกใช้ MCU เพราะจะถูกกว่า ขนาดเล็กกว่า และดัดแปลงวงจรง่ายๆ ด้วยโปรแกรม
คุณสมบัติของผลิตภัณฑ์
- ควบคุมหลอดไฟฟ้าที่แรงดันสูงสุดสูงสุด 12 โวลต์ กระแสสูงสุด 0.8 แอมป์ กำลังสูงสุด 10 วัตต์ ต่อชุด
- ทำงานด้วยสวิทช์เพียง 2 ตัว
- ตัวแรกเป็นตัววนเลือกหลอดไฟ (Select) และตั้งเวลาไฟก่อนนอน (Sleep)
- อีกตัวเอาไว้ปิดไฟในทุกกรณี
- ควบคุมไฟสว่าง 3 จุด โดยที่ 1 จุดเป็นไฟ
ก่อนนอนสามารถตั้งเวลาไว้ 1 ชั่วโมง หลอดไฟจะวูบสว่างขึ้นและวูบดับ (fade in - fade out) ไม่กระโชกเหมือนเปิดปกติ แต่ละจุดรับแรงดันสูงถึง 12 โวลต์ (สูงได้ถึง 24 โวลต์แต่กระแสสูงสุดจะแปรผันลดลง) และกระแสสูงสุด 0.8 แอมป์ (10 วัตต์)
หมายเหตุ ถ้าต้องการควบคุมกำลังไฟฟ้ามากกว่านี้หรือใช้แรงดันไฟบ้านได้ ให้เปลี่ยนหลอดไฟเป็นรีเลย์ 12 โวลต์แทน (มี fast recovery diode ต่อ reversr bias คร่อมขาคอยล์ด้วยนะ) ยกเว้นจุดไฟก่อนนอนห้ามเปลี่ยนเพราะมันมีส่วนทำงานแบบ pwm อยู่
- เมื่อเข้าในโหมดก่อนนอน จะมีหลอดไฟมอนิเตอร์สีแดงสว่างขึ้น (Sleep minitoring) ให้รู้ว่าอยู่ในโหมดตั้งเวลา
- มีภาค watchdag จะหน้าที่ตั้งระบบในตัวเอง เมื่อเกิดความผิดพลาดในโปรแกรม (แฮงก์จ
การทำงาน ประกอบด้วย 2 ปุ่ม คือ
1. ปุ่ม Select/Sleep
- เมื่อกดแต่ละครั้ง หลอดไฟก็จะเปิดวนในลักษณะ หลอด 1 --- > หลอด 2 --- > หลอด1 และ หลอด 2 --- > ไฟก่อนนอน --- > ดับหมด
- เมื่อกดแช่นาน ประมาณ 0.3 วินาที จะเข้าโหมด Sleep หลอดไฟ 1และ 2 จะดับ หลอดไฟก่อนนอนเฟดสว่างขึ้นจนเต็มที่ และสว่างนาน 1 ชั่วโมงจากนั้นจะค่อยวูบดับลง ระหว่างนี้จะไม่สามารถกดสวิทช์เลือกไฟได้อีก ยกเว้นกดอีกปุ่ม (Off) ซึ่งทำหน้าที่ดับไฟ
2. ปุ่ม Off
- เอาไว้ดับหลอดไฟ ไม่ว่าจะอยู่โหมดไหน กดปุมนี้จะดับหมด
อุปกรณ์สำคัญ
MCU ที่ผมเลือกใช้นั้น เป็น PIC เบอร์ 12F509 จากบริษัทไมโครชิพ เนื่องจากมีขนาดเล็กแค่ 8 ขา ง่ายต่อการโปรแกรม ไม่ต้องคอนฟิกมาก เนื่องจากมีแค่ไม่กี่รีจิสเตอร์ ที่สำคัญคือ ราคาถูกและทนทานสูง โดยที่ 12F509 นั้นมีหน่วยความจำเก็บโปรแกรม 1 กิโลไบต์ มีRAM 41 ไบต์ Digital I/O 6 ขา มีวงจรสร้างสัญญาณนาฬิกาในตัว 4 MHz แต่ความเร็วทำงานต้องหาร 4 เพราะโครงสร้างแบบ pipeline ตามสถาปัตยกรรมแบบฮาเวิร์ด (RISC) นั่นคือเหลือ 1 ล้านคำสั่งต่อวินาที ถึงต่อคริสตอลข้างนอกก็เพิ่มความถี่ไม่ได้มากกว่านี้ ไม่มีลูกเล่นใดๆ เช่น พอร์ทอนุกรม PWM EEPROM A/D Comparator หรือแม้แต่อินเตอร์รัพท์ มีไทม์เมอร์รีจีสเตอร์ 8 บิทแค่ตัวเดียว มันข้นแค้นจนคุณไม่อยากเชื่อว่ามีคอนโทรลเลอร์แบบนี้มีอยู่ในโลก แต่เพราะการไม่มีอะไรมันเลยเรียบง่าย และมีความเชื่อถือได้สูง ผมจะพยายามใช้มันให้เต็มความสามารถเพื่อให้คุ้มกับเงินมากที่สุด
หลอดไฟหัวเตียงนั้นผมใช้ของ ROHM รุ่น LBF1048-45DXB จากญี่ปุ่น ต่อกับตัวต้านทาน 2 โอห์ม 3 วัตต์ (1 วัตต์ก็เหลือเฟือแล้ว เพราะกำลังแทบทั้งหมดจะถูกส่งไปที่หลอด) ให้แสงประมาณ 600 ลูเมนส์ ถือว่าเพียงพอ (อย่าลิมว่ามันมีมุมสว่างเพียง 120 องศา 1/4 ของหลอดกลมหรือ CFL ทั่วไป ดังนั้นที่พื้นที่เท่ากันมันจะสว่างกว่า 4 เท่าเมื่อเทียบกับหลอดกลมที่ค่าลูเมนส์เท่ากัน)
ส่วนไฟนอนหลับนั้นเป็นของ Dominant รุ่น NPW-RSZ-TU-1 ต่ออนุกรม 3 ดวงอนุกรมกับตัวต้านทาน 12 โอห์ม บนแผงสำเร็จ จริงๆ แล้วหาหลอด 12 โวลต์ 2-3 วัตต์อะไรก็ได้ อย่างไรก็ตามเรื่องหลอดไฟผมคงไม่เน้นในกระทู้นี้
วงจรและข้อมูลทั่วไป
การทำงานของวงจร
การทำงานนี้ไม่มีอะไร มี 3 ส่วนหลัก
1. ส่วนแหล่งจ่ายไฟของวงจร ผมใช้ ไอซี7805 ในการลดแรงดัน 12 โวลต์จากอะแด้ปเตอร์ข้างนอก (อันนี้ไปหาเอาเอง กระแสที่จ่ายต่ำสุดไม่น้อยกว่า 1 แอมป์) ป้อนพลังงานเข้าบอร์ดควบคุม ถ้าใช้แบบสวิทชิ่งก็จะดีตรงที่ไฟตกเหลือแค่ 100 โวลต์มันก็ยังทำงานปกติ
2. ส่วนรับอินพุทของ MCU เป็น TACT สวิทช์กดติดปล่อยดับทั่วไป ต่อกับตัวต้านทาน weak pull up ขนาด 2 กิโลโอห์ม 0.25 วัตต์ จริงๆ ใน MCU ก็มี Weak pull up resistors แต่มันไม่เวิร์ค สู้สัญญาณรบกวนไม่ได้ และตัวโปรแกรมที่ให้มาก็เปิดใช้อยู่
3. ส่วนควบคุมขาออกของ MCU เพื่อจะไปเปิด-ปิดหลอดไฟ โดยใช้ทรานซิสเตอร์ 2SD882 เป็นตัวขับกำลังให้แต่ละหลอด และมีตัวต้านทาน 200 โอห์ม 0.25 วัตต์ก็พอเป็นตัวไบอัสขาเบส เพื่อไม่ให้โหลดกระแสซอร์สของ MCU มากเกินไป อีกจุดหนึ่งคือไฟมอนิเตอร์โหมดไฟก่อนนอน ที่ใช้ตัวต้านทาน 200 โอห์ม 0.25 วัตต์ อนุกรมไว้
สังเกตุว่าอุปกรณ์อินพุท กับ เอาท์พุทแต่ละชุดจะใช้ค่าตัวต้านทานที่เหมือนกันจะได้ง่ายต่อการจำและเลือกซื้อ และเป็นค่าที่ถูกคำนวนและตรวจสอบแล้วว่าเหมาะสมที่สุด แทบไม่เกิดความร้อนแม้ในภาคขับกำลัง
อีกจุดหนึ่งคือหลอดแอลอีดีแสดง Power On จะต่อกับอินพุท 12 โวลต์เพื่อโชว์ว่ามีไฟเข้ามาในวงจรหรือไม่ ตัวนี้อนุกรมด้วยตัวต้านทาน 910 โอห์ม (ใช้ 1 กิโลโอห์มก็ได้ แต่อนนั้นผมหาไม่เจอ) 0.25 วัตต์
หลอด Power On กับ Sleep Monitor นั้น ผมใช้หลอด 2 สีในตัวถังเดียวกัน เพื่อประหยัดการต่อวงจรและ ใช้การมองที่จุดเดียว
ส่วนแผ่นวงจรผมใช้แบบสำเร็จรูปตัดแต่งลายทางไฟฟ้าตามที่ออกแบบมา รูปยังไม่ได้ตัดลายเส้นทองแดง
โปรแกรมการทำงาน
#include <htc.h>
#include <pic.h>
#define _XTAL_FREQ 4000000
// int reset, no code protect, watchdog, 4MHz internal clock
__CONFIG(MCLREN & UNPROTECT & WDTEN & INTRC);
void main()
{
unsigned char sGPIO; // GPIO Shadow register
unsigned char db_cnt; // debounce counter
unsigned char Lamp; // Lamp sequence on
unsigned char Selected; // Lamp sequence on
unsigned char Dimmer;
unsigned char DimPWM;
unsigned char DimOff;
unsigned char Sel_cnt; // Check between Lamp or Sleep
unsigned int dly; // Lamp sequence on
// Initialisation
OPTION = ~GPPU; // enable weak pull-ups
OPTION = PSA | 0b111;
GPIO = 0; // All LED off
sGPIO = 0; // update shadow register
Lamp = 0;
Selected =1;
Sel_cnt = 0;
dly = 0;
Dimmer = 0;
DimPWM = 0;
DimOff = 0;
TRIS = 0b001100; // configure GP541 (only) as an output
// Main loop
for (;;) {
// wait until button pressed (GP2 low), debounce by counting:
for (db_cnt = 0; db_cnt <= 10; db_cnt++) {
__delay_ms(1); // sample every 1 ms
if (GP2 == 1) // if button up (GP2 high)
db_cnt = 0; // restart count
} // until button down for 10 successive reads
// wait until button released (GP2 high), debounce by counting:
for (db_cnt = 0; db_cnt <= 10; db_cnt++) {
__delay_ms(1); // sample every 1 ms
if (GP2 == 0) { // if button down (GP2 low)
Sel_cnt = Sel_cnt + 1;
if (Sel_cnt > 250) {
Selected = 2; Sel_cnt = 254; Lamp = 5;
for (Dimmer == 0 ; Dimmer < 184 ; Dimmer++) {
DimPWM = Dimmer;
sGPIO =0b001101;
GPIO = sGPIO; // write to GPIO
for (DimPWM = DimPWM; DimPWM < 184; DimPWM++) {
__delay_us(15); // sample every 1 ms
}
DimPWM = 185 - Dimmer;
sGPIO =0b001111;
GPIO = sGPIO; // write to GPIO
for (DimPWM = DimPWM; DimPWM < 184; DimPWM++) {
__delay_us(15); // sample every 1 ms
}
}
}
db_cnt = 0; // restart count
}
} // until button up for 10 successive reads
// toggle LED on GP1
Sel_cnt = 0;
if (Selected == 1) {
Lamp = Lamp + 1;
if (Lamp == 1)
{sGPIO =0b011100;}
if (Lamp == 2)
{sGPIO =0b101100;}
if (Lamp == 3)
{sGPIO =0b111100;}
if (Lamp == 4)
{sGPIO =0b001110;}
if (Lamp > 4)
{Lamp = 0; sGPIO =0b001100;}
Dimmer = 0;
GPIO = sGPIO; // write to GPIO
CLRWDT();
}
if (Selected == 2) {
CLRWDT();
for (dly = 0; dly <= 36000; dly++) {
__delay_ms(100); // sample every0 100 ms
CLRWDT();
}
for (Dimmer == 0 ; Dimmer < 254 ; Dimmer++) {
DimPWM = Dimmer;
sGPIO =0b00111;
GPIO = sGPIO; // write to GPIO
for (DimPWM = DimPWM; DimPWM < 254; DimPWM++) {
__delay_us(50); // sample every 1 ms
}
DimPWM = 255 - Dimmer;
sGPIO =0b00101;
GPIO = sGPIO; // write to GPIO
for (DimPWM = DimPWM; DimPWM < 254; DimPWM++) {
__delay_us(50); // sample every 1 ms
}
CLRWDT();
}
sGPIO =0b001101;
GPIO = sGPIO; // write to GPIO
Selected = 1;
SLEEP();
}
} // Always loop
}
ไม่มีความคิดเห็น:
แสดงความคิดเห็น