This is a Reflow Oven Controller ported to the mbed platform Original article: http://www.circuitcellar.com/renesas/winners/Abstracts/H3323%20abstract.pdf

Dependencies:   mbed

Revision:
0:9526e71a200f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Jan 15 06:13:50 2012 +0000
@@ -0,0 +1,409 @@
+//-----------------------------------------------------------------------
+// reflow oven controller
+//
+// Version 1.0 - December 2003
+//
+// ATOM-Pro basic for Renesas '3687
+//
+// Copyright (name deleted)
+
+// This project is a port from the original basic code for the Basic Micro EVB87 
+// Renesas evaluation board to the mbed in C.
+//
+// We use the same setup as the original project:
+// For the thermocouple, a AD595 cnnected to one of the analog input of the mbed.
+// For the buttons, 3 push buttons connected to ground and pullups.
+// For the heater, any driver configuration.
+//
+// http://www.circuitcellar.com/renesas/winners/Abstracts/H3323%20abstract.pdf
+//-----------------------------------------------------------------------
+
+#include "mbed.h"
+#include "TextLCD.h"
+
+//TextLCD lcd(p6, p7, p8, p13, p14, p15, p16); // rs, rw, e, d4, d5, d6, d7
+TextLCD lcd(p6, p8, p13, p14, p15, p16); // rs, e, d4, d5, d6, d7
+
+// 0 button pressed, 1 button released
+DigitalIn IN8(p30);
+DigitalIn IN9(p29);
+DigitalIn IN10(p28);
+
+// 0 off, 1 on
+DigitalOut HeaterOutput(p27);
+
+// Use the USB link as serial port
+Serial pc(USBTX, USBRX); // tx, rx
+
+// The 0.0v to 3.3v range of the AnalogIn is represented in software
+// as a normalised floating point number from 0.0 to 1.0.
+AnalogIn ain(p15);
+
+// AD595 10mv/'C at 3.3V -> 330'C
+
+//=======================================================================
+// variables
+//=======================================================================
+
+int PreheatSlope;          // 1 to 255, 1/10° per sec
+int DryingTemp;            // 20 to 250, °C
+int Hysteresis;            // 1 to 20, °C
+int DryingTime;            // 1 to 255, seconds
+int HeatingSlope;         // 1 to 255, 1/10° per sec
+int ReflowTemp;            // 150 to 255, °C
+int ReflowTime;            // 1 to 255, seconds
+int CoolingSlope;        // 1 to 255, 1/10° per sec
+int Kd;                    // kd muliplier for pid, in 1/10
+
+char status;            // state machine status
+int t;                    // current temperature
+int tini;                // initial temperature
+int tset10;                // set temperature times 10
+int tset;                // set temperature
+int remaining_time;                // remaining time in s
+char heater;            // heater on/off
+int tprec;              // previous temperature
+int testim;                // estimated future temperature
+
+// Used to toggle between 2 display screens
+char dispcycle;            // display cycle (0/1/0/1...)
+
+int alow;
+int ahigh;
+
+char *lcd_status[] = {
+    "UpDry  ","WtDry  ","Drying ","UpFlow ","WtFlow ","Reflow ","Coolng "
+};
+
+#define PREHEAT         1
+#define WAIT_DRYING     2
+#define DRYING          3
+#define HEAT            4
+#define WAIT_REFLOW     5
+#define REFLOW          6
+#define COOLING         7
+
+void heater_off(void) {
+    HeaterOutput = 0;
+}
+
+void heater_on(void) {
+    HeaterOutput = 1;
+}
+
+//=======================================================================
+// Subroutines
+//=======================================================================
+
+// Initialisation
+void Init(void) {
+    // Welcome screen
+    lcd.cls();
+    lcd.printf(" REFLOW CONTROL ");
+    lcd.locate(0,1);
+    lcd.printf("       V1.0     ");
+
+    wait_ms(10);
+
+    // Initialize variables to default values
+    PreheatSlope = 10;    // 1 to 255, 1/10° per sec
+    DryingTemp = 100;    // 20 to 250, °C
+    Hysteresis = 5;        // 1 to 20, °C
+    DryingTime = 120;    // 1 to 255, seconds
+    HeatingSlope = 40;    // 1 to 255, 1/10° per sec
+    ReflowTemp = 250;    // 150 to 255, °C
+    ReflowTime = 45;    // 1 to 255, seconds
+    CoolingSlope = 20;    // 1 to 255, 1/10° per sec
+    Kd = 10;            // 0 to 100, kd multiplier in 1/10
+}
+
+void editnum(int *value,int minval,int maxval) {
+    int v;
+
+    v = *value;
+
+    do {
+        wait_ms(200);
+        lcd.locate(10,0);
+        lcd.printf("%d  ",v);
+        lcd.locate(0,1);
+        lcd.printf("[2+][1-] [0:end]");
+
+        if (IN9 == 0) {
+            v--;
+            if (v < minval) v = minval;
+        }
+
+        if (IN10 == 0) {
+            v++;
+            if (v > maxval) v = maxval;
+        }
+
+    } while (IN8 != 0);
+
+    *value = v;
+}
+
+void UpdateStateMachine(void) {
+    if (status == 0) return;
+
+    switch (status - 1) {
+        case PREHEAT:
+            tset10 = tset10 + PreheatSlope;
+            tset = tset10/10;
+
+            if (tset > DryingTemp) {
+                tset10 = DryingTemp * 10;
+                status = WAIT_DRYING;
+                dispcycle = 1;
+            }
+            break;
+
+        case WAIT_DRYING:
+            if ((t + Hysteresis) > DryingTemp) {
+                remaining_time = DryingTime;
+                status = DRYING;
+                dispcycle = 1;
+            }
+            break;
+
+        case DRYING:
+            if (remaining_time == 0) {
+                remaining_time = (10 * (ReflowTemp - DryingTemp))/HeatingSlope;
+                status = HEAT;
+                dispcycle = 1;
+            }
+            break;
+
+        case HEAT:
+            tset10 = tset10 + HeatingSlope;
+            tset = tset10/10;
+            if (tset > ReflowTemp) {
+                tset10 = 10 * ReflowTemp;
+                status = WAIT_REFLOW;
+                dispcycle = 1;
+            }
+            break;
+
+        case WAIT_REFLOW:
+            if ((t + Hysteresis) > ReflowTemp) {
+                remaining_time = ReflowTime;
+                status = REFLOW;
+                dispcycle = 1;
+            }
+            break;
+
+        case REFLOW:
+            if (remaining_time == 0) {
+                remaining_time = (10 * (ReflowTemp - tini))/CoolingSlope;
+                status = COOLING;
+                dispcycle = 1;
+            }
+            break;
+
+        case COOLING:
+            tset10 = tset10 - CoolingSlope;
+            tset = tset10/10;
+            if (tset < tini) {
+                tset10 = 10 * tini;
+                status = 0;
+                dispcycle = 1;
+            }
+            break;
+
+        default:
+            status = 0;
+    }
+}
+
+// Read current temperature
+// return temperature in ahigh (degrees) and alow (tens of a degree)
+void readtemperature(void) {
+    long int atemp;
+    long int a;             // temporary
+    int i;
+
+    a = 0;
+
+    /* 1000 readings */
+    for (i=1; i <= 1000; i++) {
+        atemp = ain * 330;    // 3.3V from an AD595 at 10mV/'C -> 330'C
+        a += atemp;
+    }
+    /* a = 1000 * avg temp */
+    // ex: 300.2    a = 300200
+
+    a = a/100;  // a = 3002
+
+    /* ahigh = */
+    ahigh = a/10;   // ahigh = 300
+    alow = a - ahigh*10;  // alow = 3002 - 3000 = 2
+}
+
+void RunMode() {
+    // initialise run mode
+    status = 1;
+    dispcycle = 0;
+    t = 0;
+    readtemperature();
+
+    t = ahigh;
+    tini = t;
+    tset10 = 10*t;
+    remaining_time = (10*(DryingTemp - t))/PreheatSlope;
+    heater = 0;
+
+    // wait for run button released
+    while (IN8 == 0);
+    wait_ms(10);
+
+    do {
+        tprec = t;
+
+        // read new temperature
+        readtemperature();
+        t = ahigh;
+
+        // estimate future temperature using kd
+        testim = ((10*t) + (t-tprec) * Kd)/10;
+
+        tset = tset10/10;
+
+        // display screen
+        lcd.cls();
+        lcd.printf("Temp:%dC  ", ahigh);
+        lcd.locate(10,0);
+
+        if (dispcycle == 1) {
+            lcd.printf("%d/7",status);
+        } else {
+            lcd.puts(lcd_status[status-1]);
+        }
+
+        lcd.locate(0,1);
+        lcd.printf("Tset:%dC  ", tset);
+        lcd.locate(10,1);
+        lcd.printf("sec %d", remaining_time);
+
+        // decrement time (in seconds, due to the 1 second pause)
+        if (remaining_time != 0) remaining_time--;
+
+        // check if abort requested
+        if (IN8 == 0) {
+            status = 0;
+            heater_off();
+
+            // wait for run button released
+            while (IN8 == 0);
+            wait_ms(10);
+        }
+
+        UpdateStateMachine();
+
+        tset = tset10/10;
+
+        // control heater
+        if (heater == 0) {
+            if (testim < (tset - Hysteresis)) heater = 1;
+        }
+
+        if (heater == 1) {
+            if (testim > (tset + Hysteresis)) heater = 0;
+        }
+
+        if (heater == 0)
+            heater_off();
+        else
+            heater_on();
+
+        // send current values to uart
+        pc.printf("S%d,%d,%d,%d\n",tset, t, status, heater);
+
+        // wait for 1 second
+        wait(1);
+
+        // next dispcycle
+        dispcycle = 1 - dispcycle;
+    } while (status != 0);
+}
+
+void ConfigurationMode(void) {
+    int i;
+
+    for (i = 1; i <= 9; i++) {
+        lcd.cls();
+        lcd.locate(0,0);
+
+        switch (i) {
+            case 1:
+                lcd.printf("DrySlope");
+                editnum(&PreheatSlope,1,255);
+                break;
+            case 2:
+                lcd.printf("DryTemp ");
+                editnum(&DryingTemp,40,150);
+                break;
+            case 3:
+                lcd.printf("Hysteres");
+                editnum(&Hysteresis,1,40);
+                break;
+            case 4:
+                lcd.printf("DryTime ");
+                editnum(&DryingTime,1,255);
+                break;
+            case 5:
+                lcd.printf("HeatSlpe");
+                editnum(&HeatingSlope,1,255);
+                break;
+            case 6:
+                lcd.printf("FlowTemp");
+                editnum(&ReflowTemp,120,255);
+                break;
+            case 7:
+                lcd.printf("Flowtime");
+                editnum(&ReflowTime,1,255);
+                break;
+            case 8:
+                lcd.printf("Coolslop");
+                editnum(&CoolingSlope,1,255);
+                break;
+            case 9:
+                lcd.printf("Kd      ");
+                editnum(&Kd,0,200);
+                break;
+        }
+    }
+}
+
+//=======================================================================
+// Main program
+//=======================================================================
+
+int main(void) {
+    // Initialisations
+    Init();
+
+    lcd.cls();
+
+    // Main loop
+    while (1) {
+        // heater off
+        heater_off();
+
+        // Display current temperature
+        lcd.locate(0,0);
+        readtemperature();
+        lcd.printf("Temp : %d.%dC    ", ahigh, alow);
+        lcd.locate(0,1);
+
+        // Display menu
+        lcd.printf("[1:CONF] [0:RUN]");
+
+        wait_ms(10);
+
+        // Run button ?
+        if (IN8 == 0)
+            RunMode();
+        else if (IN9 == 0) ConfigurationMode();
+    }
+}