Add settable seed TEC setpoint and °C readout
Expose the Koheron CTL200 thermistor setpoint (rtset) as a settable HA number in ohms, clamped to SEED_RT_SETPOINT_MIN/MAX_OHM. The former read-only setpoint sensor is replaced by this control. Add a read-only seed temperature in °C, computed in firmware from the actual thermistor resistance via an NTC β-model (constants in config.h; update once the DFB1550LP thermistor R25/β are confirmed). Verified end-to-end over MQTT: set/clamp/restore of rtset and the °C conversion (10 kΩ → 25.00 °C). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
61f4526d09
commit
b31065acd7
+24
-1
@@ -120,8 +120,8 @@ static void publishDiscovery() {
|
||||
binaryDiscovery("seed_laser_enabled", "Seed Laser Enabled", "seed/laser_enabled", "1", "0", nullptr, false);
|
||||
sensorDiscovery("seed_current", "Seed Current", "seed/current_ma", "mA", "current", "mdi:current-dc", false);
|
||||
sensorDiscovery("seed_voltage", "Seed Voltage", "seed/voltage_v", "V", "voltage", nullptr, false);
|
||||
sensorDiscovery("seed_rt_setpoint", "Seed Thermistor Setpoint", "seed/rt_setpoint_ohm", "Ω", nullptr, "mdi:resistor", false);
|
||||
sensorDiscovery("seed_rt_actual", "Seed Thermistor", "seed/rt_actual_ohm", "Ω", nullptr, "mdi:resistor", false);
|
||||
sensorDiscovery("seed_temp", "Seed Temperature", "seed/temp_c", "°C", "temperature", nullptr, false);
|
||||
sensorDiscovery("seed_tec_current", "Seed TEC Current", "seed/tec_current_a", "A", "current", nullptr, false);
|
||||
sensorDiscovery("seed_tec_voltage", "Seed TEC Voltage", "seed/tec_voltage_v", "V", "voltage", nullptr, false);
|
||||
sensorDiscovery("seed_board_temp", "Seed Board Temperature", "seed/board_temp_c", "°C", "temperature", nullptr, false);
|
||||
@@ -132,6 +132,10 @@ static void publishDiscovery() {
|
||||
switchDiscovery("seed_laser", "Seed Laser", "seed/laser_enabled", "seed/laser", "1", "0", "mdi:laser-pointer");
|
||||
numberDiscovery("seed_set_current", "Seed Set Current", "seed/current_ma", "seed/current_ma",
|
||||
0, SEED_CURRENT_MAX_MA, 1, "mA", "mdi:current-dc");
|
||||
// Seed TEC setpoint: settable in ohms (CTL200 `rtset`); state mirrors the
|
||||
// `seed/rt_setpoint_ohm` telemetry. °C is exposed read-only via seed/temp_c.
|
||||
numberDiscovery("seed_set_rt_setpoint", "Seed Thermistor Setpoint", "seed/rt_setpoint_ohm", "seed/rt_setpoint_ohm",
|
||||
SEED_RT_SETPOINT_MIN_OHM, SEED_RT_SETPOINT_MAX_OHM, 10, "Ω", "mdi:thermometer");
|
||||
|
||||
// Amp (Agiltron M511)
|
||||
binaryDiscovery("amp_link", "Amp Link", "amp/link", AVAIL_ONLINE, AVAIL_OFFLINE, "connectivity", true);
|
||||
@@ -161,6 +165,14 @@ static void publishDiag() {
|
||||
}
|
||||
|
||||
// Each seed value is the raw string the CTL200 returns (already numeric text).
|
||||
// NTC β-model: thermistor resistance (Ω) -> °C. Display-only approximation;
|
||||
// the CTL200 regulates in ohms, not against this figure.
|
||||
static float seedOhmToC(float r) {
|
||||
float invT = 1.0f / SEED_THERMISTOR_T25_K
|
||||
+ logf(r / SEED_THERMISTOR_R25_OHM) / SEED_THERMISTOR_BETA_K;
|
||||
return 1.0f / invT - 273.15f;
|
||||
}
|
||||
|
||||
struct SeedPoint { const char *cmd; const char *sub; };
|
||||
static const SeedPoint seedPoints[] = {
|
||||
{"lason", "seed/laser_enabled"},
|
||||
@@ -177,14 +189,18 @@ static const SeedPoint seedPoints[] = {
|
||||
|
||||
static void publishSeed() {
|
||||
bool any = false;
|
||||
float rtActOhm = 0;
|
||||
for (const auto &pt : seedPoints) {
|
||||
String v = koheron.query(pt.cmd);
|
||||
if (v.length()) {
|
||||
mqtt.publish((String(TOPIC_BASE) + "/" + pt.sub).c_str(), v.c_str(), true);
|
||||
if (strcmp(pt.cmd, "rtact") == 0) rtActOhm = v.toFloat();
|
||||
any = true;
|
||||
}
|
||||
mqtt.loop(); // keep MQTT serviced between (potentially slow) UART round-trips
|
||||
}
|
||||
if (rtActOhm > 0)
|
||||
mqtt.publish(TOPIC_BASE "/seed/temp_c", String(seedOhmToC(rtActOhm), 2).c_str(), true);
|
||||
mqtt.publish(TOPIC_BASE "/seed/link", any ? AVAIL_ONLINE : AVAIL_OFFLINE, true);
|
||||
}
|
||||
|
||||
@@ -230,6 +246,13 @@ static void onMqtt(char *topic, byte *payload, unsigned int len) {
|
||||
koheron.query((String("ilaser ") + String(ma, 1)).c_str());
|
||||
pub("seed/current_ma", String(ma, 3));
|
||||
|
||||
} else if (t == TOPIC_CMD "/seed/rt_setpoint_ohm") {
|
||||
long ohm = p.toInt();
|
||||
if (ohm < SEED_RT_SETPOINT_MIN_OHM) ohm = SEED_RT_SETPOINT_MIN_OHM;
|
||||
if (ohm > SEED_RT_SETPOINT_MAX_OHM) ohm = SEED_RT_SETPOINT_MAX_OHM; // firmware clamp
|
||||
koheron.query((String("rtset ") + String(ohm)).c_str());
|
||||
pub("seed/rt_setpoint_ohm", String(ohm));
|
||||
|
||||
} else if (t == TOPIC_CMD "/amp/pump") {
|
||||
bool on = (p == "1" || p.equalsIgnoreCase("on") || p.equalsIgnoreCase(AVAIL_ONLINE));
|
||||
bool ok = on ? agiltron.pumpOn() : agiltron.pumpOff();
|
||||
|
||||
Reference in New Issue
Block a user