![](/media/cache/profiles/a7bf3f5462cc82062e41b3a2262e1a21.50x50_q85.jpg)
based on existing code, added support for max31855 and i2c display
Diff: main.cpp
- 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(); + } +}