INIT:
counter = 0 'increases each PID period (1 second)
counter2 = 0 'counter for profile selection and setpoint updates
cracks = 0 'counter for 1st and 2nd cracks
roastlevel = 0 'adjustment for roast end temp
pwmout 3, 255, 1023 'set fan to full for a while to get going
pause 200 'pause to give fan time to start
do 'LOOP FOR PROFILE SELECTION
if input_button1 = 1 then 'Waits in this loop until button1 is pressed
do
loop while input_button1 = 1 'debounce
pause 200
exit
endif
if input_button2 = 1 then 'increase counter2 if button2 is pressed
inc counter2
pause 200
if counter2 > 2 then 'reset counter2 if > 2
counter2 = 0
endif
endif
if counter2 = 0 then 'show which profile is selected
high manual_led
low ssr_led
elseif counter2 = 1 then
low manual_led
high ssr_led
else
high manual_led
high ssr_led
endif
readadc10 manual_val, fanspeed 'read value for fan speed
if fanspeed < 350 then
fanspeed = 0
endif
pwmout 3, 255, fanspeed 'set manual fan speed. Fan will go to auto when roasting starts
loop
low manual_led
do 'LOOP FOR PROFILE CUTOFF TEMP ADJUSTMENT
if input_button1 = 1 then 'Waits in this loop until button1 is pressed. Then starts roast
do
loop while input_button1 = 1 'debounce
pause 200
exit
endif
if input_button2 = 1 then 'increase counter2 if button2 is pressed
do
loop while input_button2 = 1 'debounce
pause 200
inc roastlevel
if roastlevel > 5 then 'reset roastlevel if > 5 ie max 5 degrees adjustment
roastlevel = 0
endif
if roastlevel <> 0 then
for z = 1 to roastlevel
pause 200
high manual_led
pause 200
low manual_led
next z
endif
endif
loop
if counter2 = 0 then 'adjust cutoff temp
if manual_switch = 0 then 'having manual_switch down will give negative adjustment
roastlevel = profile1cutoff + roastlevel
else
roastlevel = profile1cutoff - roastlevel
endif
elseif counter2 = 1 then
if manual_switch = 0 then
roastlevel = profile2cutoff + roastlevel
else
roastlevel = profile2cutoff - roastlevel
endif
elseif counter2 = 2 then
if manual_switch = 0 then
roastlevel = profile3cutoff + roastlevel
else
roastlevel = profile3cutoff - roastlevel
endif
endif
roastlevel = roastlevel + 1 'will cut off roast when setpoint reaches roast level + 1. ie. temp gets to previous setpoint
if manual_switch = 1 then 'manual_switch must be returned to off otherwise manual instead of PID
for z = 1 to 20 'gives warning if manual_switch is on. Time to switch it off if desired
high manual_led
pause 200
low manual_led
high ssr_led
pause 200
low ssr_led
next z
endif
sertxd("Roast Temp Cutoff = ",#roastlevel)
'end
if counter2 = 0 then 'Send selected profile
sertxd ("Profile 1",13,10)
counter2 = 0 'set eeprom location for start of profile 1 storage
elseif counter2 = 1 then
counter2 = 85 'set eeprom location for start of profile 2 storage
sertxd ("Profile 2",13,10)
else
counter2 = 170 'set eeprom location for start of profile 3 storage
sertxd ("Profile 3",13,10)
endif
sertxd ("Time Setpoint Temp PID FanSpeed Cracks",13,10) 'Send column headings
poke INT_lsb, 0
poke INT_msb, 128 'set initial pid value to 32768. i.e. false zero
pwmout 3, 255, 1023 'set fan to full for a while to get going
pause 200 'pause to give fan time to start
'#########################################################################################
MAIN:
if manual_switch = 1 then 'Manual temp control
high manual_led
gosub GETMANUALVAL
gosub GETTEMP
gosub SETFANSPEEDHEATING
sertxd ("- - ",#t, " ", #PID, " ", #fanspeed, #13,10)
else 'Or PID Control
low manual_led
z = counter // 15
if z = 0 then 'Every 15 seconds update setpoint
read counter2, sp
inc counter2
endif
if sp = 0 or sp = roastlevel then 'At end of profile send completed message
sertxd ("Roast Profile Completed",13,10)
gosub COOLBEANS
end 'END PROGRAM after cooling
endif
if input_button2 = 1 then 'Send terminated message if button2 is pressed during roast
sertxd ("Roast Terminated",13,10)
gosub COOLBEANS
end 'END PROGRAM after cooling
endif
gosub DOPID 'RUN PID ROUTINE
gosub SETFANSPEEDHEATING 'changes fan speed based on current temp
sertxd (#counter," ",#sp," ",#t," ",#PID, " ", #fanspeed) 'Send serial data
if input_button1 = 1 then 'Add to serial data if button1 is pressed during roast
high manual_led
if cracks = 0 then
sertxd (" FirstCrack")
elseif cracks = 1 then
sertxd (" SecondCrack")
else
sertxd (" Crack")
endif
inc cracks
endif
sertxd (13,10) 'Add carriage return and line feed to serial data
inc counter 'Increase loop counter
endif
for z = 1 to 100 'Manual PWM with 1 second period (adjust pause at end of main routine to get 1 sec period)
if z > PID then
low ssr
low ssr_led
else
high ssr
high ssr_led
endif
pause 6
next z
high ssr 'Keep output high while doing PID calcs
high ssr_led
pause 45 'Adjust to get timing right on PID mode (1 sec PWM period)
goto main
'#########################################################################################
DOPID: 'PID CALCULATIONS
gosub GETTEMP 'Get temp reading from thermocouple
peek INT_lsb, b4 'read old int value into PID w2 (PID)
peek INT_msb, b5
if PID > 49000 then
PID = 49000
else
PID = PID
endif
if t <= sp then 'for negative errors
b0 = sp - t max 65 'error
w3 = Ki * b0 * dt max INT_MAX 'INTEGRAL..........................
PID = PID + w3 max PID_MAX 'Add new int value to previous int value
poke INT_lsb, b4 'store new int value w2
poke INT_msb, b5
w3 = Kp * b0 max PRO_MAX 'PROPORTIONAL......................
PID = PID + w3 max PID_MAX 'Int + Pro
else 'for positive errors
b0 = t - sp max 65 'error
w3 = Ki * b0 * dt max INT_MAX 'INTEGRAL.........................
PID = PID - w3 min PID_MIN 'subtract new int value to previous int value
poke INT_lsb, b4 'store new int value w2
poke INT_msb, b5
w3 = Kp * b0 max PRO_MAX 'PROPORTIONAL....................
PID = PID - w3 min PID_MIN 'Int + Pro
endif
poke PRO_lsb, b6 'store pro value w3
poke PRO_msb, b7
'goto SKIPDER
peek pt, b0
if t > b0 then 'temp increasing
w3 = t - b0
w3 = w3 * Kd max DER_MAX 'DERIVATIVE ......................
PID = PID - w3 min PID_MIN 'int + pro + der
elseif t < b0 then 'temp decreasing
w3 = b0 - t
w3 = w3 * Kd max DER_MAX 'DERIVATIVE ......................
PID = PID + w3 max PID_MAX 'int + pro + der
else
w3 = 0 'no derivative part
endif
poke DER_lsb, b6 'store der value w3
poke DER_msb, b7
poke pt,t 'store current temp as previous temp
SKIPDER:
if PID <= 32678 then
PID = 0
else
PID = PID - 32678 'convert to range 1-20000
PID = PID / 200 'convert to range 1-100
endif
'PID = 100
'peek INT_lsb, b6
'peek INT_msb, b7
'sertxd("INT: ",#w3,13,10)
'peek PRO_lsb, b6
'peek PRO_msb, b7
'sertxd("PRO: ",#w3,13,10)
'peek DER_lsb, b6
'peek DER_msb, b7
'sertxd("DER: ",#w3,13,10)
'sertxd("PID: ",#w2,13,10)
'pause 4000
return
'#########################################################################################
GETTEMP: 'Manual SPI
high cs
low sck
low cs
w3 = 0
for z = 1 to 16
high sck
w3 = w3 * 2 + miso
low sck
next z
high cs
w3 = w3 / 8
t = w3 / 4
'sertxd (#w3, 13, 10)
return
'#########################################################################################
GETMANUALVAL: 'Reads POT instead of thermocouple in manual mode
readadc10 manual_val, PID
'sertxd (#PID,13,10)
PID = PID + 1024
PID = PID / 20 'Convert adc value into the range approx 50 - 100
return
'#########################################################################################
COOLBEANS:
low ssr 'Turn SSR off
low ssr_led
for counter2 = 1 to 240 'About 4 minutes cooling time
high manual_led
pause 250
low manual_led
pause 250
high manual_led
pause 250
low manual_led
pause 250
gosub GETTEMP
sertxd (#t, " ",#counter2 ,13,10)
if t < 40 and counter2 > 60 then 'end cooling if beans are < 40 deg. But minimum 1 min cooling
pwmout 3, 0, 0
low 3
exit
endif
gosub SETFANSPEEDCOOLING
next counter2
if t < 50 then
pwmout 3, 0, 0
low 3
else
goto COOLBEANS
endif
return
'#########################################################################################
SETFANSPEEDHEATING:
fanspeed = sp * fanconstant2 / fanconstant3 'set fan speed based on current setpoint
fanspeed = fanconstant1 - fanspeed * 4 max maxfanspeed
pwmout 3, 255, fanspeed
return
'#########################################################################################
SETFANSPEEDCOOLING:
fanspeed = t * fanconstant5 / fanconstant6 'set fan speed based on current temp
fanspeed = fanconstant4 - fanspeed * 4 max maxfanspeed
pwmout 3, 255, fanspeed
return