mirror of
https://github.com/arwidcool/Solder-Plate.git
synced 2024-11-12 01:10:52 +01:00
Reflow not starting when split
This commit is contained in:
parent
f62a71352e
commit
751aaa6b8c
@ -70,4 +70,7 @@ enum ThermistorXY_Placement
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
236
src/reflow.cpp
Normal file
236
src/reflow.cpp
Normal file
@ -0,0 +1,236 @@
|
||||
#include "reflow.h"
|
||||
|
||||
//extern TemperatureController tempController;
|
||||
|
||||
ReflowStep::ReflowStep()
|
||||
{
|
||||
}
|
||||
|
||||
ReflowStep::ReflowStep(ReflowProcessState state, uint8_t time, uint8_t targetTemp) : state(state), duration(time), targetTemp(targetTemp), easeFunction(LINEAR) {}
|
||||
|
||||
ReflowStep::ReflowStep(ReflowProcessState state, uint8_t time, uint8_t targetTemp, ReflowStepEaseFunction fn) : state(state),
|
||||
duration(time),
|
||||
targetTemp(targetTemp),
|
||||
easeFunction(fn)
|
||||
{
|
||||
}
|
||||
|
||||
float ReflowStep::calcTempAtPercentage(uint8_t startTemp, float percentage)
|
||||
|
||||
{
|
||||
switch (this->easeFunction)
|
||||
{
|
||||
case LINEAR:
|
||||
return startTemp + (this->targetTemp - startTemp) * percentage;
|
||||
case EASE_IN_OUT:
|
||||
return startTemp + (this->targetTemp - startTemp) * -(cos(percentage * PI) - 1) / (double)2;
|
||||
case EASE_IN:
|
||||
return startTemp + (this->targetTemp - startTemp) * (1 - cos(percentage * PI / (double)2));
|
||||
case EASE_OUT:
|
||||
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:
|
||||
|
||||
if (percentage <= 0.50)
|
||||
{
|
||||
// Ramp up to the target temperature over the first half of the time
|
||||
return startTemp + (this->targetTemp - startTemp) * (percentage / 0.50);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReflowProfile::ReflowProfile(ReflowStep steps[5], char name[20])
|
||||
{
|
||||
|
||||
{
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
this->steps[i] = steps[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
this->name[i] = name[i];
|
||||
}
|
||||
calculateValues();
|
||||
}
|
||||
}
|
||||
|
||||
void ReflowProfile::start()
|
||||
|
||||
{
|
||||
timer = StopWatch(StopWatch::MILLIS);
|
||||
timer.start();
|
||||
}
|
||||
|
||||
void ReflowProfile::calculateValues()
|
||||
|
||||
{
|
||||
endTimes[0] = steps[0].duration;
|
||||
endTimes[1] = endTimes[0] + steps[1].duration;
|
||||
endTimes[2] = endTimes[1] + steps[2].duration;
|
||||
endTimes[3] = endTimes[2] + steps[3].duration;
|
||||
endTimes[4] = endTimes[3] + steps[4].duration;
|
||||
|
||||
startTimes[0] = 0;
|
||||
startTimes[1] = endTimes[0];
|
||||
startTimes[2] = endTimes[1];
|
||||
startTimes[3] = endTimes[2];
|
||||
startTimes[4] = endTimes[3];
|
||||
|
||||
startTemps[0] = 20; // USe ambient temp as the starting temp for the first step
|
||||
|
||||
// We will grab the current PCB temp from the PID as the start temp otherwise the PID will be off
|
||||
//startTemps[0] = tempController.getPlateTemperature();
|
||||
|
||||
endTemps[0] = steps[0].calcTempAtPercentage(startTemps[0], 1);
|
||||
endTemps[1] = steps[1].calcTempAtPercentage(endTemps[0], 1);
|
||||
endTemps[2] = steps[2].calcTempAtPercentage(endTemps[1], 1);
|
||||
endTemps[3] = steps[3].calcTempAtPercentage(endTemps[2], 1);
|
||||
endTemps[4] = steps[4].calcTempAtPercentage(endTemps[3], 1);
|
||||
|
||||
startTemps[1] = endTemps[0];
|
||||
startTemps[2] = endTemps[1];
|
||||
startTemps[3] = endTemps[2];
|
||||
startTemps[4] = endTemps[3];
|
||||
}
|
||||
|
||||
ReflowStep ReflowProfile::reflowStep()
|
||||
|
||||
{
|
||||
if (!timer.isRunning())
|
||||
{
|
||||
return steps[0];
|
||||
}
|
||||
return reflowStep(timer.elapsed());
|
||||
}
|
||||
|
||||
ReflowStep ReflowProfile::reflowStep(uint32_t elapsedMS)
|
||||
|
||||
{
|
||||
if (!timer.isRunning())
|
||||
{
|
||||
return steps[0];
|
||||
}
|
||||
return reflowStep(timer.elapsed());
|
||||
}
|
||||
|
||||
float ReflowProfile::getPercentage()
|
||||
|
||||
{
|
||||
return timer.elapsed() / (double)TOMILLIS(endTimes[4]);
|
||||
}
|
||||
|
||||
float ReflowProfile::getTargetTemp()
|
||||
|
||||
{
|
||||
if (!timer.isRunning())
|
||||
{
|
||||
return startTemps[0];
|
||||
}
|
||||
return getTargetTemp(timer.elapsed());
|
||||
}
|
||||
|
||||
float ReflowProfile::getTargetTemp(uint32_t elapsedMS)
|
||||
|
||||
{
|
||||
ReflowStep curStep = reflowStep(elapsedMS);
|
||||
|
||||
uint32_t startTimeMS = TOMILLIS(startTimes[STEPINDEX(curStep)]);
|
||||
uint32_t relativeElapsedTime = elapsedMS - startTimeMS;
|
||||
|
||||
float stepPercentage = relativeElapsedTime / (double)TOMILLIS(curStep.duration);
|
||||
return curStep.calcTempAtPercentage(startTemps[STEPINDEX(curStep)], stepPercentage);
|
||||
}
|
||||
|
||||
float ReflowProfile::getTargetTempFromPercentage(double processPercentage)
|
||||
|
||||
{
|
||||
return getTargetTemp(TOMILLIS(endTimes[4]) * processPercentage);
|
||||
}
|
||||
|
||||
uint8_t ReflowProfile::getCurrentStepRelativeTime()
|
||||
|
||||
{
|
||||
uint32_t elapsedMS = timer.elapsed();
|
||||
uint32_t startTimeMS = TOMILLIS(startTimes[STEPINDEX(reflowStep())]);
|
||||
return (elapsedMS - startTimeMS) / 1000;
|
||||
}
|
||||
|
||||
void ReflowProfile::toBuffer(uint8_t *b)
|
||||
|
||||
{
|
||||
memset(b, 0, PROFILE_SERIALIZED_SIZE);
|
||||
memcpy(b, name, PROFILE_SERIALIZED_NAME_SIZE);
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
b[PROFILE_SERIALIZED_NAME_SIZE + i * 3] = steps[i].duration;
|
||||
b[PROFILE_SERIALIZED_NAME_SIZE + 1 + i * 3] = steps[i].targetTemp;
|
||||
b[PROFILE_SERIALIZED_NAME_SIZE + 2 + i * 3] = steps[i].easeFunction;
|
||||
}
|
||||
}
|
||||
|
||||
void ReflowProfile::toEEPROM(uint8_t index)
|
||||
|
||||
{
|
||||
uint8_t b[40];
|
||||
toBuffer(b);
|
||||
EEPROM.put(index * PROFILE_SERIALIZED_SIZE, b);
|
||||
}
|
||||
|
||||
ReflowProfile ReflowProfile::fromBuffer(const uint8_t *b)
|
||||
|
||||
{
|
||||
char name[PROFILE_SERIALIZED_NAME_SIZE];
|
||||
memcpy(name, b, PROFILE_SERIALIZED_NAME_SIZE);
|
||||
ReflowStep steps[5] = {};
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
steps[i] = ReflowStep(
|
||||
(ReflowProcessState)(i + PREHEAT),
|
||||
b[PROFILE_SERIALIZED_NAME_SIZE + i * 3],
|
||||
b[PROFILE_SERIALIZED_NAME_SIZE + 1 + i * 3],
|
||||
(ReflowStepEaseFunction)b[PROFILE_SERIALIZED_NAME_SIZE + 2 + i * 3]);
|
||||
}
|
||||
return ReflowProfile(steps, name);
|
||||
}
|
||||
|
||||
ReflowProfile ReflowProfile::fromEEPROM(uint8_t index)
|
||||
|
||||
{
|
||||
uint8_t b[40];
|
||||
EEPROM.get(index * PROFILE_SERIALIZED_SIZE, b);
|
||||
return fromBuffer(b);
|
||||
}
|
233
src/reflow.h
233
src/reflow.h
@ -4,10 +4,7 @@
|
||||
#include <EEPROM.h>
|
||||
#include "StopWatch.h"
|
||||
#include "thermistors/Thermistor.h"
|
||||
|
||||
|
||||
|
||||
|
||||
//#include "thermistors/TemperatureController.h"
|
||||
|
||||
// STATE MACHINE
|
||||
enum ReflowProcessState
|
||||
@ -41,98 +38,35 @@ enum ReflowStepEaseFunction
|
||||
MID_RAMP_HOLD,
|
||||
FAST_RAMP_HOLD
|
||||
};
|
||||
|
||||
class ReflowStep
|
||||
{
|
||||
public:
|
||||
ReflowStep() {}
|
||||
ReflowStep(ReflowProcessState state, uint8_t time, uint8_t targetTemp) : state(state), duration(time), targetTemp(targetTemp), easeFunction(LINEAR) {}
|
||||
ReflowStep(ReflowProcessState state, uint8_t time, uint8_t targetTemp, ReflowStepEaseFunction fn) : state(state),
|
||||
duration(time),
|
||||
targetTemp(targetTemp),
|
||||
easeFunction(fn)
|
||||
{
|
||||
}
|
||||
ReflowStep() ;
|
||||
ReflowStep(ReflowProcessState state, uint8_t time, uint8_t targetTemp) ;
|
||||
ReflowStep(ReflowProcessState state, uint8_t time, uint8_t targetTemp, ReflowStepEaseFunction fn);
|
||||
|
||||
uint8_t duration;
|
||||
uint8_t targetTemp;
|
||||
ReflowProcessState state;
|
||||
ReflowStepEaseFunction easeFunction;
|
||||
|
||||
float calcTempAtPercentage(uint8_t startTemp, float percentage)
|
||||
{
|
||||
switch (this->easeFunction)
|
||||
{
|
||||
case LINEAR:
|
||||
return startTemp + (this->targetTemp - startTemp) * percentage;
|
||||
case EASE_IN_OUT:
|
||||
return startTemp + (this->targetTemp - startTemp) * -(cos(percentage * PI) - 1) / (double)2;
|
||||
case EASE_IN:
|
||||
return startTemp + (this->targetTemp - startTemp) * (1 - cos(percentage * PI / (double)2));
|
||||
case EASE_OUT:
|
||||
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:
|
||||
|
||||
if (percentage <= 0.50)
|
||||
{
|
||||
// Ramp up to the target temperature over the first half of the time
|
||||
return startTemp + (this->targetTemp - startTemp) * (percentage / 0.50);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
float calcTempAtPercentage(uint8_t startTemp, float percentage);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define PROFILE_SERIALIZED_SIZE 40
|
||||
#define PROFILE_SERIALIZED_NAME_SIZE 20
|
||||
#define STEPINDEX(step) (step.state - PREHEAT)
|
||||
#define TOMILLIS(x) (((uint32_t)x) * (uint32_t)1000)
|
||||
|
||||
|
||||
class ReflowProfile
|
||||
{
|
||||
|
||||
public:
|
||||
ReflowProfile(ReflowStep steps[5], char name[20])
|
||||
{
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
this->steps[i] = steps[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
this->name[i] = name[i];
|
||||
}
|
||||
calculateValues();
|
||||
}
|
||||
ReflowProfile(ReflowStep steps[5], char name[20]);
|
||||
ReflowStep steps[5];
|
||||
char name[20];
|
||||
uint16_t endTimes[5] = {0};
|
||||
@ -141,146 +75,31 @@ public:
|
||||
uint8_t startTemps[5] = {0};
|
||||
StopWatch timer;
|
||||
|
||||
void start()
|
||||
{
|
||||
timer = StopWatch(StopWatch::MILLIS);
|
||||
timer.start();
|
||||
}
|
||||
void start();
|
||||
|
||||
void calculateValues()
|
||||
{
|
||||
endTimes[0] = steps[0].duration;
|
||||
endTimes[1] = endTimes[0] + steps[1].duration;
|
||||
endTimes[2] = endTimes[1] + steps[2].duration;
|
||||
endTimes[3] = endTimes[2] + steps[3].duration;
|
||||
endTimes[4] = endTimes[3] + steps[4].duration;
|
||||
void calculateValues();
|
||||
|
||||
startTimes[0] = 0;
|
||||
startTimes[1] = endTimes[0];
|
||||
startTimes[2] = endTimes[1];
|
||||
startTimes[3] = endTimes[2];
|
||||
startTimes[4] = endTimes[3];
|
||||
ReflowStep reflowStep();
|
||||
|
||||
// We will grab the current PCB temp from the PID as the start temp otherwise the PID will be off
|
||||
|
||||
|
||||
startTemps[0] = 20; // USe ambient temp as the starting temp for the first step
|
||||
|
||||
endTemps[0] = steps[0].calcTempAtPercentage(startTemps[0], 1);
|
||||
endTemps[1] = steps[1].calcTempAtPercentage(endTemps[0], 1);
|
||||
endTemps[2] = steps[2].calcTempAtPercentage(endTemps[1], 1);
|
||||
endTemps[3] = steps[3].calcTempAtPercentage(endTemps[2], 1);
|
||||
endTemps[4] = steps[4].calcTempAtPercentage(endTemps[3], 1);
|
||||
|
||||
startTemps[1] = endTemps[0];
|
||||
startTemps[2] = endTemps[1];
|
||||
startTemps[3] = endTemps[2];
|
||||
startTemps[4] = endTemps[3];
|
||||
}
|
||||
|
||||
ReflowStep reflowStep()
|
||||
{
|
||||
if (!timer.isRunning())
|
||||
{
|
||||
return steps[0];
|
||||
}
|
||||
return reflowStep(timer.elapsed());
|
||||
}
|
||||
|
||||
ReflowStep reflowStep(uint32_t elapsedMS)
|
||||
{
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
if (elapsedMS >= TOMILLIS(startTimes[i]) && elapsedMS < TOMILLIS(endTimes[i]))
|
||||
{
|
||||
return steps[i];
|
||||
}
|
||||
}
|
||||
return steps[4]; // DONE by default
|
||||
}
|
||||
|
||||
float getPercentage()
|
||||
{
|
||||
return timer.elapsed() / (double)TOMILLIS(endTimes[4]);
|
||||
}
|
||||
|
||||
float getTargetTemp()
|
||||
{
|
||||
if (!timer.isRunning())
|
||||
{
|
||||
return startTemps[0];
|
||||
}
|
||||
return getTargetTemp(timer.elapsed());
|
||||
}
|
||||
float getTargetTemp(uint32_t elapsedMS)
|
||||
{
|
||||
ReflowStep curStep = reflowStep(elapsedMS);
|
||||
|
||||
uint32_t startTimeMS = TOMILLIS(startTimes[STEPINDEX(curStep)]);
|
||||
uint32_t relativeElapsedTime = elapsedMS - startTimeMS;
|
||||
|
||||
float stepPercentage = relativeElapsedTime / (double)TOMILLIS(curStep.duration);
|
||||
return curStep.calcTempAtPercentage(startTemps[STEPINDEX(curStep)], stepPercentage);
|
||||
}
|
||||
ReflowStep reflowStep(uint32_t elapsedMS);
|
||||
float getPercentage();
|
||||
float getTargetTemp();
|
||||
float getTargetTemp(uint32_t elapsedMS);
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
return getTargetTemp(TOMILLIS(endTimes[4]) * processPercentage);
|
||||
}
|
||||
float getTargetTempFromPercentage(double processPercentage);
|
||||
uint8_t getCurrentStepRelativeTime();
|
||||
|
||||
uint8_t getCurrentStepRelativeTime()
|
||||
{
|
||||
uint32_t elapsedMS = timer.elapsed();
|
||||
uint32_t startTimeMS = TOMILLIS(startTimes[STEPINDEX(reflowStep())]);
|
||||
return (elapsedMS - startTimeMS) / 1000;
|
||||
}
|
||||
void toBuffer(uint8_t *b);
|
||||
|
||||
void toBuffer(uint8_t *b)
|
||||
{
|
||||
memset(b, 0, PROFILE_SERIALIZED_SIZE);
|
||||
memcpy(b, name, PROFILE_SERIALIZED_NAME_SIZE);
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
b[PROFILE_SERIALIZED_NAME_SIZE + i * 3] = steps[i].duration;
|
||||
b[PROFILE_SERIALIZED_NAME_SIZE + 1 + i * 3] = steps[i].targetTemp;
|
||||
b[PROFILE_SERIALIZED_NAME_SIZE + 2 + i * 3] = steps[i].easeFunction;
|
||||
}
|
||||
}
|
||||
void toEEPROM(uint8_t index);
|
||||
static ReflowProfile fromBuffer(const uint8_t *b);
|
||||
|
||||
void toEEPROM(uint8_t index)
|
||||
{
|
||||
uint8_t b[40];
|
||||
toBuffer(b);
|
||||
EEPROM.put(index * PROFILE_SERIALIZED_SIZE, b);
|
||||
}
|
||||
|
||||
static ReflowProfile fromBuffer(const uint8_t *b)
|
||||
{
|
||||
char name[PROFILE_SERIALIZED_NAME_SIZE];
|
||||
memcpy(name, b, PROFILE_SERIALIZED_NAME_SIZE);
|
||||
ReflowStep steps[5] = {};
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
steps[i] = ReflowStep(
|
||||
(ReflowProcessState)(i + PREHEAT),
|
||||
b[PROFILE_SERIALIZED_NAME_SIZE + i * 3],
|
||||
b[PROFILE_SERIALIZED_NAME_SIZE + 1 + i * 3],
|
||||
(ReflowStepEaseFunction)b[PROFILE_SERIALIZED_NAME_SIZE + 2 + i * 3]);
|
||||
}
|
||||
return ReflowProfile(steps, name);
|
||||
}
|
||||
|
||||
static ReflowProfile fromEEPROM(uint8_t index)
|
||||
{
|
||||
uint8_t b[40];
|
||||
EEPROM.get(index * PROFILE_SERIALIZED_SIZE, b);
|
||||
return fromBuffer(b);
|
||||
}
|
||||
static ReflowProfile fromEEPROM(uint8_t index);
|
||||
};
|
||||
|
||||
#endif
|
@ -37,8 +37,8 @@ void TemperatureController::checkPluggedInThermistors()
|
||||
// debugC(isPluggedIn == 1 ? "true" : "false");
|
||||
}
|
||||
|
||||
debugC("Active thermistor count: ");
|
||||
debugC(activeThermistorCount);
|
||||
//debugC("Active thermistor count: ");
|
||||
// debugC(activeThermistorCount);
|
||||
}
|
||||
|
||||
float TemperatureController::getThermistorTempFast(uint8_t thermistorIndex)
|
||||
|
@ -1,8 +1,9 @@
|
||||
#ifndef TEMPERATURE_CONTROLLER_H
|
||||
#define TEMPERATURE_CONTROLLER_H
|
||||
|
||||
// #include "Thermistor.h"
|
||||
#include "../globals.h"
|
||||
|
||||
#include "Thermistor.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user