Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;***************************************************************************
- ;* Title : SolarLight
- ;* Version : rev. 2.1
- ;* Last updated : 2009.12.11
- ;* Target : ATTiny15L @ 1.6MHz (internal osc)
- ;* DESCRIPTION :
- ;***************************************************************************
- ;*
- ;* Code Control
- ;*
- .nolist
- .include "tn15def.inc" ; Import Register definitions
- .list
- ;*
- ;* DEBUG CONTROL VARIABLES
- ;*
- ; .def DEBUG = R29 ; debug control variable
- ; .def DB_CNT = R28 ; debug help variable
- ;*
- ;* Equates
- ;*
- ; ATTiny15L PinNb Prototype
- ; RESET/ADC0 - 1 - RST
- ; PortB4/ADC3(*) - 2 - Vsun
- ; PortB3/ADC2(*) - 3 - Vled
- ; - 4 - GND
- ; PortB0/AIN0/AREF - 5 - Status LED
- ; PortB1/AIN1/OC1A - 6 - MOSFET output
- ; PortB2/ADC1/T0/INT0 - 7 - Vbat
- ; - 8 - VCC
- ;(*) change in ATTiny25/45/85
- ; FCLK WATCHDOG = 350kHz @ Vcc=3V;
- ; FCLK WATCHDOG = 500kHz @ Vcc=3.5V (* arround this value)
- ; FCLK WATCHDOG = 700kHz @ Vcc=4V
- .equ CNT_CHRG =3600 ; at least 1 hour of charging
- .equ VCHRG =200/20 ; 200mV if (Vf(diode)> 200mV) => charging
- .equ VBATMIN =3000/20; 3000mV
- .equ VSUNMIN =3000/20; 3000mV
- .equ VLEDMAX =4750/20; 4700mV i.e. no LED! or Overcurrent
- .equ VLEDREF =3200/20; Vf=3720mV@1A (3200mV@700mA simulation tests)
- .equ PWMMAX =166 ; maximum allowable duty cycle =0.60
- .equ PWMREF =145 ; reference duty cycle =0.57
- .equ PWMMIN =100 ; minimum allowable duty cycle =0.39
- ;*
- ;* Definitions
- ;*
- .def zero =R0 ; register holding zero (after oscillator calibration!)
- .def one =R1
- .def mcusr_sv =R3 ; save MCUSR for later testing
- .def chrg_cntl =R7 ; charging counter low
- .def chrg_cnth =R8 ; charging counter high
- .def accl =R16 ; accumulator low/temporary holding variable
- .def acch =R17 ; accumulator high/temporary holding variable
- .def vsun =R18 ; result of conversion Vsolarpanel
- .def vbat =R19 ; result of conversion Vbattery
- .def vled =R20 ; result of conversion VLED
- .def pwm =R21 ; next pwm value
- ;*
- ;* Code
- ;*
- .cseg
- .org 0
- rjmp RESET ; RESET handle
- reti ; INT0
- reti ; PCI0
- reti ; OC1
- reti ; OVF1
- reti ; OVF0
- reti ; ERDY
- reti ; ACI
- reti ; ADCC
- ;*
- ;* Main
- ;*
- RESET:
- wdr ; WDT reset - just to be sure !
- ldi accl,0b00011111
- out WDTCR,accl
- ldi accl,0b00010111
- out WDTCR,accl ; WDT disabled
- in mcusr_sv,MCUSR ; save MCUSR for test of watchdog timer reset
- sbrc mcusr_sv,WDRF ; skip if not wdt reset (power up)
- rjmp INIT ; jump if watchdog reset
- rcall chrg_ld ; reset counter of charging times
- INIT:
- ldi ZH,high(FLASHEND<<1)
- ldi ZL,low((FLASHEND<<1)+1) ; get OSCCAL value
- lpm ; read from ROM(Z)->R0
- out OSCCAL,zero ; set oscillator calibration
- clr zero ; setup zero register (lpm destroys zero reg!!)
- out MCUSR,zero ; clear MCUSR
- out PORTB,zero ; clear output port
- ldi accl,0b0000_0010 ; Bit 0 as input (check if LED is tied to VCC => allways on)
- out DDRB,accl ; set LED as input, MOSFET GATE as output.
- sbic PINB,PORTB0 ; skip if not connected to VCC
- rjmp LIGHT_001
- ldi accl,0b0000_0011
- out DDRB,accl ; set status LED/MOSFET GATE as outputs
- BEGIN:
- rcall sample ; sample light values
- mov accl,vsun ; check if charging Vsun > Vbat+.1V
- sub accl,vbat ; accl = vsun-vbat
- brmi BEGIN_000 ; difference negative (vbat>vsun)
- cpi accl,VCHRG ; compare difference with diode drop
- brlo BEGIN_000 ; Negative ?
- rcall chrg_dec ; decrement charging counter
- rjmp deep_sleep ; goto sleep unit WDT
- BEGIN_000:
- mov accl,chrg_cntl
- or accl,chrg_cnth ; test charge time for zero, return with Z set
- breq BEGIN_001 ; if counter == 0 do other checks
- rjmp deep_sleep ; else deep sleep
- BEGIN_001:
- rcall chrg_ld ; reload counter
- LIGHT:
- cpi vbat,VBATMIN ; check if enough battery 3.0V
- brsh LIGHT_000 ; jump if >=
- rjmp deep_sleep ; wait another counter period
- LIGHT_000:
- cpi vsun,VSUNMIN ; check if Vsun above 3.5V
- brlo LIGHT_001 ; light on if lower
- rjmp deep_sleep ; else deep sleep
- LIGHT_001:
- ldi accl,0b0110_0010 ; PWM mode, non inverted PWM,PCK/2
- out TCCR1,accl
- ser accl
- out OCR1B,accl ; set OCR1B=0hFF, PWM frequency 50KHz
- ldi accl,PWMREF
- out OCR1A,accl ; reference duty cycle
- mov pwm,accl ; set pwm
- LIGHT_ON:
- rcall sample ; sample analog values
- cpi vbat,VBATMIN ; if vbatt < vbatt min
- brlo deep_sleep
- cpi vsun,VSUNMIN ; if Vsun > vsun min , sun shinning
- brsh deep_sleep
- cpi vled,VLEDMAX ; if Vled > vled max
- brsh deep_sleep ; shutdown !!
- ; adjusting pwm
- cpi vled,VLEDREF
- breq LIGHT_ON ; branch if vled == VLEDREF ...stable just continue...
- brsh LIGHT_ON_000 ; branch if vled >= VLEDREF
- cpi pwm,PWMMAX
- brsh LIGHT_ON_001 ; branch if pwm >= PWMMAX
- inc pwm
- rjmp LIGHT_ON_001
- LIGHT_ON_000:
- cpi pwm,PWMMIN
- brlo LIGHT_ON_001 ; branch if pwm < PWMMIN
- dec pwm
- LIGHT_ON_001:
- out OCR1A,pwm ; update pwm register
- rjmp LIGHT_ON ; loop
- ;*
- ;* Functions
- ;*
- ;* Function : Sample
- ;* Description : sample 3 analog inputs, store MSB of conversion in registers
- ;* : use only 8 bits of the conversion for reduced complexity
- ;* : Value = Vin*(10/(10+10))/(2.56/256)
- ;* : 1LSB = 20mV
- ;* Code Size : 22 Words
- ;* Cycles : 108 + conversion time!
- ;* Low Register Usage : R4,R5,R6 (results of conversion)
- ;* High Register Usage : R16 (acc)
- ;* Interrupt Usage : None
- ;* Notes: all conversions are extended (change of channel) according to datasheet pg 45
- ;* sample and hold is 13.5 cy, total conversion in 25 cy. currently ADC clock is CK/128,
- ;* could be changed for system stability to CK/2,CK/4|8|16|32|64|128 in ADCSR (0bxxxx_x000,010,011,100,101,110,111)
- ;* current setting CK/128 ADCSR =0bxxxx_x111.
- ;*
- sample:
- sbi PORTB,PORTB0
- ldi accl,0b1010_0001 ; select PB2/Vbat, ADLAR=1 (Left justified), Vref=2.56V
- out ADMUX,accl
- ldi accl,0b1100_0111 ; Enable, Start conversion, CK/128 *
- out ADCSR,accl
- smpl_000:
- sbic ADCSR,ADSC ; wait for end of conversion
- rjmp smpl_000
- in vbat,ADCH ; store conversion result
- ldi accl,0b1010_0010 ; select PB3/Vled, ADLAR=1 (Left justified), Vref=2.56V
- out ADMUX,accl
- ldi accl,0b1100_0111 ; Enable, Start conversion, CK/128 *
- out ADCSR,accl
- smpl_001:
- sbic ADCSR,ADSC ; wait for end of conversion
- rjmp smpl_001
- in vled,ADCH ; store conversion result
- ldi accl,0b1010_0011 ; select PB4/Vsun, ADLAR=1 (Left justified), Vref=2.56V
- out ADMUX,accl
- ldi accl,0b1100_0111 ; Enable, Start conversion, CK/128 *
- out ADCSR,accl
- smpl_002:
- sbic ADCSR,ADSC ; wait for end of conversion
- rjmp smpl_002
- in vsun,ADCH ; store conversion result
- cbi PORTB,PORTB0
- ret
- ;* Function : Charge Counter Load
- ;* Description : Load counter with reload value
- ;* Code Size : 5 Words
- ;* Low Register Usage : R7,R8 (Charge counter)
- ;* High Register Usage : R16 (accl)
- ;* Interrupt Usage : None
- chrg_ld:
- ldi accl,high(CNT_CHRG) ; if power on reset
- mov chrg_cnth,accl
- ldi accl,low(CNT_CHRG) ; load charging counter
- mov chrg_cntl,accl
- ret
- ;* Function : Charge decrement / Zero?
- ;* Description : decrement counter (if > 0), Z set if Zero
- ;* Code Size : 12 Words
- ;* Low Register Usage : R7,R8 (Charge counter)
- ;* High Register Usage : R16 (accl)
- ;* Interrupt Usage : None
- chrg_dec:
- mov accl,chrg_cntl
- or accl,chrg_cnth ; test for zero, return with Z set
- brne chrg_dec_000 ; skip return if non zero
- ret ; with Z set
- chrg_dec_000:
- mov accl,chrg_cntl
- subi accl,1
- mov chrg_cntl,accl ; counterL - 1
- brcs chrg_dec_001 ; adjust counterH if carry
- ret ; return if no carry
- chrg_dec_001:
- dec chrg_cnth
- clz ; just in case dec counter H was zero
- ret
- ;* Function : Deep Sleep
- ;* Description :
- ;* Code Size : Words
- ;* Low Register Usage :
- ;* High Register Usage :
- ;* Interrupt Usage : None
- deep_sleep:
- out TCCR1,zero ; stop timer
- out PORTB,zero ; clear all outputs
- out ADCSR,zero ; power off ADC
- ldi accl,0b0000_1111 ; WDT EN, 2048K
- out WDTCR,accl ; start watchdog timer and wait 4 seconds
- ldi accl,0b0011_0000 ; Sleep enable, Power Down
- out MCUCR,accl
- wdr
- sleep
- deep_sleep_000:
- rjmp deep_sleep_000
- ;***** DEBUG *****
- .IFDEF DEBUG
- ;* Function : DEBUG OUTPUT
- ;* Description : outputs in the LED pin 1 byte coded as FM clock+data(0,1) MSB first
- ;* Code Size : 25 Words
- ;* Low Register Usage : None
- ;* High Register Usage : R29,R28
- ;* Interrupt Usage : None
- dbug:
- ldi DB_CNT,8 ; output 8 bits [1]
- sbi DDRB,PORTB0 ; always do it [2]
- sbi PORTB,PORTB0 ; start bit longer than normal 1 [2]
- nop
- nop
- nop
- nop
- cbi PORTB,PORTB0 ; short break, begin of data [2]
- dbug_000:
- rol DEBUG ; bit7 -> C [1]
- brcc dbug_001 ; branch if C=0 [2] non taken [1]
- sbi PORTB,PORTB0 ; send a one [2]
- cbi PORTB,PORTB0
- sbi PORTB,PORTB0 ; send a one [2]
- cbi PORTB,PORTB0
- rjmp dbug_002 ; [2]
- dbug_001:
- sbi PORTB,PORTB0 ; send a one [2]
- cbi PORTB,PORTB0
- nop
- nop
- nop
- nop
- nop
- dbug_002:
- dec DB_CNT ; [1]
- brne dbug_000 ; [1] false, [2] taken
- ret
- .ENDIF
- ;***** DEBUG *****
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement