We had looked online at temperature controllers but they all seemed to be quite pricey for what they were - a cheap thermistor, a few 4x7 segment displays and a fancy box. Since we've currently got loads of 16x2 character displays and a boxful of PIC microcontrollers knocking about, it made sense (to us at least) to make our own temperature controller with a simple menu system.
We stuck an HD44780 character display onto a breadboard with a massive old PIC16F877A chip that just happened to be lying around. To this we also added the newly acquired temperature module and bundled some firmware onto the chip.
The LED on this breadboard indicates whether or not a relay would be activated, to switch the mains supply to our 300W cartridge heaters. As our target temperature in this example has yet to be met, the heater element is still switched on.
Here's the firmware for our controller. It's pretty basic. The most notable thing about it are the button press routines - we're using just three buttons, up/down/select. But, like an alarm clock, a "short press" will cause the values to increase/decrease by just one at a time, but a "long press" results in the numbers whizzing by in multiples of ten.
Define CONFIG = 0x3f32
Define CLOCK_FREQUENCY = 20
Define STRING_MAX_LENGTH = 30
AllDigital
definitions:
Define LCD_BITS = 4 'no of pins to connect to character LCD
Define LCD_DREG = PORTD '4-pin interface on this port
Define LCD_DBIT = 4 '4-pin interface is on (0=0-3, 4=4-7)
Define LCD_RSREG = PORTD
Define LCD_RSBIT = 2
Define LCD_EREG = PORTD
Define LCD_EBIT = 3
Define LCD_RWREG = PORTD
Define LCD_RWBIT = 1
Define SPI_CS_REG = PORTC
Define SPI_CS_BIT = 1
Define SPI_SCK_REG = PORTC
Define SPI_SCK_BIT = 0
Define SPI_SDI_REG = PORTC
Define SPI_SDI_BIT = 2
Define SPI_SDO_REG = PORTC
Define SPI_SDO_BIT = 3
Define SPICLOCK_STRETCH = 9
Symbol led_pin = PORTA.0
Symbol led_heater = PORTA.1
Symbol heater_relay = PORTA.2
Symbol button_up = PORTB.0
Symbol button_down = PORTB.1
Symbol button_ok = PORTB.2
Symbol spi_sck = PORTC.0
Symbol spi_cs = PORTC.1
Symbol spi_si = PORTC.2
ConfigPin PORTD = Output
ConfigPin PORTB = Input
ConfigPin led_pin = Output
ConfigPin led_heater = Output
ConfigPin heater_relay = Output
ConfigPin spi_sck = Output
ConfigPin spi_cs = Output
ConfigPin spi_si = Input
Dim state As Byte
Dim return_state As Byte
Dim b As Byte
Dim target_temp As Word
Dim current_temp As Word
Dim tmp_temp As Word
Dim overshoot As Word
Dim last_temp As Word
Dim temp_direction As Bit
Dim button_press_count As Byte
initialise:
SPIPrepare 'prepare the software SPI interface
OPTION_REG.7 = 0 'enable pullups on portb (/RBPU)
Lcdinit 0 'no cursor on the lcd display
Low led_heater 'make sure we boot up with the heater off
Low heater_relay 'heater indicator is off
state = 0
overshoot = 0
temp_direction = 0
SPIPrepare
High spi_cs
Low spi_sck
loop:
Select Case state
Case 0 'first boot up
Lcdcmdout LcdClear
Lcdout "Temperature"
Lcdcmdout LcdLine2Home
Lcdout "Controller"
'read the last set temperature value (we'll automatically go back to this)
Read 2, b
target_temp.LB = b
Read 3, b
target_temp.HB = b
If target_temp.LB = 0xff And target_temp.HB = 0xff Then
'we've just read two blank values from eeprom, so choose
'any old default value - why not aim for, say, 100?
target_temp = 100
Endif
'read the last set overshoot value
Read 4, b
overshoot.LB = b
Read 5, b
overshoot.HB = b
If overshoot.LB = 0xff And overshoot.HB = 0xff Then
'we've just read two blank values from eeprom, so choose
'any old default value - why not, say, ten?
overshoot = 10
Endif
'read the last overshoot value from eeprom (this is how many degrees before
'reaching target temp we need to shut off for, to allow for overshooting)
WaitMs 1000
state = 1
Case 1 'show the target and current temperature(s)
Gosub get_current_temp
Lcdcmdout LcdClear
Lcdout "Target temp: "
If target_temp < 100 Then Lcdout " "
If target_temp < 10 Then Lcdout " "
Lcdout #target_temp
Lcdcmdout LcdLine2Home
Lcdout "Actual temp: "
If current_temp < 100 Then Lcdout " "
If current_temp < 10 Then Lcdout " "
Lcdout #current_temp
state = 2
Case 2 'monitor the current temp and the target temp
Gosub get_current_temp
Lcdcmdout LcdLine2Home
If current_temp = 999 Then
'something has gone wrong
Low heater_relay
Low led_heater
Lcdout "**** ERROR! ****"
Else
If current_temp <> last_temp Then
Lcdout "Actual temp: "
If current_temp < 100 Then Lcdout " "
If current_temp < 10 Then Lcdout " "
Lcdout #current_temp
Endif
If last_temp <= current_temp Then
'temperature is rising
temp_direction = 1
Else
'temperature is falling
temp_direction = 0
Endif
If current_temp > target_temp Then
'we're over the target temperature so shut the heaters off
Low heater_relay
Low led_heater
Else
If temp_direction = 1 Then
'while the temperature is rising, we want to keep the heaters on
'until we cross the threshold of (target_temp-overshoot_value)
'and then turn them off and allow the block to continue heating
'even for a very short time
tmp_temp = target_temp - overshoot
If current_temp > tmp_temp Then
'threshold exceeded, turn off the heater(s)
Low led_heater
Low heater_relay
Else
'still not quite there, keep the heaters on
High led_heater
High heater_relay
Endif
Else
'if the temperature is falling, the bottom threshold
'is our target temperature minus the overshoot value; once we
'fall below that, turn the heaters back on
tmp_temp = target_temp - overshoot
If current_temp < tmp_temp Then
'we've cooled down too much, turn the heaters on again
High heater_relay
High led_heater
Else
'we're cooling down, but are still pretty close to the target
'temperature, so allow a little more cooling
Low heater_relay
Low led_heater
Endif
Endif
Endif
last_temp = current_temp
Endif
'now while the temperature is being monitored, check for button presses
'(on a button press, turn off the heater(s) just for good measure, and
'go to a new state just for handling changing the settings
If button_up = 0 Or button_down = 0 Or button_ok = 0 Then
Low heater_relay
Low led_heater
WaitMs 50
While button_up = 0 Or button_down = 0 Or button_ok = 0
'wait for the button to be released
WaitMs 50
Wend
state = 3
Endif
WaitMs 1000
Case 3 'press buttons to change menu option
Lcdcmdout LcdClear
Lcdout "> Change target"
Lcdcmdout LcdLine2Home
Lcdout " Edit overshoot"
state = 4
Case 4
If button_up = 0 Or button_down = 0 Then
WaitMs 50
While button_up = 0 Or button_down = 0
'wait for the button to be released
WaitMs 50
Wend
state = 5
Endif
If button_ok = 0 Then
'debounce the button press
WaitMs 50
While button_ok = 0
WaitMs 50
Wend
state = 10
Endif
Case 5 'press buttons to change menu option
Lcdcmdout LcdClear
Lcdout " Change target"
Lcdcmdout LcdLine2Home
Lcdout "> Edit overshoot"
state = 6
Case 6
If button_up = 0 Or button_down = 0 Then
WaitMs 50
While button_up = 0 Or button_down = 0
'wait for the button to be released
WaitMs 50
Wend
state = 3
Endif
If button_ok = 0 Then
'debounce the button press
WaitMs 50
While button_ok = 0
WaitMs 50
Wend
state = 11
Endif
Case 10 'change the target temperature value
Gosub show_target_temp
return_state = 10
state = 12
Case 11 'change the overshoot value
Gosub show_overshoot
return_state = 11
state = 12
Case 12 'button presses to alter target temperature/overshoot value
If button_up = 0 Then
WaitMs 50
button_press_count = 0
While button_up = 0
'wait for the button to be released
button_press_count = button_press_count + 1
WaitMs 100
If button_press_count >= 5 Then
'this is a "long press" so increase the value by 10 every loop
If return_state = 10 Then
target_temp = target_temp + 10
If target_temp > 500 Then target_temp = 500
target_temp = target_temp / 10
target_temp = target_temp * 10
Gosub show_target_temp
Endif
If return_state = 11 Then
overshoot = overshoot + 10
If overshoot > 500 Then overshoot = 500
overshoot = overshoot / 10
overshoot = overshoot * 10
If overshoot >= target_temp Then overshoot = target_temp - 1
Gosub show_overshoot
Endif
WaitMs 200
'stop the counter from rolling over
button_press_count = 5
Endif
Wend
If button_press_count < 5 Then
'this is a "short" press so increase the value by just one
If return_state = 10 Then target_temp = target_temp + 1
If return_state = 11 Then overshoot = overshoot + 1
Endif
If target_temp > 500 Then target_temp = 500
If overshoot > 500 Then overshoot = 500
If overshoot >= target_temp Then overshoot = target_temp - 1
state = return_state
Endif
If button_down = 0 Then
WaitMs 50
button_press_count = 0
While button_down = 0
'wait for the button to be released
button_press_count = button_press_count + 1
WaitMs 100
If button_press_count >= 5 Then
'this is a "long press" so decrease the value by 10 every loop
If return_state = 10 Then
b = target_temp Mod 10
If b = 0 Then
If target_temp > 10 Then target_temp = target_temp - 10 Else target_temp = 0
Else
target_temp = target_temp / 10
target_temp = target_temp * 10
Endif
Gosub show_target_temp
Endif
If return_state = 11 Then
b = overshoot Mod 10
If b = 0 Then
If overshoot > 10 Then overshoot = overshoot - 10 Else overshoot = 0
Else
overshoot = overshoot / 10
overshoot = overshoot * 10
Endif
Gosub show_overshoot
Endif
WaitMs 200
'stop the counter from rolling over
button_press_count = 5
Endif
Wend
If button_press_count < 5 Then
'this is a "short" press so increase the value by just one
If return_state = 10 Then
If target_temp > 1 Then target_temp = target_temp - 1 Else target_temp = 0
Endif
If return_state = 11 Then
If overshoot > 1 Then overshoot = overshoot - 1 Else overshoot = 0
Endif
Endif
state = return_state
Endif
If button_ok = 0 Then
WaitMs 50 'simple debounce
While button_ok = 0
'wait for button to be released
Wend
If return_state = 10 Then
'write the new target temp to eeprom
b = target_temp.LB
Write 2, b
b = target_temp.HB
Write 3, b
Else
'write the new overshoot value to eeprom
b = overshoot.LB
Write 4, b
b = overshoot.HB
Write 5, b
Endif
state = 1
Endif
EndSelect
Goto loop
End
get_current_temp:
'read the value from the thermistor
'in some libraries, they suggest performing a "dummy read"
'to force the device to re-sample the temperature
Low spi_cs
WaitMs 2
High spi_cs
WaitMs 220
'the device should now have a new temperature in it's buffer
'enable CS so we can read data back from the device
SPICSOn
'give the device time to settle
WaitMs 50
'get the data as two bytes
SPIReceive b
current_temp.HB = b
SPIReceive b
current_temp.LB = b
SPICSOff
'now according to the datasheet, bit 15 is a dummy, bits 0-2 are status
'so the actual temperature we need is in bits 14-3
b = current_temp.LB
b = b And 00000100b
If b > 0 Then
'bit 2 is normally low, and goes high when the thermistor is not connected
current_temp = 999
Else
'bit-shift three places to the right
current_temp = ShiftRight(current_temp, 3)
'and mask out to get only the lower 12 bits
current_temp = current_temp And 0x0fff
Endif
If current_temp = 0 Or current_temp = 0x0fff Then
'something has gone wrong here
current_temp = 999
Else
'the temperature reported has a resolution of 0.25 deg C
'so we need to divide our final answer by 4 (or multiply by 0.25)
'to get the actual temperature in degrees
current_temp = current_temp / 4
Endif
Return
show_target_temp:
Lcdcmdout LcdClear
Lcdout "Target temp: "
If target_temp < 100 Then Lcdout " "
If target_temp < 10 Then Lcdout " "
Lcdout #target_temp
Return
show_overshoot:
Lcdcmdout LcdClear
Lcdout "Overshoot: "
If target_temp < 100 Then Lcdout " "
If target_temp < 10 Then Lcdout " "
Lcdout #overshoot
Return
Define CLOCK_FREQUENCY = 20
Define STRING_MAX_LENGTH = 30
AllDigital
definitions:
Define LCD_BITS = 4 'no of pins to connect to character LCD
Define LCD_DREG = PORTD '4-pin interface on this port
Define LCD_DBIT = 4 '4-pin interface is on (0=0-3, 4=4-7)
Define LCD_RSREG = PORTD
Define LCD_RSBIT = 2
Define LCD_EREG = PORTD
Define LCD_EBIT = 3
Define LCD_RWREG = PORTD
Define LCD_RWBIT = 1
Define SPI_CS_REG = PORTC
Define SPI_CS_BIT = 1
Define SPI_SCK_REG = PORTC
Define SPI_SCK_BIT = 0
Define SPI_SDI_REG = PORTC
Define SPI_SDI_BIT = 2
Define SPI_SDO_REG = PORTC
Define SPI_SDO_BIT = 3
Define SPICLOCK_STRETCH = 9
Symbol led_pin = PORTA.0
Symbol led_heater = PORTA.1
Symbol heater_relay = PORTA.2
Symbol button_up = PORTB.0
Symbol button_down = PORTB.1
Symbol button_ok = PORTB.2
Symbol spi_sck = PORTC.0
Symbol spi_cs = PORTC.1
Symbol spi_si = PORTC.2
ConfigPin PORTD = Output
ConfigPin PORTB = Input
ConfigPin led_pin = Output
ConfigPin led_heater = Output
ConfigPin heater_relay = Output
ConfigPin spi_sck = Output
ConfigPin spi_cs = Output
ConfigPin spi_si = Input
Dim state As Byte
Dim return_state As Byte
Dim b As Byte
Dim target_temp As Word
Dim current_temp As Word
Dim tmp_temp As Word
Dim overshoot As Word
Dim last_temp As Word
Dim temp_direction As Bit
Dim button_press_count As Byte
initialise:
SPIPrepare 'prepare the software SPI interface
OPTION_REG.7 = 0 'enable pullups on portb (/RBPU)
Lcdinit 0 'no cursor on the lcd display
Low led_heater 'make sure we boot up with the heater off
Low heater_relay 'heater indicator is off
state = 0
overshoot = 0
temp_direction = 0
SPIPrepare
High spi_cs
Low spi_sck
loop:
Select Case state
Case 0 'first boot up
Lcdcmdout LcdClear
Lcdout "Temperature"
Lcdcmdout LcdLine2Home
Lcdout "Controller"
'read the last set temperature value (we'll automatically go back to this)
Read 2, b
target_temp.LB = b
Read 3, b
target_temp.HB = b
If target_temp.LB = 0xff And target_temp.HB = 0xff Then
'we've just read two blank values from eeprom, so choose
'any old default value - why not aim for, say, 100?
target_temp = 100
Endif
'read the last set overshoot value
Read 4, b
overshoot.LB = b
Read 5, b
overshoot.HB = b
If overshoot.LB = 0xff And overshoot.HB = 0xff Then
'we've just read two blank values from eeprom, so choose
'any old default value - why not, say, ten?
overshoot = 10
Endif
'read the last overshoot value from eeprom (this is how many degrees before
'reaching target temp we need to shut off for, to allow for overshooting)
WaitMs 1000
state = 1
Case 1 'show the target and current temperature(s)
Gosub get_current_temp
Lcdcmdout LcdClear
Lcdout "Target temp: "
If target_temp < 100 Then Lcdout " "
If target_temp < 10 Then Lcdout " "
Lcdout #target_temp
Lcdcmdout LcdLine2Home
Lcdout "Actual temp: "
If current_temp < 100 Then Lcdout " "
If current_temp < 10 Then Lcdout " "
Lcdout #current_temp
state = 2
Case 2 'monitor the current temp and the target temp
Gosub get_current_temp
Lcdcmdout LcdLine2Home
If current_temp = 999 Then
'something has gone wrong
Low heater_relay
Low led_heater
Lcdout "**** ERROR! ****"
Else
If current_temp <> last_temp Then
Lcdout "Actual temp: "
If current_temp < 100 Then Lcdout " "
If current_temp < 10 Then Lcdout " "
Lcdout #current_temp
Endif
If last_temp <= current_temp Then
'temperature is rising
temp_direction = 1
Else
'temperature is falling
temp_direction = 0
Endif
If current_temp > target_temp Then
'we're over the target temperature so shut the heaters off
Low heater_relay
Low led_heater
Else
If temp_direction = 1 Then
'while the temperature is rising, we want to keep the heaters on
'until we cross the threshold of (target_temp-overshoot_value)
'and then turn them off and allow the block to continue heating
'even for a very short time
tmp_temp = target_temp - overshoot
If current_temp > tmp_temp Then
'threshold exceeded, turn off the heater(s)
Low led_heater
Low heater_relay
Else
'still not quite there, keep the heaters on
High led_heater
High heater_relay
Endif
Else
'if the temperature is falling, the bottom threshold
'is our target temperature minus the overshoot value; once we
'fall below that, turn the heaters back on
tmp_temp = target_temp - overshoot
If current_temp < tmp_temp Then
'we've cooled down too much, turn the heaters on again
High heater_relay
High led_heater
Else
'we're cooling down, but are still pretty close to the target
'temperature, so allow a little more cooling
Low heater_relay
Low led_heater
Endif
Endif
Endif
last_temp = current_temp
Endif
'now while the temperature is being monitored, check for button presses
'(on a button press, turn off the heater(s) just for good measure, and
'go to a new state just for handling changing the settings
If button_up = 0 Or button_down = 0 Or button_ok = 0 Then
Low heater_relay
Low led_heater
WaitMs 50
While button_up = 0 Or button_down = 0 Or button_ok = 0
'wait for the button to be released
WaitMs 50
Wend
state = 3
Endif
WaitMs 1000
Case 3 'press buttons to change menu option
Lcdcmdout LcdClear
Lcdout "> Change target"
Lcdcmdout LcdLine2Home
Lcdout " Edit overshoot"
state = 4
Case 4
If button_up = 0 Or button_down = 0 Then
WaitMs 50
While button_up = 0 Or button_down = 0
'wait for the button to be released
WaitMs 50
Wend
state = 5
Endif
If button_ok = 0 Then
'debounce the button press
WaitMs 50
While button_ok = 0
WaitMs 50
Wend
state = 10
Endif
Case 5 'press buttons to change menu option
Lcdcmdout LcdClear
Lcdout " Change target"
Lcdcmdout LcdLine2Home
Lcdout "> Edit overshoot"
state = 6
Case 6
If button_up = 0 Or button_down = 0 Then
WaitMs 50
While button_up = 0 Or button_down = 0
'wait for the button to be released
WaitMs 50
Wend
state = 3
Endif
If button_ok = 0 Then
'debounce the button press
WaitMs 50
While button_ok = 0
WaitMs 50
Wend
state = 11
Endif
Case 10 'change the target temperature value
Gosub show_target_temp
return_state = 10
state = 12
Case 11 'change the overshoot value
Gosub show_overshoot
return_state = 11
state = 12
Case 12 'button presses to alter target temperature/overshoot value
If button_up = 0 Then
WaitMs 50
button_press_count = 0
While button_up = 0
'wait for the button to be released
button_press_count = button_press_count + 1
WaitMs 100
If button_press_count >= 5 Then
'this is a "long press" so increase the value by 10 every loop
If return_state = 10 Then
target_temp = target_temp + 10
If target_temp > 500 Then target_temp = 500
target_temp = target_temp / 10
target_temp = target_temp * 10
Gosub show_target_temp
Endif
If return_state = 11 Then
overshoot = overshoot + 10
If overshoot > 500 Then overshoot = 500
overshoot = overshoot / 10
overshoot = overshoot * 10
If overshoot >= target_temp Then overshoot = target_temp - 1
Gosub show_overshoot
Endif
WaitMs 200
'stop the counter from rolling over
button_press_count = 5
Endif
Wend
If button_press_count < 5 Then
'this is a "short" press so increase the value by just one
If return_state = 10 Then target_temp = target_temp + 1
If return_state = 11 Then overshoot = overshoot + 1
Endif
If target_temp > 500 Then target_temp = 500
If overshoot > 500 Then overshoot = 500
If overshoot >= target_temp Then overshoot = target_temp - 1
state = return_state
Endif
If button_down = 0 Then
WaitMs 50
button_press_count = 0
While button_down = 0
'wait for the button to be released
button_press_count = button_press_count + 1
WaitMs 100
If button_press_count >= 5 Then
'this is a "long press" so decrease the value by 10 every loop
If return_state = 10 Then
b = target_temp Mod 10
If b = 0 Then
If target_temp > 10 Then target_temp = target_temp - 10 Else target_temp = 0
Else
target_temp = target_temp / 10
target_temp = target_temp * 10
Endif
Gosub show_target_temp
Endif
If return_state = 11 Then
b = overshoot Mod 10
If b = 0 Then
If overshoot > 10 Then overshoot = overshoot - 10 Else overshoot = 0
Else
overshoot = overshoot / 10
overshoot = overshoot * 10
Endif
Gosub show_overshoot
Endif
WaitMs 200
'stop the counter from rolling over
button_press_count = 5
Endif
Wend
If button_press_count < 5 Then
'this is a "short" press so increase the value by just one
If return_state = 10 Then
If target_temp > 1 Then target_temp = target_temp - 1 Else target_temp = 0
Endif
If return_state = 11 Then
If overshoot > 1 Then overshoot = overshoot - 1 Else overshoot = 0
Endif
Endif
state = return_state
Endif
If button_ok = 0 Then
WaitMs 50 'simple debounce
While button_ok = 0
'wait for button to be released
Wend
If return_state = 10 Then
'write the new target temp to eeprom
b = target_temp.LB
Write 2, b
b = target_temp.HB
Write 3, b
Else
'write the new overshoot value to eeprom
b = overshoot.LB
Write 4, b
b = overshoot.HB
Write 5, b
Endif
state = 1
Endif
EndSelect
Goto loop
End
get_current_temp:
'read the value from the thermistor
'in some libraries, they suggest performing a "dummy read"
'to force the device to re-sample the temperature
Low spi_cs
WaitMs 2
High spi_cs
WaitMs 220
'the device should now have a new temperature in it's buffer
'enable CS so we can read data back from the device
SPICSOn
'give the device time to settle
WaitMs 50
'get the data as two bytes
SPIReceive b
current_temp.HB = b
SPIReceive b
current_temp.LB = b
SPICSOff
'now according to the datasheet, bit 15 is a dummy, bits 0-2 are status
'so the actual temperature we need is in bits 14-3
b = current_temp.LB
b = b And 00000100b
If b > 0 Then
'bit 2 is normally low, and goes high when the thermistor is not connected
current_temp = 999
Else
'bit-shift three places to the right
current_temp = ShiftRight(current_temp, 3)
'and mask out to get only the lower 12 bits
current_temp = current_temp And 0x0fff
Endif
If current_temp = 0 Or current_temp = 0x0fff Then
'something has gone wrong here
current_temp = 999
Else
'the temperature reported has a resolution of 0.25 deg C
'so we need to divide our final answer by 4 (or multiply by 0.25)
'to get the actual temperature in degrees
current_temp = current_temp / 4
Endif
Return
show_target_temp:
Lcdcmdout LcdClear
Lcdout "Target temp: "
If target_temp < 100 Then Lcdout " "
If target_temp < 10 Then Lcdout " "
Lcdout #target_temp
Return
show_overshoot:
Lcdcmdout LcdClear
Lcdout "Overshoot: "
If target_temp < 100 Then Lcdout " "
If target_temp < 10 Then Lcdout " "
Lcdout #overshoot
Return
Our firmware allows the user to press a couple of buttons to change two different parameters:
Firstly, and most obviously, the target temperature to reach. When this is connected up, we're expecting to heat up a block of aluminium. The basic idea is to take a temperature reading and if we're below a certain threshold, turn the heaters on, until the block is "up to temperature"
We also added in another user-defined parameter: something we've called "overshoot".
This is because it's quite possible - as sometimes happens with heated elements like soldering irons for example - that the target temperature is exceeded. By how much can sometimes be predicted, so our variable "overshoot" means that the heaters will cut out a little bit before the ideal temperature has been reached.
So if the temperature of the block continues to rise, even when the heater(s) are turned off, it should - ideally - only reach, and not exceed, the target temperature.
We also use the "overshoot" value for monitoring a falling temperature, to give us a "safe zone" during which the heaters remain inactive. If we simply said "if the temperature is below this threshold, turn on the heaters" it's quite possible that the heaters will come on for a second or two, the temperature could rise by a single degree and the heaters get turned off - a few seconds later, the temperature drops a little, and the heaters are fired up again.
To avoid this "bouncing around" on a single value, our overshoot parameter allows us a "safety zone" of, say, 10 degrees (the user can make this wider or narrower as required). If our target temperature is 180 degrees, and our overshoot value is 10, this means:
When we first switch on, the heaters come on.
The heaters stay on until the temperature has climbed to 170 degrees.
When 170 degrees is exceeded, the heaters are turned off.
The temperature can continue to climb (if it climbs too high - i.e. the target temperature has been overshot by a long way, the user can edit the overshoot parameter to make it a larger value)
Eventually the temperature of the block will start to fall. Even if it falls below 180 degrees, we don't yet switch on the heaters
When the temperature of the block has fallen below 170 degrees (our target value minus the overshoot value) and the temperature is falling, we turn the heaters back on.
By monitoring the "direction" of the temperature (either rising or falling) and by switching the heaters off slightly before the target temperature is reached, we should be able to maintain a fairly stable temperature in our heater block.
During testing, everything appeared to work as it should - immerse the thermistor into a cup of cold water and the temperature fell sharply. At the same time, the heater LED indicator lit up. We set our target temperature quite low (28 degrees) and our overshoot value to just 3 degrees, then held the thermistor in a closed fist.
The temperature continued to rise and at 25 degrees (three degrees before the target temperature) the heater indicator went out. After releasing the probe, the temperature continued to fall to ambient room temperature (and as the temperature fell below 25, the heater indicator once again came on to show that the heaters would normally have been activated).
Next time we're at the space, we should be able to drill and tap a small hole for the thermistor to be embedded into the heater block (hopefully avoiding drilling all the way through to the main chamber) mount a relay in place of/as well as our heater indicator LED, and actually try our temperature controller out for real!
Hi
ReplyDeleteCan I measure temperature for 1300c with this project?