From c5f6f6d04475803d506d26671ec27735c5b62ecf Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Mon, 7 Oct 2019 18:20:09 +1100 Subject: [PATCH] Roughing out concept of patent based temp curve --- workspace/TS100/Core/Src/GUIThread.cpp | 3 +- workspace/TS100/Core/Src/TipThermoModel.cpp | 205 ++++++++++++++++++++ workspace/TS100/Core/Src/TipThermoModel.h | 20 ++ 3 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 workspace/TS100/Core/Src/TipThermoModel.cpp create mode 100644 workspace/TS100/Core/Src/TipThermoModel.h diff --git a/workspace/TS100/Core/Src/GUIThread.cpp b/workspace/TS100/Core/Src/GUIThread.cpp index 8d93716f..2cee6943 100644 --- a/workspace/TS100/Core/Src/GUIThread.cpp +++ b/workspace/TS100/Core/Src/GUIThread.cpp @@ -16,6 +16,7 @@ #include "stdlib.h" #include "stm32f1xx_hal.h" #include "string.h" +#include "TipThermoModel.h" extern uint8_t PCBVersion; // File local variables extern uint32_t currentlyActiveTemperatureTarget; @@ -647,7 +648,7 @@ void showDebugMenu(void) { break; case 6: //Raw Tip - OLED::printNumber(getTipRawTemp(0), 6); + OLED::printNumber(TipThermoModel::convertTipRawADCToDegC(getTipRawTemp(0)), 6); break; case 7: //Temp in C diff --git a/workspace/TS100/Core/Src/TipThermoModel.cpp b/workspace/TS100/Core/Src/TipThermoModel.cpp new file mode 100644 index 00000000..bb18602c --- /dev/null +++ b/workspace/TS100/Core/Src/TipThermoModel.cpp @@ -0,0 +1,205 @@ +/* + * TipThermoModel.cpp + * + * Created on: 7 Oct 2019 + * Author: ralim + */ + +#include "TipThermoModel.h" + +/* + * 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 + */ + +#ifdef MODEL_TS100 +#define OP_AMP_Rf 750*1000 /*750 Kilo-ohms -> From schematic, R1*/ +#define OP_AMP_Rin 2370 /*2.37 Kilo-ohms -> From schematic, R2*/ + +#else +#define OP_AMP_Rf 180*1000 /*180 Kilo-ohms -> From schematic, R6*/ +#define OP_AMP_Rin 2000 /*2.0 Kilo-ohms -> From schematic, R3*/ + +#endif + +#define op_amp_gain_stage (1+(OP_AMP_Rf/OP_AMP_Rin)) +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; //TODO use ADC Vref to calculate this + // 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 = (valueuV) / op_amp_gain_stage; + //Remove uV tipOffset + //TODO + return valueuV; +} + +uint32_t TipThermoModel::convertTipRawADCToDegC(uint16_t rawADC) { + return convertuVToDegC(convertTipRawADCTouV(rawADC)); +} + +//Table that is designed to be walked to find the best sample for the lookup + +struct HakkoThermocoupleLookup { + // 0 is the uV reading + // 1 is the deg C X10 + // This was created from numbers transcribed from the patent by + constexpr HakkoThermocoupleLookup() : + values() { + values[0][0] = 0; + values[0][1] = 0; + values[1][0] = 175; + values[1][1] = 100; + values[2][0] = 381; + values[2][1] = 200; + values[3][0] = 587; + values[3][1] = 300; + values[4][0] = 804; + values[4][1] = 400; + values[5][0] = 1005; + values[5][1] = 500; + values[6][0] = 1007; + values[6][1] = 600; + values[7][0] = 1107; + values[7][1] = 700; + values[8][0] = 1310; + values[8][1] = 800; + values[9][0] = 1522; + values[9][1] = 900; + values[10][0] = 1731; + values[10][1] = 1000; + values[11][0] = 1939; + values[11][1] = 1100; + values[12][0] = 2079; + values[12][1] = 1200; + values[13][0] = 2265; + values[13][1] = 1300; + values[14][0] = 2470; + values[14][1] = 1400; + values[15][0] = 2676; + values[15][1] = 1500; + values[16][0] = 2899; + values[16][1] = 1600; + values[17][0] = 3081; + values[17][1] = 1700; + values[18][0] = 3186; + values[18][1] = 1800; + values[19][0] = 3422; + values[19][1] = 1900; + values[20][0] = 3622; + values[20][1] = 2000; + values[21][0] = 3830; + values[21][1] = 2100; + values[22][0] = 4044; + values[22][1] = 2200; + values[23][0] = 4400; + values[23][1] = 2300; + values[24][0] = 4691; + values[24][1] = 2400; + values[25][0] = 4989; + values[25][1] = 2500; + values[26][0] = 5289; + values[26][1] = 2600; + values[27][0] = 5583; + values[27][1] = 2700; + values[28][0] = 5879; + values[28][1] = 2800; + values[29][0] = 6075; + values[29][1] = 2900; + values[30][0] = 6332; + values[30][1] = 3000; + values[31][0] = 6521; + values[31][1] = 3100; + values[32][0] = 6724; + values[32][1] = 3200; + values[33][0] = 6929; + values[33][1] = 3300; + values[34][0] = 7132; + values[34][1] = 3400; + values[35][0] = 7356; + values[35][1] = 3500; + values[36][0] = 7561; + values[36][1] = 3600; + values[37][0] = 7774; + values[37][1] = 3700; + values[38][0] = 7992; + values[38][1] = 3800; + values[39][0] = 8200; + values[39][1] = 3900; + values[40][0] = 8410; + values[40][1] = 4000; + values[41][0] = 8626; + values[41][1] = 4100; + values[42][0] = 8849; + values[42][1] = 4200; + values[43][0] = 9060; + values[43][1] = 4300; + values[44][0] = 9271; + values[44][1] = 4400; + values[45][0] = 9531; + values[45][1] = 4500; + values[46][0] = 9748; + values[46][1] = 4600; + values[47][0] = 10210; + values[47][1] = 4700; + values[48][0] = 10219; + values[48][1] = 4800; + values[49][0] = 10429; + values[49][1] = 4900; + values[50][0] = 10649; + values[50][1] = 5000; + + } + uint32_t count = 51; + uint32_t values[51][2]; + +}; +constexpr auto ThermalTable = HakkoThermocoupleLookup(); +//Extrapolate between two points +// [x1, y1] = point 1 +// [x2, y2] = point 2 +// x = input value +// output is x's extrapolated 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; +} + +uint32_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) { + //Perform lookup on table of values to find the closest two measurement points, and then linearly interpolate these + + //This assumes results in the table are increasing order + // TODO -> Should this be made into a binary search? Is it much faster?? + 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 + + } + } + return 5000; +} diff --git a/workspace/TS100/Core/Src/TipThermoModel.h b/workspace/TS100/Core/Src/TipThermoModel.h new file mode 100644 index 00000000..8e57d55b --- /dev/null +++ b/workspace/TS100/Core/Src/TipThermoModel.h @@ -0,0 +1,20 @@ +/* + * TipThermoModel.h + * + * Created on: 7 Oct 2019 + * Author: ralim + */ + +#ifndef SRC_TIPTHERMOMODEL_H_ +#define SRC_TIPTHERMOMODEL_H_ +#include "stdint.h" +#include "hardware.h" +class TipThermoModel { +public: + //Returns the uV of the tip reading before the op-amp compensating for pullups + static uint32_t convertTipRawADCTouV(uint16_t rawADC); + static uint32_t convertTipRawADCToDegC(uint16_t rawADC); + static uint32_t convertuVToDegC(uint32_t tipuVDelta); +}; + +#endif /* SRC_TIPTHERMOMODEL_H_ */