From dc86174deae11975b2e83fc3a53dac9f2d5d7ff3 Mon Sep 17 00:00:00 2001 From: Fake-Name Date: Sun, 27 Sep 2020 23:58:27 -0700 Subject: [PATCH 1/6] Build with platformio. --- Code/Reflow_Master/platformio.ini | 22 +++++++++++++++++++ .../{ => src}/ReflowMasterProfile.h | 0 .../Reflow_Master/{ => src}/Reflow_Master.ino | 0 3 files changed, 22 insertions(+) create mode 100644 Code/Reflow_Master/platformio.ini rename Code/Reflow_Master/{ => src}/ReflowMasterProfile.h (100%) rename Code/Reflow_Master/{ => src}/Reflow_Master.ino (100%) diff --git a/Code/Reflow_Master/platformio.ini b/Code/Reflow_Master/platformio.ini new file mode 100644 index 0000000..bfb8c16 --- /dev/null +++ b/Code/Reflow_Master/platformio.ini @@ -0,0 +1,22 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:samd21g18a] +platform = atmelsam +board = adafruit_feather_m0 +upload_protocol = sam-ba +framework = arduino +monitor_speed = 115200 +lib_deps = + adafruit/Adafruit ILI9341@^1.5.6 + adafruit/Adafruit GFX Library@^1.10.1 + mathertel/OneButton@0.0.0-alpha+sha.eb583d713a + adafruit/Adafruit BusIO@^1.5.0 + Wire \ No newline at end of file diff --git a/Code/Reflow_Master/ReflowMasterProfile.h b/Code/Reflow_Master/src/ReflowMasterProfile.h similarity index 100% rename from Code/Reflow_Master/ReflowMasterProfile.h rename to Code/Reflow_Master/src/ReflowMasterProfile.h diff --git a/Code/Reflow_Master/Reflow_Master.ino b/Code/Reflow_Master/src/Reflow_Master.ino similarity index 100% rename from Code/Reflow_Master/Reflow_Master.ino rename to Code/Reflow_Master/src/Reflow_Master.ino From 1dab6f9161d854a28de809dd145a31b8cf538988 Mon Sep 17 00:00:00 2001 From: Fake-Name Date: Mon, 28 Sep 2020 00:00:15 -0700 Subject: [PATCH 2/6] Code formatting. Whitespace changes only. --- Code/Reflow_Master/src/ReflowMasterProfile.h | 196 +- Code/Reflow_Master/src/Reflow_Master.ino | 2838 +++++++++--------- 2 files changed, 1561 insertions(+), 1473 deletions(-) diff --git a/Code/Reflow_Master/src/ReflowMasterProfile.h b/Code/Reflow_Master/src/ReflowMasterProfile.h index b8898e8..222e9ef 100644 --- a/Code/Reflow_Master/src/ReflowMasterProfile.h +++ b/Code/Reflow_Master/src/ReflowMasterProfile.h @@ -11,7 +11,7 @@ Project home: github.com/unexpectedmaker/reflowmaster Blog: unexpectedmaker.com DISCLAIMER: -This software is furnished "as is", without technical support, and with no +This software is furnished "as is", without technical support, and with no warranty, express or implied, as to its usefulness for any purpose. PURPOSE: @@ -33,95 +33,115 @@ This is the profile structure used by the Reflow Master toaster oven controller Fan kick in time if using a fan ( int, seconds ) Open door message time ( int, seconds ) */ + +#pragma once + #define ELEMENTS(x) (sizeof(x) / sizeof(x[0])) - class ReflowGraph - { - - public: - String n; - String t; - int tempDeg; - float reflowGraphX[10]; - float reflowGraphY[10]; - float reflowTangents[10] { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; - float wantedCurve[480]; - int len = -1; - int fanTime = -1; - int offTime = -1; - int completeTime = -1; - - float maxWantedDelta = 0; - - ReflowGraph() - { - } - - ReflowGraph(String nm, String tp, int temp, float flowX[], float flowY[], int leng, int fanT, int offT ) - { - n = nm; - t = tp; - tempDeg = temp; - offTime = offT; - fanTime = fanT; - - int minLength = min( 10, leng ); - - len = minLength; - - completeTime = flowX[ len -1 ]; - - for ( int i = 0; i < minLength; i++ ) - { - reflowGraphX[i] = flowX[i]; - reflowGraphY[i] = flowY[i]; - - if ( i == 0 ) - reflowTangents[i] = 1; - else if ( i >= fanT ) - reflowTangents[i] = 1; - else - reflowTangents[i] = 0; - } - - for ( int i = 0; i < ELEMENTS(wantedCurve); i++ ) - wantedCurve[i] = -1; - } - - ~ReflowGraph() - { - } - - float MaxValue() - { - float maxV = -1; - for( int i = 0; i < len; i++ ) - maxV = max( maxV, reflowGraphY[i] ); - - return maxV; - } - - float MinValue() - { - float minV = 1000; - for( int i = 0; i < len; i++ ) - { - if ( reflowGraphY[i] > 0 ) - minV = min( minV, reflowGraphY[i] ); - } - - return minV; - } - - float MaxTime() - { - float maxV = -1; - for( int i = 0; i < len; i++ ) - maxV = max( maxV, reflowGraphX[i] ); - - return maxV; - } - }; +class ReflowGraph +{ + + public: + String n; + String t; + int tempDeg; + float reflowGraphX[10]; + float reflowGraphY[10]; + float reflowTangents[10] { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; + float wantedCurve[480]; + int len = -1; + int fanTime = -1; + int offTime = -1; + int completeTime = -1; + + float maxWantedDelta = 0; + + ReflowGraph() + { + } + + ReflowGraph(String nm, String tp, int temp, float flowX[], float flowY[], int leng, int fanT, int offT ) + { + n = nm; + t = tp; + tempDeg = temp; + offTime = offT; + fanTime = fanT; + + int minLength = min( 10, leng ); + + len = minLength; + + completeTime = flowX[ len - 1 ]; + + for ( int i = 0; i < minLength; i++ ) + { + reflowGraphX[i] = flowX[i]; + reflowGraphY[i] = flowY[i]; + + if ( i == 0 ) + { + reflowTangents[i] = 1; + } + else if ( i >= fanT ) + { + reflowTangents[i] = 1; + } + else + { + reflowTangents[i] = 0; + } + } + + for ( int i = 0; i < ELEMENTS(wantedCurve); i++ ) + { + wantedCurve[i] = -1; + } + } + + ~ReflowGraph() + { + } + + float MaxValue() + { + float maxV = -1; + + for ( int i = 0; i < len; i++ ) + { + maxV = max( maxV, reflowGraphY[i] ); + } + + return maxV; + } + + float MinValue() + { + float minV = 1000; + + for ( int i = 0; i < len; i++ ) + { + if ( reflowGraphY[i] > 0 ) + { + minV = min( minV, reflowGraphY[i] ); + } + } + + return minV; + } + + float MaxTime() + { + float maxV = -1; + + for ( int i = 0; i < len; i++ ) + { + maxV = max( maxV, reflowGraphX[i] ); + } + + return maxV; + } +}; /* diff --git a/Code/Reflow_Master/src/Reflow_Master.ino b/Code/Reflow_Master/src/Reflow_Master.ino index 1c07d5f..2c49eca 100644 --- a/Code/Reflow_Master/src/Reflow_Master.ino +++ b/Code/Reflow_Master/src/Reflow_Master.ino @@ -94,16 +94,17 @@ #define DKGREY 0x4A49 // Save data struct -typedef struct { - boolean valid = false; - boolean useFan = false; - int fanTimeAfterReflow = 60; - byte paste = 0; - float power = 1; - int lookAhead = 6; - int lookAheadWarm = 1; - int tempOffset = 0; - bool startFullBlast = false; +typedef struct +{ + boolean valid = false; + boolean useFan = false; + int fanTimeAfterReflow = 60; + byte paste = 0; + float power = 1; + int lookAhead = 6; + int lookAheadWarm = 1; + int tempOffset = 0; + bool startFullBlast = false; } Settings; const String ver = "1.08"; @@ -182,427 +183,444 @@ FlashStorage(flash_store, Settings); // This is where we initialise each of the profiles that will get loaded into the Reflkow Master void LoadPaste() { - /* - Each profile is initialised with the follow data: + /* + Each profile is initialised with the follow data: + + Paste name ( String ) + Paste type ( String ) + Paste Reflow Temperature ( int ) + Profile graph X values - time + Profile graph Y values - temperature + Length of the graph ( int, how long if the graph array ) + Fan kick in time if using a fan ( int, seconds ) + Open door message time ( int, seconds ) + */ + float baseGraphX[7] = { 1, 90, 180, 210, 240, 270, 300 }; // time + float baseGraphY[7] = { 27, 90, 130, 138, 165, 138, 27 }; // value - Paste name ( String ) - Paste type ( String ) - Paste Reflow Temperature ( int ) - Profile graph X values - time - Profile graph Y values - temperature - Length of the graph ( int, how long if the graph array ) - Fan kick in time if using a fan ( int, seconds ) - Open door message time ( int, seconds ) - */ - float baseGraphX[7] = { 1, 90, 180, 210, 240, 270, 300 }; // time - float baseGraphY[7] = { 27, 90, 130, 138, 165, 138, 27 }; // value + solderPaste[0] = ReflowGraph( "CHIPQUIK", "No-Clean Sn42/Bi57.6/Ag0.4", 138, baseGraphX, baseGraphY, ELEMENTS(baseGraphX), 240, 270 ); - solderPaste[0] = ReflowGraph( "CHIPQUIK", "No-Clean Sn42/Bi57.6/Ag0.4", 138, baseGraphX, baseGraphY, ELEMENTS(baseGraphX), 240, 270 ); + float baseGraphX1[7] = { 1, 90, 180, 225, 240, 270, 300 }; // time + float baseGraphY1[7] = { 25, 150, 175, 190, 210, 125, 50 }; // value - float baseGraphX1[7] = { 1, 90, 180, 225, 240, 270, 300 }; // time - float baseGraphY1[7] = { 25, 150, 175, 190, 210, 125, 50 }; // value + solderPaste[1] = ReflowGraph( "CHEMTOOLS L", "No Clean 63CR218 Sn63/Pb37", 183, baseGraphX1, baseGraphY1, ELEMENTS(baseGraphX1), 240, 270 ); - solderPaste[1] = ReflowGraph( "CHEMTOOLS L", "No Clean 63CR218 Sn63/Pb37", 183, baseGraphX1, baseGraphY1, ELEMENTS(baseGraphX1), 240, 270 ); + float baseGraphX2[6] = { 1, 75, 130, 180, 210, 250 }; // time + float baseGraphY2[6] = { 25, 150, 175, 210, 150, 50 }; // value - float baseGraphX2[6] = { 1, 75, 130, 180, 210, 250 }; // time - float baseGraphY2[6] = { 25, 150, 175, 210, 150, 50 }; // value + solderPaste[2] = ReflowGraph( "CHEMTOOLS S", "No Clean 63CR218 Sn63/Pb37", 183, baseGraphX2, baseGraphY2, ELEMENTS(baseGraphX2), 180, 210 ); - solderPaste[2] = ReflowGraph( "CHEMTOOLS S", "No Clean 63CR218 Sn63/Pb37", 183, baseGraphX2, baseGraphY2, ELEMENTS(baseGraphX2), 180, 210 ); + float baseGraphX3[7] = { 1, 60, 120, 160, 210, 260, 310 }; // time + float baseGraphY3[7] = { 25, 105, 150, 150, 220, 150, 20 }; // value - float baseGraphX3[7] = { 1, 60, 120, 160, 210, 260, 310 }; // time - float baseGraphY3[7] = { 25, 105, 150, 150, 220, 150, 20 }; // value + solderPaste[3] = ReflowGraph( "DOC SOLDER", "No Clean Sn63/Pb36/Ag2", 187, baseGraphX3, baseGraphY3, ELEMENTS(baseGraphX3), 210, 260 ); - solderPaste[3] = ReflowGraph( "DOC SOLDER", "No Clean Sn63/Pb36/Ag2", 187, baseGraphX3, baseGraphY3, ELEMENTS(baseGraphX3), 210, 260 ); + float baseGraphX4[6] = { 1, 90, 165, 225, 330, 360 }; // time + float baseGraphY4[6] = { 25, 150, 175, 235, 100, 25 }; // value - float baseGraphX4[6] = { 1, 90, 165, 225, 330, 360 }; // time - float baseGraphY4[6] = { 25, 150, 175, 235, 100, 25 }; // value + solderPaste[4] = ReflowGraph( "CHEMTOOLS SAC305 HD", "Sn96.5/Ag3.0/Cu0.5", 225, baseGraphX4, baseGraphY4, ELEMENTS(baseGraphX4), 225, 230 ); - solderPaste[4] = ReflowGraph( "CHEMTOOLS SAC305 HD", "Sn96.5/Ag3.0/Cu0.5", 225, baseGraphX4, baseGraphY4, ELEMENTS(baseGraphX4), 225, 230 ); - - //TODO: Think of a better way to initalise these baseGraph arrays to not need unique array creation + //TODO: Think of a better way to initalise these baseGraph arrays to not need unique array creation } // Obtain the temp value of the current profile at time X int GetGraphValue( int x ) { - return ( CurrentGraph().reflowGraphY[x] ); + return ( CurrentGraph().reflowGraphY[x] ); } int GetGraphTime( int x ) { - return ( CurrentGraph().reflowGraphX[x] ); + return ( CurrentGraph().reflowGraphX[x] ); } // Obtain the current profile ReflowGraph CurrentGraph() { - return solderPaste[ currentGraphIndex ]; + return solderPaste[ currentGraphIndex ]; } // Set the current profile via the array index void SetCurrentGraph( int index ) { - currentGraphIndex = index; - graphRangeMax_X = CurrentGraph().MaxTime(); - graphRangeMax_Y = CurrentGraph().MaxValue() + 5; // extra padding - graphRangeMin_Y = CurrentGraph().MinValue(); - -#ifdef DEBUG - Serial.print("Setting Paste: "); - Serial.println( CurrentGraph().n ); - Serial.println( CurrentGraph().t ); -#endif - - // Initialise the spline for the profile to allow for smooth graph display on UI - timeX = 0; - baseCurve.setPoints(CurrentGraph().reflowGraphX, CurrentGraph().reflowGraphY, CurrentGraph().reflowTangents, CurrentGraph().len); - baseCurve.setDegree( Hermite ); - - - // Re-interpolate data based on spline - for ( int ii = 0; ii <= graphRangeMax_X; ii += 1 ) - { - solderPaste[ currentGraphIndex ].wantedCurve[ii] = baseCurve.value(ii); - } - - // calculate the biggest graph movement delta - float lastWanted = -1; - for ( int i = 0; i < solderPaste[ currentGraphIndex ].offTime; i++ ) - { - float wantedTemp = solderPaste[ currentGraphIndex ].wantedCurve[ i ]; - - if ( lastWanted > -1 ) - { - float wantedDiff = (wantedTemp - lastWanted ); - - if ( wantedDiff > solderPaste[ currentGraphIndex ].maxWantedDelta ) - solderPaste[ currentGraphIndex ].maxWantedDelta = wantedDiff; - } - lastWanted = wantedTemp; - } + currentGraphIndex = index; + graphRangeMax_X = CurrentGraph().MaxTime(); + graphRangeMax_Y = CurrentGraph().MaxValue() + 5; // extra padding + graphRangeMin_Y = CurrentGraph().MinValue(); + + #ifdef DEBUG + Serial.print("Setting Paste: "); + Serial.println( CurrentGraph().n ); + Serial.println( CurrentGraph().t ); + #endif + + // Initialise the spline for the profile to allow for smooth graph display on UI + timeX = 0; + baseCurve.setPoints(CurrentGraph().reflowGraphX, CurrentGraph().reflowGraphY, CurrentGraph().reflowTangents, CurrentGraph().len); + baseCurve.setDegree( Hermite ); + + + // Re-interpolate data based on spline + for ( int ii = 0; ii <= graphRangeMax_X; ii += 1 ) + { + solderPaste[ currentGraphIndex ].wantedCurve[ii] = baseCurve.value(ii); + } + + // calculate the biggest graph movement delta + float lastWanted = -1; + + for ( int i = 0; i < solderPaste[ currentGraphIndex ].offTime; i++ ) + { + float wantedTemp = solderPaste[ currentGraphIndex ].wantedCurve[ i ]; + + if ( lastWanted > -1 ) + { + float wantedDiff = (wantedTemp - lastWanted ); + + if ( wantedDiff > solderPaste[ currentGraphIndex ].maxWantedDelta ) + { + solderPaste[ currentGraphIndex ].maxWantedDelta = wantedDiff; + } + } + + lastWanted = wantedTemp; + } } void setup() { - // Setup all GPIO - pinMode( BUZZER, OUTPUT ); - pinMode( RELAY, OUTPUT ); - pinMode( FAN, OUTPUT ); - - // Turn of Green Debug LED - pinMode( 13, INPUT ); - - pinMode( BUTTON0, INPUT ); - pinMode( BUTTON1, INPUT ); - pinMode( BUTTON2, INPUT ); - pinMode( BUTTON3, INPUT ); - - // Turn off the SSR - duty cycle of 0 - SetRelayFrequency( 0 ); - -#ifdef DEBUG - Serial.begin(115200); -#endif - - // just wait a bit before we try to load settings from FLASH - delay(500); - - // load settings from FLASH - set = flash_store.read(); - - // If no settings were loaded, initialise data and save - if ( !set.valid ) - { - SetDefaults(); - newSettings = true; - flash_store.write(set); - } - - // Attatch button IO for OneButton - button0.attachClick(button0Press); - button1.attachClick(button1Press); - button2.attachClick(button2Press); - button3.attachClick(button3Press); - -#ifdef DEBUG - Serial.println("TFT Begin..."); -#endif - - // Start up the TFT and show the boot screen - tft.begin(32000000); - BootScreen(); - BuzzerStart(); - - delay(200); - - // Start up the MAX31855 -#ifdef DEBUG - Serial.println("Thermocouple Begin..."); -#endif - tc.begin(); - - // delay for initial temp probe read to be garbage - delay(500); - - // Load up the profiles - LoadPaste(); - // Set the current profile based on last selected - SetCurrentGraph( set.paste ); - - delay(500); - - // Show the main menu - ShowMenu(); + // Setup all GPIO + pinMode( BUZZER, OUTPUT ); + pinMode( RELAY, OUTPUT ); + pinMode( FAN, OUTPUT ); + + // Turn of Green Debug LED + pinMode( 13, INPUT ); + + pinMode( BUTTON0, INPUT ); + pinMode( BUTTON1, INPUT ); + pinMode( BUTTON2, INPUT ); + pinMode( BUTTON3, INPUT ); + + // Turn off the SSR - duty cycle of 0 + SetRelayFrequency( 0 ); + + #ifdef DEBUG + Serial.begin(115200); + #endif + + // just wait a bit before we try to load settings from FLASH + delay(500); + + // load settings from FLASH + set = flash_store.read(); + + // If no settings were loaded, initialise data and save + if ( !set.valid ) + { + SetDefaults(); + newSettings = true; + flash_store.write(set); + } + + // Attatch button IO for OneButton + button0.attachClick(button0Press); + button1.attachClick(button1Press); + button2.attachClick(button2Press); + button3.attachClick(button3Press); + + #ifdef DEBUG + Serial.println("TFT Begin..."); + #endif + + // Start up the TFT and show the boot screen + tft.begin(32000000); + BootScreen(); + BuzzerStart(); + + delay(200); + + // Start up the MAX31855 + #ifdef DEBUG + Serial.println("Thermocouple Begin..."); + #endif + tc.begin(); + + // delay for initial temp probe read to be garbage + delay(500); + + // Load up the profiles + LoadPaste(); + // Set the current profile based on last selected + SetCurrentGraph( set.paste ); + + delay(500); + + // Show the main menu + ShowMenu(); } void loop() { - // Used by OneButton to poll for button inputs - button0.tick(); - button1.tick(); - button2.tick(); - button3.tick(); - - // Current activity state machine - if ( state == 0 ) // BOOT - { - return; - } - else if ( state == 1 ) // WARMUP - We sit here until the probe reaches the starting temp for the profile - { - if ( nextTempRead < millis() ) // we only read the probe every second - { - nextTempRead = millis() + 1000; - - ReadCurrentTemp(); - MatchTemp(); - - if ( currentTemp >= GetGraphValue(0) ) - { - // We have reached the starting temp for the profile, so lets start baking our boards! - lastTemp = currentTemp; - avgReadCount = 0; - currentTempAvg = 0; - - StartReflow(); - } - else if ( currentTemp > 0 ) - { - // Show the current probe temp so we can watch as it reaches the minimum starting value - tft.setTextColor( YELLOW, BLACK ); - tft.setTextSize(5); - println_Center( tft, " " + String( round( currentTemp ) ) + "c ", tft.width() / 2, ( tft.height() / 2 ) + 10 ); - } - } - return; - } - else if ( state == 3 ) // FINISHED - { - // do we keep the fan on after reflow finishes to help cooldown? - KeepFanOnCheck(); - return; - } - else if ( state == 11 || state == 12 || state == 13 ) // SETTINGS - { - // Currently not used - return; - } - else if ( state == 10 ) // MENU - { - if ( nextTempRead < millis() ) - { - nextTempRead = millis() + 1000; - - // We show the current probe temp in the men screen just for info - ReadCurrentTemp(); - - if ( currentTemp > 0 ) - { - tft.setTextColor( YELLOW, BLACK ); - tft.setTextSize(5); - int third = tft.width() / 4; - println_Center( tft, " " + String( round( currentTemp ) ) + "c ", tft.width() / 2, ( tft.height() / 2 ) + 10 ); - } - } - - // do we keep the fan on after reflow finishes to help cooldown? - KeepFanOnCheck(); - return; - } - else if ( state == 15 ) - { - // Currently not used - return; - } - else if ( state == 16 ) // calibration - not currently used - { - if ( nextTempRead < millis() ) - { - nextTempRead = millis() + 1000; - - ReadCurrentTemp(); - - MatchCalibrationTemp(); - - if ( calibrationState < 2 ) - { - tft.setTextColor( CYAN, BLACK ); - tft.setTextSize(2); - - if ( calibrationState == 0 ) - { - if ( currentTemp < GetGraphValue(0) ) - println_Center( tft, "WARMING UP", tft.width() / 2, ( tft.height() / 2 ) - 15 ); - else - println_Center( tft, "HEAT UP SPEED", tft.width() / 2, ( tft.height() / 2 ) - 15 ); - - println_Center( tft, "TARGET " + String( GetGraphValue(1) ) + "c in " + String( GetGraphTime(1) ) + "s", tft.width() / 2, ( tft.height() - 18 ) ); - } - else if ( calibrationState == 1 ) - { - println_Center( tft, "COOL DOWN LEVEL", tft.width() / 2, ( tft.height() / 2 ) - 15 ); - tft.fillRect( 0, tft.height() - 30, tft.width(), 30, BLACK ); - } - - - // only show the timer when we have hit the profile starting temp - if (currentTemp >= GetGraphValue(0) ) - { - // adjust the timer colour based on good or bad values - if ( calibrationState == 0 ) - { - if ( calibrationSeconds <= GetGraphTime(1) ) - tft.setTextColor( WHITE, BLACK ); - else - tft.setTextColor( ORANGE, BLACK ); - } - else - { - tft.setTextColor( WHITE, BLACK ); - } - - tft.setTextSize(4); - println_Center( tft, " " + String( calibrationSeconds ) + " secs ", tft.width() / 2, ( tft.height() / 2 ) + 20 ); - } - tft.setTextSize(5); - tft.setTextColor( YELLOW, BLACK ); - println_Center( tft, " " + String( round( currentTemp ) ) + "c ", tft.width() / 2, ( tft.height() / 2 ) + 65 ); - - - } - else if ( calibrationState == 2 ) - { - calibrationState = 3; - - tft.setTextColor( GREEN, BLACK ); - tft.setTextSize(2); - tft.fillRect( 0, (tft.height() / 2 ) - 45, tft.width(), (tft.height() / 2 ) + 45, BLACK ); - println_Center( tft, "RESULTS!", tft.width() / 2, ( tft.height() / 2 ) - 45 ); - - tft.setTextColor( WHITE, BLACK ); - tft.setCursor( 20, ( tft.height() / 2 ) - 10 ); - tft.print( "RISE " ); - if ( calibrationUpMatch ) - { - tft.setTextColor( GREEN, BLACK ); - tft.print( "PASS" ); - } - else - { - tft.setTextColor( ORANGE, BLACK ); - tft.print( "FAIL " ); - tft.setTextColor( WHITE, BLACK ); - tft.print( "REACHED " + String( round(calibrationRiseVal * 100) ) + "%") ; - } - - tft.setTextColor( WHITE, BLACK ); - tft.setCursor( 20, ( tft.height() / 2 ) + 20 ); - tft.print( "DROP " ); - if ( calibrationDownMatch ) - { - tft.setTextColor( GREEN, BLACK ); - tft.print( "PASS" ); - tft.setTextColor( WHITE, BLACK ); - tft.print( "DROPPED " + String( round(calibrationDropVal * 100) ) + "%") ; - } - else - { - tft.setTextColor( ORANGE, BLACK ); - tft.print( "FAIL " ); - tft.setTextColor( WHITE, BLACK ); - tft.print( "DROPPED " + String( round(calibrationDropVal * 100) ) + "%") ; - - tft.setTextColor( WHITE, BLACK ); - tft.setCursor( 20, ( tft.height() / 2 ) + 40 ); - tft.print( "RECOMMEND ADDING FAN") ; - } - } - } - } - else // state is 2 - REFLOW - { - if ( nextTempAvgRead < millis() ) - { - nextTempAvgRead = millis() + 100; - ReadCurrentTempAvg(); - } - if ( nextTempRead < millis() ) - { - nextTempRead = millis() + 1000; - - // Set the temp from the average - currentTemp = ( currentTempAvg / avgReadCount ); - // clear the variables for next run - avgReadCount = 0; - currentTempAvg = 0; - - // Control the SSR - MatchTemp(); - - if ( currentTemp > 0 ) - { - timeX++; - - if ( timeX > CurrentGraph().completeTime ) - { - EndReflow(); - } - else - { - Graph(tft, timeX, currentTemp, 30, 220, 270, 180 ); - - if ( timeX < CurrentGraph().fanTime ) - { - float wantedTemp = CurrentGraph().wantedCurve[ (int)timeX ]; - DrawHeading( String( round( currentTemp ) ) + "/" + String( (int)wantedTemp ) + "c", currentPlotColor, BLACK ); - -#ifdef DEBUG - tft.setCursor( 60, 40 ); - tft.setTextSize(2); - tft.fillRect( 60, 40, 80, 20, BLACK ); - tft.println( String( round((currentDuty / 256) * 100 )) + "%" ); -#endif - } - } - } - } - } + // Used by OneButton to poll for button inputs + button0.tick(); + button1.tick(); + button2.tick(); + button3.tick(); + + // Current activity state machine + if ( state == 0 ) // BOOT + { + return; + } + else if ( state == 1 ) // WARMUP - We sit here until the probe reaches the starting temp for the profile + { + if ( nextTempRead < millis() ) // we only read the probe every second + { + nextTempRead = millis() + 1000; + + ReadCurrentTemp(); + MatchTemp(); + + if ( currentTemp >= GetGraphValue(0) ) + { + // We have reached the starting temp for the profile, so lets start baking our boards! + lastTemp = currentTemp; + avgReadCount = 0; + currentTempAvg = 0; + + StartReflow(); + } + else if ( currentTemp > 0 ) + { + // Show the current probe temp so we can watch as it reaches the minimum starting value + tft.setTextColor( YELLOW, BLACK ); + tft.setTextSize(5); + println_Center( tft, " " + String( round( currentTemp ) ) + "c ", tft.width() / 2, ( tft.height() / 2 ) + 10 ); + } + } + + return; + } + else if ( state == 3 ) // FINISHED + { + // do we keep the fan on after reflow finishes to help cooldown? + KeepFanOnCheck(); + return; + } + else if ( state == 11 || state == 12 || state == 13 ) // SETTINGS + { + // Currently not used + return; + } + else if ( state == 10 ) // MENU + { + if ( nextTempRead < millis() ) + { + nextTempRead = millis() + 1000; + + // We show the current probe temp in the men screen just for info + ReadCurrentTemp(); + + if ( currentTemp > 0 ) + { + tft.setTextColor( YELLOW, BLACK ); + tft.setTextSize(5); + int third = tft.width() / 4; + println_Center( tft, " " + String( round( currentTemp ) ) + "c ", tft.width() / 2, ( tft.height() / 2 ) + 10 ); + } + } + + // do we keep the fan on after reflow finishes to help cooldown? + KeepFanOnCheck(); + return; + } + else if ( state == 15 ) + { + // Currently not used + return; + } + else if ( state == 16 ) // calibration - not currently used + { + if ( nextTempRead < millis() ) + { + nextTempRead = millis() + 1000; + + ReadCurrentTemp(); + + MatchCalibrationTemp(); + + if ( calibrationState < 2 ) + { + tft.setTextColor( CYAN, BLACK ); + tft.setTextSize(2); + + if ( calibrationState == 0 ) + { + if ( currentTemp < GetGraphValue(0) ) + { + println_Center( tft, "WARMING UP", tft.width() / 2, ( tft.height() / 2 ) - 15 ); + } + else + { + println_Center( tft, "HEAT UP SPEED", tft.width() / 2, ( tft.height() / 2 ) - 15 ); + } + + println_Center( tft, "TARGET " + String( GetGraphValue(1) ) + "c in " + String( GetGraphTime(1) ) + "s", tft.width() / 2, ( tft.height() - 18 ) ); + } + else if ( calibrationState == 1 ) + { + println_Center( tft, "COOL DOWN LEVEL", tft.width() / 2, ( tft.height() / 2 ) - 15 ); + tft.fillRect( 0, tft.height() - 30, tft.width(), 30, BLACK ); + } + + + // only show the timer when we have hit the profile starting temp + if (currentTemp >= GetGraphValue(0) ) + { + // adjust the timer colour based on good or bad values + if ( calibrationState == 0 ) + { + if ( calibrationSeconds <= GetGraphTime(1) ) + { + tft.setTextColor( WHITE, BLACK ); + } + else + { + tft.setTextColor( ORANGE, BLACK ); + } + } + else + { + tft.setTextColor( WHITE, BLACK ); + } + + tft.setTextSize(4); + println_Center( tft, " " + String( calibrationSeconds ) + " secs ", tft.width() / 2, ( tft.height() / 2 ) + 20 ); + } + + tft.setTextSize(5); + tft.setTextColor( YELLOW, BLACK ); + println_Center( tft, " " + String( round( currentTemp ) ) + "c ", tft.width() / 2, ( tft.height() / 2 ) + 65 ); + + + } + else if ( calibrationState == 2 ) + { + calibrationState = 3; + + tft.setTextColor( GREEN, BLACK ); + tft.setTextSize(2); + tft.fillRect( 0, (tft.height() / 2 ) - 45, tft.width(), (tft.height() / 2 ) + 45, BLACK ); + println_Center( tft, "RESULTS!", tft.width() / 2, ( tft.height() / 2 ) - 45 ); + + tft.setTextColor( WHITE, BLACK ); + tft.setCursor( 20, ( tft.height() / 2 ) - 10 ); + tft.print( "RISE " ); + + if ( calibrationUpMatch ) + { + tft.setTextColor( GREEN, BLACK ); + tft.print( "PASS" ); + } + else + { + tft.setTextColor( ORANGE, BLACK ); + tft.print( "FAIL " ); + tft.setTextColor( WHITE, BLACK ); + tft.print( "REACHED " + String( round(calibrationRiseVal * 100) ) + "%") ; + } + + tft.setTextColor( WHITE, BLACK ); + tft.setCursor( 20, ( tft.height() / 2 ) + 20 ); + tft.print( "DROP " ); + + if ( calibrationDownMatch ) + { + tft.setTextColor( GREEN, BLACK ); + tft.print( "PASS" ); + tft.setTextColor( WHITE, BLACK ); + tft.print( "DROPPED " + String( round(calibrationDropVal * 100) ) + "%") ; + } + else + { + tft.setTextColor( ORANGE, BLACK ); + tft.print( "FAIL " ); + tft.setTextColor( WHITE, BLACK ); + tft.print( "DROPPED " + String( round(calibrationDropVal * 100) ) + "%") ; + + tft.setTextColor( WHITE, BLACK ); + tft.setCursor( 20, ( tft.height() / 2 ) + 40 ); + tft.print( "RECOMMEND ADDING FAN") ; + } + } + } + } + else // state is 2 - REFLOW + { + if ( nextTempAvgRead < millis() ) + { + nextTempAvgRead = millis() + 100; + ReadCurrentTempAvg(); + } + + if ( nextTempRead < millis() ) + { + nextTempRead = millis() + 1000; + + // Set the temp from the average + currentTemp = ( currentTempAvg / avgReadCount ); + // clear the variables for next run + avgReadCount = 0; + currentTempAvg = 0; + + // Control the SSR + MatchTemp(); + + if ( currentTemp > 0 ) + { + timeX++; + + if ( timeX > CurrentGraph().completeTime ) + { + EndReflow(); + } + else + { + Graph(tft, timeX, currentTemp, 30, 220, 270, 180 ); + + if ( timeX < CurrentGraph().fanTime ) + { + float wantedTemp = CurrentGraph().wantedCurve[ (int)timeX ]; + DrawHeading( String( round( currentTemp ) ) + "/" + String( (int)wantedTemp ) + "c", currentPlotColor, BLACK ); + + #ifdef DEBUG + tft.setCursor( 60, 40 ); + tft.setTextSize(2); + tft.fillRect( 60, 40, 80, 20, BLACK ); + tft.println( String( round((currentDuty / 256) * 100 )) + "%" ); + #endif + } + } + } + } + } } // This is where the SSR is controlled via PWM void SetRelayFrequency( int duty ) { - // calculate the wanted duty based on settings power override - currentDuty = ((float)duty * set.power ); + // calculate the wanted duty based on settings power override + currentDuty = ((float)duty * set.power ); - // Write the clamped duty cycle to the RELAY GPIO - analogWrite( RELAY, constrain( round( currentDuty ), 0, 255) ); + // Write the clamped duty cycle to the RELAY GPIO + analogWrite( RELAY, constrain( round( currentDuty ), 0, 255) ); -#ifdef DEBUG - Serial.print("RELAY Duty Cycle: "); - Serial.println( String( ( currentDuty / 256.0 ) * 100) + "%" + " Using Power: " + String( round( set.power * 100 )) + "%" ); -#endif + #ifdef DEBUG + Serial.print("RELAY Duty Cycle: "); + Serial.println( String( ( currentDuty / 256.0 ) * 100) + "%" + " Using Power: " + String( round( set.power * 100 )) + "%" ); + #endif } /* @@ -612,52 +630,54 @@ void SetRelayFrequency( int duty ) void MatchCalibrationTemp() { - if ( calibrationState == 0 ) // temp speed - { - // Set SSR to full duty cycle - 100% - SetRelayFrequency( 255 ); - - // Only count seconds from when we reach the profile starting temp - if ( currentTemp >= GetGraphValue(0) ) - calibrationSeconds ++; - - if ( currentTemp >= GetGraphValue(1) ) - { -#ifdef DEBUG - Serial.println("Cal Heat Up Speed " + String( calibrationSeconds ) ); -#endif - - calibrationRiseVal = ( (float)currentTemp / (float)( GetGraphValue(1) ) ); - calibrationUpMatch = ( calibrationSeconds <= GetGraphTime(1) ); - - - calibrationState = 1; // cooldown - SetRelayFrequency( 0 ); - StartFan( false ); - Buzzer( 2000, 50 ); - } - } - else if ( calibrationState == 1 ) - { - calibrationSeconds --; - SetRelayFrequency( 0 ); - - if ( calibrationSeconds <= 0 ) - { - Buzzer( 2000, 50 ); -#ifdef DEBUG - Serial.println("Cal Cool Down Temp " + String( currentTemp ) ); -#endif - - // calc calibration drop percentage value - calibrationDropVal = ( (float)( GetGraphValue(1) - currentTemp ) / (float)GetGraphValue(1) ); - // Did we drop in temp > 33% of our target temp? If not, recomment using a fan! - calibrationDownMatch = ( calibrationDropVal > 0.33 ); - - calibrationState = 2; // finished - StartFan( true ); - } - } + if ( calibrationState == 0 ) // temp speed + { + // Set SSR to full duty cycle - 100% + SetRelayFrequency( 255 ); + + // Only count seconds from when we reach the profile starting temp + if ( currentTemp >= GetGraphValue(0) ) + { + calibrationSeconds ++; + } + + if ( currentTemp >= GetGraphValue(1) ) + { + #ifdef DEBUG + Serial.println("Cal Heat Up Speed " + String( calibrationSeconds ) ); + #endif + + calibrationRiseVal = ( (float)currentTemp / (float)( GetGraphValue(1) ) ); + calibrationUpMatch = ( calibrationSeconds <= GetGraphTime(1) ); + + + calibrationState = 1; // cooldown + SetRelayFrequency( 0 ); + StartFan( false ); + Buzzer( 2000, 50 ); + } + } + else if ( calibrationState == 1 ) + { + calibrationSeconds --; + SetRelayFrequency( 0 ); + + if ( calibrationSeconds <= 0 ) + { + Buzzer( 2000, 50 ); + #ifdef DEBUG + Serial.println("Cal Cool Down Temp " + String( currentTemp ) ); + #endif + + // calc calibration drop percentage value + calibrationDropVal = ( (float)( GetGraphValue(1) - currentTemp ) / (float)GetGraphValue(1) ); + // Did we drop in temp > 33% of our target temp? If not, recomment using a fan! + calibrationDownMatch = ( calibrationDropVal > 0.33 ); + + calibrationState = 2; // finished + StartFan( true ); + } + } } /* @@ -667,219 +687,234 @@ void MatchCalibrationTemp() void KeepFanOnCheck() { - // do we keep the fan on after reflow finishes to help cooldown? - if ( set.useFan && millis() < keepFanOnTime ) - StartFan( true ); - else - StartFan( false ); + // do we keep the fan on after reflow finishes to help cooldown? + if ( set.useFan && millis() < keepFanOnTime ) + { + StartFan( true ); + } + else + { + StartFan( false ); + } } void ReadCurrentTempAvg() { - int status = tc.read(); + int status = tc.read(); - float internal = tc.getInternal(); - currentTempAvg += tc.getTemperature() + set.tempOffset; - avgReadCount++; + float internal = tc.getInternal(); + currentTempAvg += tc.getTemperature() + set.tempOffset; + avgReadCount++; } // Read the temp probe void ReadCurrentTemp() { - int status = tc.read(); -#ifdef DEBUG - if (status != 0 ) - { - Serial.print("TC Read Error Status: "); - Serial.println( status ); - } -#endif - float internal = tc.getInternal(); - currentTemp = tc.getTemperature() + set.tempOffset; + int status = tc.read(); + #ifdef DEBUG + + if (status != 0 ) + { + Serial.print("TC Read Error Status: "); + Serial.println( status ); + } + + #endif + float internal = tc.getInternal(); + currentTemp = tc.getTemperature() + set.tempOffset; } // This is where the magic happens for temperature matching void MatchTemp() { - float duty = 0; - float wantedTemp = 0; - float wantedDiff = 0; - float tempDiff = 0; - float perc = 0; - - // if we are still before the main flow cut-off time (last peak) - if ( timeX < CurrentGraph().offTime ) - { - // We are looking XXX steps ahead of the ideal graph to compensate for slow movement of oven temp - if ( timeX < CurrentGraph().reflowGraphX[2] ) - wantedTemp = CurrentGraph().wantedCurve[ (int)timeX + set.lookAheadWarm ]; - else - wantedTemp = CurrentGraph().wantedCurve[ (int)timeX + set.lookAhead ]; - - wantedDiff = (wantedTemp - lastWantedTemp ); - lastWantedTemp = wantedTemp; - - tempDiff = ( currentTemp - lastTemp ); - lastTemp = currentTemp; - - perc = wantedDiff - tempDiff; - -#ifdef DEBUG - Serial.print( "T: " ); - Serial.print( timeX ); - - Serial.print( " Current: " ); - Serial.print( currentTemp ); - - Serial.print( " Wanted: " ); - Serial.print( wantedTemp ); - - Serial.print( " T Diff: " ); - Serial.print( tempDiff ); - - Serial.print( " W Diff: " ); - Serial.print( wantedDiff ); - - Serial.print( " Perc: " ); - Serial.print( perc ); -#endif - - isCuttoff = false; - - // have to passed the fan turn on time? - if ( !isFanOn && timeX >= CurrentGraph().fanTime ) - { -#ifdef DEBUG - Serial.print( "COOLDOWN: " ); -#endif - // If we are usng the fan, turn it on - if ( set.useFan ) - { - DrawHeading( "COOLDOWN!", GREEN, BLACK ); - Buzzer( 2000, 2000 ); - - StartFan ( true ); - } - else // otherwise YELL at the user to open the oven door - { - if ( buzzerCount > 0 ) - { - DrawHeading( "OPEN OVEN", RED, BLACK ); - Buzzer( 2000, 2000 ); - buzzerCount--; - } - } - } - } - else - { - // YELL at the user to open the oven door - if ( !isCuttoff && set.useFan ) - { - DrawHeading( "OPEN OVEN", GREEN, BLACK ); - Buzzer( 2000, 2000 ); - -#ifdef DEBUG - Serial.print( "CUTOFF: " ); -#endif - } - else if ( !set.useFan ) - { - StartFan ( false ); - } - - isCuttoff = true; - } - - currentDetla = (wantedTemp - currentTemp); - -#ifdef DEBUG - Serial.print( " Delta: " ); - Serial.print( currentDetla ); -#endif - - float base = 128; - - if ( currentDetla >= 0 ) - { - base = 128 + ( currentDetla * 5 ); - } - else if ( currentDetla < 0 ) - { - base = 32 + ( currentDetla * 15 ); - } - - base = constrain( base, 0, 256 ); - -#ifdef DEBUG - Serial.print(" Base: "); - Serial.print( base ); - Serial.print( " -> " ); -#endif - - duty = base + ( 172 * perc ); - duty = constrain( duty, 0, 256 ); - - // override for full blast at start only if the current Temp is less than the wanted Temp, and it's in the ram before pre-soak starts. - if ( set.startFullBlast && timeX < CurrentGraph().reflowGraphX[1] && currentTemp < wantedTemp ) - duty = 256; - - currentPlotColor = GREEN; - - SetRelayFrequency( duty ); + float duty = 0; + float wantedTemp = 0; + float wantedDiff = 0; + float tempDiff = 0; + float perc = 0; + + // if we are still before the main flow cut-off time (last peak) + if ( timeX < CurrentGraph().offTime ) + { + // We are looking XXX steps ahead of the ideal graph to compensate for slow movement of oven temp + if ( timeX < CurrentGraph().reflowGraphX[2] ) + { + wantedTemp = CurrentGraph().wantedCurve[ (int)timeX + set.lookAheadWarm ]; + } + else + { + wantedTemp = CurrentGraph().wantedCurve[ (int)timeX + set.lookAhead ]; + } + + wantedDiff = (wantedTemp - lastWantedTemp ); + lastWantedTemp = wantedTemp; + + tempDiff = ( currentTemp - lastTemp ); + lastTemp = currentTemp; + + perc = wantedDiff - tempDiff; + + #ifdef DEBUG + Serial.print( "T: " ); + Serial.print( timeX ); + + Serial.print( " Current: " ); + Serial.print( currentTemp ); + + Serial.print( " Wanted: " ); + Serial.print( wantedTemp ); + + Serial.print( " T Diff: " ); + Serial.print( tempDiff ); + + Serial.print( " W Diff: " ); + Serial.print( wantedDiff ); + + Serial.print( " Perc: " ); + Serial.print( perc ); + #endif + + isCuttoff = false; + + // have to passed the fan turn on time? + if ( !isFanOn && timeX >= CurrentGraph().fanTime ) + { + #ifdef DEBUG + Serial.print( "COOLDOWN: " ); + #endif + + // If we are usng the fan, turn it on + if ( set.useFan ) + { + DrawHeading( "COOLDOWN!", GREEN, BLACK ); + Buzzer( 2000, 2000 ); + + StartFan ( true ); + } + else // otherwise YELL at the user to open the oven door + { + if ( buzzerCount > 0 ) + { + DrawHeading( "OPEN OVEN", RED, BLACK ); + Buzzer( 2000, 2000 ); + buzzerCount--; + } + } + } + } + else + { + // YELL at the user to open the oven door + if ( !isCuttoff && set.useFan ) + { + DrawHeading( "OPEN OVEN", GREEN, BLACK ); + Buzzer( 2000, 2000 ); + + #ifdef DEBUG + Serial.print( "CUTOFF: " ); + #endif + } + else if ( !set.useFan ) + { + StartFan ( false ); + } + + isCuttoff = true; + } + + currentDetla = (wantedTemp - currentTemp); + + #ifdef DEBUG + Serial.print( " Delta: " ); + Serial.print( currentDetla ); + #endif + + float base = 128; + + if ( currentDetla >= 0 ) + { + base = 128 + ( currentDetla * 5 ); + } + else if ( currentDetla < 0 ) + { + base = 32 + ( currentDetla * 15 ); + } + + base = constrain( base, 0, 256 ); + + #ifdef DEBUG + Serial.print(" Base: "); + Serial.print( base ); + Serial.print( " -> " ); + #endif + + duty = base + ( 172 * perc ); + duty = constrain( duty, 0, 256 ); + + // override for full blast at start only if the current Temp is less than the wanted Temp, and it's in the ram before pre-soak starts. + if ( set.startFullBlast && timeX < CurrentGraph().reflowGraphX[1] && currentTemp < wantedTemp ) + { + duty = 256; + } + + currentPlotColor = GREEN; + + SetRelayFrequency( duty ); } void StartFan ( bool start ) { - if ( set.useFan ) - { - bool isOn = digitalRead( FAN ); - if ( start != isOn ) - { - -#ifdef DEBUG - Serial.print("***** FAN Use? "); - Serial.print( set.useFan ); - Serial.print( " start? "); - Serial.println( start ); -#endif - - digitalWrite ( FAN, ( start ? HIGH : LOW ) ); - } - isFanOn = start; - } - else - { - isFanOn = false; - } + if ( set.useFan ) + { + bool isOn = digitalRead( FAN ); + + if ( start != isOn ) + { + + #ifdef DEBUG + Serial.print("***** FAN Use? "); + Serial.print( set.useFan ); + Serial.print( " start? "); + Serial.println( start ); + #endif + + digitalWrite ( FAN, ( start ? HIGH : LOW ) ); + } + + isFanOn = start; + } + else + { + isFanOn = false; + } } void DrawHeading( String lbl, unsigned int acolor, unsigned int bcolor ) { - tft.setTextSize(4); - tft.setTextColor(acolor , bcolor); - tft.setCursor(0, 0); - tft.fillRect( 0, 0, 220, 40, BLACK ); - tft.println( String(lbl) ); + tft.setTextSize(4); + tft.setTextColor(acolor , bcolor); + tft.setCursor(0, 0); + tft.fillRect( 0, 0, 220, 40, BLACK ); + tft.println( String(lbl) ); } // buzz the buzzer void Buzzer( int hertz, int len ) { - tone( BUZZER, hertz, len); + tone( BUZZER, hertz, len); } // Startup Tune void BuzzerStart() { - tone( BUZZER, 262, 200); - delay(210); - tone( BUZZER, 523, 100); - delay(150); - tone( BUZZER, 523, 100); - delay(150); - noTone(BUZZER); + tone( BUZZER, 262, 200); + delay(210); + tone( BUZZER, 523, 100); + delay(150); + tone( BUZZER, 523, 100); + delay(150); + noTone(BUZZER); } @@ -888,475 +923,484 @@ double ox , oy ; void DrawBaseGraph() { - oy = 220; - ox = 30; - timeX = 0; - - for ( int ii = 0; ii <= graphRangeMax_X; ii += 5 ) - { - GraphDefault(tft, ii, CurrentGraph().wantedCurve[ii], 30, 220, 270, 180, PINK ); - } - - ox = 30; - oy = 220; - timeX = 0; + oy = 220; + ox = 30; + timeX = 0; + + for ( int ii = 0; ii <= graphRangeMax_X; ii += 5 ) + { + GraphDefault(tft, ii, CurrentGraph().wantedCurve[ii], 30, 220, 270, 180, PINK ); + } + + ox = 30; + oy = 220; + timeX = 0; } void BootScreen() { - tft.setRotation(1); - tft.fillScreen(BLACK); + tft.setRotation(1); + tft.fillScreen(BLACK); - tft.setTextColor( GREEN, BLACK ); - tft.setTextSize(3); - println_Center( tft, "REFLOW MASTER", tft.width() / 2, ( tft.height() / 2 ) - 8 ); + tft.setTextColor( GREEN, BLACK ); + tft.setTextSize(3); + println_Center( tft, "REFLOW MASTER", tft.width() / 2, ( tft.height() / 2 ) - 8 ); - tft.setTextSize(2); - tft.setTextColor( WHITE, BLACK ); - println_Center( tft, "unexpectedmaker.com", tft.width() / 2, ( tft.height() / 2 ) + 20 ); - tft.setTextSize(1); - println_Center( tft, "Code v" + ver, tft.width() / 2, tft.height() - 20 ); + tft.setTextSize(2); + tft.setTextColor( WHITE, BLACK ); + println_Center( tft, "unexpectedmaker.com", tft.width() / 2, ( tft.height() / 2 ) + 20 ); + tft.setTextSize(1); + println_Center( tft, "Code v" + ver, tft.width() / 2, tft.height() - 20 ); - state = 10; + state = 10; } void ShowMenu() { - state = 10; - SetRelayFrequency( 0 ); + state = 10; + SetRelayFrequency( 0 ); - set = flash_store.read(); + set = flash_store.read(); - tft.fillScreen(BLACK); + tft.fillScreen(BLACK); - tft.setTextColor( WHITE, BLACK ); - tft.setTextSize(2); - tft.setCursor( 20, 20 ); - tft.println( "CURRENT PASTE" ); + tft.setTextColor( WHITE, BLACK ); + tft.setTextSize(2); + tft.setCursor( 20, 20 ); + tft.println( "CURRENT PASTE" ); - tft.setTextColor( YELLOW, BLACK ); - tft.setCursor( 20, 40 ); - tft.println( CurrentGraph().n ); - tft.setCursor( 20, 60 ); - tft.println( String(CurrentGraph().tempDeg) + "deg"); + tft.setTextColor( YELLOW, BLACK ); + tft.setCursor( 20, 40 ); + tft.println( CurrentGraph().n ); + tft.setCursor( 20, 60 ); + tft.println( String(CurrentGraph().tempDeg) + "deg"); - if ( newSettings ) - { - tft.setTextColor( CYAN, BLACK ); - println_Center( tft, "Settings Stomped!!", tft.width() / 2, tft.height() - 80 ); - } + if ( newSettings ) + { + tft.setTextColor( CYAN, BLACK ); + println_Center( tft, "Settings Stomped!!", tft.width() / 2, tft.height() - 80 ); + } - tft.setTextSize(1); - tft.setTextColor( WHITE, BLACK ); - println_Center( tft, "Reflow Master - Code v" + ver, tft.width() / 2, tft.height() - 20 ); + tft.setTextSize(1); + tft.setTextColor( WHITE, BLACK ); + println_Center( tft, "Reflow Master - Code v" + ver, tft.width() / 2, tft.height() - 20 ); - ShowMenuOptions( true ); + ShowMenuOptions( true ); } void ShowSettings() { - state = 11; - SetRelayFrequency( 0 ); + state = 11; + SetRelayFrequency( 0 ); - newSettings = false; + newSettings = false; - int posY = 45; - int incY = 19; + int posY = 45; + int incY = 19; - tft.setTextColor( BLUE, BLACK ); - tft.fillScreen(BLACK); + tft.setTextColor( BLUE, BLACK ); + tft.fillScreen(BLACK); - tft.setTextColor( BLUE, BLACK ); - tft.setTextSize(2); - tft.setCursor( 20, 20 ); - tft.println( "SETTINGS" ); + tft.setTextColor( BLUE, BLACK ); + tft.setTextSize(2); + tft.setCursor( 20, 20 ); + tft.println( "SETTINGS" ); - tft.setTextColor( WHITE, BLACK ); - tft.setCursor( 20, posY ); - tft.print( "SWITCH PASTE" ); + tft.setTextColor( WHITE, BLACK ); + tft.setCursor( 20, posY ); + tft.print( "SWITCH PASTE" ); - posY += incY; + posY += incY; - // y 64 - UpdateSettingsFan( posY ); + // y 64 + UpdateSettingsFan( posY ); - posY += incY; + posY += incY; - // y 83 - UpdateSettingsFanTime( posY ); + // y 83 + UpdateSettingsFanTime( posY ); - posY += incY; + posY += incY; - // y 102 - UpdateSettingsLookAhead( posY ); - + // y 102 + UpdateSettingsLookAhead( posY ); - posY += incY; - // y 121 - UpdateSettingsPower( posY ); + posY += incY; - posY += incY; + // y 121 + UpdateSettingsPower( posY ); - // y 140 - UpdateSettingsTempOffset( posY ); + posY += incY; - posY += incY; + // y 140 + UpdateSettingsTempOffset( posY ); - // y 159 - UpdateSettingsStartFullBlast( posY ); + posY += incY; - posY += incY; + // y 159 + UpdateSettingsStartFullBlast( posY ); - // y 178 - tft.setTextColor( WHITE, BLACK ); - tft.setCursor( 20, posY ); - tft.print( "RESET TO DEFAULTS" ); + posY += incY; - posY += incY; + // y 178 + tft.setTextColor( WHITE, BLACK ); + tft.setCursor( 20, posY ); + tft.print( "RESET TO DEFAULTS" ); - ShowMenuOptions( true ); + posY += incY; + + ShowMenuOptions( true ); } void ShowPaste() { - state = 12; - SetRelayFrequency( 0 ); + state = 12; + SetRelayFrequency( 0 ); - tft.fillScreen(BLACK); + tft.fillScreen(BLACK); - tft.setTextColor( BLUE, BLACK ); - tft.setTextSize(2); - tft.setCursor( 20, 20 ); - tft.println( "SWITCH PASTE" ); + tft.setTextColor( BLUE, BLACK ); + tft.setTextSize(2); + tft.setCursor( 20, 20 ); + tft.println( "SWITCH PASTE" ); - tft.setTextColor( WHITE, BLACK ); + tft.setTextColor( WHITE, BLACK ); - int y = 50; + int y = 50; - for ( int i = 0; i < ELEMENTS(solderPaste); i++ ) - { - if ( i == set.paste ) - tft.setTextColor( YELLOW, BLACK ); - else - tft.setTextColor( WHITE, BLACK ); + for ( int i = 0; i < ELEMENTS(solderPaste); i++ ) + { + if ( i == set.paste ) + { + tft.setTextColor( YELLOW, BLACK ); + } + else + { + tft.setTextColor( WHITE, BLACK ); + } - tft.setTextSize(2); - tft.setCursor( 20, y ); + tft.setTextSize(2); + tft.setCursor( 20, y ); - tft.println( String( solderPaste[i].tempDeg) + "d " + solderPaste[i].n ); - tft.setTextSize(1); - tft.setCursor( 20, y + 17 ); - tft.println( solderPaste[i].t ); - tft.setTextColor( GREY, BLACK ); + tft.println( String( solderPaste[i].tempDeg) + "d " + solderPaste[i].n ); + tft.setTextSize(1); + tft.setCursor( 20, y + 17 ); + tft.println( solderPaste[i].t ); + tft.setTextColor( GREY, BLACK ); - y += 40; - } + y += 40; + } - ShowMenuOptions( true ); + ShowMenuOptions( true ); } void ShowMenuOptions( bool clearAll ) { - int buttonPosY[] = { 19, 74, 129, 184 }; - int buttonHeight = 16; - int buttonWidth = 4; - - tft.setTextColor( WHITE, BLACK ); - tft.setTextSize(2); - - if ( clearAll ) - { - // Clear All - for ( int i = 0; i < 4; i++ ) - tft.fillRect( tft.width() - 95, buttonPosY[i] - 2, 95, buttonHeight + 4, BLACK ); - } - - if ( state == 10 ) - { - // button 0 - tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); - println_Right( tft, "START", tft.width() - 27, buttonPosY[0] + 8 ); - - // button 1 - tft.fillRect( tft.width() - 5, buttonPosY[1], buttonWidth, buttonHeight, RED ); - println_Right( tft, "SETTINGS", tft.width() - 27, buttonPosY[1] + 8 ); - - // button 3 - tft.fillRect( tft.width() - 5, buttonPosY[3], buttonWidth, buttonHeight, YELLOW ); - println_Right( tft, "OVEN CHECK", tft.width() - 27, buttonPosY[3] + 8 ); - } - else if ( state == 11 ) - { - // button 0 - tft.fillRect( tft.width() - 100, buttonPosY[0] - 2, 100, buttonHeight + 4, BLACK ); - tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); - switch ( settings_pointer ) - { - - case 1: - case 2: - case 3: - case 4: - case 5: - println_Right( tft, "CHANGE", tft.width() - 27, buttonPosY[0] + 8 ); - break; - - default: - println_Right( tft, "SELECT", tft.width() - 27, buttonPosY[0] + 8 ); - break; - } - - // button 1 - tft.fillRect( tft.width() - 5, buttonPosY[1], buttonWidth, buttonHeight, RED ); - println_Right( tft, "BACK", tft.width() - 27, buttonPosY[1] + 8 ); - - // button 2 - tft.fillRect( tft.width() - 5, buttonPosY[2], buttonWidth, buttonHeight, BLUE ); - println_Right( tft, "/\\", tft.width() - 27, buttonPosY[2] + 8 ); - - // button 3 - tft.fillRect( tft.width() - 5, buttonPosY[3], buttonWidth, buttonHeight, YELLOW ); - println_Right( tft, "\\/", tft.width() - 27, buttonPosY[3] + 8 ); - - UpdateSettingsPointer(); - } - else if ( state == 12 ) - { - // button 0 - tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); - println_Right( tft, "SELECT", tft.width() - 27, buttonPosY[0] + 8 ); - - // button 1 - tft.fillRect( tft.width() - 5, buttonPosY[1], buttonWidth, buttonHeight, RED ); - println_Right( tft, "BACK", tft.width() - 27, buttonPosY[1] + 8 ); - - // button 2 - tft.fillRect( tft.width() - 5, buttonPosY[2], buttonWidth, buttonHeight, BLUE ); - println_Right( tft, "/\\", tft.width() - 27, buttonPosY[2] + 8 ); - - // button 3 - tft.fillRect( tft.width() - 5, buttonPosY[3], buttonWidth, buttonHeight, YELLOW ); - println_Right( tft, "\\/", tft.width() - 27, buttonPosY[3] + 8 ); - - UpdateSettingsPointer(); - } - else if ( state == 13 ) // restore settings to default - { - // button 0 - tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); - println_Right( tft, "YES", tft.width() - 27, buttonPosY[0] + 8 ); - - // button 1 - tft.fillRect( tft.width() - 5, buttonPosY[1], buttonWidth, buttonHeight, RED ); - println_Right( tft, "NO", tft.width() - 27, buttonPosY[1] + 8 ); - } - else if ( state == 1 || state == 2 || state == 16 ) // warmup, reflow, calibration - { - // button 0 - tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); - println_Right( tft, "ABORT", tft.width() - 27, buttonPosY[0] + 8 ); - } - else if ( state == 3 ) // Finished - { - tft.fillRect( tft.width() - 100, buttonPosY[0] - 2, 100, buttonHeight + 4, BLACK ); - - // button 0 - tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); - println_Right( tft, "MENU", tft.width() - 27, buttonPosY[0] + 8 ); - } - else if ( state == 15 ) - { - // button 0 - tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); - println_Right( tft, "START", tft.width() - 27, buttonPosY[0] + 8 ); - - // button 1 - tft.fillRect( tft.width() - 5, buttonPosY[1], buttonWidth, buttonHeight, RED ); - println_Right( tft, "BACK", tft.width() - 27, buttonPosY[1] + 8 ); - } + int buttonPosY[] = { 19, 74, 129, 184 }; + int buttonHeight = 16; + int buttonWidth = 4; + + tft.setTextColor( WHITE, BLACK ); + tft.setTextSize(2); + + if ( clearAll ) + { + // Clear All + for ( int i = 0; i < 4; i++ ) + { + tft.fillRect( tft.width() - 95, buttonPosY[i] - 2, 95, buttonHeight + 4, BLACK ); + } + } + + if ( state == 10 ) + { + // button 0 + tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); + println_Right( tft, "START", tft.width() - 27, buttonPosY[0] + 8 ); + + // button 1 + tft.fillRect( tft.width() - 5, buttonPosY[1], buttonWidth, buttonHeight, RED ); + println_Right( tft, "SETTINGS", tft.width() - 27, buttonPosY[1] + 8 ); + + // button 3 + tft.fillRect( tft.width() - 5, buttonPosY[3], buttonWidth, buttonHeight, YELLOW ); + println_Right( tft, "OVEN CHECK", tft.width() - 27, buttonPosY[3] + 8 ); + } + else if ( state == 11 ) + { + // button 0 + tft.fillRect( tft.width() - 100, buttonPosY[0] - 2, 100, buttonHeight + 4, BLACK ); + tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); + + switch ( settings_pointer ) + { + + case 1: + case 2: + case 3: + case 4: + case 5: + println_Right( tft, "CHANGE", tft.width() - 27, buttonPosY[0] + 8 ); + break; + + default: + println_Right( tft, "SELECT", tft.width() - 27, buttonPosY[0] + 8 ); + break; + } + + // button 1 + tft.fillRect( tft.width() - 5, buttonPosY[1], buttonWidth, buttonHeight, RED ); + println_Right( tft, "BACK", tft.width() - 27, buttonPosY[1] + 8 ); + + // button 2 + tft.fillRect( tft.width() - 5, buttonPosY[2], buttonWidth, buttonHeight, BLUE ); + println_Right( tft, "/\\", tft.width() - 27, buttonPosY[2] + 8 ); + + // button 3 + tft.fillRect( tft.width() - 5, buttonPosY[3], buttonWidth, buttonHeight, YELLOW ); + println_Right( tft, "\\/", tft.width() - 27, buttonPosY[3] + 8 ); + + UpdateSettingsPointer(); + } + else if ( state == 12 ) + { + // button 0 + tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); + println_Right( tft, "SELECT", tft.width() - 27, buttonPosY[0] + 8 ); + + // button 1 + tft.fillRect( tft.width() - 5, buttonPosY[1], buttonWidth, buttonHeight, RED ); + println_Right( tft, "BACK", tft.width() - 27, buttonPosY[1] + 8 ); + + // button 2 + tft.fillRect( tft.width() - 5, buttonPosY[2], buttonWidth, buttonHeight, BLUE ); + println_Right( tft, "/\\", tft.width() - 27, buttonPosY[2] + 8 ); + + // button 3 + tft.fillRect( tft.width() - 5, buttonPosY[3], buttonWidth, buttonHeight, YELLOW ); + println_Right( tft, "\\/", tft.width() - 27, buttonPosY[3] + 8 ); + + UpdateSettingsPointer(); + } + else if ( state == 13 ) // restore settings to default + { + // button 0 + tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); + println_Right( tft, "YES", tft.width() - 27, buttonPosY[0] + 8 ); + + // button 1 + tft.fillRect( tft.width() - 5, buttonPosY[1], buttonWidth, buttonHeight, RED ); + println_Right( tft, "NO", tft.width() - 27, buttonPosY[1] + 8 ); + } + else if ( state == 1 || state == 2 || state == 16 ) // warmup, reflow, calibration + { + // button 0 + tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); + println_Right( tft, "ABORT", tft.width() - 27, buttonPosY[0] + 8 ); + } + else if ( state == 3 ) // Finished + { + tft.fillRect( tft.width() - 100, buttonPosY[0] - 2, 100, buttonHeight + 4, BLACK ); + + // button 0 + tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); + println_Right( tft, "MENU", tft.width() - 27, buttonPosY[0] + 8 ); + } + else if ( state == 15 ) + { + // button 0 + tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); + println_Right( tft, "START", tft.width() - 27, buttonPosY[0] + 8 ); + + // button 1 + tft.fillRect( tft.width() - 5, buttonPosY[1], buttonWidth, buttonHeight, RED ); + println_Right( tft, "BACK", tft.width() - 27, buttonPosY[1] + 8 ); + } } void UpdateSettingsPointer() { - if ( state == 11 ) - { - tft.setTextColor( BLUE, BLACK ); - tft.setTextSize(2); - tft.fillRect( 0, 20, 20, tft.height() - 20, BLACK ); - tft.setCursor( 5, ( 45 + ( 19 * settings_pointer ) ) ); - tft.println(">"); - - - tft.setTextSize(1); - tft.setTextColor( GREEN, BLACK ); - tft.fillRect( 0, tft.height() - 40, tft.width(), 40, BLACK ); - switch ( settings_pointer ) - { - case 0: - println_Center( tft, "Select which profile to reflow", tft.width() / 2, tft.height() - 20 ); - break; - - case 1: - println_Center( tft, "Enable fan for end of reflow, requires 5V DC fan", tft.width() / 2, tft.height() - 20 ); - break; - - case 2: - println_Center( tft, "Keep fan on for XXX sec after reflow", tft.width() / 2, tft.height() - 20 ); - break; - - case 3: - println_Center( tft, "Soak and Reflow look ahead for rate change speed", tft.width() / 2, tft.height() - 20 ); - break; - - case 4: - println_Center( tft, "Adjust the power boost", tft.width() / 2, tft.height() - 20 ); - break; - - case 5: - println_Center( tft, "Adjust temp probe reading offset", tft.width() / 2, tft.height() - 20 ); - break; - - case 6: - println_Center( tft, "Force full power on initial ramp-up - be careful!", tft.width() / 2, tft.height() - 20 ); - break; - - case 7: - println_Center( tft, "Reset to default settings", tft.width() / 2, tft.height() - 20 ); - break; - - default: - //println_Center( tft, "", tft.width() / 2, tft.height() - 20 ); - break; - } - tft.setTextSize(2); - } - else if ( state == 12 ) - { - tft.setTextColor( BLUE, BLACK ); - tft.setTextSize(2); - tft.fillRect( 0, 20, 20, tft.height() - 20, BLACK ); - tft.setCursor( 5, ( 50 + ( 20 * ( settings_pointer * 2 ) ) ) ); - tft.println(">"); - } + if ( state == 11 ) + { + tft.setTextColor( BLUE, BLACK ); + tft.setTextSize(2); + tft.fillRect( 0, 20, 20, tft.height() - 20, BLACK ); + tft.setCursor( 5, ( 45 + ( 19 * settings_pointer ) ) ); + tft.println(">"); + + + tft.setTextSize(1); + tft.setTextColor( GREEN, BLACK ); + tft.fillRect( 0, tft.height() - 40, tft.width(), 40, BLACK ); + + switch ( settings_pointer ) + { + case 0: + println_Center( tft, "Select which profile to reflow", tft.width() / 2, tft.height() - 20 ); + break; + + case 1: + println_Center( tft, "Enable fan for end of reflow, requires 5V DC fan", tft.width() / 2, tft.height() - 20 ); + break; + + case 2: + println_Center( tft, "Keep fan on for XXX sec after reflow", tft.width() / 2, tft.height() - 20 ); + break; + + case 3: + println_Center( tft, "Soak and Reflow look ahead for rate change speed", tft.width() / 2, tft.height() - 20 ); + break; + + case 4: + println_Center( tft, "Adjust the power boost", tft.width() / 2, tft.height() - 20 ); + break; + + case 5: + println_Center( tft, "Adjust temp probe reading offset", tft.width() / 2, tft.height() - 20 ); + break; + + case 6: + println_Center( tft, "Force full power on initial ramp-up - be careful!", tft.width() / 2, tft.height() - 20 ); + break; + + case 7: + println_Center( tft, "Reset to default settings", tft.width() / 2, tft.height() - 20 ); + break; + + default: + //println_Center( tft, "", tft.width() / 2, tft.height() - 20 ); + break; + } + + tft.setTextSize(2); + } + else if ( state == 12 ) + { + tft.setTextColor( BLUE, BLACK ); + tft.setTextSize(2); + tft.fillRect( 0, 20, 20, tft.height() - 20, BLACK ); + tft.setCursor( 5, ( 50 + ( 20 * ( settings_pointer * 2 ) ) ) ); + tft.println(">"); + } } void StartWarmup() { - tft.fillScreen(BLACK); - - state = 1; - timeX = 0; - ShowMenuOptions( true ); - lastWantedTemp = -1; - buzzerCount = 5; - keepFanOnTime = 0; - StartFan( false ); - - tft.setTextColor( GREEN, BLACK ); - tft.setTextSize(3); - println_Center( tft, "WARMING UP", tft.width() / 2, ( tft.height() / 2 ) - 30 ); - - tft.setTextColor( WHITE, BLACK ); - println_Center( tft, "START @ " + String( GetGraphValue(0) ) + "c", tft.width() / 2, ( tft.height() / 2 ) + 50 ); + tft.fillScreen(BLACK); + + state = 1; + timeX = 0; + ShowMenuOptions( true ); + lastWantedTemp = -1; + buzzerCount = 5; + keepFanOnTime = 0; + StartFan( false ); + + tft.setTextColor( GREEN, BLACK ); + tft.setTextSize(3); + println_Center( tft, "WARMING UP", tft.width() / 2, ( tft.height() / 2 ) - 30 ); + + tft.setTextColor( WHITE, BLACK ); + println_Center( tft, "START @ " + String( GetGraphValue(0) ) + "c", tft.width() / 2, ( tft.height() / 2 ) + 50 ); } void StartReflow() { - tft.fillScreen(BLACK); + tft.fillScreen(BLACK); - state = 2; - ShowMenuOptions( true ); + state = 2; + ShowMenuOptions( true ); - timeX = 0; - SetupGraph(tft, 0, 0, 30, 220, 270, 180, graphRangeMin_X, graphRangeMax_X, graphRangeStep_X, graphRangeMin_Y, graphRangeMax_Y, graphRangeStep_Y, "Reflow Temp", " Time [s]", "deg [C]", DKBLUE, BLUE, WHITE, BLACK ); + timeX = 0; + SetupGraph(tft, 0, 0, 30, 220, 270, 180, graphRangeMin_X, graphRangeMax_X, graphRangeStep_X, graphRangeMin_Y, graphRangeMax_Y, graphRangeStep_Y, "Reflow Temp", " Time [s]", "deg [C]", DKBLUE, BLUE, WHITE, BLACK ); - DrawHeading( "READY", WHITE, BLACK ); - DrawBaseGraph(); + DrawHeading( "READY", WHITE, BLACK ); + DrawBaseGraph(); } void AbortReflow() { - if ( state == 1 || state == 2 || state == 16 ) // if we are in warmup or reflow states - { - state = 99; - - SetRelayFrequency(0); // Turn the SSR off immediately - - DrawHeading( "ABORT", RED, BLACK ); - - if ( set.useFan && set.fanTimeAfterReflow > 0 ) - { - keepFanOnTime = millis() + set.fanTimeAfterReflow * 1000; - } - else - { - StartFan( false ); - } - - delay(1000); - - state = 10; - ShowMenu(); - } + if ( state == 1 || state == 2 || state == 16 ) // if we are in warmup or reflow states + { + state = 99; + + SetRelayFrequency(0); // Turn the SSR off immediately + + DrawHeading( "ABORT", RED, BLACK ); + + if ( set.useFan && set.fanTimeAfterReflow > 0 ) + { + keepFanOnTime = millis() + set.fanTimeAfterReflow * 1000; + } + else + { + StartFan( false ); + } + + delay(1000); + + state = 10; + ShowMenu(); + } } void EndReflow() { - if ( state == 2 ) - { - SetRelayFrequency( 0 ); - state = 3; + if ( state == 2 ) + { + SetRelayFrequency( 0 ); + state = 3; - Buzzer( 2000, 500 ); + Buzzer( 2000, 500 ); - DrawHeading( "DONE!", WHITE, BLACK ); + DrawHeading( "DONE!", WHITE, BLACK ); - ShowMenuOptions( false ); + ShowMenuOptions( false ); - if ( set.useFan && set.fanTimeAfterReflow > 0 ) - { - keepFanOnTime = millis() + set.fanTimeAfterReflow * 1000; - } - else - { - StartFan( false ); - } + if ( set.useFan && set.fanTimeAfterReflow > 0 ) + { + keepFanOnTime = millis() + set.fanTimeAfterReflow * 1000; + } + else + { + StartFan( false ); + } - delay(750); - Buzzer( 2000, 500 ); - } + delay(750); + Buzzer( 2000, 500 ); + } } void SetDefaults() { - // Default settings values - set.valid = true; - set.fanTimeAfterReflow = 60; - set.power = 1; - set.paste = 0; - set.useFan = true; - set.lookAhead = 7; - set.lookAheadWarm = 7; - set.startFullBlast = false; - set.tempOffset = 0; + // Default settings values + set.valid = true; + set.fanTimeAfterReflow = 60; + set.power = 1; + set.paste = 0; + set.useFan = true; + set.lookAhead = 7; + set.lookAheadWarm = 7; + set.startFullBlast = false; + set.tempOffset = 0; } void ResetSettingsToDefault() { - // set default values again and save - SetDefaults(); - flash_store.write(set); + // set default values again and save + SetDefaults(); + flash_store.write(set); - // load the default paste - SetCurrentGraph( set.paste ); + // load the default paste + SetCurrentGraph( set.paste ); - // show settings - settings_pointer = 0; - ShowSettings(); + // show settings + settings_pointer = 0; + ShowSettings(); } @@ -1366,79 +1410,79 @@ void ResetSettingsToDefault() */ void StartOvenCheck() { -#ifdef DEBUG - Serial.println("Oven Check Start Temp " + String( currentTemp ) ); -#endif - state = 16; - calibrationSeconds = 0; - calibrationState = 0; - calibrationStatsUp = 0; - calibrationStatsDown = 300; - calibrationUpMatch = false; - calibrationDownMatch = false; - calibrationDropVal = 0; - calibrationRiseVal = 0; - SetRelayFrequency( 0 ); - StartFan( false ); - -#ifdef DEBUG - Serial.println("Running Oven Check"); -#endif - tft.fillScreen(BLACK); - tft.setTextColor( CYAN, BLACK ); - tft.setTextSize(2); - tft.setCursor( 20, 20 ); - tft.println( "OVEN CHECK" ); - - tft.setTextColor( YELLOW, BLACK ); - tft.setCursor( 20, 40 ); - tft.println( CurrentGraph().n ); - tft.setCursor( 20, 60 ); - tft.println( String(CurrentGraph().tempDeg) + "deg"); - - ShowMenuOptions( true ); + #ifdef DEBUG + Serial.println("Oven Check Start Temp " + String( currentTemp ) ); + #endif + state = 16; + calibrationSeconds = 0; + calibrationState = 0; + calibrationStatsUp = 0; + calibrationStatsDown = 300; + calibrationUpMatch = false; + calibrationDownMatch = false; + calibrationDropVal = 0; + calibrationRiseVal = 0; + SetRelayFrequency( 0 ); + StartFan( false ); + + #ifdef DEBUG + Serial.println("Running Oven Check"); + #endif + tft.fillScreen(BLACK); + tft.setTextColor( CYAN, BLACK ); + tft.setTextSize(2); + tft.setCursor( 20, 20 ); + tft.println( "OVEN CHECK" ); + + tft.setTextColor( YELLOW, BLACK ); + tft.setCursor( 20, 40 ); + tft.println( CurrentGraph().n ); + tft.setCursor( 20, 60 ); + tft.println( String(CurrentGraph().tempDeg) + "deg"); + + ShowMenuOptions( true ); } void ShowOvenCheck() { - state = 15; - SetRelayFrequency( 0 ); - StartFan( true ); + state = 15; + SetRelayFrequency( 0 ); + StartFan( true ); - int posY = 50; - int incY = 20; + int posY = 50; + int incY = 20; -#ifdef DEBUG - Serial.println("Oven Check"); -#endif + #ifdef DEBUG + Serial.println("Oven Check"); + #endif - tft.fillScreen(BLACK); - tft.setTextColor( CYAN, BLACK ); - tft.setTextSize(2); - tft.setCursor( 20, 20 ); - tft.println( "OVEN CHECK" ); + tft.fillScreen(BLACK); + tft.setTextColor( CYAN, BLACK ); + tft.setTextSize(2); + tft.setCursor( 20, 20 ); + tft.println( "OVEN CHECK" ); - tft.setTextColor( WHITE, BLACK ); + tft.setTextColor( WHITE, BLACK ); - ShowMenuOptions( true ); + ShowMenuOptions( true ); - tft.setTextSize(2); - tft.setCursor( 0, 60 ); - tft.setTextColor( YELLOW, BLACK ); + tft.setTextSize(2); + tft.setCursor( 0, 60 ); + tft.setTextColor( YELLOW, BLACK ); - tft.println( " Oven Check allows"); - tft.println( " you to measure your"); - tft.println( " oven's rate of heat"); - tft.println( " up & cool down to"); - tft.println( " see if your oven"); - tft.println( " is powerful enough"); - tft.println( " to reflow your "); - tft.println( " selected profile."); - tft.println( ""); + tft.println( " Oven Check allows"); + tft.println( " you to measure your"); + tft.println( " oven's rate of heat"); + tft.println( " up & cool down to"); + tft.println( " see if your oven"); + tft.println( " is powerful enough"); + tft.println( " to reflow your "); + tft.println( " selected profile."); + tft.println( ""); - tft.setTextColor( YELLOW, RED ); - tft.println( " EMPTY YOUR OVEN FIRST!"); + tft.setTextColor( YELLOW, RED ); + tft.println( " EMPTY YOUR OVEN FIRST!"); } /* @@ -1453,60 +1497,61 @@ void ShowOvenCheck() void ShowResetDefaults() { - tft.fillScreen(BLACK); - tft.setTextColor( WHITE, BLACK ); - tft.setTextSize(2); - tft.setCursor( 20, 90 ); - - tft.setTextColor( WHITE, BLACK ); - tft.print( "RESET SETTINGS" ); - tft.setTextSize(3); - tft.setCursor( 20, 120 ); - tft.println( "ARE YOU SURE?" ); - - state = 13; - ShowMenuOptions( false ); - - tft.setTextSize(1); - tft.setTextColor( GREEN, BLACK ); - tft.fillRect( 0, tft.height() - 40, tft.width(), 40, BLACK ); - println_Center( tft, "Settings restore cannot be undone!", tft.width() / 2, tft.height() - 20 ); + tft.fillScreen(BLACK); + tft.setTextColor( WHITE, BLACK ); + tft.setTextSize(2); + tft.setCursor( 20, 90 ); + + tft.setTextColor( WHITE, BLACK ); + tft.print( "RESET SETTINGS" ); + tft.setTextSize(3); + tft.setCursor( 20, 120 ); + tft.println( "ARE YOU SURE?" ); + + state = 13; + ShowMenuOptions( false ); + + tft.setTextSize(1); + tft.setTextColor( GREEN, BLACK ); + tft.fillRect( 0, tft.height() - 40, tft.width(), 40, BLACK ); + println_Center( tft, "Settings restore cannot be undone!", tft.width() / 2, tft.height() - 20 ); } void UpdateSettingsFan( int posY ) { - tft.fillRect( 15, posY - 5, 200, 20, BLACK ); - tft.setTextColor( WHITE, BLACK ); - tft.setCursor( 20, posY ); - - tft.setTextColor( WHITE, BLACK ); - tft.print( "USE FAN " ); - tft.setTextColor( YELLOW, BLACK ); - - if ( set.useFan ) - { - tft.println( "ON" ); - } - else - { - tft.println( "OFF" ); - } - tft.setTextColor( WHITE, BLACK ); + tft.fillRect( 15, posY - 5, 200, 20, BLACK ); + tft.setTextColor( WHITE, BLACK ); + tft.setCursor( 20, posY ); + + tft.setTextColor( WHITE, BLACK ); + tft.print( "USE FAN " ); + tft.setTextColor( YELLOW, BLACK ); + + if ( set.useFan ) + { + tft.println( "ON" ); + } + else + { + tft.println( "OFF" ); + } + + tft.setTextColor( WHITE, BLACK ); } void UpdateSettingsFanTime( int posY ) { - tft.fillRect( 15, posY - 5, 230, 20, BLACK ); - tft.setTextColor( WHITE, BLACK ); - tft.setCursor( 20, posY ); + tft.fillRect( 15, posY - 5, 230, 20, BLACK ); + tft.setTextColor( WHITE, BLACK ); + tft.setCursor( 20, posY ); - tft.setTextColor( WHITE, BLACK ); - tft.print( "FAN COUNTDOWN " ); - tft.setTextColor( YELLOW, BLACK ); + tft.setTextColor( WHITE, BLACK ); + tft.print( "FAN COUNTDOWN " ); + tft.setTextColor( YELLOW, BLACK ); - tft.println( String( set.fanTimeAfterReflow ) + "s"); + tft.println( String( set.fanTimeAfterReflow ) + "s"); - tft.setTextColor( WHITE, BLACK ); + tft.setTextColor( WHITE, BLACK ); } @@ -1514,45 +1559,46 @@ void UpdateSettingsFanTime( int posY ) void UpdateSettingsStartFullBlast( int posY ) { - tft.fillRect( 15, posY - 5, 240, 20, BLACK ); - tft.setTextColor( WHITE, BLACK ); - tft.setCursor( 20, posY ); - tft.print( "START RAMP 100% " ); - tft.setTextColor( YELLOW, BLACK ); - - if ( set.startFullBlast ) - { - tft.println( "ON" ); - } - else - { - tft.println( "OFF" ); - } - tft.setTextColor( WHITE, BLACK ); + tft.fillRect( 15, posY - 5, 240, 20, BLACK ); + tft.setTextColor( WHITE, BLACK ); + tft.setCursor( 20, posY ); + tft.print( "START RAMP 100% " ); + tft.setTextColor( YELLOW, BLACK ); + + if ( set.startFullBlast ) + { + tft.println( "ON" ); + } + else + { + tft.println( "OFF" ); + } + + tft.setTextColor( WHITE, BLACK ); } void UpdateSettingsPower( int posY ) { - tft.fillRect( 15, posY - 5, 240, 20, BLACK ); - tft.setTextColor( WHITE, BLACK ); - - tft.setCursor( 20, posY ); - tft.print( "POWER "); - tft.setTextColor( YELLOW, BLACK ); - tft.println( String( round((set.power * 100))) + "%"); - tft.setTextColor( WHITE, BLACK ); + tft.fillRect( 15, posY - 5, 240, 20, BLACK ); + tft.setTextColor( WHITE, BLACK ); + + tft.setCursor( 20, posY ); + tft.print( "POWER "); + tft.setTextColor( YELLOW, BLACK ); + tft.println( String( round((set.power * 100))) + "%"); + tft.setTextColor( WHITE, BLACK ); } void UpdateSettingsLookAhead( int posY ) { - tft.fillRect( 15, posY - 5, 260, 20, BLACK ); - tft.setTextColor( WHITE, BLACK ); - - tft.setCursor( 20, posY ); - tft.print( "GRAPH LOOK AHEAD "); - tft.setTextColor( YELLOW, BLACK ); - tft.println( String( set.lookAhead) ); - tft.setTextColor( WHITE, BLACK ); + tft.fillRect( 15, posY - 5, 260, 20, BLACK ); + tft.setTextColor( WHITE, BLACK ); + + tft.setCursor( 20, posY ); + tft.print( "GRAPH LOOK AHEAD "); + tft.setTextColor( YELLOW, BLACK ); + tft.println( String( set.lookAhead) ); + tft.setTextColor( WHITE, BLACK ); } //void UpdateSettingsLookAheadWarm( int posY ) @@ -1569,14 +1615,14 @@ void UpdateSettingsLookAhead( int posY ) void UpdateSettingsTempOffset( int posY ) { - tft.fillRect( 15, posY - 5, 220, 20, BLACK ); - tft.setTextColor( WHITE, BLACK ); - - tft.setCursor( 20, posY ); - tft.print( "TEMP OFFSET "); - tft.setTextColor( YELLOW, BLACK ); - tft.println( String( set.tempOffset) ); - tft.setTextColor( WHITE, BLACK ); + tft.fillRect( 15, posY - 5, 220, 20, BLACK ); + tft.setTextColor( WHITE, BLACK ); + + tft.setCursor( 20, posY ); + tft.print( "TEMP OFFSET "); + tft.setTextColor( YELLOW, BLACK ); + tft.println( String( set.tempOffset) ); + tft.setTextColor( WHITE, BLACK ); } @@ -1589,174 +1635,186 @@ long nextButtonPress = 0; void button0Press() { - if ( nextButtonPress < millis() ) - { - nextButtonPress = millis() + 20; - Buzzer( 2000, 50 ); - - if ( state == 10 ) - { - StartWarmup(); - } - else if ( state == 1 || state == 2 || state == 16 ) - { - AbortReflow(); - } - else if ( state == 3 ) - { - ShowMenu(); - } - else if ( state == 11 ) - { - if ( settings_pointer == 0 ) // change paste - { - settings_pointer = set.paste; - ShowPaste(); - } - else if ( settings_pointer == 1 ) // switch fan use - { - set.useFan = !set.useFan; - - UpdateSettingsFan( 64 ); - } - else if ( settings_pointer == 2 ) // fan countdown after reflow - { - set.fanTimeAfterReflow += 5; - if ( set.fanTimeAfterReflow > 60 ) - set.fanTimeAfterReflow = 0; - - UpdateSettingsFanTime( 83 ); - } - else if ( settings_pointer == 3 ) // change lookahead for reflow - { - set.lookAhead += 1; - if ( set.lookAhead > 15 ) - set.lookAhead = 1; - - UpdateSettingsLookAhead( 102 ); - } - else if ( settings_pointer == 4 ) // change power - { - set.power += 0.1; - if ( set.power > 1.55 ) - set.power = 0.5; - - UpdateSettingsPower( 121 ); - } - else if ( settings_pointer == 5 ) // change temp probe offset - { - set.tempOffset += 1; - if ( set.tempOffset > 15 ) - set.tempOffset = -15; - - UpdateSettingsTempOffset( 140 ); - } - else if ( settings_pointer == 6 ) // change use full power on initial ramp - { - set.startFullBlast = !set.startFullBlast; - - UpdateSettingsStartFullBlast( 159 ); - } - else if ( settings_pointer == 7 ) // reset defaults - { - ShowResetDefaults(); - } - } - else if ( state == 12 ) - { - if ( set.paste != settings_pointer ) - { - set.paste = settings_pointer; - SetCurrentGraph( set.paste ); - ShowPaste(); - } - } - else if ( state == 13 ) - { - ResetSettingsToDefault(); - } - else if ( state == 15 ) - { - StartOvenCheck(); - } - } + if ( nextButtonPress < millis() ) + { + nextButtonPress = millis() + 20; + Buzzer( 2000, 50 ); + + if ( state == 10 ) + { + StartWarmup(); + } + else if ( state == 1 || state == 2 || state == 16 ) + { + AbortReflow(); + } + else if ( state == 3 ) + { + ShowMenu(); + } + else if ( state == 11 ) + { + if ( settings_pointer == 0 ) // change paste + { + settings_pointer = set.paste; + ShowPaste(); + } + else if ( settings_pointer == 1 ) // switch fan use + { + set.useFan = !set.useFan; + + UpdateSettingsFan( 64 ); + } + else if ( settings_pointer == 2 ) // fan countdown after reflow + { + set.fanTimeAfterReflow += 5; + + if ( set.fanTimeAfterReflow > 60 ) + { + set.fanTimeAfterReflow = 0; + } + + UpdateSettingsFanTime( 83 ); + } + else if ( settings_pointer == 3 ) // change lookahead for reflow + { + set.lookAhead += 1; + + if ( set.lookAhead > 15 ) + { + set.lookAhead = 1; + } + + UpdateSettingsLookAhead( 102 ); + } + else if ( settings_pointer == 4 ) // change power + { + set.power += 0.1; + + if ( set.power > 1.55 ) + { + set.power = 0.5; + } + + UpdateSettingsPower( 121 ); + } + else if ( settings_pointer == 5 ) // change temp probe offset + { + set.tempOffset += 1; + + if ( set.tempOffset > 15 ) + { + set.tempOffset = -15; + } + + UpdateSettingsTempOffset( 140 ); + } + else if ( settings_pointer == 6 ) // change use full power on initial ramp + { + set.startFullBlast = !set.startFullBlast; + + UpdateSettingsStartFullBlast( 159 ); + } + else if ( settings_pointer == 7 ) // reset defaults + { + ShowResetDefaults(); + } + } + else if ( state == 12 ) + { + if ( set.paste != settings_pointer ) + { + set.paste = settings_pointer; + SetCurrentGraph( set.paste ); + ShowPaste(); + } + } + else if ( state == 13 ) + { + ResetSettingsToDefault(); + } + else if ( state == 15 ) + { + StartOvenCheck(); + } + } } void button1Press() { - if ( nextButtonPress < millis() ) - { - nextButtonPress = millis() + 20; - Buzzer( 2000, 50 ); - - if ( state == 10 ) - { - settings_pointer = 0; - ShowSettings(); - } - else if ( state == 11 ) // leaving settings so save - { - // save data in flash - flash_store.write(set); - ShowMenu(); - } - else if ( state == 12 || state == 13 ) - { - settings_pointer = 0; - ShowSettings(); - } - else if ( state == 15 ) // cancel oven check - { - ShowMenu(); - } - } + if ( nextButtonPress < millis() ) + { + nextButtonPress = millis() + 20; + Buzzer( 2000, 50 ); + + if ( state == 10 ) + { + settings_pointer = 0; + ShowSettings(); + } + else if ( state == 11 ) // leaving settings so save + { + // save data in flash + flash_store.write(set); + ShowMenu(); + } + else if ( state == 12 || state == 13 ) + { + settings_pointer = 0; + ShowSettings(); + } + else if ( state == 15 ) // cancel oven check + { + ShowMenu(); + } + } } void button2Press() { - if ( nextButtonPress < millis() ) - { - nextButtonPress = millis() + 20; - Buzzer( 2000, 50 ); - - if ( state == 11 ) - { - settings_pointer = constrain( settings_pointer - 1, 0, 7 ); - ShowMenuOptions( false ); - //UpdateSettingsPointer(); - } - else if ( state == 12 ) - { - settings_pointer = constrain( settings_pointer - 1, 0, ELEMENTS(solderPaste) - 1 ); - UpdateSettingsPointer(); - } - } + if ( nextButtonPress < millis() ) + { + nextButtonPress = millis() + 20; + Buzzer( 2000, 50 ); + + if ( state == 11 ) + { + settings_pointer = constrain( settings_pointer - 1, 0, 7 ); + ShowMenuOptions( false ); + //UpdateSettingsPointer(); + } + else if ( state == 12 ) + { + settings_pointer = constrain( settings_pointer - 1, 0, ELEMENTS(solderPaste) - 1 ); + UpdateSettingsPointer(); + } + } } void button3Press() { - if ( nextButtonPress < millis() ) - { - nextButtonPress = millis() + 20; - Buzzer( 2000, 50 ); - - if ( state == 10 ) - { - ShowOvenCheck(); - } - else if ( state == 11 ) - { - settings_pointer = constrain( settings_pointer + 1, 0, 7 ); - ShowMenuOptions( false ); - //UpdateSettingsPointer(); - } - else if ( state == 12 ) - { - settings_pointer = constrain( settings_pointer + 1, 0, ELEMENTS(solderPaste) - 1 ); - UpdateSettingsPointer(); - } - } + if ( nextButtonPress < millis() ) + { + nextButtonPress = millis() + 20; + Buzzer( 2000, 50 ); + + if ( state == 10 ) + { + ShowOvenCheck(); + } + else if ( state == 11 ) + { + settings_pointer = constrain( settings_pointer + 1, 0, 7 ); + ShowMenuOptions( false ); + //UpdateSettingsPointer(); + } + else if ( state == 12 ) + { + settings_pointer = constrain( settings_pointer + 1, 0, ELEMENTS(solderPaste) - 1 ); + UpdateSettingsPointer(); + } + } } /* @@ -1767,137 +1825,147 @@ void button3Press() void SetupGraph(Adafruit_ILI9341 &d, double x, double y, double gx, double gy, double w, double h, double xlo, double xhi, double xinc, double ylo, double yhi, double yinc, String title, String xlabel, String ylabel, unsigned int gcolor, unsigned int acolor, unsigned int tcolor, unsigned int bcolor ) { - double ydiv, xdiv; - double i; - int temp; - int rot, newrot; - - ox = (x - xlo) * ( w) / (xhi - xlo) + gx; - oy = (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy; - // draw y scale - for ( i = ylo; i <= yhi; i += yinc) - { - // compute the transform - temp = (i - ylo) * (gy - h - gy) / (yhi - ylo) + gy; - - if (i == ylo) { - d.drawLine(gx, temp, gx + w, temp, acolor); - } - else { - d.drawLine(gx, temp, gx + w, temp, gcolor); - } - - d.setTextSize(1); - d.setTextColor(tcolor, bcolor); - d.setCursor(gx - 25, temp); - println_Right( d, String(round(i)), gx - 25, temp ); - } - - // draw x scale - for (i = xlo; i <= xhi; i += xinc) - { - temp = (i - xlo) * ( w) / (xhi - xlo) + gx; - if (i == 0) - { - d.drawLine(temp, gy, temp, gy - h, acolor); - } - else - { - d.drawLine(temp, gy, temp, gy - h, gcolor); - } - - d.setTextSize(1); - d.setTextColor(tcolor, bcolor); - d.setCursor(temp, gy + 10); - - if ( i <= xhi - xinc ) - println_Center(d, String(round(i)), temp, gy + 10 ); - else - println_Center(d, String(round(xhi)), temp, gy + 10 ); - } - - //now draw the labels - d.setTextSize(2); - d.setTextColor(tcolor, bcolor); - d.setCursor(gx , gy - h - 30); - d.println(title); - - d.setTextSize(1); - d.setTextColor(acolor, bcolor); - d.setCursor(w - 25 , gy - 10); - d.println(xlabel); - - tft.setRotation(0); - d.setTextSize(1); - d.setTextColor(acolor, bcolor); - d.setCursor(w - 116, 34 ); - d.println(ylabel); - tft.setRotation(1); + double ydiv, xdiv; + double i; + int temp; + int rot, newrot; + + ox = (x - xlo) * ( w) / (xhi - xlo) + gx; + oy = (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy; + + // draw y scale + for ( i = ylo; i <= yhi; i += yinc) + { + // compute the transform + temp = (i - ylo) * (gy - h - gy) / (yhi - ylo) + gy; + + if (i == ylo) + { + d.drawLine(gx, temp, gx + w, temp, acolor); + } + else + { + d.drawLine(gx, temp, gx + w, temp, gcolor); + } + + d.setTextSize(1); + d.setTextColor(tcolor, bcolor); + d.setCursor(gx - 25, temp); + println_Right( d, String(round(i)), gx - 25, temp ); + } + + // draw x scale + for (i = xlo; i <= xhi; i += xinc) + { + temp = (i - xlo) * ( w) / (xhi - xlo) + gx; + + if (i == 0) + { + d.drawLine(temp, gy, temp, gy - h, acolor); + } + else + { + d.drawLine(temp, gy, temp, gy - h, gcolor); + } + + d.setTextSize(1); + d.setTextColor(tcolor, bcolor); + d.setCursor(temp, gy + 10); + + if ( i <= xhi - xinc ) + { + println_Center(d, String(round(i)), temp, gy + 10 ); + } + else + { + println_Center(d, String(round(xhi)), temp, gy + 10 ); + } + } + + //now draw the labels + d.setTextSize(2); + d.setTextColor(tcolor, bcolor); + d.setCursor(gx , gy - h - 30); + d.println(title); + + d.setTextSize(1); + d.setTextColor(acolor, bcolor); + d.setCursor(w - 25 , gy - 10); + d.println(xlabel); + + tft.setRotation(0); + d.setTextSize(1); + d.setTextColor(acolor, bcolor); + d.setCursor(w - 116, 34 ); + d.println(ylabel); + tft.setRotation(1); } void Graph(Adafruit_ILI9341 &d, double x, double y, double gx, double gy, double w, double h ) { - // recall that ox and oy are initialized as static above - x = (x - graphRangeMin_X) * ( w) / (graphRangeMax_X - graphRangeMin_X) + gx; - y = (y - graphRangeMin_Y) * (gy - h - gy) / (graphRangeMax_Y - graphRangeMin_Y) + gy; + // recall that ox and oy are initialized as static above + x = (x - graphRangeMin_X) * ( w) / (graphRangeMax_X - graphRangeMin_X) + gx; + y = (y - graphRangeMin_Y) * (gy - h - gy) / (graphRangeMax_Y - graphRangeMin_Y) + gy; - if ( timeX < 2 ) - oy = min( oy, y ); + if ( timeX < 2 ) + { + oy = min( oy, y ); + } - y = min( y, 220 ); // bottom of graph! + y = min( y, 220 ); // bottom of graph! - // d.fillRect( ox-1, oy-1, 3, 3, currentPlotColor ); + // d.fillRect( ox-1, oy-1, 3, 3, currentPlotColor ); - d.drawLine(ox, oy + 1, x, y + 1, currentPlotColor); - d.drawLine(ox, oy - 1, x, y - 1, currentPlotColor); - d.drawLine(ox, oy, x, y, currentPlotColor ); - ox = x; - oy = y; + d.drawLine(ox, oy + 1, x, y + 1, currentPlotColor); + d.drawLine(ox, oy - 1, x, y - 1, currentPlotColor); + d.drawLine(ox, oy, x, y, currentPlotColor ); + ox = x; + oy = y; } void GraphDefault(Adafruit_ILI9341 &d, double x, double y, double gx, double gy, double w, double h, unsigned int pcolor ) { - // recall that ox and oy are initialized as static above - x = (x - graphRangeMin_X) * ( w) / (graphRangeMax_X - graphRangeMin_X) + gx; - y = (y - graphRangeMin_Y) * (gy - h - gy) / (graphRangeMax_Y - graphRangeMin_Y) + gy; - - //Serial.println( oy ); - d.drawLine(ox, oy, x, y, pcolor); - d.drawLine(ox, oy + 1, x, y + 1, pcolor); - d.drawLine(ox, oy - 1, x, y - 1, pcolor); - ox = x; - oy = y; + // recall that ox and oy are initialized as static above + x = (x - graphRangeMin_X) * ( w) / (graphRangeMax_X - graphRangeMin_X) + gx; + y = (y - graphRangeMin_Y) * (gy - h - gy) / (graphRangeMax_Y - graphRangeMin_Y) + gy; + + //Serial.println( oy ); + d.drawLine(ox, oy, x, y, pcolor); + d.drawLine(ox, oy + 1, x, y + 1, pcolor); + d.drawLine(ox, oy - 1, x, y - 1, pcolor); + ox = x; + oy = y; } char* string2char(String command) { - if (command.length() != 0) - { - char *p = const_cast(command.c_str()); - return p; - } + if (command.length() != 0) + { + char *p = const_cast(command.c_str()); + return p; + } } void println_Center( Adafruit_ILI9341 &d, String heading, int centerX, int centerY ) { - int x = 0; - int y = 0; - int16_t x1, y1; - uint16_t ww, hh; - - d.getTextBounds( string2char(heading), x, y, &x1, &y1, &ww, &hh ); - d.setCursor( centerX - ww / 2 + 2, centerY - hh / 2); - d.println( heading ); + int x = 0; + int y = 0; + int16_t x1, y1; + uint16_t ww, hh; + + d.getTextBounds( string2char(heading), x, y, &x1, &y1, &ww, &hh ); + d.setCursor( centerX - ww / 2 + 2, centerY - hh / 2); + d.println( heading ); } void println_Right( Adafruit_ILI9341 &d, String heading, int centerX, int centerY ) { - int x = 0; - int y = 0; - int16_t x1, y1; - uint16_t ww, hh; - - d.getTextBounds( string2char(heading), x, y, &x1, &y1, &ww, &hh ); - d.setCursor( centerX + ( 18 - ww ), centerY - hh / 2); - d.println( heading ); + int x = 0; + int y = 0; + int16_t x1, y1; + uint16_t ww, hh; + + d.getTextBounds( string2char(heading), x, y, &x1, &y1, &ww, &hh ); + d.setCursor( centerX + ( 18 - ww ), centerY - hh / 2); + d.println( heading ); } From 449a8b4fb8ec70ff306b1ed8c4cba62a90758391 Mon Sep 17 00:00:00 2001 From: Fake-Name Date: Mon, 28 Sep 2020 00:02:48 -0700 Subject: [PATCH 3/6] Vendor libraries that aren't easily available. --- Code/Reflow_Master/src/MAX31855.cpp | 107 ++++++++++++++++++++++ Code/Reflow_Master/src/MAX31855.h | 94 +++++++++++++++++++ Code/Reflow_Master/src/Reflow_Master.ino | 21 ++++- Code/Reflow_Master/src/spline.cpp | 111 +++++++++++++++++++++++ Code/Reflow_Master/src/spline.h | 42 +++++++++ 5 files changed, 374 insertions(+), 1 deletion(-) create mode 100644 Code/Reflow_Master/src/MAX31855.cpp create mode 100644 Code/Reflow_Master/src/MAX31855.h create mode 100644 Code/Reflow_Master/src/spline.cpp create mode 100644 Code/Reflow_Master/src/spline.h diff --git a/Code/Reflow_Master/src/MAX31855.cpp b/Code/Reflow_Master/src/MAX31855.cpp new file mode 100644 index 0000000..ef0a750 --- /dev/null +++ b/Code/Reflow_Master/src/MAX31855.cpp @@ -0,0 +1,107 @@ +// +// FILE: MAX31855.cpp +// AUTHOR: Rob Tillaart +// VERSION: 0.1.10 +// PURPOSE: MAX31855 - Thermocouple +// DATE: 2014-01-01 +// URL: http://forum.arduino.cc/index.php?topic=208061 +// +// HISTORY: +// 0.1.10 2019-07-31 add 3 inline functions to test errors + demo sketch +// 0.1.9 2017-07-27 reverted double -> float (issue33) +// 0.1.08 2015-12-06 replaced all temperature calls with one TCfactor + update demos. +// 0.1.07 2015-12-06 updated TC factors from the MAX31855 datasheet +// 0.1.06 2015-12-05 added support for other types of TC's (experimental) +// 0.1.05 2015-07-12 refactor robust constructor +// 0.1.04 2015-03-09 replaced float -> double (ARM support) +// 0.1.03 fixed negative temperature +// 0.1.02 added offset +// 0.1.01 refactored speed/performance +// 0.1.00 initial version. +// +// Released to the public domain +// + +#include "MAX31855.h" + +MAX31855::MAX31855(const uint8_t sclk, const uint8_t cs, const uint8_t miso) +{ + _sclk = sclk; + _cs = cs; + _miso = miso; + _offset = 0; + _TCfactor = K_TC; + _status = STATUS_NOREAD; + _temperature = -999; + _internal = -999; +} + +void MAX31855::begin() +{ + pinMode(_cs, OUTPUT); + digitalWrite(_cs, HIGH); + + pinMode(_sclk, OUTPUT); + pinMode(_miso, INPUT); +} + +uint8_t MAX31855::read() +{ + uint32_t value = _read(); + + // process status bit 0-2 + _status = value & 0x0007; + value >>= 3; + + // reserved bit 3 + value >>= 1; + + // process internal bit 4-15 + _internal = (value & 0x07FF) * 0.0625; + if (value & 0x0800) + { + _internal = -128 + _internal; // fix neg temp + } + value >>= 12; + + // Fault bit ignored as we have the 3 status bits + // _fault = value & 0x01; + value >>= 1; + + // reserved bit 17 + value >>= 1; + + // process temperature bit 18-30 + sign bit = 31 + _temperature = (value & 0x1FFF) * 0.25; + if (value & 0x2000) // negative flag + { + _temperature = -2048 + _temperature; // fix neg temp + } + if (_offset != 0) _temperature += _offset; + + return _status; +} + +// TODO: optimize performance by direct port manipulation? +uint32_t MAX31855::_read(void) +{ + uint32_t value = 0; + + digitalWrite(_cs, LOW); + + for (int8_t i = 31; i >= 0; i--) + { + value <<= 1; + digitalWrite(_sclk, LOW); + // delayMicroseconds(1); // DUE + if ( digitalRead(_miso) ) value += 1; + digitalWrite(_sclk, HIGH); + // delayMicroseconds(1); // DUE + } + + digitalWrite(_cs, HIGH); + + return value; +} + +// END OF FILE diff --git a/Code/Reflow_Master/src/MAX31855.h b/Code/Reflow_Master/src/MAX31855.h new file mode 100644 index 0000000..20f1bc1 --- /dev/null +++ b/Code/Reflow_Master/src/MAX31855.h @@ -0,0 +1,94 @@ +// +// FILE: MAX31855.h +// AUTHOR: Rob Tillaart +// VERSION: 0.1.10 +// PURPOSE: MAX31855 - Thermocouple +// DATE: 2014-01-01 +// URL: http://forum.arduino.cc/index.php?topic=208061 +// +// Released to the public domain +// +#ifndef MAX31855_H +#define MAX31855_H + +#if (ARDUINO < 100) +#include "WProgram.h" +#else +#include "Arduino.h" +#endif + +#define MAX31855_VERSION "0.1.10" + +#define STATUS_OK 0x00 +#define STATUS_OPEN_CIRCUIT 0x01 +#define STATUS_SHORT_TO_GND 0x02 +#define STATUS_SHORT_TO_VCC 0x04 +#define STATUS_ERROR 0x07 +#define STATUS_NOREAD 0x80 + +// Thermocouples working is based upon Seebeck effect. +// Different TC have a different Seebeck Coefficient (µV/°C) +// From http://www.analog.com/library/analogDialogue/archives/44-10/thermocouple.html +// +// As the MAX31855 is designed for K type sensors, one can calculate +// the factor needed to convert other sensors measurements. +// note this is only a linear approximation. +// +// E_TC = 61 => 41/61 = 0.6721311475 +// J_TC = 52 => 41/52 = 0.7884615385 +// K_TC = 41 => 41/41 = 1 +// N_TC = 27 => 41/27 = 1.5185185185 +// R_TC = 9 => 41/9 = 4.5555555556 +// S_TC = 6 => 41/6 = 6.8333333333 +// T_TC = 41 => 41/41 = 1 + +// 0.1.07 updated with numbers from the MAX31855 datasheet +#define E_TC (41.276/76.373) +#define J_TC (41.276/57.953) +#define K_TC (41.276/41.276) +#define N_TC (41.276/36.256) +#define R_TC (41.276/10.506) +#define S_TC (41.276/9.587) +#define T_TC (41.276/52.18) + + +class MAX31855 +{ +public: + MAX31855(uint8_t SCLK, uint8_t CS, uint8_t MISO); + void begin(); + + uint8_t read(); + + float getInternal(void) const { return _internal; } + float getTemperature(void) const { return _temperature * _TCfactor; }; + + uint8_t getStatus(void) const { return _status; }; + // next 4 applies to last read + inline bool statusError() { return (_status & STATUS_ERROR) != 0; }; + inline bool shortToGND() { return (_status & STATUS_SHORT_TO_GND) != 0; }; + inline bool shortToVCC() { return (_status & STATUS_SHORT_TO_VCC) != 0; }; + inline bool openCircuit() { return (_status & STATUS_OPEN_CIRCUIT) != 0; }; + + void setOffset(const float t) { _offset = t; }; + float getOffset() const { return _offset; }; + + void setTCfactor(const float TCfactor) { _TCfactor = TCfactor; }; + float getTCfactor() const { return _TCfactor; }; + +private: + uint32_t _read(); + float _internal; + float _temperature; + uint8_t _status; + float _offset; + float _TCfactor; + + uint8_t _sclk; + uint8_t _miso; + uint8_t _cs; +}; + +#endif + +// END OF FILE diff --git a/Code/Reflow_Master/src/Reflow_Master.ino b/Code/Reflow_Master/src/Reflow_Master.ino index 2c49eca..2823bd0 100644 --- a/Code/Reflow_Master/src/Reflow_Master.ino +++ b/Code/Reflow_Master/src/Reflow_Master.ino @@ -1823,7 +1823,26 @@ void button3Press() https://www.youtube.com/watch?v=YejRbIKe6e0 */ -void SetupGraph(Adafruit_ILI9341 &d, double x, double y, double gx, double gy, double w, double h, double xlo, double xhi, double xinc, double ylo, double yhi, double yinc, String title, String xlabel, String ylabel, unsigned int gcolor, unsigned int acolor, unsigned int tcolor, unsigned int bcolor ) +void SetupGraph(Adafruit_ILI9341 &d, + double x, + double y, + double gx, + double gy, + double w, + double h, + double xlo, + double xhi, + double xinc, + double ylo, + double yhi, + double yinc, + String title, + String xlabel, + String ylabel, + unsigned int gcolor, + unsigned int acolor, + unsigned int tcolor, + unsigned int bcolor ) { double ydiv, xdiv; double i; diff --git a/Code/Reflow_Master/src/spline.cpp b/Code/Reflow_Master/src/spline.cpp new file mode 100644 index 0000000..4094ce4 --- /dev/null +++ b/Code/Reflow_Master/src/spline.cpp @@ -0,0 +1,111 @@ + +#include "Arduino.h" +#include "spline.h" +#include + +Spline::Spline(void) { + _prev_point = 0; +} + +Spline::Spline( float x[], float y[], int numPoints, int degree ) +{ + setPoints(x,y,numPoints); + setDegree(degree); + _prev_point = 0; +} + +Spline::Spline( float x[], float y[], float m[], int numPoints ) +{ + setPoints(x,y,m,numPoints); + setDegree(Hermite); + _prev_point = 0; +} + +void Spline::setPoints( float x[], float y[], int numPoints ) { + _x = x; + _y = y; + _length = numPoints; +} + +void Spline::setPoints( float x[], float y[], float m[], int numPoints ) { + _x = x; + _y = y; + _m = m; + _length = numPoints; +} + +void Spline::setDegree( int degree ){ + _degree = degree; +} + +float Spline::value( float x ) +{ + if( _x[0] > x ) { + return _y[0]; + } + else if ( _x[_length-1] < x ) { + return _y[_length-1]; + } + else { + for(int i = 0; i < _length; i++ ) + { + int index = ( i + _prev_point ) % _length; + + if( _x[index] == x ) { + _prev_point = index; + return _y[index]; + } else if( (_x[index] < x) && (x < _x[index+1]) ) { + _prev_point = index; + return calc( x, index ); + } + } + } +} + +float Spline::calc( float x, int i ) +{ + switch( _degree ) { + case 0: + return _y[i]; + case 1: + if( _x[i] == _x[i+1] ) { + // Avoids division by 0 + return _y[i]; + } else { + return _y[i] + (_y[i+1] - _y[i]) * ( x - _x[i]) / ( _x[i+1] - _x[i] ); + } + case Hermite: + return hermite( ((x-_x[i]) / (_x[i+1]-_x[i])), _y[i], _y[i+1], _m[i], _m[i+1], _x[i], _x[i+1] ); + case Catmull: + if( i == 0 ) { + // x prior to spline start - first point used to determine tangent + return _y[1]; + } else if( i == _length-2 ) { + // x after spline end - last point used to determine tangent + return _y[_length-2]; + } else { + float t = (x-_x[i]) / (_x[i+1]-_x[i]); + float m0 = (i==0 ? 0 : catmull_tangent(i) ); + float m1 = (i==_length-1 ? 0 : catmull_tangent(i+1) ); + return hermite( t, _y[i], _y[i+1], m0, m1, _x[i], _x[i+1]); + } + } +} + +float Spline::hermite( float t, float p0, float p1, float m0, float m1, float x0, float x1 ) { + return (hermite_00(t)*p0) + (hermite_10(t)*(x1-x0)*m0) + (hermite_01(t)*p1) + (hermite_11(t)*(x1-x0)*m1); +} +float Spline::hermite_00( float t ) { return (2*pow(t,3)) - (3*pow(t,2)) + 1;} +float Spline::hermite_10( float t ) { return pow(t,3) - (2*pow(t,2)) + t; } +float Spline::hermite_01( float t ) { return (3*pow(t,2)) - (2*pow(t,3)); } +float Spline::hermite_11( float t ) { return pow(t,3) - pow(t,2); } + +float Spline::catmull_tangent( int i ) +{ + if( _x[i+1] == _x[i-1] ) { + // Avoids division by 0 + return 0; + } else { + return (_y[i+1] - _y[i-1]) / (_x[i+1] - _x[i-1]); + } +} diff --git a/Code/Reflow_Master/src/spline.h b/Code/Reflow_Master/src/spline.h new file mode 100644 index 0000000..5b1ac5f --- /dev/null +++ b/Code/Reflow_Master/src/spline.h @@ -0,0 +1,42 @@ +/* + Library for 1-d splines + Copyright Ryan Michael + Licensed under the LGPLv3 +*/ +#ifndef spline_h +#define spline_h + +#include "Arduino.h" + +#define Hermite 10 +#define Catmull 11 + +class Spline +{ + public: + Spline( void ); + Spline( float x[], float y[], int numPoints, int degree = 1 ); + Spline( float x[], float y[], float m[], int numPoints ); + float value( float x ); + void setPoints( float x[], float y[], int numPoints ); + void setPoints( float x[], float y[], float m[], int numPoints ); + void setDegree( int degree ); + + private: + float calc( float, int); + float* _x; + float* _y; + float* _m; + int _degree; + int _length; + int _prev_point; + + float hermite( float t, float p0, float p1, float m0, float m1, float x0, float x1 ); + float hermite_00( float t ); + float hermite_10( float t ); + float hermite_01( float t ); + float hermite_11( float t ); + float catmull_tangent( int i ); +}; + +#endif From 9c580df1462fbd56c4ed272a095e6b704e41ec14 Mon Sep 17 00:00:00 2001 From: Fake-Name Date: Mon, 28 Sep 2020 00:07:28 -0700 Subject: [PATCH 4/6] Ok, MAX31855 is a available PIO library, just use that. Also, add .gitignore. --- .gitignore | 1 + Code/Reflow_Master/platformio.ini | 6 +- Code/Reflow_Master/src/MAX31855.cpp | 107 ---------------------------- Code/Reflow_Master/src/MAX31855.h | 94 ------------------------ 4 files changed, 5 insertions(+), 203 deletions(-) create mode 100644 .gitignore delete mode 100644 Code/Reflow_Master/src/MAX31855.cpp delete mode 100644 Code/Reflow_Master/src/MAX31855.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..03f4a3c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.pio diff --git a/Code/Reflow_Master/platformio.ini b/Code/Reflow_Master/platformio.ini index bfb8c16..a602e09 100644 --- a/Code/Reflow_Master/platformio.ini +++ b/Code/Reflow_Master/platformio.ini @@ -14,9 +14,11 @@ board = adafruit_feather_m0 upload_protocol = sam-ba framework = arduino monitor_speed = 115200 -lib_deps = +lib_deps = adafruit/Adafruit ILI9341@^1.5.6 adafruit/Adafruit GFX Library@^1.10.1 mathertel/OneButton@0.0.0-alpha+sha.eb583d713a adafruit/Adafruit BusIO@^1.5.0 - Wire \ No newline at end of file + cmaglie/FlashStorage@^1.0.0 + Wire + robtillaart/MAX31855@^0.2.3 diff --git a/Code/Reflow_Master/src/MAX31855.cpp b/Code/Reflow_Master/src/MAX31855.cpp deleted file mode 100644 index ef0a750..0000000 --- a/Code/Reflow_Master/src/MAX31855.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// -// FILE: MAX31855.cpp -// AUTHOR: Rob Tillaart -// VERSION: 0.1.10 -// PURPOSE: MAX31855 - Thermocouple -// DATE: 2014-01-01 -// URL: http://forum.arduino.cc/index.php?topic=208061 -// -// HISTORY: -// 0.1.10 2019-07-31 add 3 inline functions to test errors + demo sketch -// 0.1.9 2017-07-27 reverted double -> float (issue33) -// 0.1.08 2015-12-06 replaced all temperature calls with one TCfactor + update demos. -// 0.1.07 2015-12-06 updated TC factors from the MAX31855 datasheet -// 0.1.06 2015-12-05 added support for other types of TC's (experimental) -// 0.1.05 2015-07-12 refactor robust constructor -// 0.1.04 2015-03-09 replaced float -> double (ARM support) -// 0.1.03 fixed negative temperature -// 0.1.02 added offset -// 0.1.01 refactored speed/performance -// 0.1.00 initial version. -// -// Released to the public domain -// - -#include "MAX31855.h" - -MAX31855::MAX31855(const uint8_t sclk, const uint8_t cs, const uint8_t miso) -{ - _sclk = sclk; - _cs = cs; - _miso = miso; - _offset = 0; - _TCfactor = K_TC; - _status = STATUS_NOREAD; - _temperature = -999; - _internal = -999; -} - -void MAX31855::begin() -{ - pinMode(_cs, OUTPUT); - digitalWrite(_cs, HIGH); - - pinMode(_sclk, OUTPUT); - pinMode(_miso, INPUT); -} - -uint8_t MAX31855::read() -{ - uint32_t value = _read(); - - // process status bit 0-2 - _status = value & 0x0007; - value >>= 3; - - // reserved bit 3 - value >>= 1; - - // process internal bit 4-15 - _internal = (value & 0x07FF) * 0.0625; - if (value & 0x0800) - { - _internal = -128 + _internal; // fix neg temp - } - value >>= 12; - - // Fault bit ignored as we have the 3 status bits - // _fault = value & 0x01; - value >>= 1; - - // reserved bit 17 - value >>= 1; - - // process temperature bit 18-30 + sign bit = 31 - _temperature = (value & 0x1FFF) * 0.25; - if (value & 0x2000) // negative flag - { - _temperature = -2048 + _temperature; // fix neg temp - } - if (_offset != 0) _temperature += _offset; - - return _status; -} - -// TODO: optimize performance by direct port manipulation? -uint32_t MAX31855::_read(void) -{ - uint32_t value = 0; - - digitalWrite(_cs, LOW); - - for (int8_t i = 31; i >= 0; i--) - { - value <<= 1; - digitalWrite(_sclk, LOW); - // delayMicroseconds(1); // DUE - if ( digitalRead(_miso) ) value += 1; - digitalWrite(_sclk, HIGH); - // delayMicroseconds(1); // DUE - } - - digitalWrite(_cs, HIGH); - - return value; -} - -// END OF FILE diff --git a/Code/Reflow_Master/src/MAX31855.h b/Code/Reflow_Master/src/MAX31855.h deleted file mode 100644 index 20f1bc1..0000000 --- a/Code/Reflow_Master/src/MAX31855.h +++ /dev/null @@ -1,94 +0,0 @@ -// -// FILE: MAX31855.h -// AUTHOR: Rob Tillaart -// VERSION: 0.1.10 -// PURPOSE: MAX31855 - Thermocouple -// DATE: 2014-01-01 -// URL: http://forum.arduino.cc/index.php?topic=208061 -// -// Released to the public domain -// -#ifndef MAX31855_H -#define MAX31855_H - -#if (ARDUINO < 100) -#include "WProgram.h" -#else -#include "Arduino.h" -#endif - -#define MAX31855_VERSION "0.1.10" - -#define STATUS_OK 0x00 -#define STATUS_OPEN_CIRCUIT 0x01 -#define STATUS_SHORT_TO_GND 0x02 -#define STATUS_SHORT_TO_VCC 0x04 -#define STATUS_ERROR 0x07 -#define STATUS_NOREAD 0x80 - -// Thermocouples working is based upon Seebeck effect. -// Different TC have a different Seebeck Coefficient (µV/°C) -// From http://www.analog.com/library/analogDialogue/archives/44-10/thermocouple.html -// -// As the MAX31855 is designed for K type sensors, one can calculate -// the factor needed to convert other sensors measurements. -// note this is only a linear approximation. -// -// E_TC = 61 => 41/61 = 0.6721311475 -// J_TC = 52 => 41/52 = 0.7884615385 -// K_TC = 41 => 41/41 = 1 -// N_TC = 27 => 41/27 = 1.5185185185 -// R_TC = 9 => 41/9 = 4.5555555556 -// S_TC = 6 => 41/6 = 6.8333333333 -// T_TC = 41 => 41/41 = 1 - -// 0.1.07 updated with numbers from the MAX31855 datasheet -#define E_TC (41.276/76.373) -#define J_TC (41.276/57.953) -#define K_TC (41.276/41.276) -#define N_TC (41.276/36.256) -#define R_TC (41.276/10.506) -#define S_TC (41.276/9.587) -#define T_TC (41.276/52.18) - - -class MAX31855 -{ -public: - MAX31855(uint8_t SCLK, uint8_t CS, uint8_t MISO); - void begin(); - - uint8_t read(); - - float getInternal(void) const { return _internal; } - float getTemperature(void) const { return _temperature * _TCfactor; }; - - uint8_t getStatus(void) const { return _status; }; - // next 4 applies to last read - inline bool statusError() { return (_status & STATUS_ERROR) != 0; }; - inline bool shortToGND() { return (_status & STATUS_SHORT_TO_GND) != 0; }; - inline bool shortToVCC() { return (_status & STATUS_SHORT_TO_VCC) != 0; }; - inline bool openCircuit() { return (_status & STATUS_OPEN_CIRCUIT) != 0; }; - - void setOffset(const float t) { _offset = t; }; - float getOffset() const { return _offset; }; - - void setTCfactor(const float TCfactor) { _TCfactor = TCfactor; }; - float getTCfactor() const { return _TCfactor; }; - -private: - uint32_t _read(); - float _internal; - float _temperature; - uint8_t _status; - float _offset; - float _TCfactor; - - uint8_t _sclk; - uint8_t _miso; - uint8_t _cs; -}; - -#endif - -// END OF FILE From 29006d6f866a3eb4b738ee9b00e44f9976973d0e Mon Sep 17 00:00:00 2001 From: Fake-Name Date: Mon, 28 Sep 2020 00:23:59 -0700 Subject: [PATCH 5/6] Fix all build warnings. Mostly lots of unsigned/signed comparisons, and removed `char* string2char(String command)` because it was an abomination. --- Code/Reflow_Master/src/ReflowMasterProfile.h | 4 +- Code/Reflow_Master/src/Reflow_Master.ino | 106 +++++++++---------- 2 files changed, 51 insertions(+), 59 deletions(-) diff --git a/Code/Reflow_Master/src/ReflowMasterProfile.h b/Code/Reflow_Master/src/ReflowMasterProfile.h index 222e9ef..ed85ee1 100644 --- a/Code/Reflow_Master/src/ReflowMasterProfile.h +++ b/Code/Reflow_Master/src/ReflowMasterProfile.h @@ -36,7 +36,7 @@ This is the profile structure used by the Reflow Master toaster oven controller #pragma once -#define ELEMENTS(x) (sizeof(x) / sizeof(x[0])) +#define ELEMENTS(x) (static_cast(sizeof(x) / sizeof(x[0]))) class ReflowGraph { @@ -93,7 +93,7 @@ class ReflowGraph } } - for ( int i = 0; i < ELEMENTS(wantedCurve); i++ ) + for ( uint32_t i = 0; i < ELEMENTS(wantedCurve); i++ ) { wantedCurve[i] = -1; } diff --git a/Code/Reflow_Master/src/Reflow_Master.ino b/Code/Reflow_Master/src/Reflow_Master.ino index 2823bd0..1c0a596 100644 --- a/Code/Reflow_Master/src/Reflow_Master.ino +++ b/Code/Reflow_Master/src/Reflow_Master.ino @@ -43,7 +43,6 @@ #include // Library Manager // used to obtain the size of an array of any type -#define ELEMENTS(x) (sizeof(x) / sizeof(x[0])) // used to show or hide serial debug output #define DEBUG @@ -110,8 +109,8 @@ typedef struct const String ver = "1.08"; bool newSettings = false; -long nextTempRead; -long nextTempAvgRead; +unsigned long nextTempRead; +unsigned long nextTempAvgRead; int avgReadCount = 0; unsigned long keepFanOnTime = 0; @@ -119,9 +118,9 @@ unsigned long keepFanOnTime = 0; double timeX = 0; double tempOffset = 60; -byte state; // 0 = ready, 1 = warmup, 2 = reflow, 3 = finished, 10 Menu, 11+ settings -byte state_settings = 0; -byte settings_pointer = 0; +uint8_t state; // 0 = ready, 1 = warmup, 2 = reflow, 3 = finished, 10 Menu, 11+ settings +uint8_t state_settings = 0; +uint8_t active_selected_settings_index = 0; // Initialise an array to hold 4 profiles // Increase this array if you plan to add more @@ -427,7 +426,7 @@ void loop() { tft.setTextColor( YELLOW, BLACK ); tft.setTextSize(5); - int third = tft.width() / 4; + // int third = tft.width() / 4; println_Center( tft, " " + String( round( currentTemp ) ) + "c ", tft.width() / 2, ( tft.height() / 2 ) + 10 ); } } @@ -700,9 +699,10 @@ void KeepFanOnCheck() void ReadCurrentTempAvg() { - int status = tc.read(); + tc.read(); + // int status = tc.read(); - float internal = tc.getInternal(); + tc.getInternal(); currentTempAvg += tc.getTemperature() + set.tempOffset; avgReadCount++; } @@ -711,17 +711,18 @@ void ReadCurrentTempAvg() // Read the temp probe void ReadCurrentTemp() { - int status = tc.read(); #ifdef DEBUG - - if (status != 0 ) - { - Serial.print("TC Read Error Status: "); - Serial.println( status ); - } - + int status = tc.read(); + if (status != 0 ) + { + Serial.print("TC Read Error Status: "); + Serial.println( status ); + } + #else + tc.read(); #endif - float internal = tc.getInternal(); + + tc.getInternal(); currentTemp = tc.getTemperature() + set.tempOffset; } @@ -1070,7 +1071,7 @@ void ShowPaste() int y = 50; - for ( int i = 0; i < ELEMENTS(solderPaste); i++ ) + for ( uint32_t i = 0; i < ELEMENTS(solderPaste); i++ ) { if ( i == set.paste ) { @@ -1134,7 +1135,7 @@ void ShowMenuOptions( bool clearAll ) tft.fillRect( tft.width() - 100, buttonPosY[0] - 2, 100, buttonHeight + 4, BLACK ); tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); - switch ( settings_pointer ) + switch ( active_selected_settings_index ) { case 1: @@ -1227,7 +1228,7 @@ void UpdateSettingsPointer() tft.setTextColor( BLUE, BLACK ); tft.setTextSize(2); tft.fillRect( 0, 20, 20, tft.height() - 20, BLACK ); - tft.setCursor( 5, ( 45 + ( 19 * settings_pointer ) ) ); + tft.setCursor( 5, ( 45 + ( 19 * active_selected_settings_index ) ) ); tft.println(">"); @@ -1235,7 +1236,7 @@ void UpdateSettingsPointer() tft.setTextColor( GREEN, BLACK ); tft.fillRect( 0, tft.height() - 40, tft.width(), 40, BLACK ); - switch ( settings_pointer ) + switch ( active_selected_settings_index ) { case 0: println_Center( tft, "Select which profile to reflow", tft.width() / 2, tft.height() - 20 ); @@ -1281,7 +1282,7 @@ void UpdateSettingsPointer() tft.setTextColor( BLUE, BLACK ); tft.setTextSize(2); tft.fillRect( 0, 20, 20, tft.height() - 20, BLACK ); - tft.setCursor( 5, ( 50 + ( 20 * ( settings_pointer * 2 ) ) ) ); + tft.setCursor( 5, ( 50 + ( 20 * ( active_selected_settings_index * 2 ) ) ) ); tft.println(">"); } } @@ -1399,7 +1400,7 @@ void ResetSettingsToDefault() SetCurrentGraph( set.paste ); // show settings - settings_pointer = 0; + active_selected_settings_index = 0; ShowSettings(); } @@ -1449,8 +1450,8 @@ void ShowOvenCheck() SetRelayFrequency( 0 ); StartFan( true ); - int posY = 50; - int incY = 20; + // int posY = 50; + // int incY = 20; #ifdef DEBUG Serial.println("Oven Check"); @@ -1631,7 +1632,7 @@ void UpdateSettingsTempOffset( int posY ) Button press code here */ -long nextButtonPress = 0; +unsigned long nextButtonPress = 0; void button0Press() { @@ -1654,18 +1655,18 @@ void button0Press() } else if ( state == 11 ) { - if ( settings_pointer == 0 ) // change paste + if ( active_selected_settings_index == 0 ) // change paste { - settings_pointer = set.paste; + active_selected_settings_index = set.paste; ShowPaste(); } - else if ( settings_pointer == 1 ) // switch fan use + else if ( active_selected_settings_index == 1 ) // switch fan use { set.useFan = !set.useFan; UpdateSettingsFan( 64 ); } - else if ( settings_pointer == 2 ) // fan countdown after reflow + else if ( active_selected_settings_index == 2 ) // fan countdown after reflow { set.fanTimeAfterReflow += 5; @@ -1676,7 +1677,7 @@ void button0Press() UpdateSettingsFanTime( 83 ); } - else if ( settings_pointer == 3 ) // change lookahead for reflow + else if ( active_selected_settings_index == 3 ) // change lookahead for reflow { set.lookAhead += 1; @@ -1687,7 +1688,7 @@ void button0Press() UpdateSettingsLookAhead( 102 ); } - else if ( settings_pointer == 4 ) // change power + else if ( active_selected_settings_index == 4 ) // change power { set.power += 0.1; @@ -1698,7 +1699,7 @@ void button0Press() UpdateSettingsPower( 121 ); } - else if ( settings_pointer == 5 ) // change temp probe offset + else if ( active_selected_settings_index == 5 ) // change temp probe offset { set.tempOffset += 1; @@ -1709,22 +1710,22 @@ void button0Press() UpdateSettingsTempOffset( 140 ); } - else if ( settings_pointer == 6 ) // change use full power on initial ramp + else if ( active_selected_settings_index == 6 ) // change use full power on initial ramp { set.startFullBlast = !set.startFullBlast; UpdateSettingsStartFullBlast( 159 ); } - else if ( settings_pointer == 7 ) // reset defaults + else if ( active_selected_settings_index == 7 ) // reset defaults { ShowResetDefaults(); } } else if ( state == 12 ) { - if ( set.paste != settings_pointer ) + if ( set.paste != active_selected_settings_index ) { - set.paste = settings_pointer; + set.paste = active_selected_settings_index; SetCurrentGraph( set.paste ); ShowPaste(); } @@ -1749,7 +1750,7 @@ void button1Press() if ( state == 10 ) { - settings_pointer = 0; + active_selected_settings_index = 0; ShowSettings(); } else if ( state == 11 ) // leaving settings so save @@ -1760,7 +1761,7 @@ void button1Press() } else if ( state == 12 || state == 13 ) { - settings_pointer = 0; + active_selected_settings_index = 0; ShowSettings(); } else if ( state == 15 ) // cancel oven check @@ -1779,13 +1780,13 @@ void button2Press() if ( state == 11 ) { - settings_pointer = constrain( settings_pointer - 1, 0, 7 ); + active_selected_settings_index = constrain( active_selected_settings_index - 1ul, 0ul, 7ul ); ShowMenuOptions( false ); //UpdateSettingsPointer(); } else if ( state == 12 ) { - settings_pointer = constrain( settings_pointer - 1, 0, ELEMENTS(solderPaste) - 1 ); + active_selected_settings_index = constrain( active_selected_settings_index - 1ul, 0ul, ELEMENTS(solderPaste) - 1ul ); UpdateSettingsPointer(); } } @@ -1805,13 +1806,13 @@ void button3Press() } else if ( state == 11 ) { - settings_pointer = constrain( settings_pointer + 1, 0, 7 ); + active_selected_settings_index = constrain( active_selected_settings_index + 1ul, 0ul, 7ul ); ShowMenuOptions( false ); //UpdateSettingsPointer(); } else if ( state == 12 ) { - settings_pointer = constrain( settings_pointer + 1, 0, ELEMENTS(solderPaste) - 1 ); + active_selected_settings_index = constrain( active_selected_settings_index + 1ul, 0ul, ELEMENTS(solderPaste) - 1ul ); UpdateSettingsPointer(); } } @@ -1844,10 +1845,10 @@ void SetupGraph(Adafruit_ILI9341 &d, unsigned int tcolor, unsigned int bcolor ) { - double ydiv, xdiv; + // double ydiv, xdiv; + // int rot, newrot; double i; int temp; - int rot, newrot; ox = (x - xlo) * ( w) / (xhi - xlo) + gx; oy = (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy; @@ -1956,15 +1957,6 @@ void GraphDefault(Adafruit_ILI9341 &d, double x, double y, double gx, double gy, oy = y; } -char* string2char(String command) -{ - if (command.length() != 0) - { - char *p = const_cast(command.c_str()); - return p; - } -} - void println_Center( Adafruit_ILI9341 &d, String heading, int centerX, int centerY ) { int x = 0; @@ -1972,7 +1964,7 @@ void println_Center( Adafruit_ILI9341 &d, String heading, int centerX, int cente int16_t x1, y1; uint16_t ww, hh; - d.getTextBounds( string2char(heading), x, y, &x1, &y1, &ww, &hh ); + d.getTextBounds( heading.c_str(), x, y, &x1, &y1, &ww, &hh ); d.setCursor( centerX - ww / 2 + 2, centerY - hh / 2); d.println( heading ); } @@ -1984,7 +1976,7 @@ void println_Right( Adafruit_ILI9341 &d, String heading, int centerX, int center int16_t x1, y1; uint16_t ww, hh; - d.getTextBounds( string2char(heading), x, y, &x1, &y1, &ww, &hh ); + d.getTextBounds( heading.c_str(), x, y, &x1, &y1, &ww, &hh ); d.setCursor( centerX + ( 18 - ww ), centerY - hh / 2); d.println( heading ); } From 5489f9ced23ec295092fd42336846f4524eaa3f1 Mon Sep 17 00:00:00 2001 From: Fake-Name Date: Mon, 28 Sep 2020 00:54:51 -0700 Subject: [PATCH 6/6] Use sane types for things. Mostly, use enums for state, instead of magic numbers everywhere. Also, add facilities for managing inverted-output fan/SSR signals. --- Code/Reflow_Master/src/Reflow_Master.ino | 197 +++++++++++++---------- 1 file changed, 116 insertions(+), 81 deletions(-) diff --git a/Code/Reflow_Master/src/Reflow_Master.ino b/Code/Reflow_Master/src/Reflow_Master.ino index 1c0a596..01280c7 100644 --- a/Code/Reflow_Master/src/Reflow_Master.ino +++ b/Code/Reflow_Master/src/Reflow_Master.ino @@ -104,22 +104,46 @@ typedef struct int lookAheadWarm = 1; int tempOffset = 0; bool startFullBlast = false; + bool invert_ssr = false; + bool invert_fan = false; } Settings; -const String ver = "1.08"; +const String ver = "1.09"; bool newSettings = false; unsigned long nextTempRead; unsigned long nextTempAvgRead; int avgReadCount = 0; +typedef enum class system_state_t: uint8_t { + BOOT = 0, // state == 0 ) // BOOT + WARMUP = 1, // state == 1 ) // WARMUP - We sit here until the probe reaches the starting temp for the profile + REFLOW = 2, // state == 1 || state == 2 || state == 16 ) // warmup, reflow, calibration + FINISHED = 3, // state == 3 ) // FINISHED + MENU = 10, // state == 10 ) // MENU + MENU_EXIT = 11, // state == 11 ) // leaving settings so save + MENU_PASTE_OPTIONS = 12, // state == 12 || state == 13 ) + MENU_RESET_DEFAULTS = 13, // state == 13 ) // restore settings to default + MENU_OVEN_CHECK = 15, // state == 15 ) // cancel oven check + MENU_OVEN_CHECK_RUNNING = 16, // state == 16 ) // calibration - not currently used + ABORT_REFLOW = 99 +} system_state; + + + +typedef enum class calibration_state_t: uint8_t { + WARMUP = 0, + COOL_DOWN = 1, + FINISHED = 2, + RESULTS = 3 +} calibration_state; + unsigned long keepFanOnTime = 0; double timeX = 0; double tempOffset = 60; -uint8_t state; // 0 = ready, 1 = warmup, 2 = reflow, 3 = finished, 10 Menu, 11+ settings -uint8_t state_settings = 0; +system_state state; // 0 = ready, 1 = warmup, 2 = reflow, 3 = finished, 10 Menu, 11+ settings uint8_t active_selected_settings_index = 0; // Initialise an array to hold 4 profiles @@ -129,7 +153,7 @@ ReflowGraph solderPaste[5]; int currentGraphIndex = 0; // Calibration data - currently diabled in this version -int calibrationState = 0; +calibration_state calibrationState = calibration_state::WARMUP; long calibrationSeconds = 0; long calibrationStatsUp = 0; long calibrationStatsDown = 300; @@ -302,7 +326,7 @@ void setup() pinMode( BUTTON3, INPUT ); // Turn off the SSR - duty cycle of 0 - SetRelayFrequency( 0 ); + SetRelayDutyCycle( 0 ); #ifdef DEBUG Serial.begin(115200); @@ -329,7 +353,7 @@ void setup() button3.attachClick(button3Press); #ifdef DEBUG - Serial.println("TFT Begin..."); + Serial.println("TFT Begin..."); #endif // Start up the TFT and show the boot screen @@ -341,7 +365,7 @@ void setup() // Start up the MAX31855 #ifdef DEBUG - Serial.println("Thermocouple Begin..."); + Serial.println("Thermocouple Begin..."); #endif tc.begin(); @@ -369,11 +393,11 @@ void loop() button3.tick(); // Current activity state machine - if ( state == 0 ) // BOOT + if ( state == system_state::BOOT ) // BOOT { return; } - else if ( state == 1 ) // WARMUP - We sit here until the probe reaches the starting temp for the profile + else if ( state == system_state::WARMUP) // WARMUP - We sit here until the probe reaches the starting temp for the profile { if ( nextTempRead < millis() ) // we only read the probe every second { @@ -402,18 +426,18 @@ void loop() return; } - else if ( state == 3 ) // FINISHED + else if ( state == system_state::FINISHED ) // FINISHED { // do we keep the fan on after reflow finishes to help cooldown? KeepFanOnCheck(); return; } - else if ( state == 11 || state == 12 || state == 13 ) // SETTINGS + else if ( state == system_state::MENU_EXIT || state == system_state::MENU_PASTE_OPTIONS || state == system_state::MENU_RESET_DEFAULTS ) // SETTINGS { // Currently not used return; } - else if ( state == 10 ) // MENU + else if ( state == system_state::MENU ) // MENU { if ( nextTempRead < millis() ) { @@ -435,12 +459,12 @@ void loop() KeepFanOnCheck(); return; } - else if ( state == 15 ) + else if ( state == system_state::MENU_OVEN_CHECK ) { // Currently not used return; } - else if ( state == 16 ) // calibration - not currently used + else if ( state == system_state::MENU_OVEN_CHECK_RUNNING ) // calibration - not currently used { if ( nextTempRead < millis() ) { @@ -450,12 +474,12 @@ void loop() MatchCalibrationTemp(); - if ( calibrationState < 2 ) + if ( calibrationState == calibration_state::WARMUP || calibrationState == calibration_state::COOL_DOWN ) { tft.setTextColor( CYAN, BLACK ); tft.setTextSize(2); - if ( calibrationState == 0 ) + if ( calibrationState == calibration_state::WARMUP ) { if ( currentTemp < GetGraphValue(0) ) { @@ -468,7 +492,7 @@ void loop() println_Center( tft, "TARGET " + String( GetGraphValue(1) ) + "c in " + String( GetGraphTime(1) ) + "s", tft.width() / 2, ( tft.height() - 18 ) ); } - else if ( calibrationState == 1 ) + else if ( calibrationState == calibration_state::COOL_DOWN ) { println_Center( tft, "COOL DOWN LEVEL", tft.width() / 2, ( tft.height() / 2 ) - 15 ); tft.fillRect( 0, tft.height() - 30, tft.width(), 30, BLACK ); @@ -479,7 +503,7 @@ void loop() if (currentTemp >= GetGraphValue(0) ) { // adjust the timer colour based on good or bad values - if ( calibrationState == 0 ) + if ( calibrationState == calibration_state::WARMUP ) { if ( calibrationSeconds <= GetGraphTime(1) ) { @@ -505,9 +529,9 @@ void loop() } - else if ( calibrationState == 2 ) + else if ( calibrationState == calibration_state::FINISHED ) { - calibrationState = 3; + calibrationState = calibration_state::RESULTS; tft.setTextColor( GREEN, BLACK ); tft.setTextSize(2); @@ -608,17 +632,23 @@ void loop() } // This is where the SSR is controlled via PWM -void SetRelayFrequency( int duty ) +void SetRelayDutyCycle( int duty ) { // calculate the wanted duty based on settings power override currentDuty = ((float)duty * set.power ); + auto output_duty = constrain( round( currentDuty ), 0, 256); + if (set.invert_ssr) + { + output_duty = 256 - output_duty; + } + // Write the clamped duty cycle to the RELAY GPIO - analogWrite( RELAY, constrain( round( currentDuty ), 0, 255) ); + analogWrite( RELAY, output_duty); #ifdef DEBUG - Serial.print("RELAY Duty Cycle: "); - Serial.println( String( ( currentDuty / 256.0 ) * 100) + "%" + " Using Power: " + String( round( set.power * 100 )) + "%" ); + Serial.print("RELAY Duty Cycle: "); + Serial.println( String( ( currentDuty / 256.0 ) * 100) + "%" + " Using Power: " + String( round( set.power * 100 )) + "%" ); #endif } @@ -629,10 +659,10 @@ void SetRelayFrequency( int duty ) void MatchCalibrationTemp() { - if ( calibrationState == 0 ) // temp speed + if ( calibrationState == calibration_state::WARMUP ) // temp speed { // Set SSR to full duty cycle - 100% - SetRelayFrequency( 255 ); + SetRelayDutyCycle( 255 ); // Only count seconds from when we reach the profile starting temp if ( currentTemp >= GetGraphValue(0) ) @@ -650,16 +680,16 @@ void MatchCalibrationTemp() calibrationUpMatch = ( calibrationSeconds <= GetGraphTime(1) ); - calibrationState = 1; // cooldown - SetRelayFrequency( 0 ); + calibrationState = calibration_state::COOL_DOWN; // cooldown + SetRelayDutyCycle( 0 ); StartFan( false ); Buzzer( 2000, 50 ); } } - else if ( calibrationState == 1 ) + else if ( calibrationState == calibration_state::COOL_DOWN ) { calibrationSeconds --; - SetRelayFrequency( 0 ); + SetRelayDutyCycle( 0 ); if ( calibrationSeconds <= 0 ) { @@ -673,7 +703,7 @@ void MatchCalibrationTemp() // Did we drop in temp > 33% of our target temp? If not, recomment using a fan! calibrationDownMatch = ( calibrationDropVal > 0.33 ); - calibrationState = 2; // finished + calibrationState = calibration_state::FINISHED; // finished StartFan( true ); } } @@ -853,7 +883,8 @@ void MatchTemp() duty = base + ( 172 * perc ); duty = constrain( duty, 0, 256 ); - // override for full blast at start only if the current Temp is less than the wanted Temp, and it's in the ram before pre-soak starts. + // override for full blast at start only if the current Temp is less than the wanted + // Temp, and it's in the ramp before pre-soak starts. if ( set.startFullBlast && timeX < CurrentGraph().reflowGraphX[1] && currentTemp < wantedTemp ) { duty = 256; @@ -861,7 +892,7 @@ void MatchTemp() currentPlotColor = GREEN; - SetRelayFrequency( duty ); + SetRelayDutyCycle( duty ); } void StartFan ( bool start ) @@ -879,8 +910,13 @@ void StartFan ( bool start ) Serial.print( " start? "); Serial.println( start ); #endif + bool fan_state = start ? HIGH : LOW; + if (set.invert_fan) + { + fan_state = !fan_state; + } - digitalWrite ( FAN, ( start ? HIGH : LOW ) ); + digitalWrite ( FAN, fan_state ); } isFanOn = start; @@ -953,13 +989,13 @@ void BootScreen() tft.setTextSize(1); println_Center( tft, "Code v" + ver, tft.width() / 2, tft.height() - 20 ); - state = 10; + state = system_state::MENU; } void ShowMenu() { - state = 10; - SetRelayFrequency( 0 ); + state = system_state::MENU; + SetRelayDutyCycle( 0 ); set = flash_store.read(); @@ -991,8 +1027,8 @@ void ShowMenu() void ShowSettings() { - state = 11; - SetRelayFrequency( 0 ); + state = system_state::MENU_EXIT; + SetRelayDutyCycle( 0 ); newSettings = false; @@ -1057,8 +1093,8 @@ void ShowSettings() void ShowPaste() { - state = 12; - SetRelayFrequency( 0 ); + state = system_state::MENU_PASTE_OPTIONS; + SetRelayDutyCycle( 0 ); tft.fillScreen(BLACK); @@ -1115,7 +1151,7 @@ void ShowMenuOptions( bool clearAll ) } } - if ( state == 10 ) + if ( state == system_state::MENU ) { // button 0 tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); @@ -1129,7 +1165,7 @@ void ShowMenuOptions( bool clearAll ) tft.fillRect( tft.width() - 5, buttonPosY[3], buttonWidth, buttonHeight, YELLOW ); println_Right( tft, "OVEN CHECK", tft.width() - 27, buttonPosY[3] + 8 ); } - else if ( state == 11 ) + else if ( state == system_state::MENU_EXIT ) { // button 0 tft.fillRect( tft.width() - 100, buttonPosY[0] - 2, 100, buttonHeight + 4, BLACK ); @@ -1165,7 +1201,7 @@ void ShowMenuOptions( bool clearAll ) UpdateSettingsPointer(); } - else if ( state == 12 ) + else if ( state == system_state::MENU_PASTE_OPTIONS ) { // button 0 tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); @@ -1185,7 +1221,7 @@ void ShowMenuOptions( bool clearAll ) UpdateSettingsPointer(); } - else if ( state == 13 ) // restore settings to default + else if ( state == system_state::MENU_RESET_DEFAULTS ) // restore settings to default { // button 0 tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); @@ -1195,13 +1231,13 @@ void ShowMenuOptions( bool clearAll ) tft.fillRect( tft.width() - 5, buttonPosY[1], buttonWidth, buttonHeight, RED ); println_Right( tft, "NO", tft.width() - 27, buttonPosY[1] + 8 ); } - else if ( state == 1 || state == 2 || state == 16 ) // warmup, reflow, calibration + else if ( state == system_state::WARMUP || state == system_state::REFLOW || state == system_state::MENU_OVEN_CHECK_RUNNING ) // warmup, reflow, calibration { // button 0 tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); println_Right( tft, "ABORT", tft.width() - 27, buttonPosY[0] + 8 ); } - else if ( state == 3 ) // Finished + else if ( state == system_state::FINISHED ) // Finished { tft.fillRect( tft.width() - 100, buttonPosY[0] - 2, 100, buttonHeight + 4, BLACK ); @@ -1209,7 +1245,7 @@ void ShowMenuOptions( bool clearAll ) tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); println_Right( tft, "MENU", tft.width() - 27, buttonPosY[0] + 8 ); } - else if ( state == 15 ) + else if ( state == system_state::MENU_OVEN_CHECK ) { // button 0 tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); @@ -1223,7 +1259,7 @@ void ShowMenuOptions( bool clearAll ) void UpdateSettingsPointer() { - if ( state == 11 ) + if ( state == system_state::MENU_EXIT ) { tft.setTextColor( BLUE, BLACK ); tft.setTextSize(2); @@ -1277,7 +1313,7 @@ void UpdateSettingsPointer() tft.setTextSize(2); } - else if ( state == 12 ) + else if ( state == system_state::MENU_PASTE_OPTIONS ) { tft.setTextColor( BLUE, BLACK ); tft.setTextSize(2); @@ -1293,7 +1329,7 @@ void StartWarmup() { tft.fillScreen(BLACK); - state = 1; + state = system_state::WARMUP; timeX = 0; ShowMenuOptions( true ); lastWantedTemp = -1; @@ -1313,7 +1349,7 @@ void StartReflow() { tft.fillScreen(BLACK); - state = 2; + state = system_state::REFLOW; ShowMenuOptions( true ); timeX = 0; @@ -1325,11 +1361,11 @@ void StartReflow() void AbortReflow() { - if ( state == 1 || state == 2 || state == 16 ) // if we are in warmup or reflow states + if ( state == system_state::WARMUP|| state == system_state::REFLOW || state == system_state::MENU_OVEN_CHECK_RUNNING ) // if we are in warmup or reflow states { - state = 99; + state = system_state::ABORT_REFLOW; - SetRelayFrequency(0); // Turn the SSR off immediately + SetRelayDutyCycle(0); // Turn the SSR off immediately DrawHeading( "ABORT", RED, BLACK ); @@ -1344,17 +1380,16 @@ void AbortReflow() delay(1000); - state = 10; ShowMenu(); } } void EndReflow() { - if ( state == 2 ) + if ( state == system_state::REFLOW ) { - SetRelayFrequency( 0 ); - state = 3; + SetRelayDutyCycle( 0 ); + state = system_state::FINISHED; Buzzer( 2000, 500 ); @@ -1414,16 +1449,16 @@ void StartOvenCheck() #ifdef DEBUG Serial.println("Oven Check Start Temp " + String( currentTemp ) ); #endif - state = 16; + state = system_state::MENU_OVEN_CHECK_RUNNING; + calibrationState = calibration_state::WARMUP; calibrationSeconds = 0; - calibrationState = 0; calibrationStatsUp = 0; calibrationStatsDown = 300; calibrationUpMatch = false; calibrationDownMatch = false; calibrationDropVal = 0; calibrationRiseVal = 0; - SetRelayFrequency( 0 ); + SetRelayDutyCycle( 0 ); StartFan( false ); #ifdef DEBUG @@ -1446,8 +1481,8 @@ void StartOvenCheck() void ShowOvenCheck() { - state = 15; - SetRelayFrequency( 0 ); + state = system_state::MENU_OVEN_CHECK; + SetRelayDutyCycle( 0 ); StartFan( true ); // int posY = 50; @@ -1509,7 +1544,7 @@ void ShowResetDefaults() tft.setCursor( 20, 120 ); tft.println( "ARE YOU SURE?" ); - state = 13; + state = system_state::MENU_RESET_DEFAULTS; ShowMenuOptions( false ); tft.setTextSize(1); @@ -1641,19 +1676,19 @@ void button0Press() nextButtonPress = millis() + 20; Buzzer( 2000, 50 ); - if ( state == 10 ) + if ( state == system_state::MENU ) { StartWarmup(); } - else if ( state == 1 || state == 2 || state == 16 ) + else if ( state == system_state::WARMUP|| state == system_state::REFLOW || state == system_state::MENU_OVEN_CHECK_RUNNING ) { AbortReflow(); } - else if ( state == 3 ) + else if ( state == system_state::FINISHED ) { ShowMenu(); } - else if ( state == 11 ) + else if ( state == system_state::MENU_EXIT ) { if ( active_selected_settings_index == 0 ) // change paste { @@ -1721,7 +1756,7 @@ void button0Press() ShowResetDefaults(); } } - else if ( state == 12 ) + else if ( state == system_state::MENU_PASTE_OPTIONS ) { if ( set.paste != active_selected_settings_index ) { @@ -1730,11 +1765,11 @@ void button0Press() ShowPaste(); } } - else if ( state == 13 ) + else if ( state == system_state::MENU_RESET_DEFAULTS ) { ResetSettingsToDefault(); } - else if ( state == 15 ) + else if ( state == system_state::MENU_OVEN_CHECK ) { StartOvenCheck(); } @@ -1748,23 +1783,23 @@ void button1Press() nextButtonPress = millis() + 20; Buzzer( 2000, 50 ); - if ( state == 10 ) + if ( state == system_state::MENU ) { active_selected_settings_index = 0; ShowSettings(); } - else if ( state == 11 ) // leaving settings so save + else if ( state == system_state::MENU_EXIT ) // leaving settings so save { // save data in flash flash_store.write(set); ShowMenu(); } - else if ( state == 12 || state == 13 ) + else if ( state == system_state::MENU_PASTE_OPTIONS || state == system_state::MENU_RESET_DEFAULTS ) { active_selected_settings_index = 0; ShowSettings(); } - else if ( state == 15 ) // cancel oven check + else if ( state == system_state::MENU_OVEN_CHECK ) // cancel oven check { ShowMenu(); } @@ -1778,13 +1813,13 @@ void button2Press() nextButtonPress = millis() + 20; Buzzer( 2000, 50 ); - if ( state == 11 ) + if ( state == system_state::MENU_EXIT ) { active_selected_settings_index = constrain( active_selected_settings_index - 1ul, 0ul, 7ul ); ShowMenuOptions( false ); //UpdateSettingsPointer(); } - else if ( state == 12 ) + else if ( state == system_state::MENU_PASTE_OPTIONS ) { active_selected_settings_index = constrain( active_selected_settings_index - 1ul, 0ul, ELEMENTS(solderPaste) - 1ul ); UpdateSettingsPointer(); @@ -1800,17 +1835,17 @@ void button3Press() nextButtonPress = millis() + 20; Buzzer( 2000, 50 ); - if ( state == 10 ) + if ( state == system_state::MENU ) { ShowOvenCheck(); } - else if ( state == 11 ) + else if ( state == system_state::MENU_EXIT ) { active_selected_settings_index = constrain( active_selected_settings_index + 1ul, 0ul, 7ul ); ShowMenuOptions( false ); //UpdateSettingsPointer(); } - else if ( state == 12 ) + else if ( state == system_state::MENU_PASTE_OPTIONS ) { active_selected_settings_index = constrain( active_selected_settings_index + 1ul, 0ul, ELEMENTS(solderPaste) - 1ul ); UpdateSettingsPointer();