;
/*
* Shutdown timer (Shutdown_timer03) (To shut off a light after a preset period and also if the battery voltage is too low.)
*
* Created: 03/09/2015
* Author: Les
* Version 2 being modified by adding low battery warning light
*/
; using ATTINY13
; Fuse bit settings
; Low 0x62 (0x6A is also OK)
; High 0xFF
; Extended 0xFF
; Lock 0xFF
;
;
;Use internal clock at 9.6 Mhz (Default value) and divide by 8 by setting CKDIV8 fuse bit (These are the default setting on a new chip.)
; 9.6 Mhz/8 = 1.2 Mhz
;(So Instruction time = 833.3 nS)
; So for 50 uS delay requires 50/0.8333 = 60 instructions
; Burst needs to be 5 mS long. This will be 50 cycles of 10 Khz
;
;**************************************************************************
.nolist
.include <tn13def.inc> ; ATtiny 13
.list
.listmac
;***************************************************************************
;*
;* Global Register Variables
;*
;***************************************************************************
; Note register number is in decimal
.def N200mS = r17 ;Number of 200 mS
.def Seconds = r18 ;Number of seconds
.def Minutes = r19 ;Number of minutes
.def count_L = r22 ;Used for time delay
.def Flags = r23 ;Bit 0 used for battery low warning flag
.equ Shutdown_volts = 0xA4 ;battery voltage shutdown value. (164 decimal. Divide battery voltage using a 4.7K resistor to ground and a 10 K resistor to the )
; (collector ofthe power switching transistor. This gives a ratio of 0.32. So for a cut off voltage )
; (of 10.0 we need to detect 3.2 volts This is 256 x 3.2/5 = 164 )
.equ Battery_Low = 0xB4 ;Battery voltage low warning level. (Set to come on at 11.0 volts so this will be 1.0 * 0.32 = 3.52 volts at ADC input
; (This will be a count of 256 * 3.52/5 = 180 = 0xB4 )
;
.equ Shutdown_minutes = 5 ;Time to shutdown in minutes.
;
;
;******************************** INTERRUPT VECTORS ***********************
.CSEG
.ORG 00
rjmp reset
reti
reti
rjmp TC_overflow ;Timer/Counter Overflow
reti
reti ; rjmp timer1_OVF
reti
reti
reti
reti
;
;******************************* RESET *************************************
;
; Initialise the stack-pointer
reset:
ldi R16,low(RAMEND)
out SPL,R16
; initialize PORTB
; Bit 0 Input (pin 5) (Input will be low when button is pressed.
; Bit 1 Input
; Bit 2 Input ADC input (Pin 7)
; Bit 3 Output (Pin 2) (Drive to low battery warning LED High for LED on)
; Bit 4 Output (Pin 3) (Drive to power control tansistor base.)
; Bit 5 Input
ldi R16,0x18 ; Bits 3 and 4 as outputs.
out DDRB,R16 ;
ldi R16,0x10
out PORTB,R16 ; PORTB Bit 3 low, bit 4 high
; initialize Flags
ldi Flags,0x00
;Initialize ADC
ldi R16,0x84 ;Enable , Prescale value 16, No auto triggering
out ADCSRA,R16
ldi R16,0b00000000
out ADCSRB,R16
ldi R16,0x21 ;Select AD1 (pin 7) input, Select VCC as analogue reference. ADLAR (Left justify result)
out ADMUX,R16
ldi R16,0x04 ;Set PB2 as analoge input
out DIDR0,R16
;Initialize timer / counter
ldi R16,0x00 ;Normal operation
Out TCCR0A,R16
ldi R16,0x05 ; Prescale value 1024 (Inc counter every 0.8333 uS x 1024 = 853.3 uS (1171.88 hZ)
Out TCCR0B,R16 ; Counter will overflow every 218.445 mS (4,58 hZ)
; Counting to 234 would give 199.7 mS ( 256 - 234 = 22 = 0x16)
ldi R16,0x02 ;TOIE0 (Bit1) : Timer/Counter0 Overflow Interrupt Enable
Out TIMSK0,R16
;Init time counters
ldi N200mS,0x05
ldi Seconds,0x00
ldi Minutes,0x00
;Wait for button to be released (Wait for input to go high
Wait_Button_High:
sbis PINB,0
rjmp Wait_Button_High
bset 7 ;Enable global interrupst.
rjmp main
;Timer/Counter Overflow interrupt handler.
TC_overflow:
ldi R20,0x16 ;Preset timer so interrupt occures every 199.7 mS
out TCNT0,R20
dec N200mS ;200mS
breq TC01
RETI
TC01:
ldi N200mS,0x05
Inc_Sec:
SBRS Flags, 0
CBI PORTB,0x03 ;Clear battery low warning LED
SBRS Flags,0 ;Bat_Warning ;Skip if battery warning bit is set
RJMP Inc_S2
in R20,PORTB
ldi R21,0x08 ;Bits 3
eor R20,R21 ; Toggle bit 3 (Pin 2) (Every second)
out PORTB,R20
Inc_S2:
ldi R20,0x3C ;60 decimal
inc Seconds ;Increment seconds counter
cpse Seconds,R20
rjmp TC_End
CLR Seconds
Inc_Min:
ldi R20,0x3C ;60 decimal
inc Minutes ;Increment minute counter
cpse Minutes,R20
rjmp TC_End
CLR Minutes
TC_End:
RETI
; ------------------------------------- End of interrupt handlers --------------------------------------
;
; Main program code
;
Main:
nop
nop
ldi R20,Shutdown_minutes
cpse Minutes,R20 ;Is it time to shutdown ?
rjmp Not_Time
cbi PORTB,4 ;Clear PORTB bit 4
rjmp End_Loop
Not_Time:
nop
nop
nop
; rjmp Main ; Just loop waiting for interrupt
;Read ADC input value
ldi R16,0x84 ;Enable , Prescale value 16, No auto triggering
out ADCSRA,R16
ldi R16,0x21 ;Select AD1 input (pin 7) Select VCC as analogue reference, ADLAR (Left justify result)
out ADMUX,R16
sbi ADCSRA,ADSC ; Start ADC conversion
nop
Wait_ADC_Ready:
sbic ADCSRA,ADSC ; Wait_ADC_Ready:
rjmp Wait_ADC_Ready
in R20,ADCL ;Read ADC result L (Value not used but need to read this register befor high byte.)
in R20,ADCH ;Read ADC result H
;Test for battery warning level
CBR Flags,0x01 ;Bat_Warning ;Clear battery warning flag
CLC ;Clear carry flag
SBCI R20,Battery_Low
BRBC 0x00,Test_Shutdown ;Branch if carry bit is clear
SBR Flags,0x01 ;Bat_Warning ;Set battery warning flag bit
;Test for battery shutdown level
Test_Shutdown:
in R20,ADCH ;Read ADC result H again
CLC ;Clear carry flag
SBCI R20,Shutdown_volts
BRBS 0x00,Bat_Low ;Branch if carry bit is set
RJMP Bat_OK
Bat_Low:
CBI PORTB,0x04 ; Shutdown
End_loop:
NOP
RJMP End_loop ; Loop until power removed.
Bat_OK:
Test_button: ;If button pressed input will be low.
sbic PINB,0
rjmp Main ; Just loop waiting for interrupt
;Now wait 100 mS and recheck that button is pressed. (De bounce switch contacts)
rcall Delay_100ms
sbic PINB,0
rjmp Main
cbi PORTB,4 ;Clear PORTB bit 4
rjmp End_Loop
;Test_button:
sbis PINB,0
rjmp Test_button ;Loop until button pressed
;Now wait 100 mS and recheck that button is pressed. (De bounce switch contacts)
rcall Delay_100ms
sbis PINB,0
rjmp Test_button ;Loop until button is pressed
Button_open_loop:
sbic PINB,0 ;
rjmp Button_open_loop; loop until pedal released
;Subroutines.
;
;
; ----------------------------------------------
; Instruction cycle time is 0.83333 uS
; Delay 1mS Rcall to get here takes 3 instruction cycles. ret instruction takes 4 instruction cycles, ldi takes 1 instruction cycle (total 8)
; For 1 mS (1000 uS) we need 1000/0.83333 = 1200 instructions so need additional 1192 instructions 5 cycles in loop.
Delay_1_mS:
ldi count_L,0xEE ;Decimal 238 0xEE (Once round the loop is 5 instructions)
D_1mS_Loop:
dec count_L ; Count_L is R22 (1 cycle)
nop ;(1 cycle)
nop ;(1 cycle)
brne D_1mS_Loop ;If not zero (2 cycles while looping, 1 on exit)
ret
Delay_100ms:
ldi R21,0x64 ;100 decimal
Del_100ms_Loop:
rcall Delay_1_mS
dec R21
brne Del_100ms_Loop
ret
; -------------End of subroutines --------------
;