SMT Toaster Oven Controller

Document Sample
SMT Toaster Oven Controller Powered By Docstoc
					SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN




                 SMT REFLOW CONTROLLER
                                        for a
FAN FORCED CONVECTION TOASTER OVEN




                                        By
                                   Peter Homann
                             peter.homann@adacel.com




1
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN




2
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN




1.          ABSTRACT .....................................................................................................................................................................5

2.          INTRODUCTION .........................................................................................................................................................6

3.          OPERATION ..................................................................................................................................................................6
     3.1       OVERVIEW.................................................................................................................................................................6
     3.2       SET POINT CONFIGURATION............................................................................................................................6
     3.3       SERIAL DATA OUTPUT..........................................................................................................................................6
4.          CIRCUIT DESCRIPTION ...........................................................................................................................................6
     4.1       MICROPROCESSOR ........................................................................................................................................................6
     4.2       TEMPERATURE MEASUREMENT ....................................................................................................................................7
     4.3       LCD DISPLAY ................................................................................................................................................................7
     4.4       PUSHBUTTON SWITCHES .............................................................................................................................................7
     4.5       ENCODER INPUTS ..........................................................................................................................................................7
     4.6       PIEZO BUZZER ..............................................................................................................................................................7
     4.7       POWER SUPPLY ..............................................................................................................................................................7
     4.8       SERIAL DATA ................................................................................................................................................................8
     4.9       RELAY OUTPUTS ...........................................................................................................................................................8
5.          SOFTWARE DESCRIPTION .....................................................................................................................................8
     5.1    OVERVIEW .....................................................................................................................................................................8
     5.2    INITIALISATION .........................................................................................................................................................8
     5.3    STATE MACHINE ..........................................................................................................................................................8
     5.4    SYSTEM EVENTS ...........................................................................................................................................................9
       5.4.1    Mode Switch .......................................................................................................................................................9
       5.4.2    Start/Stop Switch ............................................................................................................................................9
       5.4.3    High Setpoint .....................................................................................................................................................9
       5.4.4    Low Setpoint .......................................................................................................................................................9
       5.4.5    Temperature Alarm.........................................................................................................................................10
     5.5    IN MODE ACTIONS ....................................................................................................................................................10
     5.6    INTERRUPT ROUTINES ...............................................................................................................................................10
       5.6.1    Encoder interrupt............................................................................................................................................10
       5.6.2    Serial Input ......................................................................................................................................................10
     5.7    DISPLAY UPDATE ........................................................................................................................................................10
     5.8    WATCHDOG TIMER .....................................................................................................................................................10
6.          FRONT PANEL LAYOUT ..........................................................................................................................................11

7.          CIRCUIT DIAGRAM ..................................................................................................................................................12

8.      PCB ARTWORK ..............................................................................................................................................................13
     8.1       COMPOSITE ..................................................................................................................................................................13
     8.2       OVERLAY .....................................................................................................................................................................14
     8.3       TOP LAYER...................................................................................................................................................................15
     8.4       BOTTOM LAYER ...........................................................................................................................................................16



3
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN

9.     SOFTWARE LISTING.....................................................................................................................................................17
     9.1     16F84.H ........................................................................................................................................................................17
     9.2     OVEN.C ........................................................................................................................................................................18




4
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN




1. ABSTRACT




5
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN




2. INTRODUCTION
This project describes a controller for converting a low cost fan-forced convection toaster oven into a
Surface Mount Technology (SMT) reflow oven, capable of providing very good results for a relatively small
outlay. The toaster oven used for the project is an Italian made Delonghi oven. The retail cost of this oven
is approximately A$220.
It is essential to use a fan-forced convection oven so as to get an even temperature during heating
throughout the oven. As built, controller replaces the manual controls on the front panel of the oven,
providing a neat integrated solution.
In addition to controlling the oven temperature, the controller provides a data port used for transmitting
the current oven temperature. This feature allows the temperature profile during reflow to be logged by an
external computer.


3. OPERATION

3.1 OVERVIEW
To use the oven, the circuit boards with their components loaded are placed into the oven. The start/stop
button is pressed and the oven begins heating. Once the high set point is reached, the piezo beeper is
sounded, the heater elements are turned off with the fan continuing to run. At this point the door is opened
to assist the cooling cycle. Once the temperature has dropped below the low set point the piezo beeper is
sounded and the fan is turned off and the board may be removed. The oven is now ready for another reflow
cycle.
Appendix 1 depicts the front panel layout.

3.2 SET POINT CONFIGURATION
From the Idle mode the operator can adjust the high and low set points by entering into the configuratiion
modes via pressing the Mode switch. In the Set high set point mode, the current set point parameter is
displayed on the LCD. By rotating the encoder knob the number will decrease or increase depending on the
rotation direction.
Once the desired value is displayed the mode switch is pressed again. If the displayed value differs from
the current value the new value is stored in eeprom. The mode then cyxles to the next parameter and then
back to Idle mode.

3.3 SERIAL DATA OUTPUT
An external computer can extract temperature data from the Controller. Whenever the controller receives
an ASCII ‘D’ character, it transmits the current temperature. This is similar in operation to many multi-
meters with data interface capability.


4. CIRCUIT DESCRIPTION

4.1 Microprocessor
The microprocessor used for the controller is the Microchip PIC16F84 running at 4MHz. The printed circuit
boards include a reset button in addition to a connecter for in circuit programming.



6
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN


As the I/O pins on the processor chip are limited, many of the pins are used for multiple purposes. That is
for output to one device and input from another. By careful assignment of the pins, maximum use of the pins
was obtained.

