Rough refactor main control loop to C

This commit is contained in:
Ben V. Brown
2019-10-07 18:58:51 +11:00
parent c5f6f6d044
commit 1cf88b2cd6
11 changed files with 233 additions and 496 deletions

View File

@@ -11,7 +11,7 @@
#define SETTINGS_H_ #define SETTINGS_H_
#include <stdint.h> #include <stdint.h>
#include "stm32f1xx_hal.h" #include "stm32f1xx_hal.h"
#define SETTINGSVERSION ( 0x19 ) #define SETTINGSVERSION ( 0x1A )
/*Change this if you change the struct below to prevent people getting \ /*Change this if you change the struct below to prevent people getting \
out of sync*/ out of sync*/
@@ -39,7 +39,7 @@ typedef struct {
uint8_t descriptionScrollSpeed :1; // Description scroll speed uint8_t descriptionScrollSpeed :1; // Description scroll speed
uint16_t voltageDiv; // Voltage divisor factor uint16_t voltageDiv; // Voltage divisor factor
uint16_t BoostTemp; // Boost mode set point for the iron uint16_t BoostTemp; // Boost mode set point for the iron
int16_t CalibrationOffset; // This stores the temperature offset for this tip uint16_t CalibrationOffset; // This stores the temperature offset for this tip
// in the iron. // in the iron.
uint8_t PID_P; // PID P Term uint8_t PID_P; // PID P Term
uint8_t PID_I; // PID I Term uint8_t PID_I; // PID I Term
@@ -47,7 +47,6 @@ typedef struct {
uint8_t version; // Used to track if a reset is needed on firmware upgrade uint8_t version; // Used to track if a reset is needed on firmware upgrade
uint8_t customTipGain; // Tip gain value if custom tuned, or 0 if using a uint8_t customTipGain; // Tip gain value if custom tuned, or 0 if using a
// tipType param // tipType param
uint8_t tipType;
#ifdef MODEL_TS80 #ifdef MODEL_TS80
uint8_t pidPowerLimit; uint8_t pidPowerLimit;
#endif #endif

View File

@@ -5,7 +5,7 @@
#include "OLED.hpp" #include "OLED.hpp"
#include "Setup.h" #include "Setup.h"
extern uint8_t PCBVersion; extern uint8_t PCBVersion;
extern uint32_t currentlyActiveTemperatureTarget; extern uint32_t currentTempTargetDegC;
enum ButtonState { enum ButtonState {
BUTTON_NONE = 0, /* No buttons pressed / < filter time*/ BUTTON_NONE = 0, /* No buttons pressed / < filter time*/
BUTTON_F_SHORT = 1, /* User has pressed the front button*/ BUTTON_F_SHORT = 1, /* User has pressed the front button*/

View File

@@ -30,7 +30,7 @@ const uint8_t tipResistance = 45; //x10 ohms, 8.5 typical for ts100, 4.5 typical
const uint8_t oscillationPeriod = 6 * PID_TIM_HZ; // I term look back value const uint8_t oscillationPeriod = 6 * PID_TIM_HZ; // I term look back value
extern history<uint32_t, oscillationPeriod> milliWattHistory; extern history<uint32_t, oscillationPeriod> milliWattHistory;
int32_t tempToMilliWatts(int32_t rawTemp, uint8_t rawC); int32_t tempToMilliWatts(int32_t rawTemp);
void setTipMilliWatts(int32_t mw); void setTipMilliWatts(int32_t mw);
uint8_t milliWattsToPWM(int32_t milliWatts, uint8_t divisor, uint8_t milliWattsToPWM(int32_t milliWatts, uint8_t divisor,
uint8_t sample = 0); uint8_t sample = 0);

View File

@@ -19,7 +19,7 @@
#include "TipThermoModel.h" #include "TipThermoModel.h"
extern uint8_t PCBVersion; extern uint8_t PCBVersion;
// File local variables // File local variables
extern uint32_t currentlyActiveTemperatureTarget; extern uint32_t currentTempTargetDegC;
extern uint32_t lastMovementTime; extern uint32_t lastMovementTime;
extern int16_t idealQCVoltage; extern int16_t idealQCVoltage;
uint32_t lastButtonTime = 0; uint32_t lastButtonTime = 0;
@@ -57,9 +57,9 @@ void gui_drawTipTemp(bool symbol) {
uint16_t Temp = getTipRawTemp(0); uint16_t Temp = getTipRawTemp(0);
if (systemSettings.temperatureInF) if (systemSettings.temperatureInF)
Temp = tipMeasurementToF(Temp); Temp = TipThermoModel::convertTipRawADCToDegF(Temp);
else else
Temp = tipMeasurementToC(Temp); Temp = TipThermoModel::convertTipRawADCToDegC(Temp);
OLED::printNumber(Temp, 3); // Draw the tip temp out finally OLED::printNumber(Temp, 3); // Draw the tip temp out finally
if (symbol) { if (symbol) {
@@ -201,7 +201,7 @@ static bool checkVoltageForExit() {
} }
OLED::refresh(); OLED::refresh();
currentlyActiveTemperatureTarget = 0; currentTempTargetDegC = 0;
waitForButtonPress(); waitForButtonPress();
return true; return true;
} }
@@ -216,17 +216,17 @@ static void gui_drawBatteryIcon() {
// we need to calculate which of the 10 levels they are on // we need to calculate which of the 10 levels they are on
uint8_t cellCount = systemSettings.cutoutSetting + 2; uint8_t cellCount = systemSettings.cutoutSetting + 2;
uint32_t cellV = getInputVoltageX10(systemSettings.voltageDiv, 0) uint32_t cellV = getInputVoltageX10(systemSettings.voltageDiv, 0)
/ cellCount; / cellCount;
// Should give us approx cell voltage X10 // Should give us approx cell voltage X10
// Range is 42 -> 33 = 9 steps therefore we will use battery 1-10 // Range is 42 -> 33 = 9 steps therefore we will use battery 1-10
if (cellV < 33) if (cellV < 33)
cellV = 33; cellV = 33;
cellV -= 33;// Should leave us a number of 0-9 cellV -= 33; // Should leave us a number of 0-9
if (cellV > 9) if (cellV > 9)
cellV = 9; cellV = 9;
OLED::drawBattery(cellV + 1); OLED::drawBattery(cellV + 1);
} else } else
OLED::drawSymbol(15); // Draw the DC Logo OLED::drawSymbol(15); // Draw the DC Logo
#else #else
// On TS80 we replace this symbol with the voltage we are operating on // On TS80 we replace this symbol with the voltage we are operating on
// If <9V then show single digit, if not show duals // If <9V then show single digit, if not show duals
@@ -250,7 +250,7 @@ static void gui_drawBatteryIcon() {
} }
static void gui_solderingTempAdjust() { static void gui_solderingTempAdjust() {
uint32_t lastChange = xTaskGetTickCount(); uint32_t lastChange = xTaskGetTickCount();
currentlyActiveTemperatureTarget = 0; currentTempTargetDegC = 0;
uint32_t autoRepeatTimer = 0; uint32_t autoRepeatTimer = 0;
uint8_t autoRepeatAcceleration = 0; uint8_t autoRepeatAcceleration = 0;
for (;;) { for (;;) {
@@ -317,7 +317,7 @@ static void gui_solderingTempAdjust() {
#ifdef MODEL_TS80 #ifdef MODEL_TS80
if (!OLED::getRotation()) if (!OLED::getRotation())
#else #else
if (OLED::getRotation()) if (OLED::getRotation())
#endif #endif
OLED::print(SymbolMinus); OLED::print(SymbolMinus);
else else
@@ -333,7 +333,7 @@ static void gui_solderingTempAdjust() {
#ifdef MODEL_TS80 #ifdef MODEL_TS80
if (!OLED::getRotation()) if (!OLED::getRotation())
#else #else
if (OLED::getRotation()) if (OLED::getRotation())
#endif #endif
OLED::print(SymbolPlus); OLED::print(SymbolPlus);
else else
@@ -354,24 +354,23 @@ static int gui_SolderingSleepingMode() {
|| (xTaskGetTickCount() - lastButtonTime < 100)) || (xTaskGetTickCount() - lastButtonTime < 100))
return 0; // user moved or pressed a button, go back to soldering return 0; // user moved or pressed a button, go back to soldering
#ifdef MODEL_TS100 #ifdef MODEL_TS100
if (checkVoltageForExit()) if (checkVoltageForExit())
return 1; // return non-zero on error return 1; // return non-zero on error
#endif #endif
if (systemSettings.temperatureInF) { if (systemSettings.temperatureInF) {
currentlyActiveTemperatureTarget = ftoTipMeasurement( currentTempTargetDegC = TipThermoModel::convertFtoC(
min(systemSettings.SleepTemp, min(systemSettings.SleepTemp,
systemSettings.SolderingTemp)); systemSettings.SolderingTemp));
} else { } else {
currentlyActiveTemperatureTarget = ctoTipMeasurement( currentTempTargetDegC = (min(systemSettings.SleepTemp,
min(systemSettings.SleepTemp, systemSettings.SolderingTemp));
systemSettings.SolderingTemp));
} }
// draw the lcd // draw the lcd
uint16_t tipTemp; uint16_t tipTemp;
if (systemSettings.temperatureInF) if (systemSettings.temperatureInF)
tipTemp = tipMeasurementToF(getTipRawTemp(0)); tipTemp = TipThermoModel::convertTipRawADCToDegF(getTipRawTemp(0));
else else
tipTemp = tipMeasurementToC(getTipRawTemp(0)); tipTemp = TipThermoModel::convertTipRawADCToDegC(getTipRawTemp(0));
OLED::clearScreen(); OLED::clearScreen();
OLED::setCursor(0, 0); OLED::setCursor(0, 0);
@@ -403,7 +402,7 @@ static int gui_SolderingSleepingMode() {
if (((uint32_t) (xTaskGetTickCount() - lastMovementTime)) if (((uint32_t) (xTaskGetTickCount() - lastMovementTime))
> (uint32_t) (systemSettings.ShutdownTime * 60 * 100)) { > (uint32_t) (systemSettings.ShutdownTime * 60 * 100)) {
// shutdown // shutdown
currentlyActiveTemperatureTarget = 0; currentTempTargetDegC = 0;
return 1; // we want to exit soldering mode return 1; // we want to exit soldering mode
} }
OLED::refresh(); OLED::refresh();
@@ -561,9 +560,9 @@ static void gui_solderingMode(uint8_t jumpToSleep) {
if (badTipCounter > 128) { if (badTipCounter > 128) {
OLED::print(BadTipString); OLED::print(BadTipString);
OLED::refresh(); OLED::refresh();
currentlyActiveTemperatureTarget = 0; currentTempTargetDegC = 0;
waitForButtonPress(); waitForButtonPress();
currentlyActiveTemperatureTarget = 0; currentTempTargetDegC = 0;
return; return;
} }
OLED::refresh(); OLED::refresh();
@@ -571,19 +570,17 @@ static void gui_solderingMode(uint8_t jumpToSleep) {
// Update the setpoints for the temperature // Update the setpoints for the temperature
if (boostModeOn) { if (boostModeOn) {
if (systemSettings.temperatureInF) if (systemSettings.temperatureInF)
currentlyActiveTemperatureTarget = ftoTipMeasurement( currentTempTargetDegC = TipThermoModel::convertFtoC(
systemSettings.BoostTemp); systemSettings.BoostTemp);
else else
currentlyActiveTemperatureTarget = ctoTipMeasurement( currentTempTargetDegC = (systemSettings.BoostTemp);
systemSettings.BoostTemp);
} else { } else {
if (systemSettings.temperatureInF) if (systemSettings.temperatureInF)
currentlyActiveTemperatureTarget = ftoTipMeasurement( currentTempTargetDegC = TipThermoModel::convertFtoC(
systemSettings.SolderingTemp); systemSettings.SolderingTemp);
else else
currentlyActiveTemperatureTarget = ctoTipMeasurement( currentTempTargetDegC = (systemSettings.SolderingTemp);
systemSettings.SolderingTemp);
} }
#ifdef MODEL_TS100 #ifdef MODEL_TS100
@@ -648,11 +645,13 @@ void showDebugMenu(void) {
break; break;
case 6: case 6:
//Raw Tip //Raw Tip
OLED::printNumber(TipThermoModel::convertTipRawADCToDegC(getTipRawTemp(0)), 6); OLED::printNumber(TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0)), 6);
break; break;
case 7: case 7:
//Temp in C //Temp in C
OLED::printNumber(tipMeasurementToC(getTipRawTemp(0)), 5); OLED::printNumber(
TipThermoModel::convertTipRawADCToDegC(getTipRawTemp(0)),
5);
break; break;
case 8: case 8:
//Handle Temp //Handle Temp
@@ -756,15 +755,14 @@ void startGUITask(void const *argument __unused) {
enterSettingsMenu(); // enter the settings menu enterSettingsMenu(); // enter the settings menu
saveSettings(); saveSettings();
buttonLockout = true; buttonLockout = true;
setCalibrationOffset(systemSettings.CalibrationOffset); // ensure cal offset is applied
break; break;
default: default:
break; break;
} }
currentlyActiveTemperatureTarget = 0; // ensure tip is off currentTempTargetDegC = 0; // ensure tip is off
getInputVoltageX10(systemSettings.voltageDiv, 0); getInputVoltageX10(systemSettings.voltageDiv, 0);
uint16_t tipTemp = tipMeasurementToC(getTipRawTemp(0)); uint16_t tipTemp = TipThermoModel::convertTipRawADCToDegC(getTipRawTemp(0));
// Preemptively turn the display on. Turn it off if and only if // Preemptively turn the display on. Turn it off if and only if
// the tip temperature is below 50 degrees C *and* motion sleep // the tip temperature is below 50 degrees C *and* motion sleep
@@ -772,9 +770,11 @@ void startGUITask(void const *argument __unused) {
// button presses) in a while. // button presses) in a while.
OLED::setDisplayState(OLED::DisplayState::ON); OLED::setDisplayState(OLED::DisplayState::ON);
if ((tipTemp < 50) && systemSettings.sensitivity && if ((tipTemp < 50) && systemSettings.sensitivity
(((xTaskGetTickCount() - lastMovementTime) > MOVEMENT_INACTIVITY_TIME) && && (((xTaskGetTickCount() - lastMovementTime)
((xTaskGetTickCount() - lastButtonTime) > BUTTON_INACTIVITY_TIME))) { > MOVEMENT_INACTIVITY_TIME)
&& ((xTaskGetTickCount() - lastButtonTime)
> BUTTON_INACTIVITY_TIME))) {
OLED::setDisplayState(OLED::DisplayState::OFF); OLED::setDisplayState(OLED::DisplayState::OFF);
} }
@@ -801,7 +801,7 @@ void startGUITask(void const *argument __unused) {
#ifdef MODEL_TS80 #ifdef MODEL_TS80
if (!OLED::getRotation()) { if (!OLED::getRotation()) {
#else #else
if (OLED::getRotation()) { if (OLED::getRotation()) {
#endif #endif
OLED::drawArea(12, 0, 84, 16, idleScreenBG); OLED::drawArea(12, 0, 84, 16, idleScreenBG);
OLED::setCursor(0, 0); OLED::setCursor(0, 0);
@@ -822,7 +822,7 @@ void startGUITask(void const *argument __unused) {
#ifdef MODEL_TS80 #ifdef MODEL_TS80
if (!OLED::getRotation()) { if (!OLED::getRotation()) {
#else #else
if (OLED::getRotation()) { if (OLED::getRotation()) {
#endif #endif
// in right handed mode we want to draw over the first part // in right handed mode we want to draw over the first part
OLED::fillArea(55, 0, 41, 16, 0); // clear the area for the temp OLED::fillArea(55, 0, 41, 16, 0); // clear the area for the temp

View File

@@ -97,7 +97,7 @@ void resetSettings() {
systemSettings.ShutdownTime = systemSettings.ShutdownTime =
10; // How many minutes until the unit turns itself off 10; // How many minutes until the unit turns itself off
systemSettings.boostModeEnabled = systemSettings.boostModeEnabled =
1; // Default to having boost mode on as most people prefer itF 1; // Default to having boost mode on as most people prefer it
systemSettings.BoostTemp = 420; // default to 400C systemSettings.BoostTemp = 420; // default to 400C
systemSettings.autoStartMode = 0; // Auto start off for safety systemSettings.autoStartMode = 0; // Auto start off for safety
systemSettings.coolingTempBlink = systemSettings.coolingTempBlink =
@@ -107,15 +107,15 @@ void resetSettings() {
systemSettings.PID_P = 42; // PID tuning constants systemSettings.PID_P = 42; // PID tuning constants
systemSettings.PID_I = 50; systemSettings.PID_I = 50;
systemSettings.PID_D = 15; systemSettings.PID_D = 15;
systemSettings.CalibrationOffset = 1400; // the adc offset
systemSettings.customTipGain =
0; // The tip type is either default or a custom gain
#ifdef MODEL_TS100 #ifdef MODEL_TS100
systemSettings.tipType = TS_B2; // Default to the B2 Tip
systemSettings.CalibrationOffset = 700; // the adc offset in uV
#endif #endif
#ifdef MODEL_TS80 #ifdef MODEL_TS80
systemSettings.pidPowerLimit=24; // Sets the max pwm power limit systemSettings.pidPowerLimit=24; // Sets the max pwm power limit
systemSettings.tipType = TS_B02; // Default to the B2 Tip systemSettings.CalibrationOffset = 700; // the adc offset in uV
#endif #endif
saveSettings(); // Save defaults saveSettings(); // Save defaults
} }

View File

@@ -6,6 +6,7 @@
*/ */
#include "TipThermoModel.h" #include "TipThermoModel.h"
#include "Settings.h"
/* /*
* The hardware is laid out as a non-inverting op-amp * The hardware is laid out as a non-inverting op-amp
@@ -48,6 +49,10 @@ uint32_t TipThermoModel::convertTipRawADCTouV(uint16_t rawADC) {
//Now to divide this down by the gain //Now to divide this down by the gain
valueuV = (valueuV) / op_amp_gain_stage; valueuV = (valueuV) / op_amp_gain_stage;
//Remove uV tipOffset //Remove uV tipOffset
if (valueuV > systemSettings.CalibrationOffset)
valueuV -= systemSettings.CalibrationOffset;
else
valueuV = 0;
//TODO //TODO
return valueuV; return valueuV;
} }
@@ -55,6 +60,9 @@ uint32_t TipThermoModel::convertTipRawADCTouV(uint16_t rawADC) {
uint32_t TipThermoModel::convertTipRawADCToDegC(uint16_t rawADC) { uint32_t TipThermoModel::convertTipRawADCToDegC(uint16_t rawADC) {
return convertuVToDegC(convertTipRawADCTouV(rawADC)); return convertuVToDegC(convertTipRawADCTouV(rawADC));
} }
uint32_t TipThermoModel::convertTipRawADCToDegF(uint16_t rawADC) {
return convertuVToDegF(convertTipRawADCTouV(rawADC));
}
//Table that is designed to be walked to find the best sample for the lookup //Table that is designed to be walked to find the best sample for the lookup
@@ -66,110 +74,112 @@ struct HakkoThermocoupleLookup {
values() { values() {
values[0][0] = 0; values[0][0] = 0;
values[0][1] = 0; values[0][1] = 0;
values[1][0] = 175; values[1][0] = 0;
values[1][1] = 100; values[1][1] = 0;
values[2][0] = 381; values[2][0] = 175;
values[2][1] = 200; values[2][1] = 100;
values[3][0] = 587; values[3][0] = 381;
values[3][1] = 300; values[3][1] = 200;
values[4][0] = 804; values[4][0] = 587;
values[4][1] = 400; values[4][1] = 300;
values[5][0] = 1005; values[5][0] = 804;
values[5][1] = 500; values[5][1] = 400;
values[6][0] = 1007; values[6][0] = 1005;
values[6][1] = 600; values[6][1] = 500;
values[7][0] = 1107; values[7][0] = 1007;
values[7][1] = 700; values[7][1] = 600;
values[8][0] = 1310; values[8][0] = 1107;
values[8][1] = 800; values[8][1] = 700;
values[9][0] = 1522; values[9][0] = 1310;
values[9][1] = 900; values[9][1] = 800;
values[10][0] = 1731; values[10][0] = 1522;
values[10][1] = 1000; values[10][1] = 900;
values[11][0] = 1939; values[11][0] = 1731;
values[11][1] = 1100; values[11][1] = 1000;
values[12][0] = 2079; values[12][0] = 1939;
values[12][1] = 1200; values[12][1] = 1100;
values[13][0] = 2265; values[13][0] = 2079;
values[13][1] = 1300; values[13][1] = 1200;
values[14][0] = 2470; values[14][0] = 2265;
values[14][1] = 1400; values[14][1] = 1300;
values[15][0] = 2676; values[15][0] = 2470;
values[15][1] = 1500; values[15][1] = 1400;
values[16][0] = 2899; values[16][0] = 2676;
values[16][1] = 1600; values[16][1] = 1500;
values[17][0] = 3081; values[17][0] = 2899;
values[17][1] = 1700; values[17][1] = 1600;
values[18][0] = 3186; values[18][0] = 3081;
values[18][1] = 1800; values[18][1] = 1700;
values[19][0] = 3422; values[19][0] = 3186;
values[19][1] = 1900; values[19][1] = 1800;
values[20][0] = 3622; values[20][0] = 3422;
values[20][1] = 2000; values[20][1] = 1900;
values[21][0] = 3830; values[21][0] = 3622;
values[21][1] = 2100; values[21][1] = 2000;
values[22][0] = 4044; values[22][0] = 3830;
values[22][1] = 2200; values[22][1] = 2100;
values[23][0] = 4400; values[23][0] = 4044;
values[23][1] = 2300; values[23][1] = 2200;
values[24][0] = 4691; values[24][0] = 4400;
values[24][1] = 2400; values[24][1] = 2300;
values[25][0] = 4989; values[25][0] = 4691;
values[25][1] = 2500; values[25][1] = 2400;
values[26][0] = 5289; values[26][0] = 4989;
values[26][1] = 2600; values[26][1] = 2500;
values[27][0] = 5583; values[27][0] = 5289;
values[27][1] = 2700; values[27][1] = 2600;
values[28][0] = 5879; values[28][0] = 5583;
values[28][1] = 2800; values[28][1] = 2700;
values[29][0] = 6075; values[29][0] = 5879;
values[29][1] = 2900; values[29][1] = 2800;
values[30][0] = 6332; values[30][0] = 6075;
values[30][1] = 3000; values[30][1] = 2900;
values[31][0] = 6521; values[31][0] = 6332;
values[31][1] = 3100; values[31][1] = 3000;
values[32][0] = 6724; values[32][0] = 6521;
values[32][1] = 3200; values[32][1] = 3100;
values[33][0] = 6929; values[33][0] = 6724;
values[33][1] = 3300; values[33][1] = 3200;
values[34][0] = 7132; values[34][0] = 6929;
values[34][1] = 3400; values[34][1] = 3300;
values[35][0] = 7356; values[35][0] = 7132;
values[35][1] = 3500; values[35][1] = 3400;
values[36][0] = 7561; values[36][0] = 7356;
values[36][1] = 3600; values[36][1] = 3500;
values[37][0] = 7774; values[37][0] = 7561;
values[37][1] = 3700; values[37][1] = 3600;
values[38][0] = 7992; values[38][0] = 7774;
values[38][1] = 3800; values[38][1] = 3700;
values[39][0] = 8200; values[39][0] = 7992;
values[39][1] = 3900; values[39][1] = 3800;
values[40][0] = 8410; values[40][0] = 8200;
values[40][1] = 4000; values[40][1] = 3900;
values[41][0] = 8626; values[41][0] = 8410;
values[41][1] = 4100; values[41][1] = 4000;
values[42][0] = 8849; values[42][0] = 8626;
values[42][1] = 4200; values[42][1] = 4100;
values[43][0] = 9060; values[43][0] = 8849;
values[43][1] = 4300; values[43][1] = 4200;
values[44][0] = 9271; values[44][0] = 9060;
values[44][1] = 4400; values[44][1] = 4300;
values[45][0] = 9531; values[45][0] = 9271;
values[45][1] = 4500; values[45][1] = 4400;
values[46][0] = 9748; values[46][0] = 9531;
values[46][1] = 4600; values[46][1] = 4500;
values[47][0] = 10210; values[47][0] = 9748;
values[47][1] = 4700; values[47][1] = 4600;
values[48][0] = 10219; values[48][0] = 10210;
values[48][1] = 4800; values[48][1] = 4700;
values[49][0] = 10429; values[49][0] = 10219;
values[49][1] = 4900; values[49][1] = 4800;
values[50][0] = 10649; values[50][0] = 10429;
values[50][1] = 5000; values[50][1] = 4900;
values[51][0] = 10649;
values[51][1] = 5000;
} }
uint32_t count = 51; uint32_t count = 52;
uint32_t values[51][2]; uint32_t values[52][2];
}; };
constexpr auto ThermalTable = HakkoThermocoupleLookup(); constexpr auto ThermalTable = HakkoThermocoupleLookup();
@@ -189,7 +199,7 @@ uint32_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) {
//This assumes results in the table are increasing order //This assumes results in the table are increasing order
// TODO -> Should this be made into a binary search? Is it much faster?? // TODO -> Should this be made into a binary search? Is it much faster??
for (uint32_t i = 1; i < ThermalTable.count; i++) { for (uint32_t i = 1; i < ThermalTable.count; i++) {
if (((uint32_t) ThermalTable.values[i][0]) < tipuVDelta) { if (((uint32_t) ThermalTable.values[i][0]) > tipuVDelta) {
//Then extrapolate //Then extrapolate
//Where i= the lower raw sample, i-1 is the higher raw sample //Where i= the lower raw sample, i-1 is the higher raw sample
return LinearInterpolate( // return LinearInterpolate( //
@@ -197,9 +207,41 @@ uint32_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) {
ThermalTable.values[i][1], // y1 ThermalTable.values[i][1], // y1
ThermalTable.values[i - 1][0], // x2 ThermalTable.values[i - 1][0], // x2
ThermalTable.values[i - 1][1], // y2 ThermalTable.values[i - 1][1], // y2
tipuVDelta); // raw sample to be interpolated tipuVDelta) / 10; // raw sample to be interpolated
} }
} }
return 5000; return 500; // fail high -> will turn off heater
} }
uint32_t TipThermoModel::convertuVToDegF(uint32_t tipuVDelta) {
//(Y °C × 9/5) + 32 =Y°F
for (uint32_t i = 1; i < ThermalTable.count; i++) {
if (((uint32_t) ThermalTable.values[i][0]) < tipuVDelta) {
//Then extrapolate
//Where i= the lower raw sample, i-1 is the higher raw sample
return ((LinearInterpolate( //
ThermalTable.values[i][0], // x1
ThermalTable.values[i][1], // y1
ThermalTable.values[i - 1][0], // x2
ThermalTable.values[i - 1][1], // y2
tipuVDelta) // raw sample to be interpolated
* 9) / 50) + 32; // Convert C ->> F for 'mericans
}
}
return 932; // fail high -> will turn off heater
}
uint32_t TipThermoModel::convertCtoF(uint32_t degC) {
//(Y °C × 9/5) + 32 =Y°F
return 32 + ((degC * 9) / 5);
}
uint32_t TipThermoModel::convertFtoC(uint32_t degF) {
//(Y°F 32) × 5/9 = Y°C
if (degF < 32)
return 0;
return ((degF - 32) * 5) / 9;
}

View File

@@ -11,10 +11,17 @@
#include "hardware.h" #include "hardware.h"
class TipThermoModel { class TipThermoModel {
public: public:
//These are the main two functions
static uint32_t convertTipRawADCToDegC(uint16_t rawADC);
static uint32_t convertTipRawADCToDegF(uint16_t rawADC);
//Returns the uV of the tip reading before the op-amp compensating for pullups //Returns the uV of the tip reading before the op-amp compensating for pullups
static uint32_t convertTipRawADCTouV(uint16_t rawADC); static uint32_t convertTipRawADCTouV(uint16_t rawADC);
static uint32_t convertTipRawADCToDegC(uint16_t rawADC); static uint32_t convertCtoF(uint32_t degC);
static uint32_t convertFtoC(uint32_t degF);
private:
static uint32_t convertuVToDegC(uint32_t tipuVDelta); static uint32_t convertuVToDegC(uint32_t tipuVDelta);
static uint32_t convertuVToDegF(uint32_t tipuVDelta);
}; };
#endif /* SRC_TIPTHERMOMODEL_H_ */ #endif /* SRC_TIPTHERMOMODEL_H_ */

View File

@@ -9,7 +9,7 @@
#include "Translation.h" #include "Translation.h"
#include "cmsis_os.h" #include "cmsis_os.h"
#include "main.hpp" #include "main.hpp"
#include "TipThermoModel.h"
#include "string.h" #include "string.h"
extern uint32_t lastButtonTime; extern uint32_t lastButtonTime;
void gui_Menu(const menuitem* menu); void gui_Menu(const menuitem* menu);
@@ -50,19 +50,11 @@ static void settings_setCoolingBlinkEnabled(void);
static void settings_displayCoolingBlinkEnabled(void); static void settings_displayCoolingBlinkEnabled(void);
static void settings_setResetSettings(void); static void settings_setResetSettings(void);
static void settings_displayResetSettings(void); static void settings_displayResetSettings(void);
static void settings_setTipModel(void);
static void settings_displayTipModel(void);
static void settings_setCalibrate(void); static void settings_setCalibrate(void);
static void settings_displayCalibrate(void); static void settings_displayCalibrate(void);
static void settings_setCalibrateVIN(void); static void settings_setCalibrateVIN(void);
static void settings_displayCalibrateVIN(void); static void settings_displayCalibrateVIN(void);
// Calibration Menu
static void calibration_displaySimpleCal(void); // Hot water cal
static void calibration_enterSimpleCal(void);
static void calibration_displayAdvancedCal(void); // two point cal
static void calibration_enterAdvancedCal(void);
// Menu functions // Menu functions
static void settings_displaySolderingMenu(void); static void settings_displaySolderingMenu(void);
static void settings_enterSolderingMenu(void); static void settings_enterSolderingMenu(void);
@@ -197,8 +189,6 @@ const menuitem advancedMenu[] = {
settings_displayAdvancedSolderingScreens } }, /* Advanced soldering screen*/ settings_displayAdvancedSolderingScreens } }, /* Advanced soldering screen*/
{ (const char*) SettingsDescriptions[13], { settings_setResetSettings }, { { (const char*) SettingsDescriptions[13], { settings_setResetSettings }, {
settings_displayResetSettings } }, /*Resets settings*/ settings_displayResetSettings } }, /*Resets settings*/
{ (const char*) SettingsDescriptions[17], { settings_setTipModel }, {
settings_displayTipModel } }, /*Select tip Model */
{ (const char*) SettingsDescriptions[12], { settings_setCalibrate }, { { (const char*) SettingsDescriptions[12], { settings_setCalibrate }, {
settings_displayCalibrate } }, /*Calibrate tip*/ settings_displayCalibrate } }, /*Calibrate tip*/
{ (const char*) SettingsDescriptions[14], { settings_setCalibrateVIN }, { { (const char*) SettingsDescriptions[14], { settings_setCalibrateVIN }, {
@@ -206,13 +196,6 @@ const menuitem advancedMenu[] = {
{ NULL, { NULL }, { NULL } } // end of menu marker. DO NOT REMOVE { NULL, { NULL }, { NULL } } // end of menu marker. DO NOT REMOVE
}; };
const menuitem calibrationMenu[] { { (const char*) SettingsDescriptions[6], {
calibration_enterSimpleCal }, { calibration_displaySimpleCal } },
/* Simple Cal*/
{ (const char*) SettingsDescriptions[6], { calibration_enterAdvancedCal }, {
calibration_displayAdvancedCal } }, /* Advanced Cal */
{ NULL, { NULL }, { NULL } } };
static void printShortDescriptionSingleLine(uint32_t shortDescIndex) { static void printShortDescriptionSingleLine(uint32_t shortDescIndex) {
OLED::setFont(0); OLED::setFont(0);
OLED::setCharCursor(0, 0); OLED::setCharCursor(0, 0);
@@ -305,7 +288,7 @@ static void settings_displayInputVRange(void) {
printShortDescription(0, 6); printShortDescription(0, 6);
if (systemSettings.cutoutSetting) { if (systemSettings.cutoutSetting) {
OLED::printNumber(2 + systemSettings.cutoutSetting,1); OLED::printNumber(2 + systemSettings.cutoutSetting, 1);
OLED::print(SymbolCellCount); OLED::print(SymbolCellCount);
} else { } else {
OLED::print(SymbolDC); OLED::print(SymbolDC);
@@ -574,47 +557,11 @@ static void settings_displayResetSettings(void) {
printShortDescription(13, 7); printShortDescription(13, 7);
} }
static void settings_setTipModel(void) {
systemSettings.tipType++;
if(systemSettings.tipType==Tip_MiniWare)
systemSettings.tipType++;
#ifdef MODEL_TS100
if(systemSettings.tipType==Tip_Hakko)
systemSettings.tipType++;
#endif
systemSettings.tipType %= (Tip_Custom + 1); // Wrap after custom
}
static void settings_displayTipModel(void) {
printShortDescription(17, 4);
// Print in small text the tip model
OLED::setFont(1);
// set the cursor
// Print the mfg
OLED::setCursor(55, 0);
if (systemSettings.tipType == Tip_Custom) {
OLED::print(TipModelStrings[Tip_Custom]);
} else if (systemSettings.tipType < Tip_MiniWare) {
OLED::print(TipModelStrings[Tip_MiniWare]);
}
#ifdef MODEL_TS100
else if (systemSettings.tipType < Tip_Hakko) {
OLED::print(TipModelStrings[Tip_Hakko]);
}
#endif
OLED::setCursor(55, 8);
if (systemSettings.tipType != Tip_Custom)
OLED::print(TipModelStrings[systemSettings.tipType]);
}
static void calibration_displaySimpleCal(void) {
printShortDescription(18, 5);
}
static void setTipOffset() { static void setTipOffset() {
setCalibrationOffset(0); // turn off the current offset systemSettings.CalibrationOffset = 0;
// If the thermocouple at the end of the tip, and the handle are at // If the thermo-couple at the end of the tip, and the handle are at
// equalibrium, then the output should be zero, as there is no temperature // equilibrium, then the output should be zero, as there is no temperature
// differential. // differential.
uint32_t offset = 0; uint32_t offset = 0;
@@ -629,147 +576,20 @@ static void setTipOffset() {
OLED::refresh(); OLED::refresh();
osDelay(100); osDelay(100);
} }
systemSettings.CalibrationOffset = offset / 15; systemSettings.CalibrationOffset = TipThermoModel::convertTipRawADCTouV(
// Need to remove from this the ambient temperature offset offset / 15);
uint32_t ambientoffset = getHandleTemperature(); // Handle temp in C x10
ambientoffset *= 100;
ambientoffset /= tipGainCalValue;
systemSettings.CalibrationOffset -= ambientoffset;
setCalibrationOffset(systemSettings.CalibrationOffset); // store the error
OLED::clearScreen(); OLED::clearScreen();
OLED::setCursor(0, 0); OLED::setCursor(0, 0);
OLED::drawCheckbox(true); OLED::drawCheckbox(true);
OLED::refresh(); OLED::refresh();
osDelay(1000); osDelay(1000);
} }
static void calibration_enterSimpleCal(void) {
// User has entered into the simple cal routine
if (userConfirmation(SettingsCalibrationWarning)) {
// User has confirmed their handle is at ambient
// So take the offset measurement
setTipOffset();
// Next we want the user to put the tip into 100C water so we can calculate
// their tip's gain Gain is the m term from rise/run plot of raw readings vs
// (tip-handle) Thus we want to calculate
// ([TipRawHot-TipRawCold])/(ActualHot-HandleHot)-(ActualCold-HandleCold)
// Thus we first need to store ->
// TiprawCold,HandleCold,ActualCold==HandleCold -> RawTipCold
uint32_t RawTipCold = getTipRawTemp(0) * 10;
OLED::clearScreen();
OLED::setCursor(0, 0);
OLED::setFont(1);
OLED::print("Please Insert Tip\nInto Boiling Water");
OLED::refresh();
osDelay(200);
waitForButtonPress();
// Now take the three hot measurements
// Assume water is boiling at 100C
uint32_t RawTipHot = getTipRawTemp(0) * 10;
uint32_t HandleTempHot = getHandleTemperature() / 10;
uint32_t gain = (RawTipHot - RawTipCold) / (100 - HandleTempHot);
// Show this to the user
OLED::clearScreen();
OLED::setCursor(0, 0);
OLED::print(YourGainMessage);
OLED::printNumber(gain, 6);
OLED::refresh();
osDelay(2000);
waitForButtonPress();
OLED::clearScreen();
OLED::setCursor(0, 0);
OLED::print(SymbolPlus);
OLED::printNumber(RawTipHot, 8);
OLED::setCursor(0, 8);
OLED::print(SymbolMinus);
OLED::printNumber(RawTipCold, 8);
OLED::refresh();
osDelay(2000);
waitForButtonPress();
}
}
static void calibration_displayAdvancedCal(void) {
printShortDescription(19, 5);
}
static void calibration_enterAdvancedCal(void) {
//Advanced cal
if (userConfirmation(SettingsCalibrationWarning)) {
//User has confirmed their handle is at ambient
//So take the offset measurement
setTipOffset();
//The tip now has a known ADC offset
//Head up until it is at 350C
//Then let the user adjust the gain value until it converges
systemSettings.customTipGain = 160; // start safe and high
bool exit = false;
while (exit == false) {
//Set tip to 350C
setTipType(Tip_Custom, systemSettings.customTipGain);
currentlyActiveTemperatureTarget = ctoTipMeasurement(350);
//Check if user has pressed button to change the gain
ButtonState buttons = getButtonState();
switch (buttons) {
case BUTTON_NONE:
break;
case BUTTON_BOTH:
case BUTTON_B_LONG:
case BUTTON_F_LONG:
exit = true;
break;
case BUTTON_F_SHORT:
systemSettings.customTipGain++;
break;
case BUTTON_B_SHORT: {
systemSettings.customTipGain--;
}
break;
default:
break;
}
if (systemSettings.customTipGain > 200)
systemSettings.customTipGain = 200;
else if (systemSettings.customTipGain <= 100)
systemSettings.customTipGain = 100;
OLED::setCursor(0, 0);
OLED::clearScreen();
OLED::setFont(0);
if (OLED::getRotation())
OLED::print(SymbolMinus);
else
OLED::print(SymbolPlus);
OLED::print(SymbolSpace);
OLED::printNumber(systemSettings.customTipGain, 4);
OLED::print(SymbolSpace);
if (OLED::getRotation())
OLED::print(SymbolPlus);
else
OLED::print(SymbolMinus);
OLED::refresh();
GUIDelay();
}
// Wait for the user to confirm the exit message that the calibration is done
userConfirmation(SettingsCalibrationDone);
}
}
//Provide the user the option to tune their own tip if custom is selected //Provide the user the option to tune their own tip if custom is selected
//If not only do single point tuning as per usual //If not only do single point tuning as per usual
static void settings_setCalibrate(void) { static void settings_setCalibrate(void) {
if (systemSettings.tipType == Tip_Custom) {
// Two types of calibration
// 1. Basic, idle temp + hot water (100C)
// 2. Advanced, 100C + 350C, we keep PID tracking to a temperature target
return gui_Menu(calibrationMenu);
}
// Else
// Ask user if handle is at the tip temperature
// Any error between handle and the tip will be a direct offset in the control
// loop
else if (userConfirmation(SettingsCalibrationWarning)) { if (userConfirmation(SettingsCalibrationWarning)) {
// User confirmed // User confirmed
// So we now perform the actual calculation // So we now perform the actual calculation
setTipOffset(); setTipOffset();

View File

@@ -9,17 +9,7 @@
#include "hardware.h" #include "hardware.h"
#include "history.hpp" #include "history.hpp"
volatile uint16_t PWMSafetyTimer = 0; volatile uint16_t PWMSafetyTimer = 0;
volatile int16_t CalibrationTempOffset = 0;
uint16_t tipGainCalValue = 0;
void setTipType(enum TipType tipType, uint8_t manualCalGain) {
if (manualCalGain)
tipGainCalValue = manualCalGain;
else
tipGainCalValue = lookupTipDefaultCalValue(tipType);
}
void setCalibrationOffset(int16_t offSet) {
CalibrationTempOffset = offSet;
}
uint16_t getHandleTemperature() { uint16_t getHandleTemperature() {
// We return the current handle temperature in X10 C // We return the current handle temperature in X10 C
// TMP36 in handle, 0.5V offset and then 10mV per deg C (0.75V @ 25C for // TMP36 in handle, 0.5V offset and then 10mV per deg C (0.75V @ 25C for
@@ -36,34 +26,7 @@ uint16_t getHandleTemperature() {
result /= 993; result /= 993;
return result; return result;
} }
uint16_t tipMeasurementToC(uint16_t raw) {
//((Raw Tip-RawOffset) * calibrationgain) / 1000 = tip delta in CX10
// tip delta in CX10 + handleTemp in CX10 = tip absolute temp in CX10
// Div answer by 10 to get final result
uint32_t tipDelta = ((raw - CalibrationTempOffset) * tipGainCalValue)
/ 1000;
tipDelta += getHandleTemperature();
return tipDelta / 10;
}
uint16_t ctoTipMeasurement(uint16_t temp) {
//[ (temp-handle/10) * 10000 ]/calibrationgain = tip raw delta
// tip raw delta + tip offset = tip ADC reading
int32_t TipRaw = ((temp - (getHandleTemperature() / 10)) * 10000)
/ tipGainCalValue;
TipRaw += CalibrationTempOffset;
return TipRaw;
}
uint16_t tipMeasurementToF(uint16_t raw) {
// Convert result from C to F
return (tipMeasurementToC(raw) * 9) / 5 + 32;
}
uint16_t ftoTipMeasurement(uint16_t temp) {
// Convert the temp back to C from F
return ctoTipMeasurement(((temp - 32) * 5) / 9);
}
uint16_t getTipInstantTemperature() { uint16_t getTipInstantTemperature() {
uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits
@@ -93,44 +56,7 @@ uint16_t getTipInstantTemperature() {
sum += readings[minID]; //Duplicate the min to make up for the missing max value sum += readings[minID]; //Duplicate the min to make up for the missing max value
return sum; // 8x over sample return sum; // 8x over sample
} }
/*
* Loopup table for the tip calibration values for
* the gain of the tip's
* This can be found by line of best fit of TipRaw on X, and TipTemp-handle on
* Y. Then take the m term * 10000
* */
uint16_t lookupTipDefaultCalValue(enum TipType tipID) {
#ifdef MODEL_TS100
switch (tipID) {
case TS_D24:
return 141;
break;
case TS_BC2:
return (133 + 129) / 2;
break;
case TS_C1:
return 133;
break;
case TS_B2:
return 133;
default:
return 132; // make this the average of all
break;
}
#else
switch (tipID) {
case TS_D25:
return 154;
break;
case TS_B02:
return 154;
break;
default:
return 154; // make this the average of all
break;
}
#endif
}
//2 second filter (ADC is PID_TIM_HZ Hz) //2 second filter (ADC is PID_TIM_HZ Hz)
history<uint16_t, PID_TIM_HZ*4> rawTempFilter = { { 0 }, 0, 0 }; history<uint16_t, PID_TIM_HZ*4> rawTempFilter = { { 0 }, 0, 0 };
@@ -333,54 +259,7 @@ void startQC(uint16_t divisor) {
if (QCTries > 10) if (QCTries > 10)
QCMode = 0; QCMode = 0;
} }
// Get tip resistance in milliohms
uint32_t calculateTipR() {
static uint32_t lastRes = 0;
if (lastRes)
return lastRes;
// We inject a small current into the front end of the iron,
// By measuring the Vdrop over the tip we can calculate the resistance
// Turn PA0 into an output and drive high to inject (3.3V-0.6)/(6K8+Rtip)
// current PA0->Diode -> 6K8 -> Tip -> GND So the op-amp will amplify the
// small signal across the tip and convert this into an easily read voltage
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); // Set low first
setTipPWM(0);
vTaskDelay(1);
uint32_t offReading = getTipRawTemp(1);
for (uint8_t i = 0; i < 49; i++) {
vTaskDelay(1); // delay to allow it to stabilize
HAL_IWDG_Refresh(&hiwdg);
offReading += getTipRawTemp(1);
}
// Turn on
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); // Set hgih
vTaskDelay(1); // delay to allow it too stabilize
uint32_t onReading = getTipInstantTemperature();
for (uint8_t i = 0; i < 49; i++) {
vTaskDelay(1); // delay to allow it to stabilize
HAL_IWDG_Refresh(&hiwdg);
onReading += getTipRawTemp(1);
}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); // Turn the output off finally
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
uint32_t difference = onReading - offReading;
// V = IR, therefore I = V/R
// We can divide this reading by a known "gain" to get the resulting
// resistance This was determined emperically This tip is 4.688444162 ohms,
// 4688 milliohms (Measured using 4 terminal measurement) 25x oversampling
// reads this as around 47490 Almost perfectly 10x the milliohms value This
// will drift massively with tip temp However we really only need 10x ohms
lastRes = (difference / 21) + 1; // ceil
return lastRes;
}
static unsigned int sqrt32(unsigned long n) { static unsigned int sqrt32(unsigned long n) {
unsigned int c = 0x8000; unsigned int c = 0x8000;
unsigned int g = 0x8000; unsigned int g = 0x8000;
@@ -398,7 +277,7 @@ int16_t calculateMaxVoltage(uint8_t useHP) {
// This measures the tip resistance, then it calculates the appropriate // This measures the tip resistance, then it calculates the appropriate
// voltage To stay under ~18W. Mosfet is "9A", so no issues there // voltage To stay under ~18W. Mosfet is "9A", so no issues there
// QC3.0 supports up to 18W, which is 2A @9V and 1.5A @12V // QC3.0 supports up to 18W, which is 2A @9V and 1.5A @12V
uint32_t milliOhms = calculateTipR(); uint32_t milliOhms = 4500;
// Check no tip // Check no tip
if (milliOhms > 10000) if (milliOhms > 10000)
return -1; return -1;

View File

@@ -11,10 +11,10 @@
#include "stdlib.h" #include "stdlib.h"
#include "stm32f1xx_hal.h" #include "stm32f1xx_hal.h"
#include "string.h" #include "string.h"
#include "TipThermoModel.h"
uint8_t PCBVersion = 0; uint8_t PCBVersion = 0;
// File local variables // File local variables
uint32_t currentlyActiveTemperatureTarget = 0; uint32_t currentTempTargetDegC = 0; // Current temperature target in C
uint32_t lastMovementTime = 0; uint32_t lastMovementTime = 0;
int16_t idealQCVoltage = 0; int16_t idealQCVoltage = 0;
// FreeRTOS variables // FreeRTOS variables
@@ -71,9 +71,7 @@ int main(void) {
} }
HAL_IWDG_Refresh(&hiwdg); HAL_IWDG_Refresh(&hiwdg);
restoreSettings(); // load the settings from flash restoreSettings(); // load the settings from flash
setCalibrationOffset(systemSettings.CalibrationOffset);
setTipType((enum TipType) systemSettings.tipType,
systemSettings.customTipGain); // apply tip type selection
HAL_IWDG_Refresh(&hiwdg); HAL_IWDG_Refresh(&hiwdg);
/* Create the thread(s) */ /* Create the thread(s) */
@@ -112,7 +110,6 @@ void startPIDTask(void const *argument __unused) {
#ifdef MODEL_TS80 #ifdef MODEL_TS80
idealQCVoltage = calculateMaxVoltage(systemSettings.cutoutSetting); idealQCVoltage = calculateMaxVoltage(systemSettings.cutoutSetting);
#endif #endif
uint8_t rawC = ctoTipMeasurement(101) - ctoTipMeasurement(100); // 1*C change in raw.
#ifdef MODEL_TS80 #ifdef MODEL_TS80
//Set power management code to the tip resistance in ohms * 10 //Set power management code to the tip resistance in ohms * 10
@@ -122,30 +119,30 @@ void startPIDTask(void const *argument __unused) {
#endif #endif
history<int32_t, 16> tempError = { { 0 }, 0, 0 }; history<int32_t, 16> tempError = { { 0 }, 0, 0 };
currentlyActiveTemperatureTarget = 0; // Force start with no output (off). If in sleep / soldering this will currentTempTargetDegC = 0; // Force start with no output (off). If in sleep / soldering this will
// be over-ridden rapidly // be over-ridden rapidly
pidTaskNotification = xTaskGetCurrentTaskHandle(); pidTaskNotification = xTaskGetCurrentTaskHandle();
for (;;) { for (;;) {
if (ulTaskNotifyTake(pdTRUE, 2000)) { if (ulTaskNotifyTake(pdTRUE, 2000)) {
// This is a call to block this thread until the ADC does its samples // This is a call to block this thread until the ADC does its samples
uint16_t rawTemp = getTipRawTemp(1); // get instantaneous reading uint16_t rawTemp = getTipRawTemp(1); // get instantaneous reading
if (currentlyActiveTemperatureTarget) { if (currentTempTargetDegC) {
// Cap the max set point to 450C // Cap the max set point to 450C
if (currentlyActiveTemperatureTarget > ctoTipMeasurement(450)) { if (currentTempTargetDegC > (450)) {
//Maximum allowed output //Maximum allowed output
currentlyActiveTemperatureTarget = ctoTipMeasurement(450); currentTempTargetDegC = (450);
} else if (currentlyActiveTemperatureTarget > 32400) {
//Cap to max adc reading
currentlyActiveTemperatureTarget = 32400;
} }
// Convert the current tip to degree's C
uint32_t currentTipTempInC =
TipThermoModel::convertTipRawADCToDegC(rawTemp);
currentTipTempInC += getHandleTemperature() / 10; //Add handle offset
// As we get close to our target, temp noise causes the system // As we get close to our target, temp noise causes the system
// to be unstable. Use a rolling average to dampen it. // to be unstable. Use a rolling average to dampen it.
// We overshoot by roughly 1/2 of 1 degree Fahrenheit. // We overshoot by roughly 1 degree C.
// This helps stabilize the display. // This helps stabilize the display.
int32_t tError = currentlyActiveTemperatureTarget - rawTemp int32_t tError = currentTempTargetDegC - currentTipTempInC + 1;
+ (rawC / 4);
tError = tError > INT16_MAX ? INT16_MAX : tError; tError = tError > INT16_MAX ? INT16_MAX : tError;
tError = tError < INT16_MIN ? INT16_MIN : tError; tError = tError < INT16_MIN ? INT16_MIN : tError;
tempError.update(tError); tempError.update(tError);
@@ -160,15 +157,8 @@ void startPIDTask(void const *argument __unused) {
// This is necessary because of the temp noise and thermal lag in the system. // This is necessary because of the temp noise and thermal lag in the system.
// Once we have feed-forward temp estimation we should be able to better tune this. // Once we have feed-forward temp estimation we should be able to better tune this.
#ifdef MODEL_TS100 int32_t milliWattsNeeded = tempToMilliWatts(
const uint16_t mass = 2020 / 20; // divide here so division is compile-time. tempError.average());
#endif
#ifdef MODEL_TS80
const uint16_t mass = 2020 / 50;
#endif
int32_t milliWattsNeeded = tempToMilliWatts(tempError.average(),
mass);
// note that milliWattsNeeded is sometimes negative, this counters overshoot // note that milliWattsNeeded is sometimes negative, this counters overshoot
// from I term's inertia. // from I term's inertia.
milliWattsOut += milliWattsNeeded; milliWattsOut += milliWattsNeeded;
@@ -193,7 +183,7 @@ void startPIDTask(void const *argument __unused) {
// This is purely guesswork :'( as everyone implements stuff differently // This is purely guesswork :'( as everyone implements stuff differently
if (xTaskGetTickCount() - lastPowerPulse < 10) { if (xTaskGetTickCount() - lastPowerPulse < 10) {
// for the first 100mS turn on for a bit // for the first 100mS turn on for a bit
setTipMilliWatts(5000); // typically its around 5W to hold the current temp, so this wont raise temp much setTipMilliWatts(2500); // typically its around 5W to hold the current temp, so this wont raise temp much
} else } else
setTipMilliWatts(0); setTipMilliWatts(0);
//Then wait until the next 0.5 seconds //Then wait until the next 0.5 seconds

View File

@@ -14,11 +14,11 @@ const uint16_t totalPWM = 255 + 17; //htim2.Init.Period, the full PWM cycle
history<uint32_t, oscillationPeriod> milliWattHistory = { { 0 }, 0, 0 }; history<uint32_t, oscillationPeriod> milliWattHistory = { { 0 }, 0, 0 };
int32_t tempToMilliWatts(int32_t rawTemp, uint8_t rawC) { int32_t tempToMilliWatts(int32_t rawTemp) {
// mass is in milliJ/*C, rawC is raw per degree C // mass is in milliJ/*C, rawC is raw per degree C
// returns milliWatts needed to raise/lower a mass by rawTemp // returns milliWatts needed to raise/lower a mass by rawTemp
// degrees in one cycle. // degrees in one cycle.
int32_t milliJoules = tipMass*10 * (rawTemp / rawC); int32_t milliJoules = tipMass*10 * rawTemp;
return milliJoules; return milliJoules;
} }