mirror of
https://github.com/arwidcool/Solder-Plate.git
synced 2025-02-21 12:49:44 +01:00
Fixed all bugs for overflow in reflow.h Bug was caused by multipling a uint_16t or uint_32t or uint_8t BEFORE casting it to a float or a unit that can handle the number. Type casting should ONLY be done WITHOUT multiplication in the cast. Its easy to create overflows like this.
This commit is contained in:
parent
a99d8d4071
commit
15302f72c7
@ -55,4 +55,5 @@ void PidController::stop()
|
|||||||
void PidController::start()
|
void PidController::start()
|
||||||
{
|
{
|
||||||
controller.start();
|
controller.start();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -147,6 +147,7 @@ void TFT_Display::drawGraph()
|
|||||||
drawGraphAxis();
|
drawGraphAxis();
|
||||||
drawGraphAxisLabels();
|
drawGraphAxisLabels();
|
||||||
drawGraphAxisTicks();
|
drawGraphAxisTicks();
|
||||||
|
drawGraphAxisTickLabels();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TFT_Display::drawGraphAxis()
|
void TFT_Display::drawGraphAxis()
|
||||||
@ -166,18 +167,29 @@ void TFT_Display::drawGraphAxisLabels()
|
|||||||
tft.setCursor(5, 10);
|
tft.setCursor(5, 10);
|
||||||
tft.println("Temp");
|
tft.println("Temp");
|
||||||
|
|
||||||
TFT_XY position = getCenteredTextXY("Time");
|
tft.setCursor(150, 228);
|
||||||
tft.setCursor(position.x, position.y +228);
|
|
||||||
tft.println("Time");
|
tft.println("Time");
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TFT_Display::drawGraphAxisTicks()
|
void TFT_Display::drawGraphAxisTicks()
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TFT_Display::drawGraphAxisTickLabels()
|
||||||
|
{
|
||||||
|
|
||||||
|
//Always starts at 20c
|
||||||
tft.setTextColor(ST77XX_WHITE);
|
tft.setTextColor(ST77XX_WHITE);
|
||||||
tft.setTextSize(1);
|
tft.setTextSize(1);
|
||||||
TFT_XY position = getRightAlignedTextXY("20", graphXY.x, graphXY.y);
|
TFT_XY position = getRightAlignedTextXY("20", graphXY.x, graphXY.y);
|
||||||
tft.setCursor(position.x, position.y);
|
tft.setCursor(position.x, position.y);
|
||||||
tft.println("20");
|
tft.println("20");
|
||||||
|
|
||||||
|
//Always ends at maxTemp
|
||||||
|
|
||||||
|
// tft.setTextColor(ST77XX_WHITE);
|
||||||
|
// tft.setTextSize(1);
|
||||||
|
// position = getRightAlignedTextXY(maxTemp, graphXY.x, graphXY.y - graphHeight);
|
||||||
|
// tft
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ private:
|
|||||||
void drawGraphAxis();
|
void drawGraphAxis();
|
||||||
void drawGraphAxisLabels();
|
void drawGraphAxisLabels();
|
||||||
void drawGraphAxisTicks();
|
void drawGraphAxisTicks();
|
||||||
|
void drawGraphAxisTickLabels();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TFT_H
|
#endif // TFT_H
|
||||||
|
@ -56,10 +56,10 @@ int nReflowProfiles = 3;
|
|||||||
ReflowProfile reflowProfiles[] = {
|
ReflowProfile reflowProfiles[] = {
|
||||||
// 138c profile Sn42Bi58
|
// 138c profile Sn42Bi58
|
||||||
ReflowProfile(new ReflowStep[5]{
|
ReflowProfile(new ReflowStep[5]{
|
||||||
ReflowStep(ReflowProcessState::PREHEAT, 120, 100, EASE_OUT),
|
ReflowStep(ReflowProcessState::PREHEAT, 2, 100, EASE_OUT),
|
||||||
ReflowStep(ReflowProcessState::SOAK, 90, 155),
|
ReflowStep(ReflowProcessState::SOAK, 5, 155),
|
||||||
ReflowStep(ReflowProcessState::REFLOW, 45, 185, EASE_OUT),
|
ReflowStep(ReflowProcessState::REFLOW, 90, 185, HALF_SINE),
|
||||||
ReflowStep(ReflowProcessState::COOL, 45, 155, EASE_OUT),
|
ReflowStep(ReflowProcessState::COOL, 60, 95, EASE_OUT),
|
||||||
ReflowStep(ReflowProcessState::DONE, 0, 0)},
|
ReflowStep(ReflowProcessState::DONE, 0, 0)},
|
||||||
"138c Sn42Bi58\0"),
|
"138c Sn42Bi58\0"),
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
// If you didnt solder the LEDS in order, change the order here just change the pin numbers till it matches your board
|
// If you didnt solder the LEDS in order, change the order here just change the pin numbers till it matches your board
|
||||||
#define LEFT_LED_PIN 20 //Should be RED
|
#define LEFT_LED_PIN 20 //Should be RED
|
||||||
#define MID_LED_PIN 19 //Should be YELLOW
|
#define MID_LED_PIN 18 //Should be YELLOW
|
||||||
#define RIGHT_LED_PIN 18 //Should be GREEN
|
#define RIGHT_LED_PIN 19 //Should be GREEN
|
||||||
#define GREEN_LED_PIN RIGHT_LED_PIN
|
#define GREEN_LED_PIN RIGHT_LED_PIN
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,9 +93,11 @@ void loop()
|
|||||||
if (newState == ReflowProcessState::PREHEAT) {
|
if (newState == ReflowProcessState::PREHEAT) {
|
||||||
|
|
||||||
tftDisplay.init(&chosenReflowProfile);
|
tftDisplay.init(&chosenReflowProfile);
|
||||||
|
|
||||||
chosenReflowProfile.start();
|
chosenReflowProfile.start();
|
||||||
// Start the PID
|
// Start the PID
|
||||||
pidController.start();
|
pidController.start();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state = newState;
|
state = newState;
|
||||||
@ -108,6 +110,7 @@ void loop()
|
|||||||
|
|
||||||
|
|
||||||
pidController.loop();
|
pidController.loop();
|
||||||
|
pidController.debug();
|
||||||
ReflowStep step = chosenReflowProfile.reflowStep();
|
ReflowStep step = chosenReflowProfile.reflowStep();
|
||||||
// Here we draw the actual temp vs time to the display
|
// Here we draw the actual temp vs time to the display
|
||||||
|
|
||||||
@ -117,6 +120,7 @@ void loop()
|
|||||||
if (step.state == ReflowProcessState::DONE)
|
if (step.state == ReflowProcessState::DONE)
|
||||||
{
|
{
|
||||||
pidController.stop();
|
pidController.stop();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
65
src/reflow.h
65
src/reflow.h
@ -32,7 +32,8 @@ enum ReflowStepEaseFunction
|
|||||||
LINEAR,
|
LINEAR,
|
||||||
EASE_IN_OUT,
|
EASE_IN_OUT,
|
||||||
EASE_IN,
|
EASE_IN,
|
||||||
EASE_OUT
|
EASE_OUT,
|
||||||
|
HALF_SINE
|
||||||
};
|
};
|
||||||
class ReflowStep
|
class ReflowStep
|
||||||
{
|
{
|
||||||
@ -56,7 +57,6 @@ public:
|
|||||||
{
|
{
|
||||||
case LINEAR:
|
case LINEAR:
|
||||||
return startTemp + (this->targetTempAtEnd - startTemp) * percentage;
|
return startTemp + (this->targetTempAtEnd - startTemp) * percentage;
|
||||||
|
|
||||||
case EASE_IN_OUT:
|
case EASE_IN_OUT:
|
||||||
return startTemp + (this->targetTempAtEnd - startTemp) * -(cos(percentage * PI) - 1) / (double)2;
|
return startTemp + (this->targetTempAtEnd - startTemp) * -(cos(percentage * PI) - 1) / (double)2;
|
||||||
case EASE_IN:
|
case EASE_IN:
|
||||||
@ -64,6 +64,8 @@ public:
|
|||||||
|
|
||||||
case EASE_OUT:
|
case EASE_OUT:
|
||||||
return startTemp + (this->targetTempAtEnd - startTemp) * (sin(percentage * PI / (double)2));
|
return startTemp + (this->targetTempAtEnd - startTemp) * (sin(percentage * PI / (double)2));
|
||||||
|
case HALF_SINE:
|
||||||
|
return startTemp + (this->targetTempAtEnd - startTemp) * (sin(percentage * PI));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -89,13 +91,13 @@ public:
|
|||||||
}
|
}
|
||||||
ReflowStep steps[5];
|
ReflowStep steps[5];
|
||||||
char name[20];
|
char name[20];
|
||||||
uint32_t endTimes[5] = {0};
|
float endTimes[5] = {0};
|
||||||
uint32_t startTimes[5] = {0};
|
float startTimes[5] = {0};
|
||||||
StopWatch timer;
|
StopWatch timer;
|
||||||
|
|
||||||
void start()
|
void start()
|
||||||
{
|
{
|
||||||
timer = StopWatch(StopWatch::Resolution::MILLIS);
|
timer.setResolution(StopWatch::MILLIS);
|
||||||
timer.start();
|
timer.start();
|
||||||
calculateTimes();
|
calculateTimes();
|
||||||
}
|
}
|
||||||
@ -128,7 +130,14 @@ public:
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < 5; i++)
|
for (int i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
if (elapsedMS >= startTimes[i] * 1000 && elapsedMS < endTimes[i] * 1000)
|
|
||||||
|
float startTimeFloat = startTimes[i];
|
||||||
|
float endTimeFloat = endTimes[i];
|
||||||
|
|
||||||
|
startTimeFloat *= 1000;
|
||||||
|
endTimeFloat *= 1000;
|
||||||
|
|
||||||
|
if (elapsedMS >= startTimeFloat && elapsedMS <endTimeFloat)
|
||||||
{
|
{
|
||||||
// Serial.println(String(elapsedMS) + " " + String(startTimes[i] * 1000) + " " + String(endTimes[i] * 1000) + " " + String(i) + " " + String(steps[i].state));
|
// Serial.println(String(elapsedMS) + " " + String(startTimes[i] * 1000) + " " + String(endTimes[i] * 1000) + " " + String(i) + " " + String(steps[i].state));
|
||||||
return steps[i];
|
return steps[i];
|
||||||
@ -138,8 +147,15 @@ public:
|
|||||||
return steps[4]; // DONE by default
|
return steps[4]; // DONE by default
|
||||||
}
|
}
|
||||||
|
|
||||||
float getPercentage() {
|
float getPercentage()
|
||||||
return (double)timer.elapsed() / (double)(endTimes[4] * 1000);
|
{
|
||||||
|
|
||||||
|
float timerElapsed = timer.elapsed();
|
||||||
|
|
||||||
|
float endTimesFloat[4];
|
||||||
|
|
||||||
|
|
||||||
|
return timerElapsed / (float)(endTimes[4] * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
float getTargetTemp()
|
float getTargetTemp()
|
||||||
@ -148,9 +164,10 @@ public:
|
|||||||
{
|
{
|
||||||
return 20;
|
return 20;
|
||||||
}
|
}
|
||||||
return getTargetTemp(timer.elapsed());
|
return getTargetTemp(timer.elapsed());
|
||||||
}
|
}
|
||||||
float getTargetTemp(uint32_t elapsedMS) {
|
float getTargetTemp(uint32_t elapsedMS)
|
||||||
|
{
|
||||||
uint8_t startTemp = 20; // always assume 20 degrees at the start
|
uint8_t startTemp = 20; // always assume 20 degrees at the start
|
||||||
|
|
||||||
ReflowStep curStep = reflowStep(elapsedMS);
|
ReflowStep curStep = reflowStep(elapsedMS);
|
||||||
@ -161,25 +178,31 @@ public:
|
|||||||
|
|
||||||
// startTemp => 20 or the targetTempAtEnd of the previous step
|
// startTemp => 20 or the targetTempAtEnd of the previous step
|
||||||
|
|
||||||
uint32_t startTimeMS = startTimes[STEPINDEX(curStep)] * 1000;
|
uint32_t startTimeMS = startTimes[STEPINDEX(curStep)];
|
||||||
|
|
||||||
|
startTimeMS *= 1000;
|
||||||
|
|
||||||
uint32_t relativeElapsedTime = elapsedMS - startTimeMS;
|
uint32_t relativeElapsedTime = elapsedMS - startTimeMS;
|
||||||
|
|
||||||
float percentage = (double)relativeElapsedTime / ((double)(curStep.duration) * 1000);
|
|
||||||
|
float duration = curStep.duration ;
|
||||||
|
duration *= 1000;
|
||||||
|
|
||||||
|
float relativeElapsedTimeF = relativeElapsedTime;
|
||||||
|
|
||||||
|
float percentage = relativeElapsedTime / duration;
|
||||||
// Serial.println(String(percentage)+ "%" + String(STATE_STR(curStep.state)) + " Elapsed: " + String(elapsedMS) + " ___ " + String(curStep.duration * 1000));
|
// Serial.println(String(percentage)+ "%" + String(STATE_STR(curStep.state)) + " Elapsed: " + String(elapsedMS) + " ___ " + String(curStep.duration * 1000));
|
||||||
return curStep.calcTempAtPercentage(startTemp, percentage);
|
return curStep.calcTempAtPercentage(startTemp, percentage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the Target Temp At Process Percentage.
|
* @brief Get the Target Temp At Process Percentage.
|
||||||
* @param processPercentage a number between 0 and 1. 0 is the start of the process, 1 is the end of the process
|
* @param processPercentage a number between 0 and 1. 0 is the start of the process, 1 is the end of the process
|
||||||
* @return float the target temperature at the given percentage of the full process
|
* @return float the target temperature at the given percentage of the full process
|
||||||
*/
|
*/
|
||||||
float getTargetTempFromPercentage(double processPercentage)
|
float getTargetTempFromPercentage(double processPercentage)
|
||||||
{
|
{
|
||||||
uint32_t duration = endTimes[4];
|
uint16_t duration = endTimes[4];
|
||||||
uint8_t startTemp = 20; // always assume 20 degrees at the start
|
uint8_t startTemp = 20; // always assume 20 degrees at the start
|
||||||
return getTargetTemp(duration * 1000 * processPercentage);
|
return getTargetTemp(duration * 1000 * processPercentage);
|
||||||
}
|
}
|
||||||
@ -191,16 +214,6 @@ public:
|
|||||||
return (elapsedMS - startTimeMS) / 1000;
|
return (elapsedMS - startTimeMS) / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void toBuffer(uint8_t *b)
|
void toBuffer(uint8_t *b)
|
||||||
{
|
{
|
||||||
memset(b, 0, PROFILE_SERIALIZED_SIZE);
|
memset(b, 0, PROFILE_SERIALIZED_SIZE);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user