PDA

View Full Version : PIC10F200 Automated IR Light Switch



Bruce
- 8th February 2006, 19:06
I know it's not BASIC, but this little gadget comes in handy for folks that are just too lazy (like myself)
to turn on/off light switches all the time.

It's pretty simple stuff, and heavily commented, but if you have questions let me know.


;************************************************* ***********************
;* Name : IR_SWITCH.asm *
;* Author : Bruce Reynolds *
;* Date : Feb 8th, 2006 *
;* Version : 1.0 *
;* Notes : PIC10F200 Automatic IR Appliance Switch *
;* Assembler : MPASMWIN v5.01 *
;* Operation : GP0 modulates an IR LED at 40kHz by generating 'Cycles' *
;* : number of 40kHz pulses. GP2 samples the IR detector output after *
;* : each carrier burst period. A logic 0 on the IR detector output *
;* : indicates a target is within range reflecting IR energy back onto *
;* : the IR detector. After 6 Hits in approximately 2 seconds GP1 will *
;* : turn on to drive a relay controlling 1 or more lights. *
;* : After OffTime number of samples with no Hits, approx 11 seconds, *
;* : the drive output on GP1 is turned back off. *
;* : As long as the target is within range the output will remain on. *
;* : When target leaves the area, after ~11 seconds, it turns back off *
;& : providing an auto light switch by sensing presence / no presence. *
;************************************************* ***********************

title "Infrared automatic light switch"
processor 10F200

include <P10F200.inc>

__CONFIG _IntRC_OSC & _WDT_OFF & _CP_OFF & _MCLRE_OFF

#define IRLED GPIO,0 ; IR LED drive output pin
#define IRDET GPIO,2 ; IR detector input pin

#define LightOn bsf GPIO,1 ; turn drive output on
#define LightOff bcf GPIO,1 ; turn drive output off

; OffTime = 45 = approx 11 seconds. Adjust as required
#define OffTime D'45' ; delay before turn off of drive output

; MAX_HITS = 6 = approx 2 seconds before turn on if target present
#define MAX_HITS D'6' ; MAX object hits before drive output turns on

; setup RAM variable space
cblock 0x10 ; user RAM starts at 0x10 for 10F200/204
DelayTime:3 ; reserve 3 locations for delay counters
Cycles ; # of carrier cycles to generate IR signal
OffDelay ; time counter for output drive turn off delay
Hits ; holds recorded # of target Hits
endc

org 0x00
goto Init ; initialize I/O & peripherals

Main:
movlw D'50' ; generate 50 x 40kHz carrier cycles
movwf Cycles ; load carrier cycle count
call Pulse ; generate carrier burst

movlw D'1' ;
call Delay2 ; delay between carrier bursts/target checks
goto Main ; loop to Main

; infrared LED connection
; GPIO,0 ----\/\/\/\----|<|---- +5V DC
; 420 IR LED

Pulse ; send 'Cycles' number of 40kHz bursts
bcf IRLED ; 1uS turn on IR LED here
goto $+1 ; 2us
goto $+1 ; 2uS
goto $+1 ; 2us
goto $+1 ; 2uS
goto $+1 ; 2us
goto $+1 ; 2uS (13uS with IR LED on)
bsf IRLED ; 1uS turn off IR LED here
goto $+1 ; 2us
goto $+1 ; 2uS
goto $+1 ; 2us
goto $+1 ; 2us
decfsz Cycles,f ; 1uS decrement Cycles count, end pulse if Cycles = 0
goto Pulse ; 2uS/1uS (25uS total = 40kHz)

; goto Pulse above is 1uS once Cycles = 0, so it takes 8uS after the LED
; is off before we test the IR detector output. This is plenty fast since
; it takes a while for the detector output to settle after ending the IR
; carrier burst.

btfsc IRDET ; test detector output. If 0, target in range, CountHits
goto AlarmOff ; else jump to AlarmOff & count down turn-off period

CountHits
incf Hits,f ; target detected, increment Hits count
movlw MAX_HITS ; load MAX_HITS for comparison with current Hits count
subwf Hits,w ; if Hits = MAX_HITS then turn on drive output
skpnc ; if no carry, skip over LightOn, has not reached MAX_HITS
LightOn ; carry true, Hits = MAX_HITS, now turn on drive output
clrf OffDelay ; reset OffDelay period after all Hits
retlw 0 ; return to caller

AlarmOff
incf OffDelay,f ; increment time until turn off
movlw OffTime ; load OffTime for comparison with current OffDelay count
subwf OffDelay,w ; if OffDelay = OffTime, then turn drive output off
skpnc ; if no carry, skip over LightOff, has not reached OffTime
LightOff ; carry true, turn off output, OffTime period has expired
clrf Hits ; reset Hits count when no target is detected
retlw 0 ; return to caller

Delay ;
movlw D'2' ; 2 = a delay period of approximately 500mS