4.2 Temperature Measurement
The temperature measurement circuitry is based on the Linear Technologies Application Note 52. The
measurement transducer is a PT100 platinum resistor probe. This transducer has a resistance of 100 ohms
at 0 degrees C. The resistance increases with temperature at a rate of 0.0385 ohms/degree C.
The probe is placed in a standard bridge circuit, which is supplied from a LT1027 5V reference. The output
from the bridge is amplified by a LT1006 amplifier and fed into a single input differential LTC1285 12 bit
A/D. The PIC16F84 processor communicates with the A/D converter via a serial bus through pins RB1, RB6
and RB7. The circuit contains trim pots for offset and gain adjustments.

4.3 LCD Display
The display used is a standard 2line by 8 LCD character module. The module is configured for 4-bit mode so
pins D0 to D3 are unused, as is the R/W pin, as data is not read from the module. D3 to D7 of the module
are driven by pins The display also incorporates a trim pot for adjusting the contrast.

4.4 Pushbutton Switches
The push button switches use the same processor pins used by the LCD, namely RB6 and RB7. To prevent a
switch from interfering with the LCD data during display updates 2 resistors are configured as shown in the
circuit diagram.
When a pin is not being used to output to the LCD, the pin is configured as an input. Therefore, if the
switch is pressed the voltage presented to the pin will be at a logic zero. If the switch is not pressed the
resistors pull the voltage to the supply, presenting a logic 1 to the pin.
When the pin is configured for output during LCD update and a switch is pressed, the switch end of the 10K
resistor is grounded. The processor is capable of pulling the other end of the 10 K resistor to a logic 1
resulting in the switch state having no effect on the data line during output to the LCD.

4.5 Encoder inputs
The encoder is read by the processor via pins RA4 and RB3. Pine RB3 is shared with the LCD register select
line and therefore uses the same circuitry detailed for the push buttons. The reading of the encoder is
interrupt driven and there uses line RA4.

4.6 Piezo Buzzer
The piezo buzzer is driven directly from the CPU via pin RA1.

4.7 Power Supply
The power supply provides two voltages, 12 volts for energising the relays in addition to a 5-volt supply for
logic circuitry. The circuit contains a bridge rectifier, filter capacitors, and two linear regulators. A 7812 is
used for the 12V supply, with the 5V supply provided by a 78L05. The circuit includes a LED for each of the
supplies indicating that it is active.




7
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN


4.8 Serial Data
RS-232 voltages for the serial port are provided by a Dallas DS1275 logic to RS-232 voltage converter. The
chip is designed to work with half duplex communication only. Therefore, the negative voltage for the
transmit line is taken from the receive line while it is in the idle state. In this state the receive line rests at
the negative voltage level supplied by the external computer. Consequently, there are no capacitors or
circuitry need to generate the negative voltage. The positive RS-232 voltage is obtained from the 5V logic
level supply.
The microprocessor uses pin RA0 for transmitting data, and pin RB0 for receiving data. RB0 is used as the
reception of data is read via the interrupt routine. The board contains a stereo 3.5 mm phono jack, in
addition to a connecter for wiring to an off-board connector

4.9 Relay Outputs
The two relays used to control the heater element and the oven fan are controlled by pins RA2 and RA3 via
a transistor switch arrangement including a flyback diode to protect the transistor from current surges
during switch off. The transistor also drives a LED to provide an indication of when the relay is energised.


5. SOFTWARE DESCRIPTION

5.1 Overview
The software is based around a continuous loop structure and interrupt service routines. The basic flow
diagram is depicted below. The software is written in C using the CCS compiler allowing for very rapid
development of the software. Detailed descriptions of the software components may be found in the
software listing attached.
The following paragraphs provide a brief overview of the major software components.

5.2 Initialisation
On start-up the software checks if the reset was caused via the watchdog timer. If this is the case the
software enters a continuous loop emitting an alarm tone, indicating a system failure.
After a normal start-up the software initialises the system including the external devices. The initial
welcome message is displayed and then IDLE mode is entered.

5.3 State Machine
The software implements a finite state-machine for controlling the mode changes with the system. On
system reset the IDLE mode is entered and mode changes are controlled via the system events. Shown
below is the state transition diagram for the system, depicting the states and the system events that cause
the state changes.
The events are prioritized so that only a single event is handled each time through the loop. Each event type
has an event array that defines what permissible mode changes are allowed and what actions are to be
performed as a result of the mode change.




8
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN



                                                Reset
                                                  Con
                                                  nect


                                                                                      Mode Switch




                                                 Idle             Mode Switch     High Setpoint        Mode Switch    Low Setpoint



                                            Start/Stop Switch




                                                 Heat



                    Temperature less                            Temperature greater
                                            Start/Stop Switch
                    than Low Setpoint                            than High Setpoint




                                                                                       Start/Stop Switch
                                                 Cool                                                                Any Mode



                                                                                                               Temperature exceeds
                                            Start/Stop Switch
                                                                                                                   safe limits




                                               Reheat                                                                 Failure




                                        Figure 1 System State Transition Diagram


5.4 System Events

5.4.1 Mode Switch
The mode_switch_event occurs when the Mode button is pressed. It is triggered on the falling edge of the
switch closure.

5.4.2 Start/Stop Switch
The go_switch event occurs when the Start/Stop button is pressed. It is triggered on the falling edge of
the switch closure.

5.4.3 High Setpoint
The hi_temp_event occurs whenever the probe temperature exceeds the high set point value stored in
eeprom.

