Skip to content

Commit 031466f

Browse files
Sensors subproject integrated, not tested
- still missing a command to confirm / swap auto-assigned sensor ids
1 parent 889a519 commit 031466f

18 files changed

+117
-171
lines changed

bc_setup.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
#ifndef BOILER_BC_SETUP_H_INCLUDED
2-
#define BOILER_BC_SETUP_H_INCLUDED
1+
#ifndef BC_SETUP_H_INCLUDED
2+
#define BC_SETUP_H_INCLUDED
33

4-
// Uncomment ONE (!) of the following lines:
5-
#define UNIT_TEST
4+
// Uncomment AT MOST ONE (!) of the following lines:
5+
// #define UNIT_TEST
66
// #define BLE_UI
77
// #define SERIAL_UI
88

boiler_controller.ino

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
#include "bc_setup.h"
2-
#ifdef UNIT_TEST
3-
#include <ArduinoUnit.h>
4-
#endif
52
#include "math.h"
63
#include "control.h"
74
#include "state.h"
@@ -10,6 +7,8 @@
107
#include "ui_ser.h"
118
#elif defined BLE_UI
129
#include "ui_ble.h"
10+
#elif defined UNIT_TEST
11+
#include <ArduinoUnit.h>
1312
#endif
1413

1514
//#define DEBUG_MAIN
@@ -31,9 +30,13 @@ typedef enum {
3130
/*
3231
* GLOBALS
3332
*/
34-
ConfigParams config = ConfigParams();
35-
Log logger = Log(sizeof(ConfigParams));
33+
ConfigParams configParams = ConfigParams();
34+
Log logger = Log(configParams.eepromSize());
3635
OperationalParams opParams;
36+
DS18B20TemperatureSensor *sensors[] = {&opParams.water, &opParams.ambient};
37+
OneWire oneWire = OneWire(ONE_WIRE_PIN); // on pin 10 (a 4.7K pull-up resistor to +5V is necessary)
38+
DS18B20Controller controller = DS18B20Controller(&oneWire, sensors, 2);
39+
3740
ExecutionContext context;
3841
ControlActions controlActions = ControlActions(&context);
3942
BoilerStateAutomaton automaton = BoilerStateAutomaton(&context);
@@ -60,11 +63,12 @@ void setup() {
6063
#else
6164
logger.init();
6265
logger.logMessage(MSG_SYSTEM_INIT, 0, 0);
63-
config.load();
66+
configParams.load();
6467

6568
context.log = &logger;
66-
context.config = &config;
69+
context.config = &configParams;
6770
context.op = &opParams;
71+
context.controller = &controller;
6872
context.control = &controlActions;
6973

7074
pinMode(HEATER_PIN, OUTPUT);

config.h

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,8 @@
1-
#ifndef BOILER_CONFIG_H_INCLUDED
2-
#define BOILER_CONFIG_H_INCLUDED
1+
#ifndef BC_CONFIG_H_INCLUDED
2+
#define BC_CONFIG_H_INCLUDED
33

44
#include "config/Configuration.h"
5-
6-
/*
7-
typedef int16_t Temperature; // [°C * 100]
8-
#define UNDEFINED_TEMPERATURE -10000 // [°C * 100];
9-
10-
#define TEMP_SENSOR_ID_BYTES 8
11-
typedef uint8_t TempSensorID[TEMP_SENSOR_ID_BYTES];
12-
const TempSensorID UNDEFINED_SENSOR_ID = {0,0,0,0,0,0,0,0};
13-
14-
*/
15-
// Water min and max values used to check that sensor-temperature readout is plausible:
16-
#define WATER_MIN_TEMP -2000 // [°C * 100]
17-
#define WATER_MAX_TEMP 10000 // [°C * 100]
18-
19-
// Water min and max values used to check that ambient-temperature readout is plausible:
20-
#define AMBIENT_MIN_TEMP -3000 // [°C * 100]
21-
#define AMBIENT_MAX_TEMP 5000 // [°C * 100]
5+
#include "sensors/OneWireSensors.h"
226

237
/*
248
* ID values are defined by ConfigParamEnum.

control.cpp

Lines changed: 28 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -11,106 +11,52 @@ uint32_t heatingTotalMillis(OperationalParams *op) {
1111
return duration;
1212
}
1313

14-
boolean undefinedSensorId(TempSensorID addr) {
15-
return ! memcmp(addr, UNDEFINED_SENSOR_ID, TEMP_SENSOR_ID_BYTES);
16-
}
17-
18-
boolean isWaterSensor(TempSensorID addr, ConfigParams *config) {
19-
return ! memcmp(addr, config->waterTempSensorId, TEMP_SENSOR_ID_BYTES);
20-
}
21-
22-
boolean isAmbientSensor(TempSensorID addr, ConfigParams *config) {
23-
return ! memcmp(addr, config->ambientTempSensorId, TEMP_SENSOR_ID_BYTES);
24-
}
2514

26-
27-
28-
void ControlActions::setupSensors() {
29-
if (undefinedSensorId(context->config->waterTempSensorId)) {
30-
context->op->water.sensorStatus = SENSOR_ID_UNDEFINED;
15+
uint8_t ControlActions::setupSensors() {
16+
context->op->water.setId(context->config->waterTempSensorId);
17+
context->op->water.rangeMin = WATER_MIN_TEMP;
18+
context->op->water.rangeMax = WATER_MAX_TEMP;
19+
20+
context->op->ambient.setId(context->config->ambientTempSensorId);
21+
context->op->ambient.rangeMin = AMBIENT_MIN_TEMP;
22+
context->op->ambient.rangeMax = AMBIENT_MAX_TEMP;
23+
24+
uint8_t matched = context->controller->setupSensors();
25+
26+
if (context->op->water.sensorStatus == SENSOR_ID_UNDEFINED) {
3127
context->log->logMessage(MSG_WATER_TEMP_SENSOR_ID_UNDEF, 0, 0);
3228
#ifdef DEBUG_CONTROL
3329
Serial.println(F("DEBUG_CONTROL: Water temp sensor ID undefined"));
3430
#endif
31+
} else if (context->op->water.sensorStatus == SENSOR_ID_AUTO_ASSIGNED) {
32+
context->log->logMessage(MSG_WATER_TEMP_SENSOR_ID_AUTO, 0, 0);
33+
#ifdef DEBUG_CONTROL
34+
Serial.println(F("DEBUG_CONTROL: Water temp sensor ID assigned automatically."));
35+
#endif
3536
}
3637

37-
if (undefinedSensorId(context->config->ambientTempSensorId)) {
38-
context->op->ambient.sensorStatus = SENSOR_ID_UNDEFINED;
39-
context->log->logMessage(MSG_AMBIENT_TEMP_SENSOR_ID_UNDEF, 0, 0);
38+
if (context->op->ambient.sensorStatus == SENSOR_ID_UNDEFINED) {
39+
context->log->logMessage(MSG_AMBIENT_TEMP_SENSOR_ID_UNDEF, 0, 0);
4040
#ifdef DEBUG_CONTROL
4141
Serial.println(F("DEBUG_CONTROL: Ambient temp sensor ID undefined"));
4242
#endif
43-
}
43+
} else if (context->op->ambient.sensorStatus == SENSOR_ID_AUTO_ASSIGNED) {
44+
context->log->logMessage(MSG_AMBIENT_TEMP_SENSOR_ID_AUTO, 0, 0);
45+
#ifdef DEBUG_CONTROL
46+
Serial.println(F("DEBUG_CONTROL: Ambient temp sensor ID assigned automatically."));
47+
#endif
48+
}
4449

45-
//
46-
// CONSIDER: set sensor resolution
47-
// CONSIDER: detect sensors and store IDs for user to choose which sensor is which
50+
return matched;
4851
}
4952

5053
void ControlActions::initSensorReadout() {
51-
oneWire.reset();
52-
// Talk to all slaves on bus:
53-
oneWire.skip();
54-
// Start temp readout and conversion to scratchpad, with parasite power on at the end
55-
oneWire.write(CMD_CONVERT_TEMP, 1);
56-
//
57-
// Important: do not oneWire.reset() now for at least 750 ms (for 12-bit temperature resolution)
58-
//
54+
context->controller->initSensorReadout();
5955
}
6056

6157

6258
void ControlActions::completeSensorReadout() {
63-
context->op->water.sensorStatus = SENSOR_NOK;
64-
context->op->water.currentTemp = UNDEFINED_TEMPERATURE;
65-
context->op->ambient.sensorStatus = SENSOR_NOK;
66-
context->op->ambient.currentTemp = UNDEFINED_TEMPERATURE;
67-
68-
uint8_t addr[TEMP_SENSOR_ID_BYTES];
69-
70-
while(oneWire.search(addr)) {
71-
if (OneWire::crc8(addr, TEMP_SENSOR_ID_BYTES-1) != addr[TEMP_SENSOR_ID_BYTES-1]) {
72-
continue;
73-
}
74-
75-
uint8_t data[TEMP_SENSOR_READOUT_BYTES];
76-
if (! readScratchpad(addr, &data[0])) {
77-
continue;
78-
}
79-
TemperatureReadout readout = getCelcius(data);
80-
81-
if (isWaterSensor(addr, context->config)) {
82-
// Ensure temperature is plausible:
83-
if( readout.celcius >= WATER_MIN_TEMP && readout.celcius <= WATER_MAX_TEMP) {
84-
context->op->water.sensorStatus = SENSOR_OK;
85-
context->op->water.currentTemp = readout.celcius;
86-
#ifdef DEBUG_CONTROL
87-
Serial.print(F("DEBUG_CONTROL: Water: Sensor OK, temp: "));
88-
Serial.println(readout.celcius);
89-
#endif
90-
}
91-
#ifdef DEBUG_CONTROL
92-
else {
93-
Serial.println(F("DEBUG_CONTROL: Water: Sensor NOK"));
94-
}
95-
#endif
96-
} else if (isAmbientSensor(addr, context->config)) {
97-
// Ensure temperature is plausible:
98-
if( readout.celcius >= AMBIENT_MIN_TEMP && readout.celcius <= AMBIENT_MAX_TEMP) {
99-
context->op->ambient.sensorStatus = SENSOR_OK;
100-
context->op->ambient.currentTemp = readout.celcius;
101-
#ifdef DEBUG_CONTROL
102-
Serial.print("DEBUG_CONTROL: Ambient: Sensor OK, temp: "));
103-
Serial.println(readout.celcius);
104-
#endif
105-
}
106-
#ifdef DEBUG_CONTROL
107-
else {
108-
Serial.println(F("DEBUG_CONTROL: Ambient: Sensor NOK"));
109-
}
110-
#endif
111-
}
112-
}
113-
oneWire.reset_search();
59+
context->controller->completeSensorReadout();
11460
}
11561

11662
void ControlActions::heat(boolean on) {

control.h

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
1-
#ifndef BOILER_CONTROL_H_INCLUDED
2-
#define BOILER_CONTROL_H_INCLUDED
1+
#ifndef BC_CONTROL_H_INCLUDED
2+
#define BC_CONTROL_H_INCLUDED
33

44
#include "bc_setup.h"
5-
#include <OneWire.h>
65
#include "config.h"
76
#include "log.h"
87

98
#define HEATER_PIN 9
109
#define ONE_WIRE_PIN 10 // Temperature sensors
1110

1211
typedef enum {
13-
MSG_WATER_TEMP_SENSOR_ID_UNDEF = 20, // Sensor ID of water-temperature sensor has not been configured. Configure and restart.
14-
MSG_AMBIENT_TEMP_SENSOR_ID_UNDEF = 21 // Sensor ID of ambient-temperature sensor has not been configured. Configure and restart.
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.
1516
} ControlMessageEnum;
1617

18+
19+
// Water min and max values used to check that sensor-temperature readout is plausible:
20+
#define WATER_MIN_TEMP -2000 // [°C * 100]
21+
#define WATER_MAX_TEMP 10000 // [°C * 100]
22+
23+
// Water min and max values used to check that ambient-temperature readout is plausible:
24+
#define AMBIENT_MIN_TEMP -3000 // [°C * 100]
25+
#define AMBIENT_MAX_TEMP 5000 // [°C * 100]
1726

1827
#define CMD_ARG_BUF_SIZE 30 // Size of the read buffer for incoming data
1928

@@ -48,22 +57,6 @@
4857
// bitwise OR combination ("|") of ReadWriteRequestEnum(s)
4958
typedef uint8_t ReadWriteRequests;
5059

51-
typedef enum {
52-
SENSOR_INITIALISING = 0,
53-
SENSOR_OK = 1,
54-
SENSOR_NOK = 2,
55-
SENSOR_ID_UNDEFINED = 3
56-
} SensorStatusEnum;
57-
58-
typedef uint8_t SensorStatusID;
59-
60-
struct TemperatureSensor {
61-
SensorStatusEnum sensorStatus = SENSOR_INITIALISING;
62-
Temperature currentTemp = UNDEFINED_TEMPERATURE;
63-
Temperature lastLoggedTemp = UNDEFINED_TEMPERATURE;
64-
uint32_t lastLoggedTime = 0L;
65-
};
66-
6760
struct UserCommand {
6861
UserCommandEnum command = CMD_NONE;
6962
char args[CMD_ARG_BUF_SIZE]; // always '\0' terminated
@@ -72,8 +65,8 @@
7265
struct OperationalParams {
7366
// timepoint [ms] of most recent transition to current state:
7467
uint32_t currentStateStartMillis = 0L;
75-
TemperatureSensor water;
76-
TemperatureSensor ambient;
68+
DS18B20TemperatureSensor water = DS18B20TemperatureSensor("Water");
69+
DS18B20TemperatureSensor ambient = DS18B20TemperatureSensor("Ambient");
7770
UserCommand *command;
7871
boolean heating = false;
7972
// time [ms] of most recent transition to state HEATING:
@@ -93,6 +86,7 @@
9386
Log *log;
9487
ConfigParams *config;
9588
OperationalParams *op;
89+
DS18B20Controller *controller;
9690
};
9791

9892
/*
@@ -105,7 +99,7 @@
10599
ControlActions(ControlContext *context) {
106100
this->context = context;
107101
}
108-
virtual void setupSensors();
102+
virtual uint8_t setupSensors();
109103
virtual void initSensorReadout();
110104
virtual void completeSensorReadout();
111105

@@ -124,7 +118,6 @@
124118

125119
protected:
126120
ControlContext *context;
127-
OneWire oneWire = OneWire(ONE_WIRE_PIN); // on pin 10 (a 4.7K pull-up resistor to +5V is necessary)
128121
ReadWriteRequests pendingRequests = READ_WRITE_NONE;
129122
};
130123

log.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#ifndef BOILER_LOG_H_INCLUDED
2-
#define BOILER_LOG_H_INCLUDED
1+
#ifndef BC_LOG_H_INCLUDED
2+
#define BC_LOG_H_INCLUDED
33

44
#include "config.h"
55
#include "log/Logging.h"

sensor/sensors/OneWireSensors.cpp renamed to sensors/OneWireSensors.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,6 @@
1717
*/
1818
#define DATA_CONFIG_BYTE 4
1919

20-
boolean isUndefinedTempSensorID(TempSensorID addr) {
21-
return ! memcmp(addr, UNDEFINED_SENSOR_ID, TEMP_SENSOR_ID_BYTES);
22-
}
23-
2420
uint8_t DS18B20Controller::setupSensors() {
2521
for(uint8_t i=0; i<numSensors; i++) {
2622
if(sensors[i]->idUndefined()) {

sensor/sensors/OneWireSensors.h renamed to sensors/OneWireSensors.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
#define TEMP_SENSOR_ID_BYTES 8
1111
typedef uint8_t TempSensorID[TEMP_SENSOR_ID_BYTES];
1212
const TempSensorID UNDEFINED_SENSOR_ID = {0,0,0,0,0,0,0,0};
13-
14-
boolean isUndefinedTempSensorID(TempSensorID addr);
1513

1614
/*
1715
* Number of bytes of data vector returned by the DS18B20: 8 byte data + 1 byte CRC
@@ -67,6 +65,13 @@
6765
* Returns true if the ID of this sensor is UNDEFINED_SENSOR_ID, i.e. this object does represent a physical sensor.
6866
*/
6967
boolean idUndefined() {
68+
return idUndefined(this->id);
69+
}
70+
71+
/*
72+
* Returns true if the given is UNDEFINED_SENSOR_ID.
73+
*/
74+
static boolean idUndefined(const TempSensorID id) {
7075
return ! memcmp(id, UNDEFINED_SENSOR_ID, TEMP_SENSOR_ID_BYTES);
7176
}
7277
};

sensor/sensors/sensors.ino renamed to sensors/sensors.ino

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,17 @@ test(a_sensor_setup) {
6969
oneWire._setSearchResults((uint8_t *) SENSOR_IDS, 2);
7070
#endif
7171
uint8_t matched = controller.setupSensors();
72+
#ifndef MOCK_ONE_WIRE
73+
if (matched < 2) }
74+
Serial.println(F("Cannot access one or more physical sensors -> check wiring."));
75+
}
76+
#endif
7277
assertEqual(matched, 2);
7378
assertEqual(s1.sensorStatus, SENSOR_ID_AUTO_ASSIGNED);
7479
assertEqual(s2.sensorStatus, SENSOR_ID_AUTO_ASSIGNED);
7580
assertEqual(s3.sensorStatus, SENSOR_ID_UNDEFINED);
7681
#ifdef MOCK_ONE_WIRE
82+
// check that the sensor IDs were "recognized" (mocking) correctly:
7783
assertTrue(! memcmp(s1.id, SENSOR_IDS[0], TEMP_SENSOR_ID_BYTES));
7884
assertTrue(! memcmp(s2.id, SENSOR_IDS[1], TEMP_SENSOR_ID_BYTES));
7985
#else

0 commit comments

Comments
 (0)