Opentherm values not right?

Hello!

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();
    }
  }
}
![Schermafbeelding 2022-04-05 152643|690x248](upload://jdn6gL5QQB9PKVnZRm7ZvNbtT0S.png)

could 0x17f8 be 23.248degrees?

give some more examples?

Sorry for my late response.

That could be right!

Another example was getting the value for the feed water temperture. I get following: 27C5 and 27DC.

Could you explain how you got the 23,48 degrees out of the 17F8?

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.

divide 0x17f8 which is 6136 decimal by 256

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

void setup() {
  Serial.begin(115200);
  int t=0x17f8;
  float temp=(t>>8) + (t & 0xff)/255.0;
  Serial.println(temp);
}

void loop() {}

which gives 0x17F8 as 23.97degrees and 0x27C5 as 39.77degrees

Really thank you!

How can i implement the conversion that all data i receive is converted and readable in the serial monitor?

I now see the data as follow:

void setup() {
    Serial.begin (9600);

    char  s [20];
    int   t = 0x17f8;
    float f = t / 256.0;

    dtostrf (f, 6, 2, s);
    Serial.println (s);
}

void loop () {
}

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.

I think you can call the f88() method , see opentherm.h

But how can i call the f88() methode in such a way all my data (temps) are gonna be readable?

I already really appreciate your help!

could you show us the serial monitor output of a run of your program

Dear horace!

I should have posted a screenshot of the serial monitor output already. But i will post it again.

possibly call f88() so

    else if (OPENTHERM::getMessage(message)) {
      Serial.print("-> ");
      OPENTHERM::printToSerial(message);
      Serial.print("temperature ");
      Serial.println(OPENTHERM::f88());
      Serial.println();
      OPENTHERM::send(BOILER_OUT, message); // forward message to boiler
      mode = MODE_LISTEN_SLAVE;
    }

Hi Horace!

I get following error when i try that: 'f88' is not a member of 'OPENTHERM'

this indeed does work! Only thing is that i cant manually put in the values...

f88 is a method in the message, not OPENTHERM itself.

yes i found that out. But how can i use it? I added the f88 function to my code but still cant see the decoded data in the serial monitor.

Could you maybe explain or show it to me?

What did you try?

I tried this and some other things i didnt save.

  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();

Try

Serial.print("<- ");
OPENTHERM::printToSerial(message);
Serial.print(" ");
Serial.print(message.f88());
Serial.println();

Not tested or even compiled.

1 Like