5.4.4 Low Setpoint
The lo_temp_event occurs whenever the probe temperature falls below the low set point value stored in
eeprom.



9
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN


5.4.5 Temperature Alarm
The temperature_alarm_event occurs whenever the probe temperature falls outside the safe limits of 5 -
250 degrees C.



5.5 In Mode Actions
These are actions that are to be performed continuously. The first action is to energise or de-energise the
relays depending on the current mode. The second action is to

5.6 Interrupt Routines

5.6.1 Encoder interrupt
The flowchart for the interrupt service routines is depicted in the figure above. This routine processes two
events in effect. The first being the external interrupt generated by the encoder, the second by the RTCC
timer overflowing during encoder debouncing.
Initially the RTCC is configured to clock on an external falling edge on pin RA4. Additionally the RTCC
counter is loaded with 255 so that the first falling edge will trigger the interrupt. When the interrupt
occurs the routine checks the direction of rotation of the encoder and increments or decrements the
encoder value accordingly.
The routine then configures the RTCC to clock from the internal clock source. This is then used for
debouncing the encoder inputs. The RTCC then generates an interrupt on overflow a number of times, until
the debounce period has expired. The RTCC then reverts back to its initial configuration.

5.6.2 Serial Input
The serial data to be read in via port RB0, with the interrupt initiating the processing of the data. RB0 is
configured to generate an interrupt on the falling edge of the start bit. The interrupt then simply calls the
getc() function supplied with the compiler. The character read in is then presented to the mainline code for
processing. If the character is an ASCII ‘D’ the system will transmit the current temperature value.

5.7 Display Update
Every pass through the main loop, the system updates the LCD display. The current mode is displayed on line
2 of the LCD, with the current temperature being displayed on line 1. If one of the set points is being
adjusted, then that set point value is displayed.

5.8 Watchdog Timer
The watchdog timer is configured to clock of the PIC16F84 prescaler. With the prescaler set to its
maximum value, the timeout for the watchdog is approximately 2 seconds. The counter is reset every cycle
through main loop




10
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN


6. Front Panel Layout




11
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN

7. Circuit Diagram




                                Figure 2 Circuit Diagram


12
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN


8. PCB Artwork

8.1 Composite




13
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN

8.2 Overlay




14
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN

8.3 Top Layer




15
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN

8.4 Bottom Layer




16
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN


9. Software Listing

9.1 16f84.h
//////// Standard Header file for the PIC16F84 device ////////
#device PIC16F84
#nolist
/////////////////////////////// I/O definitions for INPUT() and OUTPUT_xxx()
#define PIN_A0 40
#define PIN_A1 41
#define PIN_A2 42
#define PIN_A3 43
#define PIN_A4 44

#define   PIN_B0   48
#define   PIN_B1   49
#define   PIN_B2   50
#define   PIN_B3   51
#define   PIN_B4   52
#define   PIN_B5   53
#define   PIN_B6   54
#define   PIN_B7   55
/////////////////////////////// Useful defines
#define FALSE 0
#define TRUE 1

#define BYTE int
#define BOOLEAN short int

#define   getc getch
#define   getchar getch
#define   puts(s) {printf(s); putchar(13); putchar(10);}
#define   putc putchar

/////////////////////////////// Constants used for RESTART_CAUSE()
#define WDT_FROM_SLEEP 0
#define WDT_TIMEOUT     8
#define MCLR_FROM_SLEEP 16
#define NORMAL_POWER_UP 24
/////////////////////////////// Constants used for SETUP_COUNTERS()
#define RTCC_INTERNAL   0
#define RTCC_EXT_L_TO_H 32
#define RTCC_EXT_H_TO_L 48
#define RTCC_DIV_2      0
#define RTCC_DIV_4      1
#define RTCC_DIV_8      2
#define RTCC_DIV_16     3
#define RTCC_DIV_32     4
#define RTCC_DIV_64     5
#define RTCC_DIV_128    6
#define RTCC_DIV_256    7
#define WDT_18MS        8
#define WDT_36MS        9
#define WDT_72MS       10
#define WDT_144MS      11
#define WDT_288MS      12
#define WDT_576MS      13
#define WDT_1152MS     14
#define WDT_2304MS     15
#define L_TO_H              0x40
#define H_TO_L                 0

#define   RTCC_ZERO           0x0B20    //   Used   for   ENABLE/DISABLE   INTERRUPTS
#define   RB_CHANGE           0x0B08    //   Used   for   ENABLE/DISABLE   INTERRUPTS
#define   EXT_INT             0x0B10    //   Used   for   ENABLE/DISABLE   INTERRUPTS
#define   GLOBAL              0x0BC0    //   Used   for   ENABLE/DISABLE   INTERRUPTS

#list




17
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN


9.2 Oven.c

