; Controller for composting loo fan. V2 May/1999 ; This program and the circuit it controls are the copyright of Eddie Matejowsky - 1998 ; It is freeware, you may copy it, build it and use it, I'll even let you make money by ; selling it. In exchange you must acknowledge it as being my design and include this notice ; with any copies you make and include a hardcopy of this notice with any units made for others. ; The main reason for this requirement is to give all users the opportunity to visit my web-site ; for up to date information on this project and related alternate technology projects. ; My website is currently at http://www.ozemail.com.au/~eddiema/ , if this changes ; a web search using my name and a keyword such as "loofan" should locate me. ; My current email address is eddiema@ozemail.com.au ; ; The Controller :- Ver1 and Ver2 ; Prevents the fan from running when battery is too flat. ; Senses when a person is in the room by using a PIR dectector and turns the fan on for about 5 minutes. ; If battery is over 13 volts turn fan on regardless of the PIR state. ; Fan is controlled via a power MOSFET on B3 ; lower resister in reference divider is attached to port B bit 2 ; lower resister in 11 volt sensing divider is attached to port D bit 6 ; lower resister in 13 volt sensing divider is attached to port B bit 4 ; PIR detector is read by port D bit 5 ; Version 2 ; in version 2 an open loop switched mode circuit has been added to enable the fan to be run at ; reduced power instead powered down. Jumpers select the power setting and a LED has been added ; to indicate the mode of operation. ;------- ; power select jumper port assignments. ; bit0 of speed select = PD0 ; bit1 of speed select = PD4 ; bit2 of speed select = PD3 ; bit3 of speed select = PD2 ;----------------------------------------------------------------- .device AT90S1200 ;Prohibits use of non-implemented instructions .nolist .include "1200def.inc" ;I/O port and bit definitions .list .CSEG ; working registers for the program. .def temp =r16 .def counter1 =r17 ; counters for various timing routines. .def counter2 =r18 .def counter3 =r19 .def counter0 = r22 .def timervalue =r20 ; reload value for on chip counter/timer .def powermode = r21 ; store current motor power mode .def flashpat = r23 ; store binary LED flash pattern eg 0x5 = 2 flashes, this byte is rotated. .def newpat = R24 ; store possibly new flash pattern .def oldpat = r25 ; store a copy of old flash pattern to see if new one is same or not. .def lvcnt = r26 ; low voltage counter, used to prevent short voltage drops being registered. ; motor power modes constants .equ nopower = 0 .equ fullpower = 1 .equ lowpower = 2 ;Reset vector (must be the first code generated) rjmp RESET ;To Reset handler .org OVF0addr rjmp tim0_ovf ;Timer0 overflow handler ;----------------------------------------------------------------- ; timer overflow interrupt routine tim0_ovf: out TCNT0,timervalue ;Reload timer dec counter0 ; used as timer by non interrupt rountine. cpi powermode,lowpower ; test power mode brne notlow ; brach if not the reduced power mode. ; turn FET on for between 14 and 30 microseconds depending on jumper settings. sbi PORTB,PB3 ; turn fet on 2 cycles sbic PIND,PB0 ; Test for jumper1 rjmp fwd1 ; these 2 instruction take 3 or 4 cycles rjmp fwd1 ; 4 if jumper in place fwd1: sbic PIND,PB4 ; Test for jumper rjmp fwd2 ; these group takes 3 or 5 cycles ) nop rjmp fwd2 fwd2: sbic PIND,PB3 ; rjmp fwd3 ; this group takes 3 or 7 cycles rjmp hop ; hop: rjmp fwd3 ; fwd3: sbic PIND,PB2 ; Test for jumper rjmp turnoff ; this group takes 3 or 11 cycles ldi temp,2 ;1 lp1: dec temp ;1 brne lp1 ;1/2 rjmp turnoff turnoff:cbi PORTB,PB3 ; turn fet off 2 cycles reti; ; waste1: rjmp fwd2 notlow: cpi powermode,fullpower brne turnoff sbi PORTB,PB3 ; turn fet on reti; ;delay routines, note all rountines use one level of stack (we can have 3 levels total) DELAY: ldi counter0,14 ; WAIT1: tst counter0 ; Check for timer overflow brge WAIT1 ; if not zero loop around dec counter1 ; decrement counter brne DELAY ; and loop more if not zero ret DELAY0: ldi counter1,1 ; Entry point for aprox 1 ms sec delay rjmp DELAY DELAY1: ldi counter1,250 ; Entry point for aprox 1/4 sec delay cp newpat,oldpat ; test if a new flash pattern is set brne updtpat ; yes go to update rjmp noupdate ; nop don't update updtpat: mov flashpat,newpat ; mov new pattern into rotating byte mov oldpat,newpat ; save it in oldpat as well noupdate: rol flashpat ; rotate pattern brcs makeon ; if carry set turn led on cbi PORTB,PB6 ; else turn LED OFF andi flashpat,0xfe ; clear low bit of byte rjmp DELAY ; jump to delay makeon: sbi PORTB,PB6 ; LED ON ori flashpat,1 ; set low bit of byte rjmp DELAY ; jump to delay ;--------------------------------------------------------------- ; code starts executing here on reset RESET: ldi temp,(0<11 volts dec lvcnt ; dec lvcnt brne OVER11A ; don't power down till counter reaches zero ldi powermode,nopower ; it's zero kill the fan ldi newpat,1 ; set pattern to single flash ldi temp,100 ; don't do anything for 100 delay periods (25 seconds) wait: rcall delay1 dec temp brne wait retest: rcall delay1 ; retest bat voltage sbis ACSR,ACO ; Skip if compare set rjmp kick ; We have enough voltage to proceed ie >11 volts rjmp retest ; the battery is flat retest till it improves. Kick: ldi powermode,fullpower ; the fan was stopped so kick it to get it spinning rcall delay1 ; wait 1/4 second OVER11: ldi lvcnt,40 ; we have over 11 volts so reset LV counter to 40 OVER11A:cbi DDRD,PB6 ; disable 11 volt divider sbis PIND,PB5 ; Test for PIR output rjmp TEST13 ; No PIR so test if bat >13 volts PIRON: ldi powermode,fullpower ; turn fan power maximum ldi newpat,0xFF ; set pattern for LED on without flashing. PIRLP: ldi COUNTER2,0 ; set counters for delay - aprox 2 minutes ldi COUNTER3,2 ; we do NOT check for undervoltage once the fan is on PIRDEL: rcall DELAY1 ; retriggerable delay, no way out except waiting! sbic PIND,PB5 ; Test for PIR output again rjmp PIRLP ; PIR on - restart timing loop dec COUNTER2 ; decrement counter brne PIRDEL ; and loop more if not zero dec COUNTER3 ; decrement counter brne PIRDEL ; and loop more if not zero rjmp LOOP ; Time elasped back to start TEST13: sbi DDRB,PB4 ; enable 13 volt divider rcall DELAY0 ; 1 ms delay to stabilize voltages sbis ACSR,ACO ; Skip if compare set rjmp OVER13 ; we have >13 volts jump to OVER13 ldi newpat,5 ; not 13 Volts but over 11 set to 2 flashes ldi powermode,lowpower ; turn fan to low power rcall delay1 ; wait rjmp LOOP ; back to start OVER13: ldi COUNTER2,50 ; we have >13V ldi powermode,fullpower ; set fan to full power ldi newpat,0x15 ; flash pattern to 3 flashes. V13DEL: rcall DELAY1 ; Non retriggerable delay, but can jump to PIR loop sbic PIND,PB5 ; Test for PIR output rjmp PIRON ; PIR on, exit 13volt loop and enter PIR loop dec COUNTER2 ; decrement counter brne V13DEL ; and loop more if not zero rjmp LOOP ; that's all folks