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:
-help 2024-01-28 04:53:54 +02:00
parent a99d8d4071
commit 15302f72c7
7 changed files with 67 additions and 36 deletions

View File

@ -55,4 +55,5 @@ void PidController::stop()
void PidController::start()
{
controller.start();
}

View File

@ -147,6 +147,7 @@ void TFT_Display::drawGraph()
drawGraphAxis();
drawGraphAxisLabels();
drawGraphAxisTicks();
drawGraphAxisTickLabels();
}
void TFT_Display::drawGraphAxis()
@ -166,18 +167,29 @@ void TFT_Display::drawGraphAxisLabels()
tft.setCursor(5, 10);
tft.println("Temp");
TFT_XY position = getCenteredTextXY("Time");
tft.setCursor(position.x, position.y +228);
tft.setCursor(150, 228);
tft.println("Time");
}
void TFT_Display::drawGraphAxisTicks()
{
}
void TFT_Display::drawGraphAxisTickLabels()
{
//Always starts at 20c
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(1);
TFT_XY position = getRightAlignedTextXY("20", graphXY.x, graphXY.y);
tft.setCursor(position.x, position.y);
tft.println("20");
//Always ends at maxTemp
// tft.setTextColor(ST77XX_WHITE);
// tft.setTextSize(1);
// position = getRightAlignedTextXY(maxTemp, graphXY.x, graphXY.y - graphHeight);
// tft
}

View File

@ -42,6 +42,7 @@ private:
void drawGraphAxis();
void drawGraphAxisLabels();
void drawGraphAxisTicks();
void drawGraphAxisTickLabels();
};
#endif // TFT_H

View File

@ -56,10 +56,10 @@ int nReflowProfiles = 3;
ReflowProfile reflowProfiles[] = {
// 138c profile Sn42Bi58
ReflowProfile(new ReflowStep[5]{
ReflowStep(ReflowProcessState::PREHEAT, 120, 100, EASE_OUT),
ReflowStep(ReflowProcessState::SOAK, 90, 155),
ReflowStep(ReflowProcessState::REFLOW, 45, 185, EASE_OUT),
ReflowStep(ReflowProcessState::COOL, 45, 155, EASE_OUT),
ReflowStep(ReflowProcessState::PREHEAT, 2, 100, EASE_OUT),
ReflowStep(ReflowProcessState::SOAK, 5, 155),
ReflowStep(ReflowProcessState::REFLOW, 90, 185, HALF_SINE),
ReflowStep(ReflowProcessState::COOL, 60, 95, EASE_OUT),
ReflowStep(ReflowProcessState::DONE, 0, 0)},
"138c Sn42Bi58\0"),

View File

@ -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
#define LEFT_LED_PIN 20 //Should be RED
#define MID_LED_PIN 19 //Should be YELLOW
#define RIGHT_LED_PIN 18 //Should be GREEN
#define MID_LED_PIN 18 //Should be YELLOW
#define RIGHT_LED_PIN 19 //Should be GREEN
#define GREEN_LED_PIN RIGHT_LED_PIN

View File

@ -93,9 +93,11 @@ void loop()
if (newState == ReflowProcessState::PREHEAT) {
tftDisplay.init(&chosenReflowProfile);
chosenReflowProfile.start();
// Start the PID
pidController.start();
}
}
state = newState;
@ -108,6 +110,7 @@ void loop()
pidController.loop();
pidController.debug();
ReflowStep step = chosenReflowProfile.reflowStep();
// Here we draw the actual temp vs time to the display
@ -117,6 +120,7 @@ void loop()
if (step.state == ReflowProcessState::DONE)
{
pidController.stop();
}
}
}

View File

@ -32,7 +32,8 @@ enum ReflowStepEaseFunction
LINEAR,
EASE_IN_OUT,
EASE_IN,
EASE_OUT
EASE_OUT,
HALF_SINE
};
class ReflowStep
{
@ -56,7 +57,6 @@ public:
{
case LINEAR:
return startTemp + (this->targetTempAtEnd - startTemp) * percentage;
case EASE_IN_OUT:
return startTemp + (this->targetTempAtEnd - startTemp) * -(cos(percentage * PI) - 1) / (double)2;
case EASE_IN:
@ -64,6 +64,8 @@ public:
case EASE_OUT:
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];
char name[20];
uint32_t endTimes[5] = {0};
uint32_t startTimes[5] = {0};
float endTimes[5] = {0};
float startTimes[5] = {0};
StopWatch timer;
void start()
{
timer = StopWatch(StopWatch::Resolution::MILLIS);
timer.setResolution(StopWatch::MILLIS);
timer.start();
calculateTimes();
}
@ -128,7 +130,14 @@ public:
{
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));
return steps[i];
@ -138,8 +147,15 @@ public:
return steps[4]; // DONE by default
}
float getPercentage() {
return (double)timer.elapsed() / (double)(endTimes[4] * 1000);
float getPercentage()
{
float timerElapsed = timer.elapsed();
float endTimesFloat[4];
return timerElapsed / (float)(endTimes[4] * 1000);
}
float getTargetTemp()
@ -148,9 +164,10 @@ public:
{
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
ReflowStep curStep = reflowStep(elapsedMS);
@ -161,25 +178,31 @@ public:
// 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;
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));
return curStep.calcTempAtPercentage(startTemp, 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
* @return float the target temperature at the given percentage of the full process
*/
*/
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
return getTargetTemp(duration * 1000 * processPercentage);
}
@ -191,16 +214,6 @@ public:
return (elapsedMS - startTimeMS) / 1000;
}
void toBuffer(uint8_t *b)
{
memset(b, 0, PROFILE_SERIALIZED_SIZE);