/////////////////////////////////////////////////////////////////////////
////                             oven.c                               ////
////                                                                  ////
//// Copyright Peter Homann 1998- 2002                                ////
////                                                                  ////
//// This program is a SMT Reflow Oven controller. It is designed to ////
//// be incorporated into a standard fan-forced convection toaster    ////
//// oven. Two relays are controlled. A heater element relay, and an ////
//// oven fan relay.                                                  ////
////                                                                  ////
//// The controller utilises a two bit quadrature encoder for         ////
//// setting the temperature set points. two pushbutton switches are ///
//// used for setting the mode and for start/stop control.            ////
////                                                                  ////
////                                                                  ////
////                           ------------------                     ////
////                         |       16F84        |                   ////
////             FAN_RELAY -|RA2              RA1|- PIEZO             ////
////                         |                    |                   ////
////          HEATER_RELAY -|RA3              RA0|- TX                ////
////                         |                    |                   ////
////             ENCODER_A -|RA4/RTCC        OSC1|-                   ////
////                         |                    |                   ////
////                  RESET -|MCR            OSC2|-                   ////
////                         |                    |                   ////
////                    GND -|VSS             VDD|- +5V               ////
////                         |                    |                   ////
////                     RX -|RB0             RB7|- LCD_D7/ADC_CLK    ////
////                         |                    |                   ////
////                 ADC_CS -|RB1             RB6|- LCD_D6/ADC_DOUT   ////
////                         |                    |                   ////
////                  LCD_E -|RB2             RB5|- LCD_D5/MODE_SWITCH////
////                         |                    |                   ////
////      LCD_DI/ENCODER_B -|RB3              RB4|- LCD_D4/GO_SWITCH ////
////                         |                    |                   ////
////                           ------------------                     ////
////                                                                  ////
////                                                                  ////
/////////////////////////////////////////////////////////////////////////




/////////////////////       I/O Pin Defines   //////////////////////////////

#define PIEZO             a_port.a1   // Piezo beeper pin
#define FAN_RELAY         a_port.a2   // Pin controlling the oven fan relay
#define HEATER_RELAY      a_port.a3   // Pin controlling the heater relay

#define TX                PIN_A0      // Serial data output pin
#define RX                PIN_B0      // Serial data input pin

#define ADC_CS            b_port.b1   // Chip select pin for the A/D chip
#define ADC_DOUT          b_port.b6   // Data output pin from the A/D chip
#define ADC_CLK           b_port.b7   // Clock output pin to the A/D chip

#define GO_SWITCH_PIN   b_port.b4     // Pin used to read the Go/Stop switch
#define MODE_SWITCH_PIN b_port.b5     // Pin used to read the mode switch

#define ENC_A             a_port.a4   // Pin used to read the encoder A output
#define ENC_B             b_port.b3   // Pin used to read the encoder B output



/////////////////////       Piezo Beep constant defines //////////////////

#define   BEEP_DURATION         100
#define   SHORT_BEEP_DURATION    25
#define   LONG_BEEP_DURATION    255
#define   BEEP_DURATION         255
#define   BEEP_PITCH            100
18
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN
#define BEEP_DELAY          100


/////////////////////             General defines //////////////////////////////

#define OFF                         0
#define ON                          1


/////////////////////             Setup compiler options/defines ///////////////

#include <16F84.H>

#fuses   HS,NOPROTECT,WDT
#use fast_io(A)
#use fast_io(B)
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=TX, rcv=RX)



/////////////////////             Temperature Defines     ////////////////////////

#define SET_POINT             0         // EEPROM address for temperature set-point
#define LOW_POINT             1         // EEPROM address for temperature low-point
#define SET_POINT_LIMIT 240             // Maximum valid temperature for set-point
#define LOW_POINT_LIMIT 30              // Minimum valid temperature for low-point

#define MAX_SAFE_LIMIT        250       // Maximum safe temperature
#define MAX_SAFE_LIMIT          5       // Minimum safe temperature

/////////////////////     System modes           ////////////////////////
// The defined system modes must not be re-ordered or have their values
// changed as the system mode is used as an index into the following tables,
// in addition to being used in the for determining which actions are to
// be performed in each mode.
/////////////////////////////////////////////////////////////////////////

enum modes
{
    IDLE       =   0,   //   Initial mode ready for operation.
    ENTER_HI   =   1,   //   Configuration mode for entering high set point temp.
    ENTER_LO   =   2,   //   Configuration mode for entering low set point temp.
    HEAT       =   3,   //   Heating onen. Oven heater and fan are on.
    COOL       =   4,   //   Cooling oven. Heater is off, fan is on.
    REHEAT     =   5,   //   Attempt to heat oven when it is above the low set point.
    FAILURE    =   6    //   Temperature value is outside safe limits.
};


/////////////////////         Event - Mode change/action arrays /////////////
////                                                                     ////
//// The following arrays identify what mode to change to on receipt ////
//// of the particular event, in addition to actions to be taken. An ////
//// example of an array entry is depicted below. The entry              ////
//// indicates the mode is to change to HEAT, and a sigle beep be        ////
//// sounded.                                                            ////
////                                                                     ////
////        0b01100001                                                   ////
////                                                                     ////
////          011           New Mode                                     ////
////              0         Read the high set point                       ////
////                0       Store the high set point and Read low set point////
////                  0     Store the low set point                       ////
////                    0   Sound three beeps                            ////
////                      1 Sound single beep                            ////
/////////////////////////////////////////////////////////////////////////


// This event occurs when the current probe temperature is less than the
// low temp set point value. It indicates when the oven has finished cooling

     byte const lo_temp_event_array[7] =
     {
         0b00000000, // Ignore the event as the oven is idle
         0b00100000, // Ignore the event as the oven is being configured
19
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN
           0b01000000,   //   Ignore   the event as the oven is being configured
           0b01100000,   //   Ignore   the event as the oven is being heated
           0b00000010,   //   Change   to the idle state as the oven has cooled
           0b00000010,   //   Change   to the idle state as the oven has cooled
           0b11000010    //   Ignore   the event as a failure has occured
      };



// This event occurs when the current probe temperature exceeds the high
// temp set point value. It indicates when the oven has reached the heating
// set point and should begin cooling.

      byte const hi_temp_event_array[7] =
      {
          0b00000000, // Ignore the event as the oven is idle
          0b00100000, // Ignore the event as the oven is being configured
          0b01000000, // Ignore the event as the oven is being configured
          0b10000010, // Change to the cooling state as the set point is reached
          0b10000000, // Ignore the event as the oven is alreading cooling
          0b10000010, // Change to the cooling state as the set point is reached
          0b11000010 // Ignore the event as a failure has occured
      };


