plt temperature

This commit is contained in:
2021-08-23 07:48:44 +02:00
parent d0fbc713a5
commit 42dd5f9261
12 changed files with 175 additions and 67 deletions

View File

@@ -16,10 +16,10 @@ upload_protocol = stlink
debug_tool = stlink debug_tool = stlink
monitor_speed = 115200 monitor_speed = 115200
lib_deps = lib_deps =
yuriisalimov/MAX6675_Thermocouple@^2.0.2
bodmer/TFT_eSPI@^2.3.70 bodmer/TFT_eSPI@^2.3.70
br3ttb/PID@^1.2.1 br3ttb/PID@^1.2.1
;siruli/MAX6675@^2.1.0 ;siruli/MAX6675@^2.1.0
zhenek-kreker/MAX6675 with hardware SPI@^1.0.0
lib_ldf_mode = deep+ lib_ldf_mode = deep+
build_flags = build_flags =
-D USER_SETUP_LOADED=1 -D USER_SETUP_LOADED=1

View File

@@ -7,9 +7,11 @@
// #define LCD_DC PB1 // #define LCD_DC PB1
// #define LCD_CS PB0 // #define LCD_CS PB0
#define THERM_CS PB5 #define THERM_SS PB12
#define THERM_SO PB4 #define THERM_MISO PB13
#define THERM_CL PB6 #define THERM_CLK PB14
#define THERM_MOSI PB15 //not used
#define HEAT_OUT PA2 #define HEAT_OUT PA2

View File

@@ -4,13 +4,9 @@
#include "button.h" #include "button.h"
#include "lcd.h" #include "lcd.h"
// Button AXIS_Y = Button(BUTTON_AXIS_Y, true, DEBOUNCE_MS); // Button AXIS_Y = Button(BUTTON_AXIS_Y, true, DEBOUNCE_MS);
// Button AXIS_X = Button(BUTTON_AXIS_X, true, DEBOUNCE_MS); // Button AXIS_X = Button(BUTTON_AXIS_X, true, DEBOUNCE_MS);
/******************************************************************************* /*******************************************************************************
Title: Reflow Oven Controller Title: Reflow Oven Controller
Version: 1.20 Version: 1.20
@@ -157,6 +153,7 @@ int oldTemp = 0;
byte state; byte state;
bool disableMenu; bool disableMenu;
bool profileIsOn; bool profileIsOn;
uint32_t processStartTime = 0;
// Specify PID control interface & it must be here, after all declaration // Specify PID control interface & it must be here, after all declaration
PID reflowOvenPID(&input, &output, &setpoint, kp, ki, kd, DIRECT); PID reflowOvenPID(&input, &output, &setpoint, kp, ki, kd, DIRECT);
@@ -169,8 +166,9 @@ void initControlLoop(void)
nextCheck = millis(); nextCheck = millis();
// Initialize thermocouple reading variable // Initialize thermocouple reading variable
nextRead = millis(); nextRead = millis();
}
pinMode(HEAT_OUT, OUTPUT);
}
String getReflowStatus_str(void) String getReflowStatus_str(void)
{ {
@@ -258,6 +256,59 @@ bool getOutputState(void)
return outputState; return outputState;
} }
uint32_t safetyTimer = 0;
#define SAFETYTIMEOUT 5000 //ms
double oldinput = 0;
#define SAFETYMARGIN 5 //degrees C
bool SafetyError = false;
bool getSafetyCheck(void)
{
uint32_t timeNow = millis();
if (!outputState)
{
safetyTimer = timeNow;
oldinput = input;
return true;
}
else
{
if (timeNow - safetyTimer > SAFETYTIMEOUT)
{
if (input - oldinput < SAFETYMARGIN)
{
setReflowStatus(false);
return false;
}
else
{
return true;
oldinput = input;
}
}
}
return true;
}
float getProcessTime(void)
{
if ((reflowStatus == REFLOW_STATUS_ON) && (processStartTime > 0))
{
float retval = (millis() - processStartTime);
retval /= 1000;
return retval;
}
else
{
return 0;
}
}
bool getOverheating(void)
{
return (reflowState == REFLOW_STATE_TOO_HOT);
}
void handleReflowStatemachine(void) void handleReflowStatemachine(void)
{ {
// Reflow oven controller state machine // Reflow oven controller state machine
@@ -265,6 +316,7 @@ void handleReflowStatemachine(void)
{ {
case REFLOW_STATE_IDLE: case REFLOW_STATE_IDLE:
activeStatus = "Idle"; activeStatus = "Idle";
processStartTime = 0;
// If oven temperature is still above room temperature // If oven temperature is still above room temperature
if (input >= TEMPERATURE_ROOM) if (input >= TEMPERATURE_ROOM)
{ {
@@ -284,7 +336,7 @@ void handleReflowStatemachine(void)
// Initialize PID control window starting time // Initialize PID control window starting time
windowStartTime = millis(); windowStartTime = millis();
// Ramp up to minimum soaking temperature // Ramp up to minimum soaking temperature
setpoint = TEMPERATURE_SOAK_MIN; setpoint = TEMPERATURE_SOAK_MIN + 5;
// Tell the PID to range between 0 and the full window size // Tell the PID to range between 0 and the full window size
reflowOvenPID.SetOutputLimits(0, windowSize); reflowOvenPID.SetOutputLimits(0, windowSize);
reflowOvenPID.SetSampleTime(PID_SAMPLE_TIME); reflowOvenPID.SetSampleTime(PID_SAMPLE_TIME);
@@ -292,6 +344,8 @@ void handleReflowStatemachine(void)
reflowOvenPID.SetMode(AUTOMATIC); reflowOvenPID.SetMode(AUTOMATIC);
// Proceed to preheat stage // Proceed to preheat stage
reflowState = REFLOW_STATE_PREHEAT; reflowState = REFLOW_STATE_PREHEAT;
// log process start time
processStartTime = millis();
} }
} }
break; break;
@@ -520,7 +574,6 @@ void handleTemperatureReadings(void)
} }
} }
/* ---- REFLOW MAIN LOOP ---- */ /* ---- REFLOW MAIN LOOP ---- */
void handleControlLoop() void handleControlLoop()
{ {
@@ -529,7 +582,7 @@ void handleControlLoop()
Serial.println("handlecontrolloop: ERROR state"); Serial.println("handlecontrolloop: ERROR state");
return; return;
} }
getSafetyCheck();
handleTemperatureReadings(); handleTemperatureReadings();
handleReflowStatemachine(); handleReflowStatemachine();
handleReflowPID(); handleReflowPID();

