ぐうたらな発想から、寝室にある4個の40w白熱電球が同時に点く室内電灯を少し改造して、
4個の電球を60w、40w、20wの白熱電球と2wの100VLEDに切り替えて、リモコンで
一つ一つ点灯できるようにしました。
こうすれば、布団に入ったまま電灯を操作できるし、身体と電気の省エネにもなりますよね??
なお、プログラムは、「PICによるホームコントロール工作入門」(中尾 司著)を参考にさせてもらい、
12chのリモコン用に作ったプリント基板をそのまま5ch用に使用しています。
写真のようにリモコン送信機は、5個のプッシュボタンで左から60w、40w、20w、
2wの点灯用に、右上のボタンは全消灯用に使っています。
電源は、2個の単4形電池を使用し、電源スイッチは付けていません。
使用しない時は,TIMER1のオーバーフロー割込みを使ってSleep状態にしてあり、
プッシュボタンを押すことによりRB状態変化割込みで起動しています。それにより1年以上
電池を交換しなくても使えています。
受信機は、写真のように電灯のスイッチの所に設置しています。このスイッチをONにすると
60Wの電灯が点灯し、OFFにすると電灯が切れるようにしてあります。
お断りしておきますが、屋内配線は電気工事士の資格が必要ですので考慮してください。
下記にリモコン送信機の回路図を表示しておきます。
1.PIC16F648Aを次のように使用しています。
(1)キー・スイッチを使用した12ch用のリモコン送信機を5chに変更しただけです。
(2)プリント基板も12ch用に作成したプリント基板をそのまま使用しています。
リモコン送信機のPICプログラムを掲載しておきます。
// remocon12ch // #include <16F648A.h> #fuses NOWDT,INTRC_IO,PUT,NOPROTECT,NOBROWNOUT,MCLR,NOLVP,NOCPD #use delay(clock=4000000) // レジスタ・アドレス #byte PORTA =0x05 #byte PORTB =0x06 #byte INTCON =0x0B struct TAG_PORT { unsigned char B0:1; unsigned char B1:1; unsigned char B2:1; unsigned char B3:1; unsigned char B4:1; unsigned char B5:1; unsigned char B6:1; unsigned char B7:1; }; struct TAG_PORT PA; #byte PA=5 struct TAG_PORT PB; #byte PB=6 #define BitTest(p,b) (p&(1<<b)) void SendData(int cmd); boolean GoSleep=false; void PulseOut(void); char KeyMtxScan(void); void KeyPress(void); BYTE KeyCode[3][4] = {{0,1,2,3},{4,5,6,7},{8,9,10,11}}; #int_RB RB_isr() { INTCON &= 0xFB; disable_interrupts(INT_RB); } #int_TIMER1 TIMER1_isr() { GoSleep=true; } BYTE BefKey=0; BYTE KPValue; BYTE KeyMatch=0; boolean KeyDown=false; boolean Repeating=false; BYTE KeyInterval=0; #define KEY_REPEAT_ENA true #define KEY_REPEAT_DIS false char KeyCheck(BYTE key, BYTE repeat_ena) { if(BefKey==key) { KeyMatch++; if(repeat_ena) { if(KeyMatch>50) { KeyMatch=50; Repeating=true; } else { Repeating=false; } } else { Repeating=false; } } else { BefKey=key; KeyMatch=0; Repeating=false; } if(KeyMatch>=2) { if(key==0xFF) { KeyDown=false; Repeating=false; } else { if(!Repeating) { if(!KeyDown) { KeyDown=true; KPValue=key; return true; } } else { if(!KeyDown) { KeyInterval=(KeyInterval+1) % 10; if(KeyInterval==0) { KeyDown=true; KPValue=key; return true; } } } } } return false; } void main() { port_b_pullups(TRUE); setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64); setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); setup_comparator(NC_NC_NC_NC); setup_vref(FALSE); setup_oscillator(OSC_4MHZ); set_tris_a(0); et_tris_b(0xF0); PORTA=0xFF; set_timer1(0); enable_interrupts(INT_TIMER1); enable_interrupts(GLOBAL); while(1) { if(GoSleep) { setup_timer_1(T1_DISABLED); set_timer0(0); PORTB &=0xF1; enable_interrupts(INT_RB); #asm SLEEP NOP #endasm GoSleep=false; } if((INTCON & 0x04) !=0 ) { INTCON &= 0xFB; if(KeyMtxScan()) { KeyPress(); } } } } void KeyPress(void) { set_timer1(0); SendData(KPValue); } BYTE lc; void SendData(int cmd) { signed char i; BYTE data; cmd &= 0x0F; data =~cmd <<4; data |=cmd; disable_interrupts(GLOBAL); lc=56; PulseOut(); delay_us(480); for(i=7;i>=0;i--) { if(BitTest(data,i)) { lc=37; PulseOut(); delay_us(480); } else { lc=19; PulseOut(); delay_us(480); } } enable_interrupts(GLOBAL); #asm NOP #endasm } void PulseOut(void) { #asm LOOP: MOVLW 0 MOVWF PORTA NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP MOVLW 0xFF MOVWF PORTA NOP NOP NOP NOP NOP NOP NOP NOP DECFSZ lc GOTO LOOP #endasm } char KeyMtxScan(void) { BYTE col,row,coldat,key=0xFF; for(row=0;row<3;row++) { PORTB|=0b1110; switch(row) { case 0: PB.B1=0; break; case 1: PB.B2=0; break; default: PB.B3=0; break; } delay_us(5); coldat=PORTB>>4; for(col=0;col<4;col++) { if(!(coldat & 1)) { key=KeyCode[row][col]; goto next; } coldat>>=1; } } next: return KeyCheck(key,KEY_REPEAT_ENA); }
参考として送信機ケース内の写真を掲載しておきます。
実にシンプルですね!!
下記にリモコン受信機の回路図を表示しておきます。
リモコン受診機のPICプログラムを掲載しておきます。(12ch用の受信機のプログラムです。)
#include <16F648A.h> #fuses NOWDT,INTRC_IO,PUT,NOPROTECT,BROWNOUT,NOMCLR,NOLVP,NOCPD #use delay(clock=4000000) #byte PORTA =0x05 #byte PORTB =0x06 #define TST_IrIN (!PB.B3) #define P0_ON (PA.B0=1) #define P0_OFF (PA.B0=0) #define P1_ON (PA.B1=1) #define P1_OFF (PA.B1=0) #define P2_ON (PA.B2=1) #define P2_OFF (PA.B2=0) #define P3_ON (PA.B3=1) #define P3_OFF (PA.B3=0) #define P4_ON (PA.B4=1) #define P4_OFF (PA.B4=0) #define P5_ON (PB.B0=1) #define P5_OFF (PB.B0=0) #define P6_ON (PB.B1=1) #define P6_OFF (PB.B1=0) #define P7_ON (PB.B2=1) #define P7_OFF (PB.B2=0) #define P8_ON (PB.B4=1) #define P8_OFF (PB.B4=0) #define P9_ON (PB.B5=1) #define P9_OFF (PB.B5=0) #define P10_ON (PB.B6=1) #define P10_OFF (PB.B6=0) #define P11_ON (PB.B7=1) #define P11_OFF (PB.B7=0) struct sPort { unsigned char B0:1; unsigned char B1:1; unsigned char B2:1; unsigned char B3:1; unsigned char B4:1; unsigned char B5:1; unsigned char B6:1; unsigned char B7:1; }; struct sPort PA; #byte PA=5 struct sPort PB; #byte PB=6 BYTE IrRcvData2(void); boolean OnSts0 = false; boolean OnSts1 = false; boolean OnSts2 = false; boolean OnSts3 = false; boolean OnSts4 = false; boolean OnSts5 = false; boolean OnSts6 = false; boolean OnSts7 = false; boolean OnSts8 = false; boolean OnSts9 = false; boolean OnSts10 = false; boolean OnSts11 = false; void main() { BYTE cmd; setup_comparator(NC_NC_NC_NC); setup_vref(FALSE); setup_oscillator(OSC_4MHZ); PA=0; PB=0; set_tris_a(0); set_tris_b(0x08); while(1) { // リモコン受信処理 cmd = IrRcvData2(); switch(cmd) { case 0: if(!OnSts0) { P0_ON; } else { P0_OFF; } OnSts0 = !OnSts0; break; case 1: if(!OnSts1) { P1_ON; } else { P1_OFF; } OnSts1 = !OnSts1; break; case 2: if(!OnSts2) { P2_ON; } else { P2_OFF; } OnSts2 = !OnSts2; break; case 3: if(!OnSts3) { P3_ON; } else { P3_OFF; } OnSts3 = !OnSts3; break; case 4: if(!OnSts4) { P4_ON; } else { P4_OFF; } OnSts4 = !OnSts4; break; case 5: if(!OnSts5) { P5_ON; } else { P5_OFF; } OnSts5 = !OnSts5; break; case 6: if(!OnSts6) { P6_ON; } else { P6_OFF; } OnSts6 = !OnSts6; break; case 7: if(!OnSts7) { P7_ON; } else { P7_OFF; } OnSts7 = !OnSts7; break; case 8: if(!OnSts8) { P8_ON; } else { P8_OFF; } OnSts8 = !OnSts8; break; case 9: if(!OnSts9) { P9_ON; } else { P9_OFF; } OnSts9 = !OnSts9; break; case 10: if(!OnSts10) { P10_ON; } else { P10_OFF; } OnSts10 = !OnSts10; break; case 11: if(!OnSts11) { P11_ON; } else { P11_OFF; } OnSts11 = !OnSts11; break; } } } BYTE IrRcvData2(void) { BYTE data, data2; BYTE i, j; for(i = 0; i < 12; i++) { if(TST_IrIN) { delay_us(100); } else { return 0xFF; } } for(i = 0; i < 30; i++) { if(!TST_IrIN) { goto next0; } delay_cycles(20); } return 0xFF; next0: data = 0; for(j = 0; j < 8; j++) { data <<= 1; for(i = 0; i < 60; i++) { if(TST_IrIN) { goto next; } delay_cycles(10); } return 0xFF; next: delay_us(700); if(TST_IrIN) { data |= 1; for(i = 0; i < 30; i++) { if(!TST_IrIN) { goto next2; } delay_cycles(20); } return 0xFF; } next2: #asm NOP #endasm } data2 = ~data >> 4; data &= 0x0F; if(data == data2) { return data; } return 0xFF; }