// This event occurs when go/stop switch is pressed.

      byte const go_switch_event_array[7]=
      {
          0b01100001, // Change to the heating state
          0b00100000, // Ignore the event as the oven is being configured
          0b01000000, // Ignore the event as the oven is being configured
          0b10000000, // Change to the cooling state
          0b10100001, // Change to the reheat state
          0b01100001, // Change to the cooling state
          0b11000010 // Ignore the event as a failure has occured
      };


// This event occurs when mode switch is pressed.

      byte const mode_switch_event_array[7] =
      {
          0b00110000, // Change to the enter high set point state
          0b01001000, // Change to the enter low set point state
          0b00000100, // Change to the idle state
          0b01100000, // Ignore the event as the oven is being configured
          0b10000000, // Ignore the event as the oven is being configured
          0b10100000, // Ignore the event as the oven is being configured
          0b11000010 // Ignore the event as a failure has occured
      };

     char const mode_string[56] =
     {
         'R','e','a','d','y',' ',' ',' ',         //   The mode strings are represented
         'M','a','x',' ','T','e','m','p',         //   as a combined character array as
         'M','i','n',' ','T','e','m','p',         //   it provides more effecient ROM
         'H','e','a','t','i','n','g',' ',         //   usage over an array of 7 strings.
         'C','o','o','l','i','n','g',' ',
         'T','o','o',' ','H','o','t','!',
         'F','a','i','l','u','r','e','!'};


/////////////////////     Global variables.            ////////
boolean mode_switch_event; // Indicates the            mode switch has been pressed
boolean go_switch_event;   // Indicates the            go/stop switch has been pressed
boolean hi_temp_event;     // Indicates the            high set point has been exceeded
boolean lo_temp_event;     // Indicates the            high set point has been exceeded
boolean
  temperature_alarm_event; // Indicates the            temp has exceeded safe values


boolean encoder_intrpt;           // Indicates whether the RTCC interrupt is caused
                                  // by an encoder change (external) or from the RTCC
                                  // counter overflowing (internal).


20
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN
modes   mode;              // Indicates the current mode.
byte    mode_mask;         // bitmask for indicating if and when in mode
                           // actions should be performed.

byte    oven_temp;          // Contains the current oven temperature.

char    cmd;                // Contains the external command character received
                            // via the serial data input.

byte    current_data;       // This variable will be incremented or
                            // decremented by the encoder ISR as the encoder is
                            // rotated.
byte    encoder_timer;      // Used by the encoder ISR for debouncing the
                            //encoder inputs.


char    display_value[5];   //Contains the ASCII characters that will be
                            // displayed on the LCD or output via the serial
                            // line when commanded to.




struct a_port_pin_map
       {                     // This structure is overlayed
            boolean a0;      // on to the I/O port A to gain
            boolean a1;      // direct access to the port pins.
            boolean a2;
            boolean a3;
            boolean a4;
         } a_port;

#byte a_port = 5              // This puts the entire structure at the address
                              // of port A


struct b_port_pin_map
       {                              // This structure is overlayed
            boolean b0;               // on to the B I/O port to gain
            boolean b1;               // direct access to the port pins.
            boolean b2;
            boolean b3;
            boolean b4;
            boolean b5;
            boolean b6;
            boolean b7;
         } b_port;

#byte b_port = 6                      // This puts the structure
                                      // on to port B (at address 6)



struct lcd_b_port_pin_map
       {                              //   This structure is overlayed
            boolean b_rx;             //   on to the B I/O port to gain
            boolean b_adc_cs;         //   direct access to the LCD pins.
            boolean lcd_enable;       //   The bits are allocated from
            boolean lcd_rs;           //   low order up. ENABLE will
            int     lcd_data : 4;     //   be pin B2.
         } lcd_b_port;

                                      // This puts the structure
#byte lcd_b_port = 6                  // on to port B (at address 6)

#define lcd_type 2                    // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40             // LCD RAM address for the second line

byte CONST LCD_INIT_STRING[4] =
{
    0x20 | (lcd_type << 2),           // These bytes need to be sent to the LCD
    0xc,                              // to start it up.
    1,
    6
};


21
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN

//   The following are used for setting the I/O port direction register via
//   the TRIS command. A '0' indicates an ouput, while a '1' indicates an
//   input for the variable. Port A TRIS is set to PORT_A_IOon initialisation
//   only. Port B Tris is set to ADC_READ on initialisation and set to
//   LCD_WRITE during LCD writes, then immediatly back to ADC_READ.

STRUCT a_port_pin_map     const PORT_A_IO = {0,0,0,0,1};
STRUCT lcd_b_port_pin_map const LCD_WRITE = {1,0,0,0,0};
STRUCT b_port_pin_map     const ADC_READ = {1,0,0,1,1,1,1,0};


// Initialises the A to D converter chip.
void
adc_init()
{
   // Deselect the converter chip.
   ADC_CS = TRUE;
}


// Read a number of bits from the A to D Converter chip. The Data is
// Shifted out of the A to D chip on the rising edge of the clock.
byte
read_adc_byte(byte number_of_bits)
{
   byte i,data;


     data=0;
     for(i=0;i<number_of_bits;++i)
     {
        ADC_CLK= TRUE;
        delay_us(500);
        shift_left(&data,1,ADC_DOUT);
        ADC_CLK = FALSE;
        delay_us(500);
     }
     return(data);
}

