Introduction: Precision Temperature Controller

About: Professional work in various electrical and mechanical fields, obscure sense of humour and typically willing to help... Currently under contract designing environmental monitoring equipment.

A problem of precision temperature control was presented. What was needed was an inexpensive yet accurate system to measure and control the temperature of a home built plastic injection molding machine. I have also used this for controlling the temperature on a plastic vacuum forming machine.

The solution of a commercially available microcontroller based control system seemed to be the ideal but sadly were way out of my price range.

The temperature controller shown here cost less than $25 CANADIAN dollars to implement.

Step 1: Which Controller to Use


Having had some experience with Cypress Semiconductors I chose one of their products.

Cypress has lots of features and great tools... Check them out!!!

Step 2: You Will Need

Parts List:

1 - CY8C27433 microcontroller

1 – NAIS JTN1AS-PA-F-DC5V Relay

1 – MCS SD1024A52S  or similar oven probe

1 – EDT EW16200GLY 16X2 LCD

1 – 1KOhm resistor

4 – 10KOhm resistors

1 – 5KOhm POT

7 - TL1105SPF160 switches

1 – 30A 300V fuse

1 – MWEX58-2HB5 heater cartridge

1 – Curtis PA266/5/4 terminal block

1 – MODE 2.1mm DC power jack

1 – 5Vdc power adapter
1 - small perf board for switches
1 - small 2 sided solder breadboard

Step 3: The Circuit


The PSOC controllers require very little in the way of external components.

I wanted to be able to switch between temperature scales as well as have an visual indication of the temperature.

The user can set the temperature from 0 to 500 degrees C, Change from C to F as well as manually start and stop the heating cycle.

The document CircuitDiagram is a word version of the picture shown below

Step 4: The Probe

Recently I discovered that my self cleaning oven has a temperature probe that is capable of handling high enough temperatures which would melt plastics effectively.

I acquired a spare 2 lead oven probe from an appliance repair shop and set out to discover its characteristics using a Fluke temperature sensing meter and a DMM.

At 0 degrees C the probe has a resistance of 1000 Ohms. This seemed to be a good base line to build on. I noted the resistance of the probe at 10 degree C intervals up to 400 Degrees C, using the self clean feature of my oven. Graphing the results in MS Excel clearly showed that the resistance of the probe increased at a linear rate as temperature increased. Since I was not concerned with values below 0 Degrees C this probe proved to be an ideal choice.

I connected one lead of the probe to ground and the other lead to an ADC input on the microcontroller. I then connected one lead of a 1KOhm resistor to 5V and the other to the same input pin. This set up a reference for the probe.
The final fine tuning for this particular probe is handled in the system programming. Changing the probe will result in an needed programming change. Using a 1KOhm POT instead of the fixed value resistor would facilitate a probe change without having to reprogram the system. The POT would be used to calibrate the reference to a known temperature value.

Step 5: The Control Box and Physical Circuit


The box itself is a standard enclosure that was hand drilled and filed to fit the display, keys and ports.

The control box consists of a 16X2 LCD, 6 user keys (from an old fax machine), 2 analog ports and a 5V external power port. The LCD is a standard 16X2 display of the type supported by the PSoC designer user module connected to Port 2, this particular one is an Emerging Display ED16200GLY. The analog ports are connected to Port 0 and are for the 2 wire probe connection and for the relay coil connection. The 6 keys are attached to Port 1 of the microcontroller and facilitate for user input. In descending order starting with P7 are: Up, Down, Clear, Start, Stop, C/F.

The oven probe is connected to Port 1/7 which is the input to the PGA PSoC block which is in turn the input 12-bit incremental ADC PSoC block. The PGA is set to a gain of 1 with a reference to AGND. The Ref Mux is set to (Vdd/2) ± (Vdd/2) to allow for a full 5V rail to Rail Swing. The reference resistor for the probe is internal to the control box and the 2 probe leads are connected to the lead port on the control box using screw terminals.

The analog output on Port 1/6 comes from a 9-bit voltage output DAC. The DAC is set for Offset Binary data format. The program uses a blind write command to initialize the DAC with a 0 output which sets the output voltage to effectively 0V. At the appropriate the time as determined by user input and the program the DAC will be blind written to with 510 which will set the output voltage to effectively 5V. This 5V state is used to energize a coil in a relay which is the switch to turn a heating element on or off as needed.



