Code:
'****************************************************************
'* Name : Aquarium LED Lighting controller. *
'* Author : M. Crabbe *
'* Notice : Original Code by M Jervice *
'* : 18F2550 *
'* Date : *
'* Version : 1.0 *
'* Ported to the 18F4580 *
'* By Malcolm Crabbe *
'* 09/12/2012 *
'* Ver 1.1 - B *
'* *
'****************************************************************
@ errorlevel -205
ASM
__CONFIG _CONFIG1H, _OSC_HSPLL_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _PBADEN_OFF_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM
DEFINE OSC 40 ; config settings 18F4580, 20mhz crystal
ADCON1 = $0F
clear
DEFINE LCD_DREG PORTB ' LCD Data port
DEFINE LCD_DBIT 0 ' starting Data bit (0 or 4)
DEFINE LCD_EREG PORTB ' LCD Enable port
DEFINE LCD_EBIT 5 ' Enable bit (on EasyPIC 5 LCD)
DEFINE LCD_RSREG PORTB ' LCD Register Select port
DEFINE LCD_RSBIT 4 ' Register Select bit (on EasyPIC 5 LCD)
DEFINE LCD_BITS 4 ' LCD bus size (4 or 8 bits)
DEFINE LCD_LINES 4 ' number of lines on LCD
DEFINE LCD_COMMANDUS 2000 ' Command delay time in us
DEFINE LCD_DATAUS 50 ' Data delay time in us
'*******************************************************************************
CMCON = 7 ' disable Comparators
ADCON1 = %00001011 ' sets up Analogue pins
ADCON2.7 = 1
TRISA = %00001111
TRISB = %00000000
TRISD = %00001111
TRISE = %1111
'*******************************************************************************
i var word 'Misc counter
iv var word
LCD_Mode var word 'LCD light mode
LCD_Timer var word 'Timer for how long the LCD is on for.
LCD_Time var word 'Counter for the timer
LCD_Tmr var word
'*******************************************************************************
' RTC Variables
'*******************************************************************************
SCLpin var PORTC.3 ' RTC pin - clk
SDApin var PORTC.4 ' RTC pin - data
RTC_Msecs var byte
RTC_Secs var byte
RTC_Mins var byte
RTC_Hours var byte
RTC_Day var byte
RTC_WDay var byte
RTC_Month var byte
RTC_Year var byte
RTC_Ctrl var byte
dummy var byte
RTclock var byte[8]
Tick_Tmr var byte
Hours var byte
Minutes var byte
TimeH var byte ' Variable to store current hour
TimeM var Byte ' Variable to store current minutes
CounterA var byte ' General purpose Variable
CounterB var byte ' General purpose Variable
CounterC var byte ' General purpose Variable
CounterD var byte ' General purpose Variable
'*******************************************************************************
' LED variables
' Whites:
'*******************************************************************************
W_Min var word 'Min Light value
W_Max var word 'Max Light value
W_Fade_In var word 'Fade in duration
W_Fade_Out var word 'Fade out duration
W_Dawn_On_H var word 'What time to turn the lights on
W_Dawn_On_M var word 'What time to turn the lights on
W_Day_On_H var word 'What time to turn the lights on
W_Day_On_M var word 'What time to turn the lights on
W_Dusk_On_H var word 'What time to turn the lights on
W_Dusk_On_M var word 'What time to turn the lights on
W_On_H var word 'What time to turn the lights on
W_On_M var word 'What time to turn the lights on
W_Off_H var word 'Time to turn lights off
W_Off_M var word 'Time to turn lights off
'*******************************************************************************
' LED variables
' Blues:
'*******************************************************************************
B_Min var word 'Min Light value
B_Max var word 'Max Light value
B_Fade_In var word 'Fade in duration
B_Fade_Out var word 'Fade out duration
B_Dawn_On_H var word 'What time to turn the lights on
B_Dawn_On_M var word 'What time to turn the lights on
B_Day_On_H var word 'What time to turn the lights on
B_Day_On_M var word 'What time to turn the lights on
B_Dusk_On_H var word 'What time to turn the lights on
B_Dusk_On_M var word 'What time to turn the lights on
B_On_H var word 'What time to turn the lights on
B_On_M var word 'What time to turn the lights on
B_Off_H var word 'Time to turn lights off
B_Off_M var word 'Time to turn lights off
'Running fade variables
B_FadeIn_Time var word 'LIVE fade delay time seconds
B_FadeOut_Time var word
W_FadeIn_Time var word
W_FadeOut_Time var word
B_Cnt var word 'Seconds counter for the timing of adjusting the PWM
W_Cnt var word
B_Tick var word
W_Tick var word
'PWM Variables where the current output values are stored
W_PWM var word 'Whites
B_PWM var word 'Royal Blues
'*******************************************************************************
Blue_Day_Cycle var word 'Store for which part of the day cycle we are in
White_Day_Cycle var word
' Constants for the current running mode cycle for the lights
DAWN con 0
DAY con 1
DUSK con 2
NIGHT con 3
'*******************************************************************************
'Expendable variables used for misc calculations etc
Vw_5 var word
Vw_6 Var word
Vw_7 var word
Vw_8 var word
Vb_5 var word
Vb_6 Var word
Vb_7 var word
Vb_8 var word
'*******************************************************************************
data @0
data 08 'Whites dawn ON Time HOURS
data 00 'Whites dawn ON Time MINS
Data 11 'Whites day ON time Hours
Data 00 'Whites day ON time Minutes
Data 16 'Whites dusk ON time Hours
Data 00 'Whites dusk On time Mins
data 20 'Whites OFF Time HOURS
data 00 'Whites OFF Time MINS
data 0 'Whites MIN Intensity %
data 75 'Whites MAX Intensity %
data 08 'Blue dawn ON Time HOURS
data 00 'Blue dawn ON Time MINS
Data 08 'Blue day ON time Hours
Data 01 'Blue day ON time Minutes
Data 08 'Blue dusk ON time Hours
Data 02 'Blue dusk On time Mins
data 08 'Blue OFF Time HOURS
data 03 'Blue OFF Time MINS
data 0 'Blue MIN Intensity %
data 100 'Blue MAX Intensity %
Data 08 'Blue On Hours
Data 30 'Blue On Min
Data 08 'White On Hrs
Data 30 'White on Min
data 00 'Blue ON time hours
data 01 'Blue ON time Mins
Data 00 'White ON time hours
Data 01 'White ON time mins
'*******************************************************************************
'Setup Interrupts
'*******************************************************************************
INCLUDE "DT_INTS-18.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP-18.bas"
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _MyTimer, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
endasm
T1CON = %10000001 ; free-running, 1:1 prescaler
@ INT_ENABLE TMR1_INT ; enable Timer1 interrupts
'*******************************************************************************
' Start the program
'*******************************************************************************
code_start:
SetupPreset:
RTC_Msecs=$00 ' Seconds preset to 00
RTC_Secs=$00 ' Seconds preset to 00
RTC_Mins=$59 ' Minutes preset
RTC_Hours=$07 ' Hours preset
RTC_WDay=$01 ' Weekday preset to 01
RTC_Day=$12 ' Day preset 12
RTC_Month=$06 ' Months preset to June
RTC_Year=$02 ' Year preset to 2002
RTC_Ctrl=$10 ' Control preset to output 1 second 'Tick' on SQWpin
I2CWrite SDApin,SCLpin,$D0,$00,[RTC_Secs,rtc_mins,RTC_Hours,RTC_Ctrl]
B_Cnt = 0
W_Cnt = 0
gosub read_eeprom 'Read in the data needed for the lighting periods
LCD_Mode = 3 'LCD Backlight always ON
gosub Calc_Fade
'*******************************************************************************
'Main program loop
'*******************************************************************************
main:
gosub Read_Clock_2
if B_Dawn_On_H < TimeH and B_Dawn_On_M <= TimeM Then
Blue_Day_Cycle = NIGHT
endif
if B_Dawn_On_H = TimeH and B_Dawn_On_M = TimeM Then
Blue_Day_Cycle = DAWN
endif
if B_Day_On_H = TimeH and B_Day_On_M = TimeM then
Blue_Day_Cycle = DAY
endif
if B_Dusk_On_H = TimeH and B_Dusk_On_M = TimeM then
Blue_Day_Cycle = Dusk
endif
if B_Off_H = TimeH and B_Off_M = TimeM then
Blue_Day_Cycle = Night
endif
if W_Dawn_On_H < TimeH and W_Dawn_On_M < TimeM Then
White_Day_Cycle = NIGHT
endif
if W_Dawn_On_H = TimeH and W_Dawn_On_M = TimeM Then
White_Day_Cycle = DAWN
endif
if W_Day_On_H = TimeH and W_Day_On_M = TimeM then
White_Day_Cycle = DAY
endif
if W_Dusk_On_H = TimeH and W_Dusk_On_M = TimeM then
White_Day_Cycle = Dusk
endif
if W_Off_H = TimeH and W_Off_M = TimeM then
White_Day_Cycle = Night
endif
;***************************
'*** Do BLUE daily cycle ***
;***************************
select case Blue_Day_Cycle
case DAWN
lcdout $FE,$94,"BLUE: DAWN "
if B_cnt = B_Fadein_time and B_PWM < B_Max then
B_PWM = B_PWM + 1
B_Cnt = 0
endif
if B_PWM >= B_Max then
Blue_Day_Cycle = DAY
endif
case DAY
lcdout $FE,$94,"BLUE: DAY "
B_PWM= B_Max
B_Cnt = 0
CASE DUSK
lcdout $FE,$94,"BLUE: DUSK "
if B_Cnt >= B_Fadeout_time and B_PWM > B_Min then
B_PWM = B_PWM - 1
B_Cnt = 0
endif
if B_PWM = b_min then
Blue_Day_Cycle = NIGHT
endif
case NIGHT
lcdout $FE,$94,"BLUE: NIGHT"
B_Cnt = 0
B_PWM=0
end select
;****************************
'*** Do WHITE daily cycle ***
;****************************
select case White_Day_Cycle
case DAWN
lcdout $FE,$D4+8,"White: DAWN "
if W_Cnt = W_Fadein_time and W_PWM <= W_Max then
W_PWM = W_PWM + 1
W_Cnt = 0
endif
if W_PWM >= W_Max then
White_Day_Cycle = DAY
endif
case DAY
lcdout $FE,$D4+8,"White: DAY "
White_Day_Cycle = DUSK
W_Cnt = 0
CASE DUSK
lcdout $FE,$D4+8,"White: DUSK "
if W_Cnt >= W_Fadeout_time and W_PWM > W_Min then
W_PWM = W_PWM - 1
W_Cnt = 0
endif
if W_PWM = B_Min then
White_Day_Cycle = NIGHT
endif
case NIGHT
lcdout $FE,$D4+8,"White: NIGHT"
W_Cnt = 0
end select
;******************************
;*** Display Results on LCD ***
;******************************
'for test pourpose only
lcdout $FE,$80,#vb_5," ",#vb_6," ",#vb_7
lcdout $FE,$C0,#B_PWM
Pwm PORTD.7,B_PWM,1 'D7 used for EasyPIC5 development board - will be changed to RB7
goto main
Calc_Fade:
';*******************************************************************************
'' LED Fade calculations
'' This routine takes the fade in/out durations and also the min/max
'' LED power values and calculates what the duration is between
'' changing the PWM value to give us a smooth fade from min to max
';*******************************************************************************
Vb_5 = ((b_fade_in.highbyte * 60) + b_fade_in.lowbyte) *60 'Get total duration time in seconds
Vb_6 = B_Max - B_Min 'Work out the 'distance' the lights go from min to max
B_Fadein_Time = Vb_5 / Vb_6 'Get number of seconds between each PWM change
Vb_7 = Vb_5 // Vb_6 'Get fractions of a second
if Vb_7 >=5 then B_Fadein_Time = B_Fadein_Time + 1 'If its over half a second then round up
Vb_5 = ((B_Fade_Out.highbyte * 60) + B_Fade_Out.lowbyte) *60
B_Fadeout_Time = Vb_5 / Vb_6
Vb_7 = Vb_5 // Vb_6 'Get fractions of a second
if Vb_7 >=5 then B_Fadeout_Time = B_Fadeout_Time + 1 'If its over half a second then round up
Vw_5 = ((W_Fade_In.highbyte * 60) + W_Fade_In.lowbyte) *60
Vw_6 = W_Max - W_Min
W_Fadein_Time = Vw_5 / Vw_6
Vw_7 = Vw_5 // Vw_6 'Get fractions of a second
if Vw_7 >=5 then W_Fadein_Time = W_Fadein_Time + 1 'If its over half a second then round up
Vw_5 = ((W_Fade_Out.highbyte * 60) + W_Fade_Out.lowbyte) *60
W_Fadeout_Time = Vw_5 / Vw_6
Vw_7 = Vw_5 // Vw_6 'Get fractions of a second
if Vw_7 >=5 then W_Fadeout_Time = W_Fadeout_Time + 1 'If its over half a second then round up
return
'Lets say 2 hours (120 mins) & 191 for the fade amount (ie 0 to 255 or 0% to 100% intensity)
'So we need to do:
' convert hours into minutes, then add minutes and then multiply by 60 to convert to seconds
' so: 2 hours = 120 mins + 0 mins * 60 to get 7200 seconds
' The distance is now based on the converted % into the PWM range of 0-255
' calculate the 'distance' the light goes from min to max (0 to 255 in this eg: 75% = 191 so: 191- 0 = 191)
' now divide total seconds by 'distance' ie: 7200 / 191 = 37.69 seconds between each PWM change
' Now we test the milliseconds and if above .5 we round up to the next second
;*******************************************************************************
' Read Eeprom data into variables
;*******************************************************************************
Read_eeprom:
read 0,W_Dawn_On_H 'Whites ON time hours
read 1,W_Dawn_On_M 'Whites ON time minutes
Read 2,W_Day_On_H
Read 3,W_Day_On_M
read 4,W_Dusk_On_H
Read 5,W_Dusk_On_M
Read 6,W_Off_H
Read 7,W_Off_M
Read 8,W_Min
Read 9,W_Max
read 10,B_Dawn_On_H 'Whites ON time hours
read 11,B_Dawn_On_M 'Whites ON time minutes
Read 12,B_Day_On_H
Read 13,B_Day_On_M
read 14,B_Dusk_On_H
Read 15,B_Dusk_On_M
Read 16,B_Off_H
Read 17,B_Off_M
Read 18,B_Min
Read 19,B_Max
read 20,B_On_H
Read 21,B_On_M
read 22,W_On_H
Read 23,W_On_M
read 24,w_fade_in.highbyte 'Whites fade IN duration hours
read 25,w_fade_in.lowbyte 'Whites fade IN duration minutes
read 26,b_fade_out.highbyte 'Whites fade IN duration hours
read 27,b_fade_out.lowbyte 'Whites fade IN duration minutes
W_Min = (W_Min *255)/100 'Convert intensity % to real PWM value (from 0-100% to 0-255)
W_Max = (W_Max *255)/100
B_Min = (B_Min *255)/100
B_Max = (B_Max *255)/100
gosub Read_Clock_2
return
;*******************************************************************************
MyTimer:
Tick_Tmr = Tick_Tmr + 1
'pause 100
if Tick_Tmr >179 then
Tick_Tmr = 0
B_Cnt = B_Cnt + 1
W_Cnt = W_Cnt + 1
endif
@ INT_RETURN
;*******************************************************************************
'**** Ds1307 RTC Clock ****
;*******************************************************************************
Read_Clock_2:
I2CRead SDApin,SCLpin,$D0,$00,[RTC_Secs,rtc_mins,rtc_hours,RTC_Ctrl] ; read DS1307 chip
If RTC_Hours.6=1 then
CounterA=(RTC_Hours>>4)&$01 ' Work-Out 12 or 24 hour Display for Hours
else
CounterA=(RTC_Hours>>4)&$03
endif
CounterA=CounterA*10+(RTC_Hours&$0F) ' Display Hours appropriately for 12 or 24 hour Mode
If RTC_Hours.6=1 then
LCDOut $FE,$D4,#CounterA
else
LCDOut $FE,$D4,#CounterA Dig 1,#CounterA Dig 0
endif
LCDOut ":",#(RTC_Mins>>4)&$0F,#RTC_Mins&$0F
TimeH=(RTC_Hours>>4) 'convert the BCD format of the hours register and store in variable timeH
TimeH=(TimeH &$03)*10
TimeH=TimeH+(RTC_Hours&$0F)
TimeM=(RTC_Mins>>4)
TimeM=(TimeM &$07)*10
TimeM=TimeM+(RTC_Mins&$0F) 'convert the BCD format of the mins register and store in variable timeM
Return
Bookmarks