// Read the temperature from the A to D converter chip.
byte
read_temperature()
{
   byte value;
   long h;

     // Enable the converter chip.
     ADC_CLK = FALSE;
     ADC_CS = FALSE;

     // Read and discard Start & Null bits.
     value = read_adc_byte(3);


     // Read bits 11 - 4 MSB. We are only interested in the High 8 bits, so
     // the lower 4 bits are not even read.
      value = read_adc_byte(8);

     // Disable the converter chip.
     ADC_CS = TRUE;
     return(value);
}


// Write a nibble to the LCD
void
lcd_send_nibble( byte n )
{
      lcd_b_port.lcd_data = n;          // Set up nibble on LCD data D4 - D7
      delay_cycles(1);
      lcd_b_port.lcd_enable = 1;        // Pulse LCD enable
      delay_us(2);
      lcd_b_port.lcd_enable = 0;
}
22
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN


// Write a byte to the LCD
void
lcd_send_byte( byte address, byte n )
{
      disable_interrupts(RTCC_ZERO);    //   Stop Encoder interrupts during
      set_tris_b(LCD_WRITE);            //   writes to the LCD
      lcd_b_port.lcd_rs = 0;            //   Select register specified by address
      delay_cycles(10);                 //   parameter
      lcd_b_port.lcd_rs = address;
      delay_cycles(1);
      lcd_b_port.lcd_enable = 0;
      lcd_send_nibble(n >> 4);          // Write the High Nibble
      lcd_send_nibble(n & 0xf);         // Write the Low Nibble
      set_tris_b(ADC_READ);             // Set up port for ADC and encoder input
      enable_interrupts(RTCC_ZERO);
}



// Initialise the LCD
void
lcd_init()
{
     byte i;

      set_tris_b(LCD_WRITE);     // Setup for LCD writes
      lcd_b_port.lcd_rs = 0;
      lcd_b_port.lcd_enable = 0;
      delay_ms(15);
      for(i=1;i<=3;++i)
      {
         lcd_send_nibble(3);
         delay_ms(5);
      }
      lcd_send_nibble(2);

      for(i=0;i<=3;++i)
      {
         lcd_send_byte(0,LCD_INIT_STRING[i]);
      }
      set_tris_b(ADC_READ);     // Setup for ADC and encoder input
}


// Set the LCD cursor to a row and column position.
void lcd_gotoxy( byte x, byte y)
{
   byte address;

     if(y!=1)                       // If address row is not 1, then set to row 2
     {
       address=lcd_line_two;
     }
     else
     {
       address=0;
     }
     address+=x-1;                   // Calculate address by adding Xaddress to
     lcd_send_byte(0,0x80|address); // the start of the address row.
}



// Print a character on the LCD
void
lcd_putc( char c)
{
   switch (c)
   {
     case '\f'    :
     {                                                 // Clear the LCD
         lcd_send_byte(0,1);
         delay_ms(5);
         break;
     }
23
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN
         case '\n'   : lcd_gotoxy(1,2);        break;   // Set to start of 2nd line
         default     : lcd_send_byte(1,c);     break;   // Print a character.
     }
}



// Display the current mode on the LCD
void
display_mode_string()
{
     byte c;
     byte m;

      lcd_putc('\n');                          // Set cursor to start of line 2
      m = mode << 3;                           // Select correct String

      for (c=0; c < 8; c++)                    // Print the 8 characters
      {
          lcd_putc(mode_string[m + c]);
      }
}




/*
void
beep(byte number, byte length)
{
     byte  count;
     byte  duration;

      for (count = number; count > 0; count--)
      {

            for (duration = 0; duration < length; duration++)
            {
                PIEZO = TRUE;
                delay_us(BEEP_PITCH);
                PIEZO = FALSE;
                delay_us(BEEP_PITCH);
            }
            if (count)
            {
                delay_ms(BEEP_DELAY);
            }
      }
}
                     Last change:   PDH   5 Jun 1998    9:37 pm
*/



// Sound the piezo beeper a number of times
void
beeps(byte number)
{
     byte  count;
     byte  duration;

      for (count = number; count > 0; count--)
      {
          for (duration = BEEP_DURATION; duration > 0; duration--)
          {
              PIEZO = !(PIEZO);          // Toggle the output pin.
              delay_us(BEEP_PITCH);
          }
          if (count)                     // Pause between beeps
          {
              delay_ms(BEEP_DELAY);
          }
      }
      PIEZO = FALSE;                     // Remove DC voltage from piezo beeper
}                                        // when not sounding


24
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN


// Setup the RTCC to clock from an external high to low transition
#inline
void
set_rtcc_ext_h_to_lo()
{
     #asm
        movlw 0x81
        movwf 0x04
        bsf   0x00,5
     #endasm
}




// Setup the RTCC to clock from the internal clock
#inline
void
set_rtcc_internal_clock()
{
     #asm
          movlw 0x81
          movwf 0x04
          bcf   0x00,5
     #endasm
}


// Process the RTCC interrupt.
#int_rtcc
encoder_isr()
{
    if (encoder_intrpt)                 //   If the interrupt was generated by the
    {                                   //   ENC_A input, test the ENC_B input to
         if (ENC_B)                     //   determine the direction the encoder has
         {                              //   been rotated. Update the current data
              current_data--;           //   accordingly.
         }
         else
         {
              current_data++;
         }
         set_rtcc_internal_clock();     // Setup the RTCC to perform encoder input
         set_rtcc(0);                   // debouncing.
         encoder_timer = 50;
         encoder_intrpt = FALSE;        // Indicate that the next RTCC interrupt
    }                                   // will be from the debouncing function
    else
    {
         encoder_timer--;               // Debounce the encoder input.
         if (!encoder_timer)
         {
              set_rtcc_ext_h_to_lo();   // Set the next interrupt to be from
              encoder_intrpt = TRUE;    // the ENC_A input.
              set_rtcc(255);
         }
    }
}


