Un-reveresed the PID logic, a bit easier to follow now

This commit is contained in:
-help 2024-02-01 21:18:05 +02:00
parent 8b78c29abc
commit 7f2c8f105a
8 changed files with 63 additions and 72 deletions

View File

@ -14,6 +14,7 @@ board = ATmega4809
framework = arduino
monitor_speed = 38400
upload_speed = 115200
board_hardware.uart = uart0
upload_protocol = arduino
lib_ldf_mode = chain+

View File

@ -14,7 +14,7 @@ PidController::PidController(PidControllerData *data)
this->data = data;
controller.begin(&(this->data->currentTemp), &(this->data->setPoint), &(this->data->targetTemp), PID_P, PID_I, PID_D);
controller.reverse();
// controller.reverse();
controller.setOutputLimits(PID_OUTPUT_MIN, PID_OUTPUT_MAX);
controller.setSampleTime(PID_SAMPLE_TIME);
controller.setWindUpLimits(PID_WINDUP_MIN, PID_WINDUP_MAX);
@ -47,7 +47,10 @@ void PidController::loop()
// float sysVoltage = analogRef.calculateSystemVoltage();
compute();
analogWrite(MOSTFET_PIN, data->setPoint);
//Reverseal of the PWM value is needed because the PID controller is set to work with a normal direction, Creates fopr a better PID control
//255= off, 0=full power
analogWrite(MOSTFET_PIN, 255- data->setPoint);
}
void PidController::stop()

View File

