diff --git a/src/Afterburner.cpp b/src/Afterburner.cpp index 69b9110..3349f4e 100644 --- a/src/Afterburner.cpp +++ b/src/Afterburner.cpp @@ -482,6 +482,32 @@ void setup() { pHourMeter->init(bESP32PowerUpInit || RTC_Store.getBootInit()); // ensure persistent memory variable are reset after powerup, or OTA update RTC_Store.setBootInit(false); + // Check for solo DS18B20 + // store it's serial number as the primary sensor + // This allows seamless standard operation, and marks the iniital sensor + // as the primary if another is added later + OneWireBus_ROMCode romCode; + TempSensor.getRomCodeIdx(0, romCode); + if(TempSensor.getNumSensors() == 1 && + memcmp(NVstore.getHeaterTuning().tempProbe[0].romCode.bytes, romCode.bytes, 8) != 0) + { + sHeaterTuning tuning = NVstore.getHeaterTuning(); + tuning.tempProbe[0].romCode = romCode; + tuning.tempProbe[1].romCode = {0}; + tuning.tempProbe[2].romCode = {0}; + tuning.tempProbe[0].offset = 0; + NVstore.setHeaterTuning(tuning); + NVstore.save(); + + DebugPort.printf("Saved solo DS18B20 %02X:%02X:%02X:%02X:%02X:%02X to NVstore\r\n", + romCode.fields.serial_number[5], + romCode.fields.serial_number[4], + romCode.fields.serial_number[3], + romCode.fields.serial_number[2], + romCode.fields.serial_number[1], + romCode.fields.serial_number[0] + ); + } TempSensor.mapSensor(0, NVstore.getHeaterTuning().tempProbe[0].romCode); TempSensor.mapSensor(1, NVstore.getHeaterTuning().tempProbe[1].romCode); TempSensor.mapSensor(2, NVstore.getHeaterTuning().tempProbe[2].romCode); @@ -804,8 +830,7 @@ void loop() lastTemperatureTime = millis(); // reset time to observe temeprature TempSensor.readSensors(); -// TempSensor.checkNumSensors(); - if(TempSensor.getTemperature(fTemperature)) { // get Primary sensor temeprature + if(TempSensor.getTemperature(0, fTemperature)) { // get Primary sensor temeprature if(DS18B20holdoff) { DS18B20holdoff--; DebugPort.printf("Skipped initial DS18B20 reading: %f\r\n", fTemperature); diff --git a/src/OLED/DS18B20Screen.cpp b/src/OLED/DS18B20Screen.cpp index d4c85b6..95c5b1f 100644 --- a/src/OLED/DS18B20Screen.cpp +++ b/src/OLED/DS18B20Screen.cpp @@ -75,23 +75,23 @@ CDS18B20Screen::show() else _showTitle("Temp Sensor Offset"); - int baseLine = 40; + int baseLine = 16; switch(_nNumSensors) { - case 1: baseLine = 18; break; - case 2: baseLine = 30; break; + case 2: baseLine = 28; break; + case 3: baseLine = 40; break; } - for(int i = 0; i<_nNumSensors; i++) { + for(int sensor = 0; sensor<_nNumSensors; sensor++) { - switch(_sensorRole[i]) { + switch(_sensorRole[sensor]) { case 0: strcpy(msg, "Pri"); break; case 1: strcpy(msg, "Sec"); break; case 2: strcpy(msg, "Ter"); break; default: strcpy(msg, " ? "); break; } - _printMenuText(border, baseLine-i*12, msg, _rowSel == (i+1) && _colSel == 0); + _printMenuText(border, baseLine-sensor*12, msg, _rowSel == (sensor+1) && _colSel == 0); OneWireBus_ROMCode romCode; - if(!TempSensor.getRomCodeIdx(romCode, i)) { + if(!TempSensor.getRomCodeIdx(sensor, romCode)) { strcpy(msg, "missing?") ; } else { @@ -103,18 +103,18 @@ CDS18B20Screen::show() } { CTransientFont AF(_display, &miniFontInfo); - _printMenuText(27, baseLine+2-i*12, msg); + _printMenuText(27, baseLine+2-sensor*12, msg); } if(_colSel == 0) { float temperature; - TempSensor.getTemperatureIdx(temperature, i); - sprintf(msg, "%.01fC", temperature + _Offset[i]); + TempSensor.getTemperatureIdx(sensor, temperature); + sprintf(msg, "%.01fC", temperature + _Offset[sensor]); } else { - sprintf(msg, "%+.01f", _Offset[i]); + sprintf(msg, "%+.01f", _Offset[sensor]); } - _printMenuText(90, baseLine-i*12, msg, _rowSel == (i+1) && _colSel == 1); + _printMenuText(90, baseLine-sensor*12, msg, _rowSel == (sensor+1) && _colSel == 1); } } @@ -166,33 +166,6 @@ CDS18B20Screen::keyHandler(uint8_t event) sUserSettings us; if(event & keyPressed) { _keyHold = 0; - // UP press - if(event & key_Up) { - if(_rowSel == SaveConfirm) { - _enableStoringMessage(); - _saveNV(); - NVstore.save(); - TempSensor.mapSensor(-1); // reset existing mapping - TempSensor.mapSensor(0, NVstore.getHeaterTuning().tempProbe[0].romCode); - TempSensor.mapSensor(1, NVstore.getHeaterTuning().tempProbe[1].romCode); - TempSensor.mapSensor(2, NVstore.getHeaterTuning().tempProbe[2].romCode); - TempSensor.mapSensor(-2); // report mapping - _rowSel = 0; - } - else { - if(_rowSel == 0) { - _getPassword(); - if(_isPasswordOK()) { - _rowSel = 1; - } - } - else { - _testCancel(); - _rowSel++; - UPPERLIMIT(_rowSel, 3); - } - } - } // DOWN press if(event & key_Down) { _testCancel(); @@ -208,11 +181,18 @@ CDS18B20Screen::keyHandler(uint8_t event) if(_keyHold >= 0) { _keyHold++; if(_keyHold == 2) { + if(event & key_Up) { + // rescan the one wire bus + TempSensor.find(); + _nNumSensors = TempSensor.getNumSensors(); + _readNV(); + } if(event & key_Left) { _colSel = 0; _scrollChar = 0; } if(event & key_Right) { + _testCancel(); _colSel = 1; _scrollChar = 0; } @@ -230,6 +210,33 @@ CDS18B20Screen::keyHandler(uint8_t event) if(event & keyReleased) { if(_keyHold == 0) { + // UP release + if(event & key_Up) { + if(_rowSel == SaveConfirm) { + _enableStoringMessage(); + _saveNV(); + NVstore.save(); + TempSensor.mapSensor(-1); // reset existing mapping + TempSensor.mapSensor(0, NVstore.getHeaterTuning().tempProbe[0].romCode); + TempSensor.mapSensor(1, NVstore.getHeaterTuning().tempProbe[1].romCode); + TempSensor.mapSensor(2, NVstore.getHeaterTuning().tempProbe[2].romCode); + TempSensor.mapSensor(-2); // report mapping + _rowSel = 0; + } + else { + if(_rowSel == 0) { + _getPassword(); + if(_isPasswordOK()) { + _rowSel = 1; + } + } + else { + _testCancel(); + _rowSel++; + UPPERLIMIT(_rowSel, 3); + } + } + } // LEFT press if(event & key_Left) { if(_rowSel == 0) @@ -327,13 +334,14 @@ CDS18B20Screen::_testCancel() void CDS18B20Screen::_readNV() { - _sensorRole[0] = _sensorRole[1] = _sensorRole[2] = -1; + for(int i=0; i< 3; i++) + _sensorRole[i] = -1; const sHeaterTuning& tuning = NVstore.getHeaterTuning(); for(int sensor = 0; sensor < TempSensor.getNumSensors(); sensor++) { OneWireBus_ROMCode romCode; - TempSensor.getRomCodeIdx(romCode, sensor); // get rom code of each attached sensor + TempSensor.getRomCodeIdx(sensor, romCode); // get rom code of each attached sensor // NV storage indices are the sensor role // ie 0 is normal thermostat // scan the NV store and match the stored romCodes @@ -342,7 +350,7 @@ CDS18B20Screen::_readNV() if(memcmp(tuning.tempProbe[i].romCode.bytes, romCode.bytes, 8) == 0) { _sensorRole[sensor] = i; // assign role to sensor according to NV placement _Offset[sensor] = tuning.tempProbe[i].offset; - continue; + break; } } } @@ -363,7 +371,7 @@ CDS18B20Screen::_saveNV() if(role != -1) { tuning.tempProbe[role].offset = _Offset[sensor]; OneWireBus_ROMCode romCode; - TempSensor.getRomCodeIdx(romCode, sensor); // get rom code of indexed sensor + TempSensor.getRomCodeIdx(sensor, romCode); // get rom code of indexed sensor memcpy(tuning.tempProbe[role].romCode.bytes, romCode.bytes, 8); } } diff --git a/src/Utility/BTC_JSON.cpp b/src/Utility/BTC_JSON.cpp index cd2eaf4..ad29d1b 100644 --- a/src/Utility/BTC_JSON.cpp +++ b/src/Utility/BTC_JSON.cpp @@ -146,14 +146,14 @@ bool makeJSONString(CModerator& moderator, char* opStr, int len) bSend |= moderator.addJson("TempCurrent", tidyTemp, root); } if(TempSensor.getNumSensors() > 1) { - TempSensor.getTemperature(tidyTemp, 1); + TempSensor.getTemperature(1, tidyTemp); tidyTemp += NVstore.getHeaterTuning().tempProbe[1].offset; tidyTemp = int(tidyTemp * 10 + 0.5) * 0.1f; // round to 0.1 resolution if(tidyTemp > -80) { bSend |= moderator.addJson("Temp2Current", tidyTemp, root); } if(TempSensor.getNumSensors() > 2) { - TempSensor.getTemperature(tidyTemp, 2); + TempSensor.getTemperature(2, tidyTemp); tidyTemp += NVstore.getHeaterTuning().tempProbe[2].offset; tidyTemp = int(tidyTemp * 10 + 0.5) * 0.1f; // round to 0.1 resolution if(tidyTemp > -80) { diff --git a/src/Utility/TempSense.cpp b/src/Utility/TempSense.cpp index 3adec6c..1307991 100644 --- a/src/Utility/TempSense.cpp +++ b/src/Utility/TempSense.cpp @@ -210,6 +210,7 @@ CTempSense::find() { printf("Single device optimisations enabled\n"); ds18b20_init_solo(ds18b20_info, _owb); // only one device on bus + ds18b20_info->rom_code = _device_rom_codes[i]; // added, for GUI setup!! } else { @@ -219,7 +220,6 @@ CTempSense::find() ds18b20_set_resolution(ds18b20_info, DS18B20_RESOLUTION_12_BIT); } - return found; } #endif @@ -313,9 +313,14 @@ CTempSense::mapSensor(int idx, OneWireBus_ROMCode romCode) if(memcmp(_Sensors[i]->rom_code.bytes, romCode.bytes, 8) == 0) { _sensorMap[idx] = i; DebugPort.printf("Mapped DS18B20 %02X:%02X:%02X:%02X:%02X:%02X as role %d\r\n", - romCode.fields.serial_number[5], romCode.fields.serial_number[4], romCode.fields.serial_number[3], - romCode.fields.serial_number[2], romCode.fields.serial_number[1], romCode.fields.serial_number[0], - idx); + romCode.fields.serial_number[5], + romCode.fields.serial_number[4], + romCode.fields.serial_number[3], + romCode.fields.serial_number[2], + romCode.fields.serial_number[1], + romCode.fields.serial_number[0], + idx + ); return true; } } @@ -323,29 +328,28 @@ CTempSense::mapSensor(int idx, OneWireBus_ROMCode romCode) } bool -CTempSense::getTemperature(float& temperature, int mapIdx) +CTempSense::getTemperature(int mapIdx, float& temperature) { - int idx = _sensorMap[mapIdx]; - if(idx < 0) - return getTemperatureIdx(temperature, 0); // default to sensor 0 if not mapped - // temperature = _Readings[idx]; - // return _Errors[idx] == DS18B20_OK; - return getTemperatureIdx(temperature, idx); + int snsIdx = _sensorMap[mapIdx]; + if(snsIdx < 0) + snsIdx = 0; // default to sensor 0 if not mapped + + return getTemperatureIdx(snsIdx, temperature); } bool -CTempSense::getTemperatureIdx(float& temperature, int idx) +CTempSense::getTemperatureIdx(int snsIdx, float& temperature) { - temperature = _Readings[idx]; - return _Errors[idx] == DS18B20_OK; + temperature = _Readings[snsIdx]; + return _Errors[snsIdx] == DS18B20_OK; } bool -CTempSense::getRomCodeIdx(OneWireBus_ROMCode& romCode, int idx) +CTempSense::getRomCodeIdx(int snsIdx, OneWireBus_ROMCode& romCode) { - if(idx >= _nNumSensors) + if(snsIdx >= _nNumSensors) return false; - romCode = _Sensors[idx]->rom_code; + romCode = _Sensors[snsIdx]->rom_code; return true; } diff --git a/src/Utility/TempSense.h b/src/Utility/TempSense.h index e78adca..4fd141f 100644 --- a/src/Utility/TempSense.h +++ b/src/Utility/TempSense.h @@ -52,9 +52,9 @@ public: bool readSensors(); void startConvert(); void waitConvertDone(); - bool getTemperature(float& tempReading, int mapIdx=0); // indexed as mapped by user - bool getTemperatureIdx(float& tempReading, int selSensor=0); // index is discovery order on one-wire bus - bool getRomCodeIdx(OneWireBus_ROMCode& romCode, int selSensor=0); // index is discovery order on one-wire bus + bool getTemperature(int mapIdx, float& tempReading); // indexed as mapped by user + bool getTemperatureIdx(int sensIdx, float& tempReading); // index is sensor discovery order on one-wire bus + bool getRomCodeIdx(int sensIdx, OneWireBus_ROMCode& romCode); // index is sensor discovery order on one-wire bus int checkNumSensors() const; int getNumSensors() const { return _nNumSensors; }; bool mapSensor(int idx, OneWireBus_ROMCode romCode = { 0 } ); diff --git a/src/WiFi/ABMqtt.cpp b/src/WiFi/ABMqtt.cpp index c783b92..d297f99 100644 --- a/src/WiFi/ABMqtt.cpp +++ b/src/WiFi/ABMqtt.cpp @@ -34,8 +34,10 @@ #include "../Utility/Moderator.h" #include "../Protocol/Protocol.h" #include "../Utility/BTC_JSON.h" +#include "Utility/TempSense.h" extern void DecodeCmd(const char* cmd, String& payload); +extern CTempSense TempSensor; #define USE_RTOS_MQTTTIMER //#define USE_LOCAL_MQTTSTRINGS @@ -49,6 +51,9 @@ char topicnameJSONin[128]; char topicnameCmd[128]; CModerator MQTTmoderator; +void subscribe(const char* topic); + + #ifdef USE_LOCAL_MQTTSTRINGS char mqttHost[128]; char mqttUser[32]; @@ -84,20 +89,23 @@ void onMqttConnect(bool sessionPresent) mqttReconnect = 0; #endif - sprintf(statusTopic, "%s/status", NVstore.getMQTTinfo().topic); DebugPort.println("MQTT: Connected to broker."); // DebugPort.printf("Session present: %d\r\n", sessionPresent); // create the topicname we use to accept incoming JSON - DebugPort.printf("MQTT: base topic name \"%s\"\r\n", NVstore.getMQTTinfo().topic); - sprintf(topicnameJSONin, "%s/JSONin", NVstore.getMQTTinfo().topic); - sprintf(topicnameCmd, "%s/cmd/#", NVstore.getMQTTinfo().topic); + DebugPort.printf("MQTT: topic prefix name \"%s\"\r\n", NVstore.getMQTTinfo().topicPrefix); + sprintf(statusTopic, "%s/status", NVstore.getMQTTinfo().topicPrefix); + sprintf(topicnameJSONin, "%s/JSONin", NVstore.getMQTTinfo().topicPrefix); + sprintf(topicnameCmd, "%s/cmd/#", NVstore.getMQTTinfo().topicPrefix); // subscribe to that topic - DebugPort.printf("MQTT: Subscribing to \"%s\"\r\n", topicnameJSONin); - MQTTclient.subscribe(topicnameJSONin, NVstore.getMQTTinfo().qos); - MQTTclient.subscribe(topicnameCmd, NVstore.getMQTTinfo().qos); - MQTTclient.subscribe(statusTopic, NVstore.getMQTTinfo().qos); + // DebugPort.printf("MQTT: Subscribing to \"%s\"\r\n", topicnameJSONin); + // MQTTclient.subscribe(topicnameJSONin, NVstore.getMQTTinfo().qos); + // MQTTclient.subscribe(topicnameCmd, NVstore.getMQTTinfo().qos); + // MQTTclient.subscribe(statusTopic, NVstore.getMQTTinfo().qos); + subscribe(topicnameJSONin); + subscribe(topicnameCmd); + subscribe(statusTopic); // spit out an "I'm here" message MQTTclient.publish(statusTopic, NVstore.getMQTTinfo().qos, true, "online"); @@ -241,7 +249,7 @@ bool mqttPublishJSON(const char* str) if(MQTTclient.connected()) { const sMQTTparams params = NVstore.getMQTTinfo(); char topic[128]; - sprintf(topic, "%s/JSONout", params.topic); + sprintf(topic, "%s/JSONout", params.topicPrefix); MQTTclient.publish(topic, params.qos, false, str); return true; } @@ -299,7 +307,7 @@ void pubTopic(const char* name, int value) if(MQTTmoderator.shouldSend(name, value)) { const sMQTTparams params = NVstore.getMQTTinfo(); char topic[128]; - sprintf(topic, "%s/sts/%s", params.topic, name); + sprintf(topic, "%s/sts/%s", params.topicPrefix, name); char payload[128]; sprintf(payload, "%d", value); MQTTclient.publish(topic, params.qos, false, payload); @@ -313,7 +321,7 @@ void pubTopic(const char* name, float value) if(MQTTmoderator.shouldSend(name, value)) { const sMQTTparams params = NVstore.getMQTTinfo(); char topic[128]; - sprintf(topic, "%s/sts/%s", params.topic, name); + sprintf(topic, "%s/sts/%s", params.topicPrefix, name); char payload[128]; sprintf(payload, "%.1f", value); MQTTclient.publish(topic, params.qos, false, payload); @@ -327,7 +335,7 @@ void pubTopic(const char* name, const char* payload) if(MQTTmoderator.shouldSend(name, payload)) { const sMQTTparams params = NVstore.getMQTTinfo(); char topic[128]; - sprintf(topic, "%s/sts/%s", params.topic, name); + sprintf(topic, "%s/sts/%s", params.topicPrefix, name); MQTTclient.publish(topic, params.qos, false, payload); } } @@ -338,9 +346,33 @@ void updateMQTT() pubTopic("RunState", getHeaterInfo().getRunStateEx()); pubTopic("Run", getHeaterInfo().getRunStateEx() ? "1" : "0"); pubTopic("RunString", getHeaterInfo().getRunStateStr()); - float tidyTemp = getTemperatureSensor(); - tidyTemp = int(tidyTemp * 10 + 0.5) * 0.1f; // round to 0.1 resolution - pubTopic("TempCurrent", tidyTemp); + + float tidyTemp; + if(TempSensor.getTemperature(0, tidyTemp)) { + tidyTemp += NVstore.getHeaterTuning().tempProbe[0].offset; + tidyTemp = int(tidyTemp * 10 + 0.5) * 0.1f; // round to 0.1 resolution + pubTopic("TempCurrent", tidyTemp); + } + else + pubTopic("TempCurrent", "n/a"); + if(TempSensor.getNumSensors() > 1) { + if(TempSensor.getTemperature(1, tidyTemp)) { + tidyTemp += NVstore.getHeaterTuning().tempProbe[1].offset; + tidyTemp = int(tidyTemp * 10 + 0.5) * 0.1f; // round to 0.1 resolution + pubTopic("Temp2Current", tidyTemp); + } + else + pubTopic("Temp2Current", "n/a"); + if(TempSensor.getNumSensors() > 2) { + if(TempSensor.getTemperature(2, tidyTemp)) { + tidyTemp += NVstore.getHeaterTuning().tempProbe[2].offset; + tidyTemp = int(tidyTemp * 10 + 0.5) * 0.1f; // round to 0.1 resolution + pubTopic("Temp3Current", tidyTemp); + } + else + pubTopic("Temp3Current", "n/a"); + } + } pubTopic("TempDesired", getTemperatureDesired()); pubTopic("TempBody", getHeaterInfo().getTemperature_HeatExchg()); pubTopic("ErrorState", getHeaterInfo().getErrState()); @@ -362,5 +394,10 @@ void refreshMQTT() MQTTmoderator.reset(); } +void subscribe(const char* topic) +{ + DebugPort.printf("MQTT: Subscribing to \"%s\"\r\n", topic); + MQTTclient.subscribe(topic, NVstore.getMQTTinfo().qos); +} #endif \ No newline at end of file