// Read the external command. This interrupt is entered at the beginning of
// the start bit.
#int_ext
serial_isr()
{
    cmd = getc();
}



// Convert the input byte to a 3 character decimal string. This routine
// is performed by successive subtraction as it is more code efficient than
// using the multiply instruction. Speed is not important.
void
format_display_value(byte value)
25
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN
{
     byte digit;
     boolean zero;

     digit = 0;
     zero = FALSE;

     while (value > 99)                  // Subtract 100 from the value until
     {                                   // value is less than 100.
         value -= 100;
         digit++;                        // The number of 100s subtracted.
     }
     if (!digit)                         // Blank leading zeros
     {
         zero = TRUE;
         digit = ' ' - '0';
     }
     display_value[0] = (digit + '0');   // Set string to ASCII value

     digit = 0;
     while (value > 9)                   // Subtract 10 from the value until
     {                                   // value is less than 10.
         value -= 10;
         digit++;                        // The number of 10s subtracted.
     }
     if (!digit && zero)                 // blank leading zero if previous
     {                                   // digit was zero
         digit = ' ' - '0';
     }
     display_value[1] = (digit + '0');   // Set string to ASCII values
     display_value[2] = (value + '0');
}



// Print the temperature value on the LCD
void
lcd_print_display_value()
{
   byte c;

     lcd_gotoxy(4,1);                    // Set the cursor position

     for (c= 0; c < 3; c++)              // Print the 3 characters on the LCD
     {
         lcd_putc(display_value[c]);
     }

     lcd_putc(0xDF);                     // Print degrees C after temperature
     lcd_putc('C');
}




// Read the two switches
void
read_switches()
{
   boolean    pin;
   static boolean last_go_switch_pin;       // Last time value of switches
   static boolean last_mode_switch_pin;

     // Read switch input to 'pin' in case it changes.
     pin = GO_SWITCH_PIN;

     // go_switch_event is true if a high to low transition has occurred
     go_switch_event = (last_go_switch_pin && !pin);
     last_go_switch_pin = pin;

     // Read switch input to 'pin' in case it changes.
     pin = MODE_SWITCH_PIN;

     // mode_switch_event is true if a high to low transition has occurred
     mode_switch_event = (last_mode_switch_pin && !pin);
     last_mode_switch_pin = pin;

26
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN
  // debounce switces
  delay_ms(50);

}

// Limit the value to be within safe limits. If the value was limited
// sound the piezo beeper.
void
limit_setpoints()
{
     if (current_data < LOW_POINT_LIMIT)
     {
         current_data = LOW_POINT_LIMIT;
         beeps(1);
     }
     if (current_data > SET_POINT_LIMIT)
     {
         current_data = SET_POINT_LIMIT;
         beeps(1);
     }
}


// The mode mask is used to efficiently determine if an action should be
// performed in a particular mode. Depending on the mode a single 1 will be
// in bits 0 -7. A boolean AND can then be used to determine if an action
// should be performed in that mode.
// Each bit in the mask corresponds to a mode, at identified in the enum
// mode type defined earlier.
void
set_mode_mask()
{
     mode_mask = 1;

      mode_mask <<= mode;   // shift the 1 to the approprite bit for the mode.
}


// Turn the relays on or off depending on the    current mode. A '1' indicates
// that the relay shoud be on in that mode. A    '0' indicates it should be off
void
set_relays()
{
   byte const heater_flags = 0b00001000;   //    indicate which modes heater is on
   byte const fan_flags    = 0b00111000;   //    Indicate which modes fan is on

     HEATER_RELAY = heater_flags & mode_mask; // Determine if the relay should
     FAN_RELAY    = fan_flags    & mode_mask; // on in this mode.
}


// The actions to be performed continueously during a particular mode are
// selected, and run. The mode_mask is used to determine this.
void
in_mode_actions()
{
   byte const limit_encoder_flags = 0b00000110; // Indicates in which modes
                                                // the limit_setpoints
   if (limit_encoder_flags & mode_mask)         // function is run, i.e. in
   {                                            // the 2 modes for entering
        limit_setpoints();                      // the set points
   }
   else                                         // Otherwise the data is set
   {                                            // to the current oven
        current_data = oven_temp;               // temperature
   }
}




// Update values in the internall data eeprom.
void
write_to_eeprom(byte address, byte value)
{
     disable_interrupts(GLOBAL);
     write_eeprom( address, value);
27
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN
#asm                                   // Clear the write complete bit to stop
    bsf 0x03, 5                        // an interrupt occuring. Workaround
    bcf 0x08, 4                        // for a possible compiler problem
    bcf 0x03, 5
#endasm
    enable_interrupts(GLOBAL);
}


// Determine if temperature has exceeded the specified set points. Also
// determine if a system fault has occurred by detecting if the temperature
// has exceeded safety limits.
void
check_temperature_events()
{
     lo_temp_event   = (oven_temp <= (read_eeprom(LOW_POINT)));

     hi_temp_event    = (oven_temp >= (read_eeprom(SET_POINT)));

     temperature_alarm_event = FALSE;
//     temperature_alarm_event =
//             ((oven_temp > MAX_SAFE_LIMIT) || (oven_temp < MAX_SAFE_LIMIT));
}




