Configurable Thermistor (#13888)

This commit is contained in:
doggyfan
2019-05-07 00:51:06 +01:00
committed by Scott Lahteine
parent 172abc305b
commit 23a8707ef1
183 changed files with 4575 additions and 151 deletions

View File

@ -243,6 +243,13 @@ typedef struct SettingsDataStruct {
//
PID_t bedPID; // M304 PID / M303 E-1 U
//
// User-defined Thermistors
//
#if HAS_USER_THERMISTORS
user_thermistor_t user_thermistor[USER_THERMISTORS]; // M305 P0 R4700 T100000 B3950
#endif
//
// HAS_LCD_CONTRAST
//
@ -800,6 +807,16 @@ void MarlinSettings::postprocess() {
#endif
}
//
// User-defined Thermistors
//
#if HAS_USER_THERMISTORS
{
_FIELD_TEST(user_thermistor);
EEPROM_WRITE(thermalManager.user_thermistor);
}
#endif
//
// LCD Contrast
//
@ -1579,6 +1596,16 @@ void MarlinSettings::postprocess() {
#endif
}
//
// User-defined Thermistors
//
#if HAS_USER_THERMISTORS
{
_FIELD_TEST(user_thermistor);
EEPROM_READ(thermalManager.user_thermistor);
}
#endif
//
// LCD Contrast
//
@ -2386,6 +2413,14 @@ void MarlinSettings::reset() {
thermalManager.temp_bed.pid.Kd = scalePID_d(DEFAULT_bedKd);
#endif
//
// User-Defined Thermistors
//
#if HAS_USER_THERMISTORS
thermalManager.reset_user_thermistors();
#endif
//
// LCD Contrast
//
@ -2951,6 +2986,12 @@ void MarlinSettings::reset() {
#endif // PIDTEMP || PIDTEMPBED
#if HAS_USER_THERMISTORS
CONFIG_ECHO_HEADING("User thermistors:");
for (uint8_t i = 0; i < USER_THERMISTORS; i++)
thermalManager.log_user_thermistor(i, true);
#endif
#if HAS_LCD_CONTRAST
CONFIG_ECHO_HEADING("LCD Contrast:");
CONFIG_ECHO_START();

View File

@ -1183,6 +1183,136 @@ void Temperature::manage_heater() {
} \
}while(0)
#if HAS_USER_THERMISTORS
user_thermistor_t Temperature::user_thermistor[USER_THERMISTORS]; // Initialized by settings.load()
void Temperature::reset_user_thermistors() {
user_thermistor_t user_thermistor[USER_THERMISTORS] = {
#if ENABLED(HEATER_0_USER_THERMISTOR)
{ true, 0, 0, HOTEND0_PULLUP_RESISTOR_OHMS, HOTEND0_RESISTANCE_25C_OHMS, 0, 0, HOTEND0_BETA, 0 },
#endif
#if ENABLED(HEATER_1_USER_THERMISTOR)
{ true, 0, 0, HOTEND1_PULLUP_RESISTOR_OHMS, HOTEND1_RESISTANCE_25C_OHMS, 0, 0, HOTEND1_BETA, 0 },
#endif
#if ENABLED(HEATER_2_USER_THERMISTOR)
{ true, 0, 0, HOTEND2_PULLUP_RESISTOR_OHMS, HOTEND2_RESISTANCE_25C_OHMS, 0, 0, HOTEND2_BETA, 0 },
#endif
#if ENABLED(HEATER_3_USER_THERMISTOR)
{ true, 0, 0, HOTEND3_PULLUP_RESISTOR_OHMS, HOTEND3_RESISTANCE_25C_OHMS, 0, 0, HOTEND3_BETA, 0 },
#endif
#if ENABLED(HEATER_4_USER_THERMISTOR)
{ true, 0, 0, HOTEND4_PULLUP_RESISTOR_OHMS, HOTEND4_RESISTANCE_25C_OHMS, 0, 0, HOTEND4_BETA, 0 },
#endif
#if ENABLED(HEATER_5_USER_THERMISTOR)
{ true, 0, 0, HOTEND5_PULLUP_RESISTOR_OHMS, HOTEND5_RESISTANCE_25C_OHMS, 0, 0, HOTEND5_BETA, 0 },
#endif
#if ENABLED(BED_USER_THERMISTOR)
{ true, 0, 0, BED_PULLUP_RESISTOR_OHMS, BED_RESISTANCE_25C_OHMS, 0, 0, BED_BETA, 0 },
#endif
#if ENABLED(CHAMBER_USER_THERMISTOR)
{ true, 0, 0, CHAMBER_PULLUP_RESISTOR_OHMS, CHAMBER_RESISTANCE_25C_OHMS, 0, 0, CHAMBER_BETA, 0 }
#endif
};
COPY(thermalManager.user_thermistor, user_thermistor);
}
void Temperature::log_user_thermistor(const uint8_t t_index, const bool eprom/*=false*/) {
if (eprom)
SERIAL_ECHOPGM(" M305 ");
else
SERIAL_ECHO_START();
SERIAL_CHAR('P');
SERIAL_CHAR('0' + t_index);
const user_thermistor_t &t = user_thermistor[t_index];
SERIAL_ECHOPAIR_F(" R", t.series_res, 1);
SERIAL_ECHOPAIR_F(" T", t.res_25, 1);
SERIAL_ECHOPAIR_F(" B", t.beta, 1);
SERIAL_ECHOPAIR_F(" C", t.sh_c_coeff, 9);
SERIAL_ECHOPGM(" ; ");
serialprintPGM(
#if ENABLED(HEATER_0_USER_THERMISTOR)
t_index == CTI_HOTEND_0 ? PSTR("HOTEND 0") :
#endif
#if ENABLED(HEATER_1_USER_THERMISTOR)
t_index == CTI_HOTEND_1 ? PSTR("HOTEND 1") :
#endif
#if ENABLED(HEATER_2_USER_THERMISTOR)
t_index == CTI_HOTEND_2 ? PSTR("HOTEND 2") :
#endif
#if ENABLED(HEATER_3_USER_THERMISTOR)
t_index == CTI_HOTEND_3 ? PSTR("HOTEND 3") :
#endif
#if ENABLED(HEATER_4_USER_THERMISTOR)
t_index == CTI_HOTEND_4 ? PSTR("HOTEND 4") :
#endif
#if ENABLED(HEATER_5_USER_THERMISTOR)
t_index == CTI_HOTEND_5 ? PSTR("HOTEND 5") :
#endif
#if ENABLED(BED_USER_THERMISTOR)
t_index == CTI_BED ? PSTR("BED") :
#endif
#if ENABLED(CHAMBER_USER_THERMISTOR)
t_index == CTI_CHAMBER ? PSTR("CHAMBER") :
#endif
NULL
);
SERIAL_EOL();
}
float Temperature::user_thermistor_to_deg_c(const uint8_t t_index, const int raw) {
//#if (MOTHERBOARD == BOARD_RAMPS_14_EFB)
// static uint32_t clocks_total = 0;
// static uint32_t calls = 0;
// uint32_t tcnt5 = TCNT5;
//#endif
if (!WITHIN(t_index, 0, COUNT(user_thermistor) - 1)) return 25;
if (user_thermistor[t_index].pre_calc) {
// pre-calculate some variables
user_thermistor[t_index].pre_calc = false;
user_thermistor[t_index].res_25_recip = 1.0f / user_thermistor[t_index].res_25;
user_thermistor[t_index].res_25_log = logf(user_thermistor[t_index].res_25);
user_thermistor[t_index].beta_recip = 1.0f / user_thermistor[t_index].beta;
user_thermistor[t_index].sh_alpha = (1.0f / (THERMISTOR_RESISTANCE_NOMINAL_C - THERMISTOR_ABS_ZERO_C)) - (user_thermistor[t_index].beta_recip * user_thermistor[t_index].res_25_log) - (user_thermistor[t_index].sh_c_coeff * user_thermistor[t_index].res_25_log * user_thermistor[t_index].res_25_log * user_thermistor[t_index].res_25_log);
}
// maximum adc value .. take into account the over sampling
const int adc_max = (THERMISTOR_ADC_RESOLUTION * OVERSAMPLENR) - 1,
adc_raw = constrain(raw, 1, adc_max - 1); // constrain to prevent divide-by-zero
const float adc_inverse = (adc_max - adc_raw) - 0.5f,
resistance = user_thermistor[t_index].series_res * (adc_raw + 0.5f) / adc_inverse,
log_resistance = logf(resistance);
float value = user_thermistor[t_index].sh_alpha;
value += log_resistance * user_thermistor[t_index].beta_recip;
if (user_thermistor[t_index].sh_c_coeff != 0)
value += user_thermistor[t_index].sh_c_coeff * log_resistance * log_resistance * log_resistance;
value = 1.0f / value;
// Convert to degrees C
float deg_c = value + THERMISTOR_ABS_ZERO_C;
// Test only
//deg_c = constrain(deg_c, 6, 100);
//#if (MOTHERBOARD == BOARD_RAMPS_14_EFB)
// int32_t clocks = TCNT5 - tcnt5;
// if (clocks >= 0) {
// clocks_total += clocks;
// calls++;
// }
//#endif
return deg_c;
}
#endif
// Derived from RepRap FiveD extruder::getTemperature()
// For hot end temperature measurement.
float Temperature::analog_to_celsius_hotend(const int raw, const uint8_t e) {
@ -1201,7 +1331,9 @@ float Temperature::analog_to_celsius_hotend(const int raw, const uint8_t e) {
switch (e) {
case 0:
#if ENABLED(HEATER_0_USES_MAX6675)
#if ENABLED(HEATER_0_USER_THERMISTOR)
return user_thermistor_to_deg_c(CTI_HOTEND_0, raw);
#elif ENABLED(HEATER_0_USES_MAX6675)
return raw * 0.25;
#elif ENABLED(HEATER_0_USES_AD595)
return TEMP_AD595(raw);
@ -1211,7 +1343,9 @@ float Temperature::analog_to_celsius_hotend(const int raw, const uint8_t e) {
break;
#endif
case 1:
#if ENABLED(HEATER_1_USES_MAX6675)
#if ENABLED(HEATER_1_USER_THERMISTOR)
return user_thermistor_to_deg_c(CTI_HOTEND_1, raw);
#elif ENABLED(HEATER_1_USES_MAX6675)
return raw * 0.25;
#elif ENABLED(HEATER_1_USES_AD595)
return TEMP_AD595(raw);
@ -1221,7 +1355,9 @@ float Temperature::analog_to_celsius_hotend(const int raw, const uint8_t e) {
break;
#endif
case 2:
#if ENABLED(HEATER_2_USES_AD595)
#if ENABLED(HEATER_2_USER_THERMISTOR)
return user_thermistor_to_deg_c(CTI_HOTEND_2, raw);
#elif ENABLED(HEATER_2_USES_AD595)
return TEMP_AD595(raw);
#elif ENABLED(HEATER_2_USES_AD8495)
return TEMP_AD8495(raw);
@ -1229,7 +1365,9 @@ float Temperature::analog_to_celsius_hotend(const int raw, const uint8_t e) {
break;
#endif
case 3:
#if ENABLED(HEATER_3_USES_AD595)
#if ENABLED(HEATER_3_USER_THERMISTOR)
return user_thermistor_to_deg_c(CTI_HOTEND_3, raw);
#elif ENABLED(HEATER_3_USES_AD595)
return TEMP_AD595(raw);
#elif ENABLED(HEATER_3_USES_AD8495)
return TEMP_AD8495(raw);
@ -1237,7 +1375,9 @@ float Temperature::analog_to_celsius_hotend(const int raw, const uint8_t e) {
break;
#endif
case 4:
#if ENABLED(HEATER_4_USES_AD595)
#if ENABLED(HEATER_4_USER_THERMISTOR)
return user_thermistor_to_deg_c(CTI_HOTEND_4, raw);
#elif ENABLED(HEATER_4_USES_AD595)
return TEMP_AD595(raw);
#elif ENABLED(HEATER_4_USES_AD8495)
return TEMP_AD8495(raw);
@ -1245,7 +1385,9 @@ float Temperature::analog_to_celsius_hotend(const int raw, const uint8_t e) {
break;
#endif
case 5:
#if ENABLED(HEATER_5_USES_AD595)
#if ENABLED(HEATER_5_USER_THERMISTOR)
return user_thermistor_to_deg_c(CTI_HOTEND_5, raw);
#elif ENABLED(HEATER_5_USES_AD595)
return TEMP_AD595(raw);
#elif ENABLED(HEATER_5_USES_AD8495)
return TEMP_AD8495(raw);
@ -1268,7 +1410,9 @@ float Temperature::analog_to_celsius_hotend(const int raw, const uint8_t e) {
// Derived from RepRap FiveD extruder::getTemperature()
// For bed temperature measurement.
float Temperature::analog_to_celsius_bed(const int raw) {
#if ENABLED(HEATER_BED_USES_THERMISTOR)
#if ENABLED(BED_USER_THERMISTOR)
return user_thermistor_to_deg_c(CTI_BED, raw);
#elif ENABLED(HEATER_BED_USES_THERMISTOR)
SCAN_THERMISTOR_TABLE(BEDTEMPTABLE, BEDTEMPTABLE_LEN);
#elif ENABLED(HEATER_BED_USES_AD595)
return TEMP_AD595(raw);
@ -1284,7 +1428,9 @@ float Temperature::analog_to_celsius_hotend(const int raw, const uint8_t e) {
// Derived from RepRap FiveD extruder::getTemperature()
// For chamber temperature measurement.
float Temperature::analog_to_celsius_chamber(const int raw) {
#if ENABLED(HEATER_CHAMBER_USES_THERMISTOR)
#if ENABLED(CHAMBER_USER_THERMISTOR)
return user_thermistor_to_deg_c(CTI_CHAMBER, raw);
#elif ENABLED(HEATER_CHAMBER_USES_THERMISTOR)
SCAN_THERMISTOR_TABLE(CHAMBERTEMPTABLE, CHAMBERTEMPTABLE_LEN);
#elif ENABLED(HEATER_CHAMBER_USES_AD595)
return TEMP_AD595(raw);

View File

@ -26,6 +26,7 @@
*/
#include "thermistor/thermistors.h"
#include "../inc/MarlinConfig.h"
#if ENABLED(AUTO_POWER_CONTROL)
@ -207,6 +208,53 @@ typedef struct { int16_t raw_min, raw_max; } raw_range_t;
typedef struct { int16_t mintemp, maxtemp; } celsius_range_t;
typedef struct { int16_t raw_min, raw_max, mintemp, maxtemp; } temp_range_t;
#define THERMISTOR_ADC_RESOLUTION 1024 // 10-bit ADC .. shame to waste 12-bits of resolution on 32-bit
#define THERMISTOR_ABS_ZERO_C -273.15f // bbbbrrrrr cold !
#define THERMISTOR_RESISTANCE_NOMINAL_C 25.0f // mmmmm comfortable
#if HAS_USER_THERMISTORS
enum CustomThermistorIndex : uint8_t {
#if ENABLED(HEATER_0_USER_THERMISTOR)
CTI_HOTEND_0,
#endif
#if ENABLED(HEATER_1_USER_THERMISTOR)
CTI_HOTEND_1,
#endif
#if ENABLED(HEATER_2_USER_THERMISTOR)
CTI_HOTEND_2,
#endif
#if ENABLED(HEATER_3_USER_THERMISTOR)
CTI_HOTEND_3,
#endif
#if ENABLED(HEATER_4_USER_THERMISTOR)
CTI_HOTEND_4,
#endif
#if ENABLED(HEATER_5_USER_THERMISTOR)
CTI_HOTEND_5,
#endif
#if ENABLED(BED_USER_THERMISTOR)
CTI_BED,
#endif
#if ENABLED(CHAMBER_USER_THERMISTOR)
CTI_CHAMBER,
#endif
USER_THERMISTORS
};
// User-defined thermistor
typedef struct {
bool pre_calc; // true if pre-calculations update needed
float sh_c_coeff, // Steinhart-Hart C coefficient .. defaults to '0.0'
sh_alpha,
series_res,
res_25, res_25_recip,
res_25_log,
beta, beta_recip;
} user_thermistor_t;
#endif
class Temperature {
public:
@ -363,6 +411,38 @@ class Temperature {
/**
* Static (class) methods
*/
#if HAS_USER_THERMISTORS
static user_thermistor_t user_thermistor[USER_THERMISTORS];
static void log_user_thermistor(const uint8_t t_index, const bool eprom=false);
static void reset_user_thermistors();
static float user_thermistor_to_deg_c(const uint8_t t_index, const int raw);
static bool set_pull_up_res(int8_t t_index, float value) {
//if (!WITHIN(t_index, 0, USER_THERMISTORS - 1)) return false;
if (!WITHIN(value, 1, 1000000)) return false;
user_thermistor[t_index].series_res = value;
return true;
}
static bool set_res25(int8_t t_index, float value) {
if (!WITHIN(value, 1, 10000000)) return false;
user_thermistor[t_index].res_25 = value;
user_thermistor[t_index].pre_calc = true;
return true;
}
static bool set_beta(int8_t t_index, float value) {
if (!WITHIN(value, 1, 1000000)) return false;
user_thermistor[t_index].beta = value;
user_thermistor[t_index].pre_calc = true;
return true;
}
static bool set_sh_coeff(int8_t t_index, float value) {
if (!WITHIN(value, -0.01f, 0.01f)) return false;
user_thermistor[t_index].sh_c_coeff = value;
user_thermistor[t_index].pre_calc = true;
return true;
}
#endif
static float analog_to_celsius_hotend(const int raw, const uint8_t e);
#if HAS_HEATED_BED

View File

@ -23,27 +23,27 @@
// PT100 with INA826 amp on Ultimaker v2.0 electronics
// The PT100 in the Ultimaker v2.0 electronics has a high sample value for a high temperature.
// This does not match the normal thermistor behaviour so we need to set the following defines
#if THERMISTORHEATER_0 == 20
#if THERMISTOR_HEATER_0 == 20
#define HEATER_0_RAW_HI_TEMP 16383
#define HEATER_0_RAW_LO_TEMP 0
#endif
#if THERMISTORHEATER_1 == 20
#if THERMISTOR_HEATER_1 == 20
#define HEATER_1_RAW_HI_TEMP 16383
#define HEATER_1_RAW_LO_TEMP 0
#endif
#if THERMISTORHEATER_2 == 20
#if THERMISTOR_HEATER_2 == 20
#define HEATER_2_RAW_HI_TEMP 16383
#define HEATER_2_RAW_LO_TEMP 0
#endif
#if THERMISTORHEATER_3 == 20
#if THERMISTOR_HEATER_3 == 20
#define HEATER_3_RAW_HI_TEMP 16383
#define HEATER_3_RAW_LO_TEMP 0
#endif
#if THERMISTORHEATER_4 == 20
#if THERMISTOR_HEATER_4 == 20
#define HEATER_4_RAW_HI_TEMP 16383
#define HEATER_4_RAW_LO_TEMP 0
#endif
#if THERMISTORHEATER_5 == 20
#if THERMISTOR_HEATER_5 == 20
#define HEATER_5_RAW_HI_TEMP 16383
#define HEATER_5_RAW_LO_TEMP 0
#endif

View File

@ -26,7 +26,7 @@
#define OVERSAMPLENR 16
#define OV(N) int16_t((N) * (OVERSAMPLENR))
#define ANY_THERMISTOR_IS(n) (THERMISTORHEATER_0 == n || THERMISTORHEATER_1 == n || THERMISTORHEATER_2 == n || THERMISTORHEATER_3 == n || THERMISTORHEATER_4 == n || THERMISTORHEATER_5 == n || THERMISTORBED == n || THERMISTORCHAMBER == n)
#define ANY_THERMISTOR_IS(n) (THERMISTOR_HEATER_0 == n || THERMISTOR_HEATER_1 == n || THERMISTOR_HEATER_2 == n || THERMISTOR_HEATER_3 == n || THERMISTOR_HEATER_4 == n || THERMISTOR_HEATER_5 == n || THERMISTORBED == n || THERMISTORCHAMBER == n)
// Pt1000 and Pt100 handling
//
@ -141,8 +141,8 @@
#define _TT_NAME(_N) temptable_ ## _N
#define TT_NAME(_N) _TT_NAME(_N)
#if THERMISTORHEATER_0
#define HEATER_0_TEMPTABLE TT_NAME(THERMISTORHEATER_0)
#if THERMISTOR_HEATER_0
#define HEATER_0_TEMPTABLE TT_NAME(THERMISTOR_HEATER_0)
#define HEATER_0_TEMPTABLE_LEN COUNT(HEATER_0_TEMPTABLE)
#elif defined(HEATER_0_USES_THERMISTOR)
#error "No heater 0 thermistor table specified"
@ -151,8 +151,8 @@
#define HEATER_0_TEMPTABLE_LEN 0
#endif
#if THERMISTORHEATER_1
#define HEATER_1_TEMPTABLE TT_NAME(THERMISTORHEATER_1)
#if THERMISTOR_HEATER_1
#define HEATER_1_TEMPTABLE TT_NAME(THERMISTOR_HEATER_1)
#define HEATER_1_TEMPTABLE_LEN COUNT(HEATER_1_TEMPTABLE)
#elif defined(HEATER_1_USES_THERMISTOR)
#error "No heater 1 thermistor table specified"
@ -161,8 +161,8 @@
#define HEATER_1_TEMPTABLE_LEN 0
#endif
#if THERMISTORHEATER_2
#define HEATER_2_TEMPTABLE TT_NAME(THERMISTORHEATER_2)
#if THERMISTOR_HEATER_2
#define HEATER_2_TEMPTABLE TT_NAME(THERMISTOR_HEATER_2)
#define HEATER_2_TEMPTABLE_LEN COUNT(HEATER_2_TEMPTABLE)
#elif defined(HEATER_2_USES_THERMISTOR)
#error "No heater 2 thermistor table specified"
@ -171,8 +171,8 @@
#define HEATER_2_TEMPTABLE_LEN 0
#endif
#if THERMISTORHEATER_3
#define HEATER_3_TEMPTABLE TT_NAME(THERMISTORHEATER_3)
#if THERMISTOR_HEATER_3
#define HEATER_3_TEMPTABLE TT_NAME(THERMISTOR_HEATER_3)
#define HEATER_3_TEMPTABLE_LEN COUNT(HEATER_3_TEMPTABLE)
#elif defined(HEATER_3_USES_THERMISTOR)
#error "No heater 3 thermistor table specified"
@ -181,8 +181,8 @@
#define HEATER_3_TEMPTABLE_LEN 0
#endif
#if THERMISTORHEATER_4
#define HEATER_4_TEMPTABLE TT_NAME(THERMISTORHEATER_4)
#if THERMISTOR_HEATER_4
#define HEATER_4_TEMPTABLE TT_NAME(THERMISTOR_HEATER_4)
#define HEATER_4_TEMPTABLE_LEN COUNT(HEATER_4_TEMPTABLE)
#elif defined(HEATER_4_USES_THERMISTOR)
#error "No heater 4 thermistor table specified"
@ -191,8 +191,8 @@
#define HEATER_4_TEMPTABLE_LEN 0
#endif
#if THERMISTORHEATER_5
#define HEATER_5_TEMPTABLE TT_NAME(THERMISTORHEATER_5)
#if THERMISTOR_HEATER_5
#define HEATER_5_TEMPTABLE TT_NAME(THERMISTOR_HEATER_5)
#define HEATER_5_TEMPTABLE_LEN COUNT(HEATER_5_TEMPTABLE)
#elif defined(HEATER_5_USES_THERMISTOR)
#error "No heater 5 thermistor table specified"