Step 6: The Program

The files here are a text version of the C program along wiht the complete Cypress Designer file in zip format.

Its not terribly long...


//----------------------------------------------------------------------------
// C program for PSOC temperature controller
//----------------------------------------------------------------------------

#include <m8c.h> // part specific constants and macros
#include "PSoCAPI.h" // PSoC API definitions for all User Modules
#include "stdlib.h"


int MAXC=0;
int TEMPC=500;
char degC[]="500";
char degF[]="932";
int TEMPF=932;



void main()
{
int w,z;
int KeyRead,KeyBuffer;
int x,buffer;
float temperature=0;
float temperature2=0;
int count=0;
int stop=1;
int CycleBuffer;
int base=1;
int InputADC;
int InputADC2;
char lcd_Reading[8];
char lcd_Setting[8];


PGA_1_SetGain(PGA_1_G1_00);
PGA_1_Start(PGA_1_LOWPOWER);
DAC9_1_Start(DAC9_1_FULLPOWER);

LCD_1_Start(); // Initialize LCD
M8C_EnableGInt; // Enable Global Interrupts

AboveTop:
DAC9_1_WriteBlind(0); //set output to 0V
ADCINC12_1_Start(ADCINC12_1_LOWPOWER); // Apply power to the SC Block
ADCINC12_1_GetSamples(0); // Have ADC run continuously
LCD_1_Control(LCD_1_DISP_CLEAR_HOME);
LCD_1_Position(0,0);
LCD_1_PrCString("MAX Limit");

LCD_1_Position(0,10);
if (base==0)
{
MAXC=TEMPF;
LCD_1_PrString(degF);
LCD_1_Position(0,14);
LCD_1_PrCString("F");

}else
{
MAXC=TEMPC;
LCD_1_PrString(degC);
LCD_1_Position(0,14);
LCD_1_PrCString("C");

}
for(;;){
Top:

KeyRead=PRT1DR; //read for keypress

while(ADCINC12_1_fIsDataAvailable() == 0); // Loop until value ready
ADCINC12_1_ClearFlag(); // Clear ADC flag

x=ADCINC12_1_iGetData(); // Get ADC result


if (InputADC>=temperature) // Set up autostop and initial condition
{

DAC9_1_WriteBlind(0); //output 0V

}

if (stop==0) // loop for auto restart in start condition
{

if (CycleBuffer<temperature)
{
DAC9_1_WriteBlind(510); //output 5V
}
}


if (x==buffer) // check for valid ADC reading
{


InputADC=(x*0.5208)-12;// correction for probe resistance.
if (base==0)
{
InputADC=(9.0/5.0*InputADC)+32;
}


if (InputADC <= 99) // set up display to increment 10's and 100's to left
{
lcd_Reading[0] = ' ';
w=1;
if (InputADC <=9)
{
lcd_Reading[1]=' ';
w=2;
}
}else w=0;

InputADC2 = abs(InputADC); // absolute value


// convert int into a base 10 null terminated ASCII string
itoa(&lcd_Reading[w], (unsigned int)InputADC2, 10);

if (temperature <= 99) // set up input to read correctly
{
lcd_Setting[0] = ' ';
z=1;
if (temperature <=9)
{
lcd_Setting[1]=' ';
z=2;
}
}else z=0;

temperature2 = abs(temperature);

// converts int into a base 10 null terminated ASCII string
itoa(&lcd_Setting[z], (unsigned int)temperature2, 10);


CycleBuffer=InputADC+2; //Set Restart lower limit
LCD_1_Position(1,0);
LCD_1_PrString(lcd_Reading); // continuous temperature display
LCD_1_Position(1,5);
LCD_1_PrCString("SET->");
LCD_1_Position(1,10);
LCD_1_PrString(lcd_Setting);

// set key repeat function for up down keys only
if (KeyRead!=0x00) //0x03 when programmer attached
{
count++;
if (count>15)
if (KeyRead==0x80||KeyRead==0x40)
goto HERE;
}else count=0;

if (KeyBuffer==KeyRead) // duplicate key ignore
goto Top;

HERE:
//Programmer will add 0X03 to all cases when attached
switch (KeyRead){
case (0x80): // increment temperature
if(count>15)
{temperature=temperature+10;
count=0;
if (temperature >=MAXC)
{goto HIGHlimit;
}
goto Top;
}
KeyBuffer=KeyRead;

if (temperature >=MAXC)
{goto HIGHlimit;
}
goto TempUp;
break;
case (0x40): // decrement temperature
if(count>15)
{temperature=temperature-10;
count=0;
if (temperature <=0)
{goto LOWlimit;
}
goto Top;
}
KeyBuffer=KeyRead;

if (temperature <=0)
{goto LOWlimit;
}
goto TempDown;
break;
case (0x20): // clear
KeyBuffer=KeyRead;
goto Clear;
break;
case (0X10): //start
KeyBuffer=KeyRead;
goto Start;
break;
case (0x08): //stop
KeyBuffer=KeyRead;
goto Stop;
break;
case (0x04): //base change
KeyBuffer=KeyRead;
if (base==1)
{ //Change to F
base=0;
goto Base;
}
if (base==0)
{ //Change to C
base=1;
}

goto Base;
break;
default:
KeyBuffer=KeyRead;
break;
}


}

buffer=x; // ADC validation buffer

goto Top;
TempUp:
temperature++; // increment setting
goto Top;
TempDown:
temperature--; // decrement setting
goto Top;
Clear:
temperature=0;
count =0;
LCD_1_Position(1,10);
LCD_1_PrString(lcd_Setting);
goto AboveTop;
Stop:
LCD_1_Control(LCD_1_DISP_CLEAR_HOME);

LCD_1_Position(0,0);
LCD_1_PrCString("STOPPED at");
LCD_1_PrString(lcd_Reading);

DAC9_1_WriteBlind(0);
stop=1;
if (base==0)
{
MAXC=TEMPF;
LCD_1_Position(0,15);
LCD_1_PrCString("F");

}else
{
MAXC=TEMPC;
LCD_1_Position(0,15);
LCD_1_PrCString("C");

}
goto Top;
Start:

LCD_1_Control(LCD_1_DISP_CLEAR_HOME);

LCD_1_Position(0,0);
LCD_1_PrCString("HEATING to ");
LCD_1_PrString(lcd_Setting);

if (InputADC<=temperature)
{

DAC9_1_WriteBlind(510);
}else
{
DAC9_1_WriteBlind(0);

}

stop=0;
if (base==0)
{
MAXC=TEMPF;
LCD_1_Position(0,15);
LCD_1_PrCString("F");

}else
{
MAXC=TEMPC;
LCD_1_Position(0,15);
LCD_1_PrCString("C");

}
goto Top;
LOWlimit:
temperature=0;
goto Top;
HIGHlimit:
temperature=MAXC;
goto Top;
Base:

if (base==1)//Degrees F to Degrees C
{
if (temperature!=0)
{
temperature2=temperature;
temperature=(5.0/9.0*(temperature2-32)); // convert F to C
}
goto BaseBottom;
}else

if (temperature!=0)
{
temperature2=temperature;
temperature=(9.0/5.0*temperature2)+32; // convert C to F
}


BaseBottom:
if (stop==0)
{
goto Top;
}else goto AboveTop;

}

}


Step 7: Operation


The user controls the temperature scale with a push button switch which toggles the system to use and display in either degrees C or degrees F. The Up/Down keys are used to set the desired temperature. Momentary pressing the up or down key results in a 1 degree change while holding the key down will change the setting by 10 degrees continuously for as long as the key is depressed up to a maximum or down to the minimum which is 0 degrees in both cases. The clear key will set the values back to a start up state and send 0V out of the DAC. The Start key will change the display to read “HEATING to “and the chosen setting. On top of sending 5V out to energize the coil of the relay. The program will automatically turn of the relay when the heat gets too high and restart it again when it gets too low. The stop key will change the display to read “STOPPED at” and the last read temperature. In addition to sending 0V to the coil to turn off the heating element.


Not shown here is the separate relay with the OGDEN Mighty Watt 400W 240V heater rod. The probe and the rod attach into the melting chamber of an injection molding machine.

Microcontroller Contest

Participated in the
Microcontroller Contest