This generates dedicates Translation.cpp files for translation language and derives all language-specific data from them. The Makefile is extended to also take care of generating these source files. This allows reuse of nearly all object files between builds of different languages for the same model and regenerating the translation sources if necessary. This speeds up the release builds and the normal write-compile-cycle considerably. It also eliminates miscompilations when manually building different languages.
235 lines
6.7 KiB
C++
235 lines
6.7 KiB
C++
/*
|
||
* TipThermoModel.cpp
|
||
*
|
||
* Created on: 7 Oct 2019
|
||
* Author: ralim
|
||
*/
|
||
|
||
#include "TipThermoModel.h"
|
||
#include "../../configuration.h"
|
||
#include "BSP.h"
|
||
#include "Settings.h"
|
||
#include "main.hpp"
|
||
#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>
|
||
*/
|
||
|
||
uint32_t TipThermoModel::convertTipRawADCTouV(uint16_t rawADC) {
|
||
// 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) {
|
||
// Remove uV tipOffset
|
||
if (valueuV >= systemSettings.CalibrationOffset)
|
||
valueuV -= systemSettings.CalibrationOffset;
|
||
else
|
||
valueuV = 0;
|
||
}
|
||
|
||
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
|
||
int32_t LinearInterpolate(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x) { return y1 + (((((x - x1) * 1000) / (x2 - x1)) * (y2 - y1))) / 1000; }
|
||
#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_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) {
|
||
if (tipuVDelta) {
|
||
int noItems = sizeof(uVtoDegC) / (2 * sizeof(uint16_t));
|
||
for (int i = 1; i < (noItems - 1); i++) {
|
||
// If current tip temp is less than current lookup, then this current lookup is the higher point to interpolate
|
||
if (tipuVDelta < uVtoDegC[i * 2]) {
|
||
return LinearInterpolate(uVtoDegC[(i - 1) * 2], uVtoDegC[((i - 1) * 2) + 1], uVtoDegC[i * 2], uVtoDegC[(i * 2) + 1], tipuVDelta);
|
||
}
|
||
}
|
||
return LinearInterpolate(uVtoDegC[(noItems - 2) * 2], uVtoDegC[((noItems - 2) * 2) + 1], uVtoDegC[(noItems - 1) * 2], uVtoDegC[((noItems - 1) * 2) + 1], tipuVDelta);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
uint32_t TipThermoModel::getTipInC(bool sampleNow) {
|
||
int32_t currentTipTempInC = TipThermoModel::convertTipRawADCToDegC(getTipRawTemp(sampleNow));
|
||
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;
|
||
}
|