For a project we want to be able to monitor a boiler via OpenTherm. I got the shield from Jiří Praus and it works.
Only the data i am seeing in the serial monitor doesnt match. For example, when i request data ID24 (Room temperature) the thermostat shows 24 degrees and in the serial monitor it says 17F8... It does this with some other values too.
Is there someone that can help me get the right values? Or tell me what i should do?
#include <opentherm.h>
// Wemos D1 R1
#define THERMOSTAT_IN 16
#define THERMOSTAT_OUT 4
#define BOILER_IN 5
#define BOILER_OUT 14
// Arduino UNO
//#define THERMOSTAT_IN 2
//#define THERMOSTAT_OUT 4
//#define BOILER_IN 3
//#define BOILER_OUT 5
OpenthermData message;
void setup() {
pinMode(THERMOSTAT_IN, INPUT);
digitalWrite(THERMOSTAT_IN, HIGH); // pull up
digitalWrite(THERMOSTAT_OUT, HIGH);
pinMode(THERMOSTAT_OUT, OUTPUT); // low output = high current, high output = low current
pinMode(BOILER_IN, INPUT);
digitalWrite(BOILER_IN, HIGH); // pull up
digitalWrite(BOILER_OUT, HIGH);
pinMode(BOILER_OUT, OUTPUT); // low output = high voltage, high output = low voltage
Serial.begin(115200);
}
#define MODE_LISTEN_MASTER 0
#define MODE_LISTEN_SLAVE 1
int mode = 0;
/**
* Loop will act as man in the middle connected between Opentherm boiler and Opentherm thermostat.
* It will listen for requests from thermostat, forward them to boiler and then wait for response from boiler and forward it to thermostat.
* Requests and response are logged to Serial on the way through the gateway.
*/
void loop() {
if (mode == MODE_LISTEN_MASTER) {
if (OPENTHERM::isSent() || OPENTHERM::isIdle() || OPENTHERM::isError()) {
OPENTHERM::listen(THERMOSTAT_IN);
}
else if (OPENTHERM::getMessage(message)) {
Serial.print("-> ");
OPENTHERM::printToSerial(message);
Serial.println();
OPENTHERM::send(BOILER_OUT, message); // forward message to boiler
mode = MODE_LISTEN_SLAVE;
}
}
else if (mode == MODE_LISTEN_SLAVE) {
if (OPENTHERM::isSent()) {
OPENTHERM::listen(BOILER_IN, 800); // response need to be send back by boiler within 800ms
}
else if (OPENTHERM::getMessage(message)) {
Serial.print("<- ");
OPENTHERM::printToSerial(message);
Serial.println();
Serial.println();
OPENTHERM::send(THERMOSTAT_OUT, message); // send message back to thermostat
mode = MODE_LISTEN_MASTER;
}
else if (OPENTHERM::isError()) {
mode = MODE_LISTEN_MASTER;
Serial.println("<- Timeout");
Serial.println();
}
}
}

non-integer values are often represented by integers multiplied by a constant which is often a power of 2. horace was quick to not that 0x17 is 23 decimal. the 0xf8 is the fractional value.
looking at 0x17f8 the first byte 0x17 may represent the whole number of the second byte 0xF8 the fractional component
this is just a guess - maybe completly wrong - check the conversions against a thermometer
thinking again the converion may be
The code now only takes the message send by the the boiler or thermostat and prints it on the serial monitor.
I for example want to convert the data with ID 25. The first number is the ID (25 in this case) and after that is the data. How can i tell the arduino that he only need to take the data after the ID, convert it and print it as degrees.
else if (mode == MODE_LISTEN_SLAVE) {
if (OPENTHERM::isSent()) {
OPENTHERM::listen(BOILER_IN, 800); // response need to be send back by boiler within 800ms
}
else if (OPENTHERM::getMessage(message)) {
Serial.print("<- ");
OPENTHERM::printToSerial(message);
float f88();
Serial.println();