mirror of
https://github.com/Ralim/IronOS.git
synced 2025-02-26 07:53:55 +00:00
262 lines
6.9 KiB
C++
262 lines
6.9 KiB
C++
/*
|
||
* TipThermoModel.cpp
|
||
*
|
||
* Created on: 7 Oct 2019
|
||
* Author: ralim
|
||
*/
|
||
|
||
#include "TipThermoModel.h"
|
||
#include "BSP.h"
|
||
#include "Settings.h"
|
||
#include "configuration.h"
|
||
#include "main.hpp"
|
||
#include "Utils.h"
|
||
#include "power.hpp"
|
||
/*
|
||
* The hardware is laid out as a non-inverting op-amp
|
||
* There is a pullup of 39k(TS100) from the +ve input to 3.9V (1M pulup on TS100)
|
||
*
|
||
* The simplest case to model this, is to ignore the pullup resistors influence, and assume that its influence is mostly constant
|
||
* -> Tip resistance *does* change with temp, but this should be much less than the rest of the system.
|
||
*
|
||
* When a thermocouple is equal temperature at both sides (hot and cold junction), then the output should be 0uV
|
||
* Therefore, by measuring the uV when both are equal, the measured reading is the offset value.
|
||
* This is a mix of the pull-up resistor, combined with tip manufacturing differences.
|
||
*
|
||
* All of the thermocouple readings are based on this expired patent
|
||
* - > https://patents.google.com/patent/US6087631A/en
|
||
*
|
||
* This was bought to my attention by <Kuba Sztandera>
|
||
*/
|
||
volatile uint32_t lastuv = 0;
|
||
uint32_t TipThermoModel::convertTipRawADCTouV(uint16_t rawADC, bool skipCalOffset) {
|
||
// This takes the raw ADC samples, converts these to uV
|
||
// Then divides this down by the gain to convert to the uV on the input to the op-amp (A+B terminals)
|
||
// Then remove the calibration value that is stored as a tip offset
|
||
uint32_t vddRailmVX10 = 33000; // The vreg is +-2%, but we have no higher accuracy available
|
||
// 4096 * 8 readings for full scale
|
||
// Convert the input ADC reading back into mV times 10 format.
|
||
uint32_t rawInputmVX10 = (rawADC * vddRailmVX10) / (4096 * 8);
|
||
|
||
uint32_t valueuV = rawInputmVX10 * 100; // shift into uV
|
||
// Now to divide this down by the gain
|
||
valueuV /= OP_AMP_GAIN_STAGE;
|
||
|
||
if (systemSettings.CalibrationOffset && skipCalOffset == false) {
|
||
// Remove uV tipOffset
|
||
if (valueuV > systemSettings.CalibrationOffset)
|
||
valueuV -= systemSettings.CalibrationOffset;
|
||
else
|
||
valueuV = 0;
|
||
}
|
||
lastuv = valueuV;
|
||
return valueuV;
|
||
}
|
||
|
||
uint32_t TipThermoModel::convertTipRawADCToDegC(uint16_t 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
|
||
|
||
// Extrapolate between two points
|
||
// [x1, y1] = point 1
|
||
// [x2, y2] = point 2
|
||
// x = input value
|
||
// output is x's interpolated y value
|
||
#ifdef TEMP_uV_LOOKUP_HAKKO
|
||
const uint16_t uVtoDegC[] = {
|
||
//
|
||
//
|
||
0, 0, //
|
||
266, 10, //
|
||
522, 20, //
|
||
770, 30, //
|
||
1010, 40, //
|
||
1244, 50, //
|
||
1473, 60, //
|
||
1697, 70, //
|
||
1917, 80, //
|
||
2135, 90, //
|
||
2351, 100, //
|
||
2566, 110, //
|
||
2780, 120, //
|
||
2994, 130, //
|
||
3209, 140, //
|
||
3426, 150, //
|
||
3644, 160, //
|
||
3865, 170, //
|
||
4088, 180, //
|
||
4314, 190, //
|
||
4544, 200, //
|
||
4777, 210, //
|
||
5014, 220, //
|
||
5255, 230, //
|
||
5500, 240, //
|
||
5750, 250, //
|
||
6003, 260, //
|
||
6261, 270, //
|
||
6523, 280, //
|
||
6789, 290, //
|
||
7059, 300, //
|
||
7332, 310, //
|
||
7609, 320, //
|
||
7889, 330, //
|
||
8171, 340, //
|
||
8456, 350, //
|
||
8742, 360, //
|
||
9030, 370, //
|
||
9319, 380, //
|
||
9607, 390, //
|
||
9896, 400, //
|
||
10183, 410, //
|
||
10468, 420, //
|
||
10750, 430, //
|
||
11029, 440, //
|
||
11304, 450, //
|
||
11573, 460, //
|
||
11835, 470, //
|
||
12091, 480, //
|
||
12337, 490, //
|
||
12575, 500, //
|
||
|
||
};
|
||
#endif
|
||
#ifdef TEMP_uV_LOOKUP_MHP30
|
||
const uint16_t uVtoDegC[] = {
|
||
//
|
||
//
|
||
0, 0, //
|
||
397, 10, //
|
||
798, 20, ///
|
||
1203, 30, //
|
||
1612, 40, //
|
||
2023, 50, //
|
||
2436, 60, //
|
||
3225, 79, //
|
||
4013, 98, //
|
||
4756, 116, //
|
||
5491, 134, //
|
||
5694, 139, //
|
||
6339, 155, //
|
||
7021, 172, //
|
||
7859, 193, //
|
||
8619, 212, //
|
||
9383, 231, //
|
||
10153, 250, //
|
||
10930, 269, //
|
||
11712, 288, //
|
||
12499, 307, //
|
||
13290, 326, //
|
||
14084, 345, //
|
||
14881, 364, //
|
||
15680, 383, //
|
||
16482, 402, //
|
||
17285, 421, //
|
||
18091, 440, //
|
||
18898, 459, //
|
||
|
||
};
|
||
#endif
|
||
|
||
#ifdef TEMP_uV_LOOKUP_TS80
|
||
|
||
const uint16_t uVtoDegC[] = {
|
||
//
|
||
//
|
||
530, 0, //
|
||
1282, 10, //
|
||
2034, 20, //
|
||
2786, 30, //
|
||
3538, 40, //
|
||
4290, 50, //
|
||
5043, 60, //
|
||
5795, 70, //
|
||
6547, 80, //
|
||
7299, 90, //
|
||
8051, 100, //
|
||
8803, 110, //
|
||
9555, 120, //
|
||
10308, 130, //
|
||
11060, 140, //
|
||
11812, 150, //
|
||
12564, 160, //
|
||
13316, 170, //
|
||
14068, 180, //
|
||
14820, 190, //
|
||
15573, 200, //
|
||
16325, 210, //
|
||
17077, 220, //
|
||
17829, 230, //
|
||
18581, 240, //
|
||
19333, 250, //
|
||
20085, 260, //
|
||
20838, 270, //
|
||
21590, 280, //
|
||
22342, 290, //
|
||
23094, 300, //
|
||
23846, 310, //
|
||
24598, 320, //
|
||
25350, 330, //
|
||
26103, 340, //
|
||
26855, 350, //
|
||
27607, 360, //
|
||
28359, 370, //
|
||
29111, 380, //
|
||
29863, 390, //
|
||
30615, 400, //
|
||
31368, 410, //
|
||
32120, 420, //
|
||
32872, 430, //
|
||
33624, 440, //
|
||
34376, 450, //
|
||
35128, 460, //
|
||
35880, 470, //
|
||
36632, 480, //
|
||
37385, 490, //
|
||
38137, 500, //
|
||
};
|
||
#endif
|
||
uint32_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) {
|
||
return Utils::InterpolateLookupTable(uVtoDegC,tipuVDelta);
|
||
}
|
||
|
||
uint32_t TipThermoModel::convertuVToDegF(uint32_t tipuVDelta) { return convertCtoF(convertuVToDegC(tipuVDelta)); }
|
||
|
||
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;
|
||
}
|
||
volatile uint32_t lastTemp = 0;
|
||
uint32_t TipThermoModel::getTipInC(bool sampleNow) {
|
||
int32_t currentTipTempInC = TipThermoModel::convertTipRawADCToDegC(getTipRawTemp(sampleNow));
|
||
lastTemp = currentTipTempInC;
|
||
currentTipTempInC += getHandleTemperature() / 10; // Add handle offset
|
||
// Power usage indicates that our tip temp is lower than our thermocouple temp.
|
||
// I found a number that doesn't unbalance the existing PID, causing overshoot.
|
||
// This could be tuned in concert with PID parameters...
|
||
currentTipTempInC -= x10WattHistory.average() / 25;
|
||
if (currentTipTempInC < 0)
|
||
return 0;
|
||
return currentTipTempInC;
|
||
}
|
||
|
||
uint32_t TipThermoModel::getTipInF(bool sampleNow) {
|
||
uint32_t currentTipTempInF = getTipInC(sampleNow);
|
||
currentTipTempInF = convertCtoF(currentTipTempInF);
|
||
return currentTipTempInF;
|
||
}
|
||
|
||
uint32_t TipThermoModel::getTipMaxInC() {
|
||
uint32_t maximumTipTemp = TipThermoModel::convertTipRawADCToDegC(0x7FFF - (21 * 5)); // back off approx 5 deg c from ADC max
|
||
maximumTipTemp += getHandleTemperature() / 10; // Add handle offset
|
||
return maximumTipTemp - 1;
|
||
}
|