Delay2 ;
movwf delaytime ; pre-load W & enter at Delay2 for different delays
movlw D'232' ;
movwf delaytime+1 ;
movlw D'255' ;
movwf delaytime+2 ;
Dloop
clrwdt ; 1
decfsz delaytime+2,f ; 1
goto $-2 ; 2/1
decfsz delaytime+1,f ; 1
goto $-4 ; 2/1
decfsz delaytime,f ; 1
goto $-6 ; 2/1
retlw 0 ; 2

Init
movwf OSCCAL ; load factory osccal value at start-up
bcf OSCCAL,0 ; do NOT output osc/4 on GP2 (IR sensor input)
movlw b'00000001' ; IR LED on GP0 off on power-up
movwf GPIO ; load port latches
movlw b'00000100' ; GP2 = IR sensor input, rest outputs
tris GPIO ; set I/O directions
movlw b'11011000' ; wake-up on pin change disabled, weak pull-ups off
; Timer0 clock select on GP2 internal
option ; write to OPTION_REG

; clear all user RAM/variables on boot

movlw 0x10 ; initialize pointer
movwf FSR ; to RAM start

ClearNext
clrf INDF ; clear RAM location @ INDF
incf FSR,f ; increment pointer to next location
btfsc FSR,4 ; have we cleared location 0x10 yet..?
goto ClearNext ; nope, keep clearing
; yep, all done, continue

; approximately ~500mS power-up delay period for
; stabilization time

call Delay
goto Main

end

I recommend using a solid state relay for AC lights/appliances if you have one in your parts bin, but a
mechanical relay will work as well. You can find a few thousand relay drive circuits on any decent
search engine.

Darrel Taylor
- 11th February 2006, 00:39
Hi Bruce,

Very interesting. It's amazing what you can do with 256 Words, and 16 bytes.

I was just wondering what the range is. Is it something that can cover a room. Or, is it more for when you sit in your favorite reading chair?

What comes to mind for me are the automatic sinks and toilets at the airport where you have to be 6 inches from the sensor. Hopefully, it can do better than that?
<br>

crematory
- 11th February 2006, 00:47
Hi Bruce

Another amazing on the list :)

Another thing on mind, which if implemented could be really nice feature...If its possible to add toggle feature such that another PIC10F200 is used as the receiver to switch on/off the light upon receiving the IR signal, so that it becomes remote light switch as well.

Thanks

Bruce
- 11th February 2006, 01:21
Hi Darrel,

Had to find some use for those itty-bitty 10F surface mount samples I had.

The whole board with regulator, PIC, resistor, etc, fit onto the back of the IR detector. Just ran wires off to the LED.

With 15mA through the LED I'm getting around 4' trip distance. You could get a lot more than that with higher LED current or a small array of LED's.

Now the wife wants one for triggering some aggravating "someone left the toilet seat up again" message...;o}.

P.S. Nice job on the instant interrupt routines. Handy stuff.

Note: In the above comments, so no one gets confused, this;


; goto Pulse above is 1uS once Cycles = 0, so it takes 8uS after the LED
; is off before we test the IR detector output
should read 10uS after the LED is off. I moved the bsf IRLED up a tad to adjust the LED duty-cycle.

You can just move this up or down to adjust it as needed. Just spaced out changing the comment text.

Darrel Taylor
- 11th February 2006, 01:58
Hah! Why do we always have to move the seat?

You could make the device say "Please return the seat to the Up-right position" if it's left down. :)

Think I'm going to play with this little guy. Haven't had a chance to mess with the 10F's yet.

Are you using the TSOP1140 IR detector module?

Darrel

P.S. Thanks! (interrupts)
Wait till I get through the 18F version. That one's even better.

Bruce
- 11th February 2006, 03:54
Yeah i used the TSOP1140, but any el-cheapo IR module should work pretty much the same for this low-budget gadget.

I used it because there was room on the back to attach my tiny little PCB with the rest of my parts. The surface mount version 10F200 parts are like a grain of salt.

Just don't sneeze when you have em in front of you. Lost 4 of my samples.



P.S. Thanks! (interrupts)
Wait till I get through the 18F version. That one's even better
You're welcome. I figured you were already working on the 18F version once you posted the 18F USART_Init macro, then modified it with CHK?RP for the 14-bit core...;o}

Keep em comin.


.

Darrel Taylor
- 11th February 2006, 04:42
I figured you were already working on the 18F version once you posted the 18F USART_Init macro, then modified it with CHK?RP for the 14-bit core...;o}
.

Busted! &nbsp; :o
<br>

Dr Bob
- 3rd May 2007, 12:40
Hi Bruce

Another amazing on the list :)

Another thing on mind, which if implemented could be really nice feature...If its possible to add toggle feature such that another PIC10F200 is used as the receiver to switch on/off the light upon receiving the IR signal, so that it becomes remote light switch as well.

Thanks

You could always the IRLED as an IR receiver