View File

@@ -77,3 +77,5 @@ reflowStatus_t getReflowStatus(void);
void setReflowStatus(bool newStatus); void setReflowStatus(bool newStatus);
double getReflowTargetTemp(void); double getReflowTargetTemp(void);
bool getOutputState(void); bool getOutputState(void);
float getProcessTime(void);
bool getOverheating(void);

View File

@@ -1,20 +0,0 @@
#include "heater.h"
uint16_t heatingProfile[] =
{
30,
50,
70,
90
};
void initHeater(void)
{
pinMode(HEAT_OUT,OUTPUT);
digitalWrite(HEAT_OUT, LOW);
}
void handleHeater(void)
{
}

View File

@@ -1,7 +0,0 @@
#pragma once
#include "Arduino.h"
#include "board.h"
void initHeater(void);
void handleHeater(void);

View File

@@ -3,6 +3,7 @@
#include "thermo.h" #include "thermo.h"
#include "controlloop.h" #include "controlloop.h"
#include "button.h" #include "button.h"
#include <vector>
#include <TFT_eSPI.h> // Include the graphics library #include <TFT_eSPI.h> // Include the graphics library
@@ -31,7 +32,7 @@ void updateTemperature(void)
chartArea_spr.drawString("A:", TEMP_X + TEMP_LABEL_X, TEMP_H / 4); chartArea_spr.drawString("A:", TEMP_X + TEMP_LABEL_X, TEMP_H / 4);
chartArea_spr.drawString("T:", TEMP_X + TEMP_LABEL_X, TEMP_H / 4 * 3); chartArea_spr.drawString("T:", TEMP_X + TEMP_LABEL_X, TEMP_H / 4 * 3);
chartArea_spr.drawNumber(getTemperature(), TEMP_X + TEMP_VALUE_X, TEMP_H / 4); chartArea_spr.drawFloat(getTemperature(), 1, TEMP_X + TEMP_VALUE_X, TEMP_H / 4);
if (getReflowStatus() == REFLOW_STATUS_OFF) if (getReflowStatus() == REFLOW_STATUS_OFF)
{ {
chartArea_spr.drawString("--", TEMP_X + TEMP_VALUE_X, TEMP_H / 4 * 3); chartArea_spr.drawString("--", TEMP_X + TEMP_VALUE_X, TEMP_H / 4 * 3);
@@ -45,7 +46,12 @@ void updateTemperature(void)
uint32_t calcTemp(double temp) uint32_t calcTemp(double temp)
{ {
//map(long x, long in_min, long in_max, long out_min, long out_max) //map(long x, long in_min, long in_max, long out_min, long out_max)
return CHART_H - map(temp, CHART_TEMP_MIN, CHART_TEMP_MAX, CHART_Y_AXIS_OFFSET, CHART_H) + CHART_X_AXIS_OFFSET; return CHART_H - map(temp, CHART_TEMP_MIN, CHART_TEMP_MAX, CHART_X_AXIS_OFFSET, CHART_H) + CHART_X_AXIS_OFFSET;
}
uint32_t calcTempY(uint32_t inputY)
{
return map(inputY, CHART_H, CHART_X_AXIS_OFFSET, CHART_TEMP_MIN, CHART_TEMP_MAX);
} }
uint32_t calcTime(uint32_t timeMs) uint32_t calcTime(uint32_t timeMs)
@@ -53,6 +59,40 @@ uint32_t calcTime(uint32_t timeMs)
return map((timeMs / 1000), 0, CHART_TIME_MAX, 0, CHART_W - CHART_Y_AXIS_OFFSET); return map((timeMs / 1000), 0, CHART_TIME_MAX, 0, CHART_W - CHART_Y_AXIS_OFFSET);
} }
std::vector<double> temperatureReading;
uint32_t lastReading = 0;
#define TEMPINTERVAL 1000
void updateRealtimeGraph(void)
{
if(getReflowStatus() == REFLOW_STATUS_OFF)
{
temperatureReading.clear();
return;
}
//record temperature
uint32_t timeNow = millis();
if (timeNow - lastReading > TEMPINTERVAL)
{
temperatureReading.push_back(getTemperature());
lastReading = timeNow;
}
//draw graph
uint32_t timeIndex = 0;
uint32_t lastX = 0;
uint32_t lastY = 0;
for (auto &&sample : temperatureReading)
{
uint32_t nowX = calcTime(timeIndex * TEMPINTERVAL);
uint32_t nowY = calcTemp(sample);
chartArea_spr.drawLine(lastX,lastY, nowX, nowY, CHART_ACTUAL_COLOR);
lastX = nowX;
lastY = nowY;
timeIndex ++;
}
}
void updateTargetChart(void) void updateTargetChart(void)
{ {
@@ -93,6 +133,8 @@ void updateTargetChart(void)
calcTemp(TEMPERATURE_ROOM), calcTemp(TEMPERATURE_ROOM),
CHART_TARGET_COLOR); CHART_TARGET_COLOR);
updateRealtimeGraph();
updateTemperature(); updateTemperature();
chartArea_spr.pushSprite(CHART_X + CHART_Y_AXIS_OFFSET, CHART_Y); chartArea_spr.pushSprite(CHART_X + CHART_Y_AXIS_OFFSET, CHART_Y);
} }
@@ -108,7 +150,12 @@ void prepTargetChart(void)
void updateReflowState(void) void updateReflowState(void)
{ {
reflowstate_spr.fillRoundRect(STATE_OFFSET, 0, (STATE_W / 2) - (2 * STATE_OFFSET), STATE_H, STATE_R, STATE_BG_COLOR); uint32_t statusColor = STATE_BG_COLOR;
if(getOverheating())
{
statusColor = TFT_RED;
}
reflowstate_spr.fillRoundRect(STATE_OFFSET, 0, (STATE_W / 2) - (2 * STATE_OFFSET), STATE_H, STATE_R, statusColor);
reflowstate_spr.fillRoundRect(STATE_W / 2 + STATE_OFFSET, 0, (STATE_W / 2) - (2 * STATE_OFFSET), STATE_H, STATE_R, STATE_BG_COLOR); reflowstate_spr.fillRoundRect(STATE_W / 2 + STATE_OFFSET, 0, (STATE_W / 2) - (2 * STATE_OFFSET), STATE_H, STATE_R, STATE_BG_COLOR);
reflowstate_spr.drawString(getReflowState_str(), STATE_W / 4, STATE_H / 2); reflowstate_spr.drawString(getReflowState_str(), STATE_W / 4, STATE_H / 2);
reflowstate_spr.drawString(getReflowStatus_str(), STATE_W / 4 * 3, STATE_H / 2); reflowstate_spr.drawString(getReflowStatus_str(), STATE_W / 4 * 3, STATE_H / 2);
@@ -161,7 +208,7 @@ void prepChart(void)
for (int i = 0; i < CHART_Y_TICKS; i++) for (int i = 0; i < CHART_Y_TICKS; i++)
{ {
//tick value //tick value
uint16_t y_tick_step = CHART_TEMP_MAX - ((CHART_TEMP_MAX - CHART_TEMP_MIN) / CHART_Y_TICKS * i + 1) + CHART_TEMP_MIN; uint16_t y_tick_step = calcTempY( tickIndex * (i +1));//CHART_TEMP_MAX - ((CHART_TEMP_MAX - CHART_TEMP_MIN) / CHART_Y_TICKS * i + 1) + CHART_TEMP_MIN;
chartYaxis_spr.drawLine(CHART_Y_AXIS_OFFSET - 8, tickIndex * (i + 1), CHART_Y_AXIS_OFFSET, tickIndex * (i + 1), CHART_LINE_COLOR); chartYaxis_spr.drawLine(CHART_Y_AXIS_OFFSET - 8, tickIndex * (i + 1), CHART_Y_AXIS_OFFSET, tickIndex * (i + 1), CHART_LINE_COLOR);
chartYaxis_spr.setTextDatum(BR_DATUM); chartYaxis_spr.setTextDatum(BR_DATUM);
chartYaxis_spr.drawString(String(y_tick_step), CHART_Y_AXIS_OFFSET - 3, tickIndex * (i + 1), CHART_FONT); chartYaxis_spr.drawString(String(y_tick_step), CHART_Y_AXIS_OFFSET - 3, tickIndex * (i + 1), CHART_FONT);
@@ -182,14 +229,17 @@ void prepChart(void)
void prepStatus(void) void prepStatus(void)
{ {
looptime_spr.createSprite(20, tft.fontHeight(1) + 1); looptime_spr.createSprite(80, tft.fontHeight(1) + 1);
} }
void updateStatus(void) void updateStatus(void)
{ {
looptime_spr.fillSprite(TFT_BLACK); looptime_spr.fillSprite(TFT_BLACK);
looptime_spr.setTextDatum(MC_DATUM); looptime_spr.setTextDatum(TL_DATUM);
looptime_spr.drawNumber(getLooptime(), looptime_spr.width() / 2, looptime_spr.height() / 2, 1); looptime_spr.setTextColor(TFT_WHITE);
looptime_spr.drawNumber(getLooptime(), 1, 1, 1);
looptime_spr.drawFloat(getProcessTime(), 2, 20, 1, 1);
looptime_spr.pushSprite(1, 1); looptime_spr.pushSprite(1, 1);
} }

View File

@@ -30,11 +30,11 @@
#define CHART_TIME_MAX 140 //time scale in seconds #define CHART_TIME_MAX 140 //time scale in seconds
#define CHART_TEMP_MIN 20 //offset in degrees #define CHART_TEMP_MIN 20 //offset in degrees
#define CHART_TEMP_MAX 240 //degrees #define CHART_TEMP_MAX 240 //degrees
#define CHART_Y_TICKS 11 #define CHART_Y_TICKS 10
#define CHART_X_TICKS 7 #define CHART_X_TICKS 7
#define CHART_LINE_COLOR TFT_WHITE #define CHART_LINE_COLOR TFT_WHITE
#define CHART_TEXT_COLOR TFT_RED #define CHART_TEXT_COLOR TFT_RED
#define CHART_TARGET_COLOR TFT_WHITE #define CHART_TARGET_COLOR TFT_LIGHTGREY
#define CHART_ACTUAL_COLOR TFT_RED #define CHART_ACTUAL_COLOR TFT_RED
#define CHART_BG_COLOR TFT_BLACK #define CHART_BG_COLOR TFT_BLACK
@@ -58,7 +58,7 @@
#define TEMP_BG_COLOR TFT_BLUE #define TEMP_BG_COLOR TFT_BLUE
#define TEMP_R TFT_DEFAULT_R #define TEMP_R TFT_DEFAULT_R
#define TEMP_LABEL_X 2 #define TEMP_LABEL_X 2
#define TEMP_VALUE_X 30 #define TEMP_VALUE_X 20
#define OUTPUT_W 12 #define OUTPUT_W 12
#define OUTPUT_H 12 #define OUTPUT_H 12

View File

@@ -4,7 +4,6 @@
#include "lcd.h" #include "lcd.h"
#include "thermo.h" #include "thermo.h"
#include "button.h" #include "button.h"
#include "heater.h"
#include "status.h" #include "status.h"
#include "controlloop.h" #include "controlloop.h"
@@ -14,7 +13,6 @@ void setup()
initLCD(); initLCD();
initThermo(); initThermo();
initButton(); initButton();
initHeater();
initControlLoop(); initControlLoop();
} }
@@ -25,7 +23,6 @@ void loop()
handleLCD(); handleLCD();
handleThermo(); handleThermo();
handleButton(); handleButton();
handleHeater();
handleStatus(); handleStatus();
handleControlLoop(); handleControlLoop();
} }

