Code:
'*******************************************************************************
'* Name : single chan version
'* Authors : Malcolm Crabbe (inc files from Darrel Taylor
'* Date : 6/2/15
'* Version : 1.00
'* Target : 18F2520 running 20 mhz xtal
'* : single DTH11 sensor
'*
'*******************************************************************************
'*******************************************************************************
' 18F2520 config settings - for use with MPSAM
'*******************************************************************************
ASM
__CONFIG _CONFIG1H, _OSC_HS_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _MCLRE_ON_3H & _LPT1OSC_OFF_3H & _PBADEN_OFF_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM
'*******************************************************************************
' Include files
'*******************************************************************************
DEFINE WRITE_INT 1
INCLUDE "DT_INTS-18.bas" ; Base Interrupt System
INCLUDE "DT18x20.pbp"
INCLUDE "incPID_mc.pbp" ' Include the multi-channel PID routine.
include "ReEnterPBP-18.bas"
'*******************************************************************************
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, HeaterDrive, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
T1CON = %00000001 ; free-running, 1:1 prescaler
@ INT_ENABLE TMR1_INT ; enable Timer1 interrupts
ENABLE DEBUG
;----[DS1820 Options]----Value----Default-----------------------------------
DEFINE DS1820_DECIMALS 1 ' 1
DEFINE DS1820_VERIFYCRC YES ' NO
DEFINE DS18B20_ONLY YES ' NO
' Include DT18x20 module
;----[Analog Settings]------------------------------------------------------ ' set A/D resolution to 14-bits
CMCON = 7 ' disable Comparators
ADCON1 = %00001011 ' sets up Analogue pins
ADCON2.7 = 1 ' ADFM bit isn't in ADCON1 anymore
;----[PID multi-channel]--------------------------------------------------------
PID_Channels CON 1
;----[Port settings]----------------------------------------------------
TRISB = %00000000
;----[Variables/Aliases]----------------------------------------------------
GIE VAR INTCON.7
TempWD VAR WORD ' temporary WORD variable
Bvar VAR BYTE ' temporary BYTE variable
TempStr VAR BYTE[8]
FlashStar VAR BIT
EditChannel VAR BYTE
viv var byte
option var byte
Hours var byte
Minutes var byte
nitetemp var byte
fn var byte
cn var byte
HeaterOut var PORTA.4
StartHour VAR WORD[1]
StartHour1 VAR StartHour[0]
StartMin VAR WORD[1]
StartMin1 VAR StartMin[0]
StopHour VAR WORD[1]
StopHour1 VAR StopHour[0]
StopMin VAR WORD[1]
StopMin1 VAR StopMin[0]
Temperatures VAR WORD[1]
Temp1 VAR Temperatures[0]
spModes VAR BYTE[1] ' controls how set point is adjusted PC or POT
spMode1 VAR spModes[0]
SetPoints VAR WORD[1] ' used to store the desired temperature setting
SetPoint1 VAR SetPoints[0]
normtemp VAR WORD[1] ' used to store the desired temperature setting
normtemp1 VAR normtemp[0]
HeatCycle VAR BYTE BANK0 SYSTEM
HeaterDrives VAR BYTE[1] BANK0 SYSTEM ' outputs to SSR's
HeatDrive1 VAR HeaterDrives[0]
SensorActive VAR BIT[4]
ChannelPWR VAR BIT[4]
Pots VAR WORD[4] ' used to set temp in manual mode
Result VAR WORD ' used to get AD results
ADavg VAR WORD[4] ' Averaging accumulators
Value VAR WORD
Sensor VAR BYTE
CounterA var byte ' General purpose Variable
CounterB var byte ' General purpose Variable
CounterC var byte ' General purpose Variable
CounterD var byte ' General purpose Variable
RTCSec var byte ' Seconds
RTCMin var byte ' Minutes
RTCHour var byte ' Hours
RTCWDay var byte ' Weekday
RTCDay var byte ' Day
RTCMonth var byte ' Months
RTCYear var byte ' Year
RTCCtrl var byte ' Control
SetTime var byte ' 12/24 Hour Clock
SetSec var byte ' Seconds
SetMin var byte ' Minutes
SetHour var byte ' Hours
SetDay var byte ' Day
SetMonth var byte ' Months
SetYear var byte ' Year
TimeOut var word ' Variable for SetUp Menu Time-Out
TimeH var byte ' Variable to store current hour for comparison to drop temp time
TimeM var Byte ' Variable to store current minutes for comparison to drop temp time
ButtonRepeat con 200 ' Timeperiod (in mS for Edit Buttons auto-repeat
' should you want to hold them down...
DecButton var PORTA.0 'Press to Decrement Button
SetButton var PORTA.1 'Press to Set/memorise Button
IncButton var PORTA.2 'Press to Increment Button
OnButton var PORTA.0 'Press to Decrement Button
OffButton var PORTA.2 'Press to Increment Button
H_butt VAR PORTA.2 'hour increase
M_butt VAR PORTA.0 'minutes increase
S_butt VAR PORTA.1 'set / memorise
SCLpin var PORTC.3 'RTC pin - clk
SDApin var PORTC.4 'RTC pin - data
DQ VAR PORTA.5 'One-wire data pin for Ds18B20
;----[EEPROM Data]----------------------------------------------------------
DATA @0,0
EE_spMode1 DATA 0 ' 0=Manual mode, temp is set by Pot.
EE_SetPoint1 DATA WORD 280 ' 28.0 deg. after programming if not in manual mode
EE_pid_Kp1 DATA WORD $0700 ' PID constants
EE_pid_Ki1 DATA WORD $0080
EE_pid_Kd1 DATA WORD $0200
EE_pid_Ti1 DATA 8 ' Update I-term every 8th call to PID
EE_pid_I_Clamp1 DATA 125 ' Clamp I-term to max ±100
EE_pid_Out_Clamp1 DATA WORD 255 ' Clamp the final output to 255
EE_CH1PWR DATA 1 ' this needs to be set to 1 to enable heater channel
;----[Initialization]-------------------------------------------------------
init:
LCDOUT $FE,1:FLAGS=0:PAUSE 250:LCDOUT $FE,1:PAUSE 250 ' Initialize LCD
FOR Bvar = 0 to 3 ; assume all sensors are working
SensorActive(Bvar) = 1
NEXT Bvar
FOR pid_Channel = 0 TO 3 ; Set # of bits in resolution
GOSUB SelectSensor ; for all sensors
GIE = 0 ; disable interrupts before 1-wire
@ DS1820_Resolution 12
GIE = 1 ; enable interrupts after 1-wire
NEXT pid_Channel
LOW HeaterOut ; set heater pins to Output
GOSUB SendPWRstat
normtemp[0] = SetPoints[0]
;____[Main Program Loop]____________________________________________________
Main:
If SetButton=0 then
Gosub SetButtonRelease
goto mainmenu
endif
pid_Channel = 0
GOSUB SelectSensor
GIE = 0 ; disable interrupts before 1-wire
@ DS1820_Convert ; start a temperature conversion
GIE = 1 ; enable interrupts after 1-wire
pid_Channel = 0
GOSUB SelectSensor
DS1820_Error = 0 ; clear any previous errors
DS1820_Flags = 0 ; clear status flags
GIE = 0 ; disable interrupts before 1-wire
@ DS1820_Stat ; check the sensors status
GIE = 1 ; enable interrupts after 1-wire
PAUSEUS 20
IF !DS1820_Done THEN SensorError ; if it's not done by now, error
GIE = 0 ; disable interrupts before 1-wire
@ DS1820_Read ; get the temperature result
GIE = 1 ; enable interrupts after 1-wire
GOSUB Check4Zeros
DS1820_Flags = 0
GIE = 0 ; disable interrupts before 1-wire
@ DS1820_Stat
GIE = 1 ; enable interrupts after 1-wire
IF (DS1820_Error = 0) AND DS1820_Done THEN ; if there were no errors
Temperatures(pid_Channel) = TempC
pid_Error = SetPoints(pid_Channel) - TempC
GOSUB PID
IF pid_Out.15 THEN pid_Out = 0 ; only keep positive values
IF ChannelPWR(pid_Channel) THEN
HeaterDrives(pid_Channel) = pid_Out
ELSE
HeaterDrives(pid_Channel) = 0
ENDIF
GOSUB ShowLCD
ELSE
SensorError:
HeaterDrives(pid_Channel) = 0 ; turn off heater if sensor's bad
SensorActive(pid_Channel) = 0
GOSUB ShowError ; display error message
ENDIF
;----[Flash Star on LCD]-------------------------------------------------------
LCDOUT $FE,$80 + 18,("*"&FlashStar*$FF)|(" "&~(FlashStar*$FF)) ; flash a star to show sample time
FlashStar = !FlashStar
;------------------------------------------------------------------------------
GOTO Main
AllZeros VAR Bit
Check4Zeros:
AllZeros = 1
FOR Bvar = 0 TO 8
IF DS1820_Buffer(Bvar) != 0 THEN AllZeros = 0
NEXT Bvar
IF AllZeros THEN DS1820_CRCfailed = 1
;------------------------------------------------------------------------------
ShowLCD:
LOOKUP pid_Channel,[$80,$C0,$89,$C9],Bvar ; Find location
LCDOUT $FE,Bvar,DEC1 pid_Channel+1,"= " ; print to LCD
TempWD = TempC : GOSUB TempToLCD ; display TempC
LCDOUT $DF ; deg symbol
LCDOut $FE,$D4+8,#setpoints(0)dig 2,#setpoints(0)dig 1,$FE,$D4+11
RETURN
SendPWRstat:
Bvar = 0
Bvar.0 = ChannelPWR(0)
RETURN
;---------------------------------------------------------------------------
SelectSensor:
SELECT CASE pid_Channel
CASE 0 : @ DS1820_Select _TempSensor1 ; Select the DS18x20 pin
END SELECT
RETURN
;----[TMR1 interrupt handler]-----------------------------------------------
ASM
HeaterDrive
incf HeatCycle,F ; HeatCycle
movf _HeatDrive1,W ; HeatDrive1
subwf HeatCycle,w
btfsc STATUS,C
bcf _HeaterOut
btfss STATUS,C
bsf _HeaterOut
INT_RETURN
ENDASM
;----[Display TempWD on LCD]------------------------------------------------
TempToLCD:
IF TempWD.15 THEN LCDOUT "-" ; if negative, display minus sign
TempWD = ABS(TempWD) ; get the positive value
LCDOUT DEC TempWD/DS1820_DIG ; Display the Integer portion
@ if (DS1820_DECIMALS > 0) ; if using decimals
LCDOUT "." ; display decimal point
TempWD = TempWD//DS1820_DIG ; get decimal portion
@ if (DS1820_DECIMALS > 1) ; with DECIMALS=2, next DIG is 1
LCDOUT DEC1 TempWD DIG 1
@ endif
@ if (DS1820_DECIMALS >= 1) ; with DECIMALS=1, next DIG is 0
LCDOUT DEC1 TempWD DIG 0
@ endif
@ endif
RETURN
;----[Display Sensor Error]-------------------------------------------------
ShowError:
LOOKUP pid_Channel,[$83,$C3,$8B,$CB],Bvar ; Find location
LCDOUT $FE,Bvar-1," N/C " ; print to LCD
RETURN
;----[Set Cursor according to Columns]--------------------------------------
GetSetpoint:
LCDOUT $FE,1
Showtemp:
' Subroutine waits until user reseases Set Button
' -----------------------------------------------
SetButtonRelease:
LCDOut $FE,1
While SetButton=0:Wend
Pause 250 ' Small pause to kill any Key-Bounce
Return
JumpStart:
Pause 200 ' Timeout for LCD to settle
' Time & Date Display Loop
' ========================
ReDisplay:
LCDOUT $FE,1:FLAGS=0:PAUSE 250:LCDOUT $FE,1:PAUSE 250 ' Initialize LCD
ReDisplayLoop:
;---------------------------------------------------------
nitetime:
LCDOUT $FE,2
nite:
LCDOUT $FE,2,"Night Time Settings"
lcdout $FE, $C0, "Use + key for Option"
IF Option = 1 THEN lcdout $FE, $D4, "Set Night Temps "
if option = 2 then lcdout $FE, $D4, "Set Start Times "
if option = 3 then lcdout $FE, $D4, "Set Stop Times "
if option = 4 then lcdout $FE, $D4, "Return To Menu "
pause 150
IF !H_butt THEN Option = option + 1
if option >4 then option = 0
If option = 1 Then
If S_butt = 0 Then
LCDOUT $FE,1
pause 100
fn=0
goto nitedrop
endif
endif
If option = 2 Then
If S_butt = 0 Then
LCDOUT $FE,1
pause 100
goto starttime
endif
endif
If option = 3 Then
If S_butt = 0 Then
LCDOUT $FE,1
pause 100
goto stoptime
endif
endif
If option = 4 Then
If S_butt = 0 Then
LCDOUT $FE,1
pause 100
goto mainmenu
endif
endif
fn = 0
viv = 1
nitetemp = 150
goto nite
;---------------------------------------------------------
starttime:
Lcdout $FE,2
LCDOUT $FE,$80,"Set Start Time For "
IF H_butt = 0 THEN GOSUB IncHours
IF M_butt = 0 THEN GOSUB IncMinutes
StartHour[fn]=Hours
StartMin[fn]=Minutes
if viv >=4 then viv =4
LCDOUT $FE,$C0,"Viv ",#viv
lcdout $FE,$94,#StartHour[fn] DIG 1,#StartHour[fn] DIG 0,":",#StartMin[fn] DIG 1,#StartMin[fn] DIG 0
pause 200
If S_butt = 0 then
pause 250
fn = fn +1
viv = viv+1
hours = 0
minutes = 0
endif
If fn > 3 then
LCDOUT $FE,1
goto nite
endif
goto starttime
;---------------------------------------------------------
stoptime:
Lcdout $FE,2
LCDOUT $FE,$80,"Set Stop Time For "
IF H_butt = 0 THEN GOSUB IncHours
IF M_butt = 0 THEN GOSUB IncMinutes
StopHour[fn] = Hours
StopMin[fn] = Minutes
if viv >=4 then viv =4
LCDOUT $FE,$C0,"Viv ",#viv
lcdout $FE,$94,#StopHour[fn] DIG 1,#StopHour[fn] DIG 0,":",#StopMin[fn] DIG 1,#StopMin[fn] DIG 0
pause 200
If !S_butt then
pause 250
fn = fn +1
viv = viv +1
hours = 0
minutes = 0
endif
If fn > 3 then
LCDOUT $FE,1
goto nite
endif
goto stoptime
;---------------------------------------------------------
nitedrop:
;---------------------------------------------------------
inctemp:
nitetemp = nitetemp + 10
IF nitetemp = 300 THEN nitetemp = 150
pause 250
return
;---------------------------------------------------------
IncHours:
Hours = Hours + 1
IF Hours = 24 THEN Hours = 0
pause 250
RETURN
IncMinutes:
Minutes = Minutes + 1
IF Minutes = 60 THEN Minutes = 0
pause 250
RETURN
;---------------------------------------------------------
mainmenu:
LCDOUT $FE,2,"Main Menu"
lcdout $FE, $C0, "Select Option"
IF Option = 1 THEN lcdout $FE, $D4, "Set Time and Date "
if option = 2 then lcdout $FE, $D4, "Set Night Period "
if option = 3 then lcdout $FE, $D4, "Set Normal Temps "
if option = 4 then lcdout $FE, $D4, "Set Lighting Period"
if option = 5 then lcdout $FE, $D4, "Run "
IF !H_butt THEN Option = option + 1
pause 150
if option >5 then option = 0
'If option = 1 Then
'If S_butt = 0 Then
'LCDOUT $FE,1
'Gosub SetButtonRelease
'goto setup
'endif
'endif
If option = 2 Then
If S_butt = 0 Then
LCDOUT $FE,1
Gosub SetButtonRelease
goto nitetime
endif
endif
If option = 3 Then
If S_butt = 0 Then
LCDOUT $FE,1
Gosub SetButtonRelease
goto GetSetpoint
endif
endif
'If option = 4 Then
'If S_butt = 0 Then
'LCDOUT $FE,1
'Gosub SetButtonRelease
'goto lighting
'endif
'endif
If option = 5 Then
If S_butt = 0 Then
LCDOUT $FE,1
Gosub SetButtonRelease
goto main
endif
endif
fn = 0
viv = 1
nitetemp = 150
Goto mainmenu
Bookmarks