@ -38,9 +38,7 @@ void TFT_Display::init(ReflowProfile *profile)
tft.setCursor(xy.x, xy.y);
tft.println(profile->name);
getMaxTempFromProfile(profile);
this->profile = profile;
drawTimer.reset();
drawTimer.setResolution(StopWatch::MILLIS);
@ -54,19 +52,11 @@ void TFT_Display::drawRealTemp(double *temp, float percentage)
uint32_t timeSinceLastDraw = drawTimer.elapsed();
// Serial.print("Time since last draw:");
// Serial.println(timeSinceLastDraw);
if (timeSinceLastDraw >= 930)
{
float temperature = static_cast<float>(*temp);
// Serial.print("Time:");
// Serial.print(percentage);
// Serial.print(" Temp:");
// Serial.println(temperature);
uint16_t eplased = drawTimer.elapsed();
// Get the xy and y pixel of the temp
@ -84,7 +74,6 @@ void TFT_Display::drawRealTemp(double *temp, float percentage)
drawTimer.reset();
drawTimer.start();
}
}
void TFT_Display::clear()
@ -272,7 +261,7 @@ void TFT_Display::drawGraphAxisTickLabels()
TFT_XY position;
// Always starts at 20c
position = getRightAlignedTextXY("20", graphXY.x, graphXY.y);
position = getRightAlignedTextXY("0", graphXY.x, graphXY.y);
tft.setCursor(position.x - tickMarkLength, position.y);
tft.println("20");
@ -286,7 +275,7 @@ void TFT_Display::drawGraphAxisTickLabels()
// Draw three tick labels on the temp axis at 1/4, 1/2 and 3/4 of the way along
for (int i = 1; i <= 3; i++)
{
uint8_t temp = (maxTemp - minTemp) * i / 4;
uint8_t temp = ((maxTemp ) * i / 4)+minTemp;
char *tempCharPtr = numberToCharPtr(temp);
position = getRightAlignedTextXY(tempCharPtr, graphXY.x, graphXY.y - (graphHeight * i / 4));
tft.setCursor(position.x - tickMarkLength, position.y);
@ -327,7 +316,8 @@ void TFT_Display::drawGraphReflowStagesBackground()
uint16_t x = graphXY.x + 1;
uint16_t y = graphXY.y;
uint16_t totalDuration = profile->endTimes[4];
for (int i=0; i<4; i++) {
for (int i = 0; i < 4; i++)
{
uint16_t y = graphXY.y - graphHeight;
uint16_t height = graphHeight;
float duration = profile->endTimes[i];
@ -336,15 +326,16 @@ void TFT_Display::drawGraphReflowStagesBackground()
Serial.println(String(i) + " - duration: " + String(duration) + " |Perc: " + String(percAtEndStep) + " - x:" + String(x) + " y:" + String(y) + " newX:" + String(newX) + " height:" + String(height) + " color:" + String(colors[i]));
tft.drawRect(x, y, newX - x, graphHeight, colors[i]);
x = newX;
}
}
void TFT_Display::drawReflowTargetTempLine() {
void TFT_Display::drawReflowTargetTempLine()
{
uint16_t y = tempYonGraph(chosenReflowProfile.startTemps[0]);
uint16_t x = percentageToX(0);
for (float i=0.00; i<=1; i+=0.01) {
for (float i = 0.00; i <= 1; i += 0.01)
{
float temp = profile->getTargetTempFromPercentage(i);
uint16_t y2 = tempYonGraph(temp);
uint16_t x2 = percentageToX(i);
@ -358,8 +349,8 @@ void TFT_Display::drawReflowTargetTempLine() {
uint16_t TFT_Display::tempYonGraph(float temp)
{
// Calculate the y position of the temperature on the graph based on the min and max temperatures and the min and max y of the graph the higher the temperature the lower the y values goes
// Calculate the y position based on the current temperature on the graph taking account for the Y start position and the height of the graph the y start is at the end of the graph
float y = graphXY.y - (graphHeight * ((temp - minTemp) / (maxTemp - minTemp)));
return y;
@ -367,7 +358,6 @@ uint16_t TFT_Display::tempYonGraph(float temp)
uint16_t TFT_Display::tempYonGraph(float *temp)
{
float y = graphXY.y - (graphHeight * ((*temp - minTemp) / (maxTemp - minTemp)));
return y;
}

View File

@ -44,6 +44,7 @@ private:
uint16_t graphHeight = 180;
uint16_t graphWidth = 255;
TFT_XY graphXY = {32, 220};
TFT_XY graphOrigin = {32, 40};
uint16_t maxTemp = 0;
uint8_t minTemp = 20;

View File

@ -62,7 +62,7 @@ uint16_t cool_COLOR = 0x00a8;
// These are the reflow profiles that you can choose from, you can add more if you want (up to 5) but you will have to change the nReflowProfiles variable to the number of profiles you have
int nReflowProfiles = 3;
int nReflowProfiles = 4;
ReflowProfile reflowProfiles[] = {
// 138c profile Sn42Bi58
@ -74,13 +74,32 @@ ReflowProfile reflowProfiles[] = {
ReflowStep(ReflowProcessState::DONE, 0, 0)},
"138c Sn42Bi58\0"),
ReflowProfile(new ReflowStep[5]{ReflowStep(ReflowProcessState::PREHEAT, 100, 150), ReflowStep(ReflowProcessState::SOAK, 30, 180), ReflowStep(ReflowProcessState::REFLOW, 80, 220, EASE_IN_OUT), ReflowStep(ReflowProcessState::COOL, 30, 183), ReflowStep(ReflowProcessState::DONE, 0, 0)}, "183C Sn63 Pb37 \0"),
// The profile target says to get to 100c in 30 seconds but our hotplate can not do that so we extended the time to 120 seconds and combine the 150 and 183c steps into one step
// With a 12V PSU it also takes a while to reach these high temps so we increase the times a bit, experemintation is needed for different boards.
ReflowProfile(new ReflowStep[5]{ReflowStep(ReflowProcessState::PREHEAT, 120, 100,EASE_OUT),
ReflowStep(ReflowProcessState::SOAK, 150, 183,EASE_IN),
ReflowStep(ReflowProcessState::REFLOW, 110, 235, EASE_OUT),
ReflowStep(ReflowProcessState::COOL, 30, 80,EASE_OUT),
ReflowStep(ReflowProcessState::DONE, 0, 0)},
"183C Sn63 Pb37 \0"),
ReflowProfile(new ReflowStep[5]{ReflowStep(ReflowProcessState::PREHEAT, 120, 77,LINEAR),
ReflowStep(ReflowProcessState::SOAK, 180, 135,LINEAR),
ReflowStep(ReflowProcessState::REFLOW, 110, 211, LINEAR),
ReflowStep(ReflowProcessState::COOL, 30, 80,EASE_OUT),
ReflowStep(ReflowProcessState::DONE, 0, 0)},
"RAMP HOLD 235c\0"),
ReflowProfile(new ReflowStep[5]{ReflowStep(
ReflowProcessState::PREHEAT, 200, 100,MID_RAMP_HOLD),
ReflowStep(ReflowProcessState::SOAK, 150, 150,FAST_RAMP_HOLD),
ReflowStep(ReflowProcessState::REFLOW, 150, 220, SLOW_RAMP_HOLD),
ReflowStep(ReflowProcessState::COOL, 200, 0,LINEAR),
ReflowStep(ReflowProcessState::DONE, 0, 0)}, "Tuning Profile \0"),
ReflowStep(ReflowProcessState::DONE, 0, 0)},
"Tuning Profile \0"),
};

View File

@ -36,17 +36,21 @@
//PID Controller values
#define PID_P .3
#define PID_I 1
#define PID_D .2
#define PID_P .05
#define PID_I .02
#define PID_D .1
#define PID_WINDUP_MIN 60
#define PID_WINDUP_MAX -20
#define PID_WINDUP_MIN -100
#define PID_WINDUP_MAX 255
////////////////////////////////////////
//The actual PWM of the mosfet is 0 for max and 255 for off
//This gets inverted after the setpoint is grabbed from the PID controller in the main loop
#define PID_OUTPUT_MIN 255
#define PID_OUTPUT_MAX 0
//////////////////////////////////////
//This gets reversed inside the PID controller
#define PID_OUTPUT_MIN 0
#define PID_OUTPUT_MAX 255
#define PID_SAMPLE_TIME 0.1

View File

@ -70,18 +70,6 @@ public:
return startTemp + (this->targetTemp - startTemp) * (sin(percentage * PI / (double)2));
case HALF_SINE:
return startTemp + (this->targetTemp - startTemp) * (sin(percentage * PI));
case SLOW_RAMP_HOLD:
if (percentage <= 0.75)
{
// Ramp up to the target temperature over the first 25% of the time
return startTemp + (this->targetTemp - startTemp) * (percentage / 0.75);
}
else
{
// Hold at the target temperature for the remaining 75% of the time
return this->targetTemp;
}
case MID_RAMP_HOLD:
@ -95,18 +83,6 @@ public:
// Hold at the target temperature for the remaining half of the time
return this->targetTemp;
}
case FAST_RAMP_HOLD:
if (percentage <= 0.25)
{
// Ramp up to the target temperature over the first 75% of the time
return startTemp + (this->targetTemp - startTemp) * (percentage / 0.25);
}
else
{
// Hold at the target temperature for the remaining 25% of the time
return this->targetTemp;
}
}
}
};
@ -169,15 +145,8 @@ public:
// We will grab the current PCB temp from the PID as the start temp otherwise the PID will be off
if (plateTemp > 30 && plateTemp < 60)
{
startTemps[0] = plateTemp; // USe ambient temp as the starting temp for the first step
}
else
{
startTemps[0] = 20;
}
endTemps[0] = steps[0].calcTempAtPercentage(startTemps[0], 1);
endTemps[1] = steps[1].calcTempAtPercentage(endTemps[0], 1);

View File

@ -65,7 +65,6 @@ float Thermistor::getTemperature()
float Thermistor::getWeightingFactor()
{
// If the thermistor is mounted on PCB we give it a weighting factor of 10
switch (zPlacement)
{
@ -129,6 +128,11 @@ float Thermistor::getWeightingFactor()
}
break;
case SIDE:
return 0.05;
break;
default:
return 1;
break;