View File

@@ -1,5 +1,6 @@
#include "status.h" #include "status.h"
#include "controlloop.h"
uint64_t timelast = 0; uint64_t timelast = 0;
uint64_t blinkrate = 500; uint64_t blinkrate = 500;
@@ -33,3 +34,8 @@ uint32_t getLooptime(void)
{ {
return looptime; return looptime;
} }
double getReflowTime(void)
{
return getProcessTime();
}

View File

@@ -1,31 +1,57 @@
#include "thermo.h" #include "thermo.h"
#include "controlloop.h"
Thermocouple *thermocouple = NULL; MAX6675 thermocouple(THERM_SS, THERM_MISO, THERM_CLK);
uint32_t thermo_lastTime = 0; uint32_t thermo_lastTime = 0;
double lastTemperature = 0; double lastTemperature = 0;
bool simulation = true;
#define SIM_TEMP_STEP 1
#define SIM_TEMP_COOL 0.08
#define SIM_INTERVAL 100
uint32_t simTimer = 0;
void initThermo() void initThermo()
{ {
Thermocouple *originThermocouple = new MAX6675_Thermocouple(THERM_CL, THERM_CS, THERM_SO); if(simulation)
thermocouple = new SmoothThermocouple(originThermocouple, SMOOTHING_FACTOR); {
lastTemperature = TEMPERATURE_ROOM-20;
}
} }
void handleThermo(void) void handleThermo(void)
{ {
// Reads temperature if(simulation)
uint32_t timeNow = millis();
if (timeNow - thermo_lastTime > THERMO_INTERVAL)
{ {
lastTemperature = thermocouple->readCelsius(); uint32_t timeNow = millis();
thermo_lastTime = timeNow; if(timeNow - simTimer > SIM_INTERVAL)
{
if(getOutputState())
{
lastTemperature += SIM_TEMP_STEP;
}
else
{
if(lastTemperature > TEMPERATURE_ROOM-20)
{
lastTemperature -= SIM_TEMP_COOL;
}
}
simTimer = timeNow;
}
}
else
{
lastTemperature = thermocouple.readTempC();
} }
} }
double getTemperature(void) double getTemperature(void)
{ {
return 23;//lastTemperature; return lastTemperature; //lastTemperature;
} }
bool getThermoCoupleFault(void) bool getThermoCoupleFault(void)

View File

@@ -2,9 +2,8 @@
#include "Arduino.h" #include "Arduino.h"
#include "board.h" #include "board.h"
#include <Thermocouple.h>
#include <MAX6675_Thermocouple.h> #include "max6675.h"
#include <SmoothThermocouple.h>
#define THERMO_INTERVAL 200 #define THERMO_INTERVAL 200
#define SMOOTHING_FACTOR 2 #define SMOOTHING_FACTOR 2