Skip to content

Commit 3786aed

Browse files
Fixed sensor setup when no sensors are attached
- state machine would forever stat at ‘init’ when no sensors were connected (sensor status ‘initialising’) - reduced Flash and RAM usage for serial UI - runs on Adafruit Micro for first time - EEPROM config block was not initialised to 0’s => random parameter values. Should have cmd to force default values.
1 parent 4b771e7 commit 3786aed

13 files changed

+241
-265
lines changed

bc_setup.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// Uncomment AT MOST ONE (!) of the following lines:
55
// #define UNIT_TEST
66
// #define BLE_UI
7-
// #define SERIAL_UI
7+
#define SERIAL_UI
88

99
#ifdef UNIT_TEST
1010
// Comment the following line to prevent execution of STATE tests:

boiler_controller.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ void setup() {
7474
pinMode(HEATER_PIN, OUTPUT);
7575
controlActions.setupSensors();
7676

77-
Serial.println(F("Ready."));
77+
Serial.println(F("Starting."));
7878
#endif
7979

8080
}

config.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,14 @@ void ConfigParams::initParams(boolean &updated) {
5151

5252

5353
void ConfigParams::print() {
54+
char buf[max(MAX_TEMPERATURE_STR_LEN, MAX_TEMP_SENSOR_ID_STR_LEN)];
5455
AbstractConfigParams::print();
55-
Serial.println(formatTemperature(targetTemp));
56-
Serial.println(formatTempSensorID(waterTempSensorId));
57-
Serial.println(formatTempSensorID(ambientTempSensorId));
58-
Serial.println(formatTemperature(heaterCutOutWaterTemp));
59-
Serial.println(formatTemperature(heaterBackOkWaterTemp));
60-
Serial.println(formatTemperature(logTempDelta));
56+
Serial.println(formatTemperature(targetTemp, buf));
57+
Serial.println(formatTempSensorID(waterTempSensorId, buf));
58+
Serial.println(formatTempSensorID(ambientTempSensorId, buf));
59+
Serial.println(formatTemperature(heaterCutOutWaterTemp, buf));
60+
Serial.println(formatTemperature(heaterBackOkWaterTemp, buf));
61+
Serial.println(formatTemperature(logTempDelta, buf));
6162
Serial.println(logTimeDelta);
6263
Serial.println(tankCapacity);
6364
Serial.println(heaterPower);

control.cpp

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,43 +24,53 @@ uint32_t heatingTotalMillis(OperationalParams *op) {
2424

2525

2626
uint8_t ControlActions::setupSensors() {
27-
context->op->water.setId(context->config->waterTempSensorId);
28-
context->op->water.rangeMin = WATER_MIN_TEMP;
29-
context->op->water.rangeMax = WATER_MAX_TEMP;
27+
DS18B20TemperatureSensor *waterSensor = &context->op->water;
28+
waterSensor->setId(context->config->waterTempSensorId);
29+
waterSensor->rangeMin = WATER_MIN_TEMP;
30+
waterSensor->rangeMax = WATER_MAX_TEMP;
3031

31-
context->op->ambient.setId(context->config->ambientTempSensorId);
32-
context->op->ambient.rangeMin = AMBIENT_MIN_TEMP;
33-
context->op->ambient.rangeMax = AMBIENT_MAX_TEMP;
32+
DS18B20TemperatureSensor *ambientSensor = &context->op->ambient;
33+
ambientSensor->setId(context->config->ambientTempSensorId);
34+
ambientSensor->rangeMin = AMBIENT_MIN_TEMP;
35+
ambientSensor->rangeMax = AMBIENT_MAX_TEMP;
3436

3537
uint8_t matched = context->controller->setupSensors();
3638

37-
if (context->op->water.sensorStatus == SENSOR_ID_UNDEFINED) {
38-
context->log->logMessage(MSG_WATER_TEMP_SENSOR_ID_UNDEF, 0, 0);
39-
#ifdef DEBUG_CONTROL
40-
Serial.println(F("DEBUG_CONTROL: Water temp sensor ID undefined"));
41-
#endif
42-
} else if (context->op->water.sensorStatus == SENSOR_ID_AUTO_ASSIGNED) {
43-
context->log->logMessage(MSG_WATER_TEMP_SENSOR_ID_AUTO, 0, 0);
44-
#ifdef DEBUG_CONTROL
45-
Serial.println(F("DEBUG_CONTROL: Water temp sensor ID assigned automatically."));
46-
#endif
39+
if (waterSensor->sensorStatus == SENSOR_INITIALISING) {
40+
logSensorSetupIssue(waterSensor, MSG_WATER_TEMP_SENSOR_SILENT);
41+
} else if (waterSensor->sensorStatus == SENSOR_ID_UNDEFINED) {
42+
logSensorSetupIssue(waterSensor, MSG_WATER_TEMP_SENSOR_ID_UNDEF);
43+
} else if (waterSensor->sensorStatus == SENSOR_ID_AUTO_ASSIGNED) {
44+
logSensorSetupIssue(waterSensor, MSG_WATER_TEMP_SENSOR_ID_AUTO);
4745
}
4846

49-
if (context->op->ambient.sensorStatus == SENSOR_ID_UNDEFINED) {
50-
context->log->logMessage(MSG_AMBIENT_TEMP_SENSOR_ID_UNDEF, 0, 0);
51-
#ifdef DEBUG_CONTROL
52-
Serial.println(F("DEBUG_CONTROL: Ambient temp sensor ID undefined"));
53-
#endif
54-
} else if (context->op->ambient.sensorStatus == SENSOR_ID_AUTO_ASSIGNED) {
55-
context->log->logMessage(MSG_AMBIENT_TEMP_SENSOR_ID_AUTO, 0, 0);
47+
if (ambientSensor->sensorStatus == SENSOR_INITIALISING) {
48+
logSensorSetupIssue(ambientSensor, MSG_AMBIENT_TEMP_SENSOR_SILENT);
49+
} else if (ambientSensor->sensorStatus == SENSOR_ID_UNDEFINED) {
50+
logSensorSetupIssue(ambientSensor, MSG_AMBIENT_TEMP_SENSOR_ID_UNDEF);
51+
} else if (ambientSensor->sensorStatus == SENSOR_ID_AUTO_ASSIGNED) {
52+
logSensorSetupIssue(ambientSensor, MSG_AMBIENT_TEMP_SENSOR_ID_AUTO);
53+
}
54+
5655
#ifdef DEBUG_CONTROL
57-
Serial.println(F("DEBUG_CONTROL: Ambient temp sensor ID assigned automatically."));
56+
Serial.print(F("DEBUG_CONTROL: Sensors matched or found = "));
57+
Serial.println(matched);
5858
#endif
59-
}
60-
6159
return matched;
6260
}
6361

62+
void ControlActions::logSensorSetupIssue(DS18B20TemperatureSensor *sensor, ControlMessageEnum msg) {
63+
context->log->logMessage(msg, 0, 0);
64+
#ifdef DEBUG_CONTROL
65+
Serial.print(F("DEBUG_CONTROL: "));
66+
Serial.print(sensor->label);
67+
Serial.print(F(" sensor status = "));
68+
Serial.println(sensor->sensorStatus);
69+
#else
70+
if (sensor != NULL) { } // prevent 'unused parameter' warning
71+
#endif
72+
}
73+
6474
void ControlActions::swapTempSensorIDs() {
6575
context->op->swapTempSensorIDs();
6676
}

control.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@
99
#define ONE_WIRE_PIN 10 // Temperature sensors
1010

1111
typedef enum {
12-
MSG_WATER_TEMP_SENSOR_ID_UNDEF = 20, // Sensor ID of water-temperature sensor could not be obtained. Check wiring and sensor, then restart.
13-
MSG_WATER_TEMP_SENSOR_ID_AUTO = 21, // Sensor ID of water-temperature sensor was assigned automatically. Confirm that it refers to the correct sensor, then restart.
14-
MSG_AMBIENT_TEMP_SENSOR_ID_UNDEF = 22, // Sensor ID of ambient-temperature sensor could not be obtained. Check wiring and sensor, then restart.
15-
MSG_AMBIENT_TEMP_SENSOR_ID_AUTO = 23, // Sensor ID of ambient-temperature sensor was assigned automatically. Confirm that it refers to the correct sensor, then restart.
16-
MSG_TEMP_SENSOR_IDS_CLEARED = 24 // Sensor IDs of water- and ambient-temperature sensor cleared. Restart to see the effect.
12+
MSG_WATER_TEMP_SENSOR_SILENT = 20, // Water-temperature sensor not responding. Check wiring and sensor, then restart.
13+
MSG_WATER_TEMP_SENSOR_ID_UNDEF = 21, // Sensor ID of water-temperature sensor could not be obtained. Check wiring and sensor, then restart.
14+
MSG_WATER_TEMP_SENSOR_ID_AUTO = 22, // Sensor ID of water-temperature sensor was assigned automatically. Confirm that it refers to the correct sensor, then restart.
15+
MSG_AMBIENT_TEMP_SENSOR_SILENT = 23, // Ambient-temperature sensor not responding. Check wiring and sensor, then restart.
16+
MSG_AMBIENT_TEMP_SENSOR_ID_UNDEF = 24, // Sensor ID of ambient-temperature sensor could not be obtained. Check wiring and sensor, then restart.
17+
MSG_AMBIENT_TEMP_SENSOR_ID_AUTO = 25, // Sensor ID of ambient-temperature sensor was assigned automatically. Confirm that it refers to the correct sensor, then restart.
18+
MSG_TEMP_SENSOR_IDS_CLEARED = 26 // Sensor IDs of water- and ambient-temperature sensor cleared. Restart to see the effect.
1719
} ControlMessageEnum;
1820

1921

@@ -160,6 +162,8 @@
160162
protected:
161163
ControlContext *context;
162164
ReadWriteRequests pendingRequests = READ_WRITE_NONE;
165+
166+
void logSensorSetupIssue(DS18B20TemperatureSensor *sensor, ControlMessageEnum msg);
163167
};
164168

165169
#endif

log/LogTime.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#include <assert.h>
22
#include "LogTime.h"
33

4-
//#define DEBUG_LOG_TIME
4+
// #define DEBUG_LOG_TIME
55

66
#define ASCII_0 48 // char(48)
77

@@ -32,7 +32,8 @@ Timestamp LogTime::timestamp() {
3232
Timestamp ts = t.sec << TIMESTAMP_ID_BITS | timestampCount;
3333
#ifdef DEBUG_LOG_TIME
3434
Serial.print(F("DEBUG_LOG_TIME: Timestamp "));
35-
Serial.println(format(ts));
35+
char buf[MAX_TIMESTAMP_STR_LEN];
36+
Serial.println(formatTimestamp(ts, buf));
3637
#endif
3738
return ts;
3839
}
@@ -56,8 +57,7 @@ void LogTime::reset() {
5657
}
5758

5859

59-
String formatTimestamp(Timestamp t) {
60-
char s[13];
60+
char *formatTimestamp(Timestamp t, char s[MAX_TIMESTAMP_STR_LEN]) {
6161
uint32_t sec = t >> TIMESTAMP_ID_BITS;
6262
uint8_t timestampCount = t % 16;
6363
s[12] = '\0';

log/LogTime.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,11 @@
7070
uint8_t timestampCount = 0;
7171
};
7272

73-
74-
/**
75-
* Returns the timestamp in a 13-character dotted notation, terminated by '\0': sssssssss.cc (s = seconds: 2^28 = 268435456 (9 digits), cc = count: 0..15 (2 digits))
76-
*/
77-
String formatTimestamp(Timestamp t);
73+
74+
#define MAX_TIMESTAMP_STR_LEN 13
75+
/**
76+
* Returns the timestamp in a 13-character dotted notation, terminated by '\0': sssssssss.cc (s = seconds: 2^28 = 268435456 (9 digits), cc = count: 0..15 (2 digits))
77+
*/
78+
char *formatTimestamp(Timestamp t, char buf[MAX_TIMESTAMP_STR_LEN]);
7879

7980
#endif

log/Logging.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ LogEntry AbstractLog::addLogEntry(LogDataTypeID type, LogData *data) {
125125
Serial.print(F("DEBUG_LOG: createLogEntry: type "));
126126
Serial.print(entry.type);
127127
Serial.print(F(" => timestamp: "));
128-
Serial.println(logTime.format(entry.timestamp));
128+
char buf[MAX_TIMESTAMP_STR_LEN];
129+
Serial.println(formatTimestamp(entry.timestamp, buf));
129130
#endif
130131
memcpy(&(entry.data), data, sizeof(LogData));
131132

@@ -180,9 +181,10 @@ boolean AbstractLog::nextLogEntry(LogEntry &entry) {
180181
EEPROM.get(entryOffset(reader.nextIndex), entry);
181182
#ifdef DEBUG_LOG
182183
Serial.print(F("DEBUG_LOG: getLogEntry: timestamp: "));
183-
Serial.print(logTime.format(entry->timestamp));
184+
char buf[MAX_TIMESTAMP_STR_LEN];
185+
Serial.print(formatTimestamp(entry.timestamp, buf));
184186
Serial.print(F(", type: "));
185-
Serial.println(entry->type);
187+
Serial.println(entry.type);
186188
#endif
187189
reader.read++;
188190
if (reader.kind == LOG_READER_MOST_RECENT) {
@@ -206,8 +208,9 @@ void AbstractLog::S_O_S(MessageID id, int16_t param1, int16_t param2) {
206208
Timestamp ts = logMessage(id, param1, param2);
207209
ts = ts; // prevents warning: unused variable
208210
#ifdef DEBUG_LOG
211+
char buf[MAX_TIMESTAMP_STR_LEN];
209212
Serial.print(F("DEBUG_LOG: S.O.S. : See log message "));
210-
Serial.println(logTime.format(ts));
213+
Serial.println(formatTimestamp(ts, buf));
211214
#endif
212215
S_O_S(NULL);
213216
}

sensors/OneWireSensors.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ uint8_t DS18B20Controller::setupSensors() {
2121
for(uint8_t i=0; i<numSensors; i++) {
2222
if(sensors[i]->idUndefined()) {
2323
sensors[i]->sensorStatus = SENSOR_ID_UNDEFINED;
24+
#ifdef DEBUG_SENSORS
25+
Serial.print(F("DEBUG_SENSORS: Sensor "));
26+
Serial.print(sensors[i]->label);
27+
Serial.println(F(": setting to status ID undefined"));
28+
#endif
2429
}
2530
}
2631

@@ -90,30 +95,31 @@ void DS18B20Controller::completeSensorReadout() {
9095

9196
DS18B20TemperatureSensor *sensor = getSensor(addr);
9297
if (sensor != NULL) {
98+
TemperatureReadout readout = getCelcius(data);
9399
#ifdef DEBUG_SENSORS
94100
Serial.print(F("DEBUG_SENSORS: Sensor "));
95101
Serial.print(sensor->label);
96102
#endif
97103

98104
// only set temperature and state for NOK sensors and AUTO_ASSIGNED sensors (leave others untouched):
99105
if (sensor->sensorStatus == SENSOR_ID_AUTO_ASSIGNED) {
100-
TemperatureReadout readout = getCelcius(data);
101106
sensor->currentTemp = readout.celcius;
102107
#ifdef DEBUG_SENSORS
108+
char buf[MAX_TEMP_SENSOR_ID_STR_LEN];
103109
Serial.print(F(": ID AUTO ASSIGNED, "));
104-
Serial.println(formatTemperature(readout.celcius));
110+
Serial.println(formatTemperature(readout.celcius, buf));
105111
#endif
106112

107113
} else if (sensor->sensorStatus == SENSOR_NOK) {
108-
TemperatureReadout readout = getCelcius(data);
109114
// Ensure temperature is plausible:
110115
if((sensor->rangeMin == UNDEFINED_TEMPERATURE || readout.celcius >= sensor->rangeMin)
111116
&& (sensor->rangeMax == UNDEFINED_TEMPERATURE || readout.celcius <= sensor->rangeMax)) {
112117
sensor->sensorStatus = SENSOR_OK;
113118
sensor->currentTemp = readout.celcius;
114119
#ifdef DEBUG_SENSORS
120+
char buf[MAX_TEMP_SENSOR_ID_STR_LEN];
115121
Serial.print(F(": OK, "));
116-
Serial.println(formatTemperature(readout.celcius));
122+
Serial.println(formatTemperature(readout.celcius, buf));
117123
#endif
118124
} else {
119125
#ifdef DEBUG_SENSORS
@@ -195,8 +201,7 @@ TemperatureReadout DS18B20Controller::getCelcius(uint8_t data[]) {
195201
}
196202

197203

198-
String formatTemperature(Temperature t) {
199-
char s[9];
204+
char *formatTemperature(Temperature t, char s[MAX_TEMPERATURE_STR_LEN]) {
200205
uint8_t deg = t / 100;
201206
uint8_t frac = t % 100;
202207
s[8] = '\0';
@@ -211,8 +216,7 @@ String formatTemperature(Temperature t) {
211216
return s;
212217
}
213218

214-
String formatTempSensorID(TempSensorID id) {
215-
char s[3*TEMP_SENSOR_ID_BYTES];
219+
char *formatTempSensorID(TempSensorID id, char s[MAX_TEMP_SENSOR_ID_STR_LEN]) {
216220
uint8_t pos = 0;
217221
for (uint8_t i=0; i<TEMP_SENSOR_ID_BYTES; i++) {
218222
sprintf(&s[pos], "%02X", id[i]);

sensors/OneWireSensors.h

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020
* States of a DS18B20 Temperature Sensor.
2121
*/
2222
typedef enum {
23-
SENSOR_INITIALISING = 1,
24-
SENSOR_ID_AUTO_ASSIGNED = 2, // a physical sensor was assigned to the logical sensor but it may not correspond to the intended sensor
25-
SENSOR_ID_UNDEFINED = 3, // no physical sensor could be found for the logical sensor
26-
SENSOR_OK = 4, // temperature value is defined and within the given range
27-
SENSOR_NOK = 5 // temperature value could not be obtained or is outside the given range
23+
SENSOR_INITIALISING = 0x1,
24+
SENSOR_ID_AUTO_ASSIGNED = 0x2, // a physical sensor was assigned to the logical sensor but it may not correspond to the intended sensor
25+
SENSOR_ID_UNDEFINED = 0x4, // no physical sensor could be found for the logical sensor
26+
SENSOR_OK = 0x8, // temperature value is defined and within the given range
27+
SENSOR_NOK = 0x10 // temperature value could not be obtained or is outside the given range
2828
} SensorStatusEnum;
2929

3030
typedef uint8_t SensorStatusID;
@@ -174,14 +174,19 @@
174174
TemperatureReadout getCelcius(uint8_t data[]);
175175
};
176176

177+
#define MAX_TEMPERATURE_STR_LEN 9
178+
177179
/**
178180
* Returns the temperature in a dotted notation, 8 chars + terminal '\0': ["-"]dd.ff"°C" (optional "-", d = degrees Celsius (2 digits), f = fraction (1 digit))
179181
*/
180-
String formatTemperature(Temperature t);
182+
char *formatTemperature(Temperature t, char buf[MAX_TEMPERATURE_STR_LEN]);
183+
181184

185+
#define MAX_TEMP_SENSOR_ID_STR_LEN (3*TEMP_SENSOR_ID_BYTES)
186+
182187
/*
183-
* Returns the ID in a dashed hex notation, e.g."28-8C-8C-79-6-0-0-89"
188+
* Returns the ID in a dashed hex notation, e.g."28-8C-8C-79-6-00-00-89"
184189
*/
185-
String formatTempSensorID(TempSensorID id);
190+
char *formatTempSensorID(TempSensorID id, char buf[MAX_TEMP_SENSOR_ID_STR_LEN]);
186191

187192
#endif

sensors/sensors.ino

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* ******* - virtual void reset_search();
1616
* ******* - virtual uint8_t search(uint8_t *newAddr, bool search_mode = true);
1717
*/
18-
#define MOCK_ONE_WIRE
18+
// #define MOCK_ONE_WIRE
1919

2020
//#define DEBUG_SENSORS_MAIN
2121

@@ -70,7 +70,7 @@ test(a_sensor_setup) {
7070
#endif
7171
uint8_t matched = controller.setupSensors();
7272
#ifndef MOCK_ONE_WIRE
73-
if (matched < 2) }
73+
if (matched < 2) {
7474
Serial.println(F("Cannot access one or more physical sensors -> check wiring."));
7575
}
7676
#endif
@@ -122,8 +122,9 @@ test(b_single_sensor_readout) {
122122
#ifdef MOCK_ONE_WIRE
123123
assertEqual(s1.currentTemp, 2300);
124124
#else
125+
char buf[MAX_TEMP_SENSOR_ID_STR_LEN];
125126
Serial.print(F("Temperature readout S1: "));
126-
Serial.println(formatTemperature(s1.currentTemp));
127+
Serial.println(formatTemperature(s1.currentTemp, buf));
127128
// assumed room temperature between 0 and 40°C:
128129
assertTrue(s1.currentTemp > 0);
129130
assertTrue(s1.currentTemp < 4000);
@@ -184,13 +185,14 @@ test(c_twin_sensor_readout) {
184185
assertEqual(s1.currentTemp, 2300);
185186
assertEqual(s2.currentTemp, 2400);
186187
#else
188+
char buf[MAX_TEMP_SENSOR_ID_STR_LEN];
187189
Serial.print(F("Temperature readout S1: "));
188-
Serial.println(formatTemperature(s1.currentTemp));
190+
Serial.println(formatTemperature(s1.currentTemp, buf));
189191
// assumed room temperature between 0 and 40°C:
190192
assertTrue(s1.currentTemp > 0);
191193
assertTrue(s1.currentTemp < 4000);
192194
Serial.print(F("Temperature readout S2: "));
193-
Serial.println(formatTemperature(s2.currentTemp));
195+
Serial.println(formatTemperature(s2.currentTemp, buf));
194196
// assumed room temperature between 0 and 40°C:
195197
assertTrue(s2.currentTemp > 0);
196198
assertTrue(s2.currentTemp < 4000);

0 commit comments

Comments
 (0)