|
|
@@ -1,4 +1,5 @@
|
|
|
#include <Arduino.h>
|
|
|
+#include <SPI.h>
|
|
|
#include <U8g2lib.h>
|
|
|
#include <PID_v1.h>
|
|
|
#include <MAX6675.h>
|
|
|
@@ -11,15 +12,16 @@
|
|
|
#define DONE_LED_PIN 5
|
|
|
#define SSR_PIN 4
|
|
|
#define BUTTON_PIN 3
|
|
|
+#define FAN_PIN 6
|
|
|
|
|
|
const char* lcdMessagesReflowStatus[] = {
|
|
|
"Ready",
|
|
|
- "Heating",
|
|
|
- "Holding temp",
|
|
|
+ "Heat",
|
|
|
+ "Hold",
|
|
|
"Cool",
|
|
|
- "Complete",
|
|
|
- "Wait,hot",
|
|
|
- "Error"
|
|
|
+ "Done",
|
|
|
+ "Wait",
|
|
|
+ "Err"
|
|
|
};
|
|
|
|
|
|
typedef enum REFLOW_STATE
|
|
|
@@ -44,13 +46,14 @@ struct reflowProfile{
|
|
|
const char* profileName;
|
|
|
int soakTemp;
|
|
|
unsigned long soakPeriodMS;
|
|
|
+ const char* timeInSeconds;
|
|
|
};
|
|
|
|
|
|
#define NUM_REFLOW_PROFILES 3
|
|
|
reflowProfile profiles[NUM_REFLOW_PROFILES] = {
|
|
|
- {"Sanitize Masks", 70, 1800000}, // 30*60*1000 30 minutes
|
|
|
- {"Dry PLA", 45, 1800000*8},
|
|
|
- {"Dry PETG", 70, 1800000*4}
|
|
|
+ {"Sanitize Masks", 70, 1800000, "1800"}, // 30*60*1000 30 minutes in ms
|
|
|
+ {"Dry PLA", 45, 1800000*8, "14400"}, // 4 hours
|
|
|
+ {"Dry PETG", 70, 1800000*4, "7200"} // 2 hours
|
|
|
};
|
|
|
|
|
|
// ***** CONSTANTS *****
|
|
|
@@ -61,8 +64,8 @@ reflowProfile profiles[NUM_REFLOW_PROFILES] = {
|
|
|
|
|
|
// ***** PID PARAMETERS *****
|
|
|
// ***** PRE-HEAT STAGE *****
|
|
|
-#define PID_KP_PREHEAT 50 // default 100
|
|
|
-#define PID_KI_PREHEAT 0.025 // default 0.025
|
|
|
+#define PID_KP_PREHEAT 20 // default 100
|
|
|
+#define PID_KI_PREHEAT 0.1 // default 0.025
|
|
|
#define PID_KD_PREHEAT 50 // default 20
|
|
|
// ***** SOAKING STAGE *****
|
|
|
#define PID_KP_SOAK 300 // default 300
|
|
|
@@ -98,7 +101,8 @@ int activeReflowProfile = 0;
|
|
|
|
|
|
MAX6675 tcouple(THERMOCOUPLE_CS_PIN);
|
|
|
U8G2_SSD1305_128X64_ADAFRUIT_F_4W_HW_SPI u8g2(U8G2_R0, DISPLAY_CS_PIN, DISPLAY_DC_PIN, DISPLAY_RESET_PIN);
|
|
|
-PID reflowOvenPID(&inputTemp, &output, &setpoint, kp, ki, kd, DIRECT);
|
|
|
+// PID reflowOvenPID(&inputTemp, &output, &setpoint, kp, ki, kd, DIRECT);
|
|
|
+PID reflowOvenPID(&inputTemp, &output, &setpoint, kp, ki, kd, P_ON_M, DIRECT);
|
|
|
EasyButton button(BUTTON_PIN);
|
|
|
|
|
|
// Called once in setup, sets global display attributes.
|
|
|
@@ -140,7 +144,6 @@ void buttonPressed(void) {
|
|
|
reflowStatus = REFLOW_STATUS_OFF;
|
|
|
// Reinitialize state machine
|
|
|
reflowState = REFLOW_STATE_IDLE;
|
|
|
- activeReflowProfile = 0;
|
|
|
} else {
|
|
|
startReflow = true;
|
|
|
}
|
|
|
@@ -154,7 +157,6 @@ void buttonHeld(void) {
|
|
|
reflowStatus = REFLOW_STATUS_OFF;
|
|
|
// Reinitialize state machine
|
|
|
reflowState = REFLOW_STATE_IDLE;
|
|
|
- activeReflowProfile = 0;
|
|
|
} else {
|
|
|
activeReflowProfile++;
|
|
|
if (activeReflowProfile >= NUM_REFLOW_PROFILES) {
|
|
|
@@ -220,7 +222,7 @@ void handleReflowState(void) {
|
|
|
break;
|
|
|
|
|
|
case REFLOW_STATE_COOL:
|
|
|
- // If minimum cool temperature is achieve
|
|
|
+ // If minimum cool temperature is achieved
|
|
|
if (inputTemp <= TEMPERATURE_COOL_MIN)
|
|
|
{
|
|
|
digitalWrite(DONE_LED_PIN, HIGH);
|
|
|
@@ -237,7 +239,6 @@ void handleReflowState(void) {
|
|
|
{
|
|
|
// Reflow process ended
|
|
|
reflowState = REFLOW_STATE_IDLE;
|
|
|
- activeReflowProfile = 0;
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
@@ -302,6 +303,7 @@ void drawScreen(void) {
|
|
|
u8g2.drawStr( 0, rowOffset, "Temp: ");
|
|
|
u8g2.drawStr( 60, rowOffset, temperatureStr);
|
|
|
u8g2.drawStr( 100, rowOffset, "C");
|
|
|
+
|
|
|
rowOffset += rowSize;
|
|
|
|
|
|
// Current Profile
|
|
|
@@ -318,18 +320,34 @@ void drawScreen(void) {
|
|
|
itoa((millis() - soakStartTime)/1000, soakSecondsStr, 10);
|
|
|
u8g2.drawStr( 0, rowOffset, "Time: ");
|
|
|
u8g2.drawStr( 40, rowOffset, soakSecondsStr);
|
|
|
- u8g2.drawStr( 80, rowOffset, "/1800");
|
|
|
+ u8g2.drawStr( 80, rowOffset, profiles[activeReflowProfile].timeInSeconds);
|
|
|
}
|
|
|
rowOffset += rowSize;
|
|
|
|
|
|
+ char *targetTempStr = "Target Temp: ";
|
|
|
+ itoa(profiles[activeReflowProfile].soakTemp, &targetTempStr[13], 10);
|
|
|
+ u8g2.drawStr( 0, rowOffset, targetTempStr);
|
|
|
+ rowOffset += rowSize;
|
|
|
+
|
|
|
u8g2.sendBuffer();
|
|
|
}
|
|
|
|
|
|
+void handleFan() {
|
|
|
+ if(reflowStatus == REFLOW_STATUS_ON || reflowState != REFLOW_STATE_IDLE) {
|
|
|
+ digitalWrite(FAN_PIN, HIGH);
|
|
|
+ } else {
|
|
|
+ digitalWrite(FAN_PIN, LOW);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void setup(void) {
|
|
|
// Turn off SSR.
|
|
|
digitalWrite(SSR_PIN, LOW);
|
|
|
pinMode(SSR_PIN, OUTPUT);
|
|
|
|
|
|
+ digitalWrite(FAN_PIN, LOW);
|
|
|
+ pinMode(FAN_PIN, OUTPUT);
|
|
|
+
|
|
|
pinMode(BUTTON_PIN, INPUT_PULLUP);
|
|
|
button.begin();
|
|
|
button.onPressed(buttonPressed);
|
|
|
@@ -346,11 +364,17 @@ void setup(void) {
|
|
|
windowSize = 2000;
|
|
|
// Initialize thermocouple reading variable
|
|
|
nextRead = millis();
|
|
|
+ // Serial.begin(9600);
|
|
|
}
|
|
|
|
|
|
void loop(void) {
|
|
|
- if (millis() > nextRead) {
|
|
|
+ now = millis();
|
|
|
+ if (now > nextRead) {
|
|
|
readTemp();
|
|
|
+ // Serial.print(setpoint);
|
|
|
+ // Serial.println(",");
|
|
|
+ // Serial.println(inputTemp);
|
|
|
+ nextRead += 1000;
|
|
|
}
|
|
|
|
|
|
handleReflowState();
|
|
|
@@ -359,5 +383,7 @@ void loop(void) {
|
|
|
|
|
|
handleSSR();
|
|
|
|
|
|
+ handleFan();
|
|
|
+
|
|
|
drawScreen();
|
|
|
}
|