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.
I recommend using a solid state relay for AC lights/appliances if you have one in your parts bin, but aCode:;************************************************************************ ;* 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
mechanical relay will work as well. You can find a few thousand relay drive circuits on any decent
search engine.







Bookmarks