based on existing code, added support for max31855 and i2c display

Dependencies:   MAX31855 mbed

Revision:
0:1f9875adab5d
Child:
1:e7ce82863fe9
diff -r 000000000000 -r 1f9875adab5d main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Jan 16 21:48:38 2014 +0000
@@ -0,0 +1,439 @@
+//-----------------------------------------------------------------------
+// reflow oven controller, adapted to i2c display
+//
+// Version 1.0 - December 2003
+//
+// ATOM-Pro basic for Renesas '3687
+//
+// Copyright (name deleted) and it's rights are not referenced in the orignal on mbed
+//
+// 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 Maxim 31855K, the GHI thermocouple board was used
+// For the buttons, 3 push buttons connected to ground and pullups.
+// For the heater, any driver configuration.
+//
+// fixed major bug in UpdateStateMachine() switch / case tests on wrong value
+//
+// http://www.circuitcellar.com/renesas/winners/Abstracts/H3323%20abstract.pdf
+// no info could be found on above link but use next link instead.
+// http://hobbybotics.com/projects/hobbybotics-reflow-controller-v8-03/ 
+//-----------------------------------------------------------------------
+
+#include "mbed.h"
+#include "lc_display.h"
+#include "max31855.h"
+
+// 0 button pressed, 1 button released
+DigitalIn Btn_0(p18);
+DigitalIn Btn_1(p19);
+DigitalIn Btn_2(p20);
+
+// 0 off, 1 on
+DigitalOut HeaterOutput(p21);
+
+// Use the USB link as serial port
+Serial pc(USBTX, USBRX); // tx, rx
+
+//SPI Interfaces
+SPI testSPI(p11,p12,p13);
+//Thermocouples
+max31855 max1(testSPI,p26);
+
+//=======================================================================
+// 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;
+float atemp;
+
+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
+    _WriteLCD(ClrDisplay);
+    _WriteLCD(DisplayON_OFF, 1, 1, 0);
+    _WriteLCD(WriteString, "  REFLOW CONTROL  ", 0);
+    _WriteLCD(SetCursor, 0x14);
+    _WriteLCD(WriteString, "        V2.0a     ", 0);
+    wait_ms(1000);
+
+    // 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
+    
+    //Initialise chip (starts internal timer)
+    max1.initialise();
+}
+
+void editnum(int *value,int minval,int maxval) {
+    int v;
+    char tmp[32] = {0};
+    v = *value;
+
+    do {
+        wait_ms(200);
+        _WriteLCD(SetCursor, 0x0a);
+        sprintf(tmp, "%3d", v);
+        _WriteLCD(WriteString, tmp, 4);
+        _WriteLCD(SetCursor, 0x14);
+        _WriteLCD(WriteString, "[2+][1-] [0:end]    ", 0);
+        
+        if (Btn_1.read() == 0) {
+            v--;
+            if (v < minval) v = minval;
+        }
+
+        if (Btn_2.read() == 0) {
+            v++;
+            if (v > maxval) v = maxval;
+        }
+
+    } while (Btn_0.read() != 0);
+
+    *value = v;
+}
+
+void UpdateStateMachine(void) {
+    if (status == 0) return;
+    // original had (status - 1) but this fail to work
+    switch (status) {        
+        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;
+            break;
+    }
+}
+
+// Read current temperature from thermo couple
+// return temperature in ahigh (degrees) and alow (tens of a degree)
+void readthermo(void) {
+        
+    if (max1.ready()==1){
+        //Get the reading (average value may be needed 100 ?)
+        atemp = max1.read_temp();
+            
+        if (atemp > 2000){
+            if(atemp == 2001){
+                printf("No TC");
+            }else if(atemp == 2002){
+                printf("Short to Ground");
+            }else if(atemp == 2004){
+                printf("Short to VCC");
+            }
+        }else{
+            ahigh = (int) atemp;
+            alow = (int) ((atemp - ahigh) * 100);
+        }
+    }
+}
+
+void RunMode() {
+    // initialise run mode
+    status = 1;
+    dispcycle = 0;
+    t = 0;
+    readthermo();
+
+    t = ahigh;
+    tini = t;
+    tset10 = 10*t;
+    remaining_time = (10*(DryingTemp - t))/PreheatSlope;
+    heater = 0;
+
+    // wait for run button released
+    while (Btn_0.read() == 0);
+    
+    wait_ms(10);
+
+    char tmp[32] = {0};
+    do {
+
+        tprec = t;
+
+        // read new temperature
+        readthermo();
+        t = ahigh;
+
+        // estimate future temperature using kd
+        testim = ((10*t) + (t-tprec) * Kd)/10;
+
+        tset = tset10/10;
+        
+        _WriteLCD(ClrDisplay);
+        sprintf(tmp, "Temp: %3d C ", ahigh);
+        _WriteLCD(WriteString, tmp, 0);
+        
+        _WriteLCD(SetCursor, 0x0c);
+
+        if (dispcycle == 1) {
+            sprintf(tmp, "%d/7",status);
+            _WriteLCD(WriteString, tmp, 0);
+        } else {
+             sprintf(tmp, lcd_status[status-1]);
+            _WriteLCD(WriteString, tmp, 0);
+        }
+        _WriteLCD(SetCursor, 0x14);
+        sprintf(tmp, "Tset: %3d C ", tset);
+        _WriteLCD(WriteString, tmp, 0);
+        _WriteLCD(SetCursor, 0x20);
+        sprintf(tmp, "Sec: %3d ", remaining_time);
+        _WriteLCD(WriteString, tmp, 0);
+        
+
+        // decrement time (in seconds, due to the 1 second pause)
+        if (remaining_time != 0) remaining_time--;
+
+        // check if abort requested
+        if (Btn_0.read() == 0) {
+
+            status = 0;
+            heater_off();
+
+            // wait for run button released
+            while (Btn_0.read() == 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++) {
+        _WriteLCD(ClrDisplay);
+        _WriteLCD(SetCursor, 0x00);
+
+        switch (i) {
+            case 1:
+                _WriteLCD(WriteString, "DrySlope", 0);
+                editnum(&PreheatSlope,1,255);
+                break;
+            case 2:
+                _WriteLCD(WriteString, "DryTemp ", 0);
+                editnum(&DryingTemp,40,150);
+                break;
+            case 3:
+                _WriteLCD(WriteString, "Hysteres", 0);
+                editnum(&Hysteresis,1,40);
+                break;
+            case 4:
+                _WriteLCD(WriteString, "DryTime ", 0);
+                editnum(&DryingTime,1,255);
+                break;
+            case 5:
+                _WriteLCD(WriteString, "HeatSlpe", 0);
+                editnum(&HeatingSlope,1,255);
+                break;
+            case 6:
+                _WriteLCD(WriteString, "FlowTemp", 0);
+                editnum(&ReflowTemp,120,255);
+                break;
+            case 7:
+                _WriteLCD(WriteString, "Flowtime", 0);
+                editnum(&ReflowTime,1,255);
+                break;
+            case 8:
+                _WriteLCD(WriteString, "CoolSlpe", 0);
+                editnum(&CoolingSlope,1,255);
+                break;
+            case 9:
+                _WriteLCD(WriteString, "Kd      ", 0);
+                editnum(&Kd,0,200);
+                break;
+        }
+    }
+}
+
+//=======================================================================
+// Main program
+//=======================================================================
+
+int main(void) {
+    // Initialisations
+    
+    pc.baud(9600);
+    pc.printf("\r\nReflow Oven Controller for mbed v1.0\r\n");
+
+    // define some user characters for LCD display
+    char MySymbol[2][9]= {{0x01,0x04,0x0e,0x1f,0x04,0x04,0x04,0x00,0x00},
+                          {0x02,0x00,0x00,0x04,0x04,0x04,0x1f,0x0e,0x04}};
+    // use the internal pull-ups
+    Btn_0.mode(PullUp);
+    Btn_1.mode(PullUp);    
+    Btn_2.mode(PullUp);
+    
+    _InitLCD();
+    _WriteLCD(LCDType,0x01);
+    _WriteLCD(WriteUserDefChar,MySymbol[0],9);
+    _WriteLCD(WriteUserDefChar,MySymbol[1],9);
+    
+    Init();
+    
+    // Main loop
+    while (1) {
+        // heater off
+        heater_off();
+        
+        // position cursor 
+        _WriteLCD(SetCursor, 0x00);
+        
+        // read thermo couple
+        readthermo();
+        char msg[32] = {0};
+        sprintf(msg, "Temp: %3.2f C        ", atemp);
+        
+        // Display current temperature
+        _WriteLCD(WriteString, msg, 0);
+        
+        // Display menu
+        _WriteLCD(SetCursor, 0x14);
+        _WriteLCD(WriteString, "[1:CONF] [0:RUN]    ", 0);
+
+        wait_ms(10);
+
+        // Run button ?
+        if (Btn_0.read() == 0)
+                RunMode();
+        else if (Btn_1.read() == 0) 
+            ConfigurationMode();
+    }
+}