// This function implements a finite state machine. There are 5 events that
// can possibly cause a state change. The event are prioritised such that if
// more than one event occurs during a loop iteration, the event with the
// highest priority is acted apon, the other events are discarded. The event
// changes are controlled by separate event tables, one for each event type.
// This was done for code efficency reasons.
void
check_mode_change()
{
     modes   new_mode;

     new_mode = mode <<5;      // Prime the new mode to be the current mode
                               // with no actions to perform.

     if (lo_temp_event)
     {
         new_mode = lo_temp_event_array[mode];    // Lowest priority event
     }
     if (hi_temp_event)
     {
         new_mode = hi_temp_event_array[mode];
     }
     if (go_switch_event)
     {
         new_mode = go_switch_event_array[mode];
     }
     if (mode_switch_event)
     {
         new_mode = mode_switch_event_array[mode]; // Highest priority normal
     }                                             // event

     if (temperature_alarm_event)                   // Override all events if
     {                                              // an temperature alarm has
         new_mode = 0b11000001;                     // occurred
     }


     // Determine what actions are to be performed as a result of the mode
     // change.
     if (shift_right(&new_mode,1,0))                  // Single beep
     {
         beeps(1);
     }

     if (shift_right(&new_mode,1,0))                   // 3 beeps
     {
         beeps(3);
     }


28
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN
   if (shift_right(&new_mode,1,0))                   // Write the low set point
   {                                                 // to eeprom if it has
        if (current_data != read_eeprom(LOW_POINT)) // changed.
        {
            write_to_eeprom( LOW_POINT, current_data);
        }
   }

     if (shift_right(&new_mode,1,0))                   //    Write the high set point
     {                                                 //    to eeprom if it has
         if (current_data != read_eeprom(SET_POINT))   //    changed, and read the
         {                                             //    the low set point ready
             write_to_eeprom( SET_POINT, current_data);//    to be set by the encoder
         }
         current_data = read_eeprom(LOW_POINT);
     }

     if (shift_right(&new_mode,1,0))                      // Read the high set point
     {                                                    // ready to be set by the
         current_data = read_eeprom(SET_POINT);           // encoder.
     }
                                                          // Set the mode to the
     mode = new_mode;                                     // new mode.
}


// Process external command received via the serial input line.
void
process_external_command()
{
     byte c;

     if (cmd != 0)                          //   If a command is received
     {                                      //   If it is a data request then
         if (cmd == 'D')                    //   transmit the currently displayed
         {                                  //   value out the serial line
             delay_ms(10);
             for (c=0; c<5; c++)
             {
                  putc(display_value[c]);
             }
         }                                  // Clear the command once processed
         cmd = 0;
     }
}



// Initialise the display value.
void
init_display_value()
{
     display_value[3] = 13;  // Set the last 2 characters to <CR><LF>
     display_value[4] = 10;
}


// Initialise the RTCC
void
init_timer()
{
   set_rtcc_ext_h_to_lo();    // Set the RTCC to interrupt of the first
   set_rtcc(255);             // High to Low external transition from the
   encoder_intrpt = TRUE;     // ENC_A input.
   encoder_timer = 0;
}




// Initialise the system.
void
initialise()
{
   lcd_init();                           // Initialise interfaces
   adc_init();
29
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN
     init_timer();
     init_display_value();

     ext_int_edge(H_TO_L);                 // Set up serial input interrpt
     restart_wdt();

     lcd_putc("\fSMT Oven\nVer: 1.0");     // Display welcome message
     delay_ms(1000);
     restart_wdt();
     delay_ms(1000);
     lcd_putc('\f');                       // Clear LCD

     cmd = 0;
     mode = IDLE;

     enable_interrupts(EXT_INT);           // Enable interrupts
     enable_interrupts(RTCC_ZERO);
     enable_interrupts(GLOBAL);
}



// Determine what external event have occurred.
void
check_for_external_events()
{
     oven_temp = read_temperature();
     read_switches();
     check_temperature_events();
}


// Determine if a mode change has occured and update the mode mask.
void
check_for_mode_change()
{
     check_mode_change();
     set_mode_mask();
}


//Update the LCD
void
update_display()
{
     format_display_value(current_data);
     lcd_print_display_value();

      display_mode_string();
}


// Perform actions that execute continueously
void
perform_in_mode_actions()
{
     set_relays();
     in_mode_actions();
}




// The main program executes a continueous loop one the system is initialised.
main()
{

     set_tris_a(PORT_A_IO);                      // Setup Port I/O
     set_tris_b(ADC_READ);

     if (restart_cause() == WDT_TIMEOUT)         //   Determine if the reset was
     {                                           //   caused by the watchdog timer. If
         HEATER_RELAY = 0;                       //   so then Lock up to keep out of
         FAN_RELAY    = 0;                       //   trouble as a system failure has
                                                 //   occurred.
         while(TRUE)
         {
30
SMT REFLOW CONTROLLER for a FAN FORCED CONVECTION TOASTER OVEN
          beeps(1);                         // Get the operators attention
       }
  }

     beeps(2);
     initialise();                          // Start up the system

     do
     {
          check_for_external_events();      // Determine if any events have
                                            // occurred, then check if a mode
          check_for_mode_change();          // change is required.

          perform_in_mode_actions();        // Perform the actions for the
                                            // current mode
          update_display();                 // Update the LCD

          process_external_command();       // Process the external command
                                            // if present
          restart_wdt();                    // Clear the watchdog timer

     } while (TRUE);                        // Continue

}




31