ぐうたらな発想から、寝室にある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;
}