Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to read 1byte data? #118

Open
Eugen4 opened this issue Dec 14, 2024 · 7 comments
Open

How to read 1byte data? #118

Eugen4 opened this issue Dec 14, 2024 · 7 comments

Comments

@Eugen4
Copy link

Eugen4 commented Dec 14, 2024

Installation specifics

  • Heating type: Vitotronic 200
  • Protocol: P300
  • Board: ESP8266 (Wemos D1 mini)

Symptom

Thank you for your project!
I'm making first steps with VitoWiFi v3 based on project's examples.

I was able to read 2byte temperature - VitoWiFi::Datapoint("T1", 0x0810, 2, VitoWiFi::div10)
Output was
Raw data received: a2 01
T1: 41.8

But I wasn't able to read 1byte temperature. I tryed different conversion types, but without success.

  • VitoWiFi::Datapoint("T2", 0x2306, 1, VitoWiFi::div10)
    Output was
    Raw data received: 0c
    T2: 1.2

  • VitoWiFi::Datapoint("T2", 0x2306, 1, VitoWiFi::noconv)
    Output was
    Raw data received: 0c
    T2: ON

Can you please edvise how to read and write 1byte data?

@bertmelis
Copy link
Owner

0C is 12 in decimal. Could that be the correct temperature?

How you print it in your Serial monitor is in your code. If you share the code, I can assist.

@Eugen4
Copy link
Author

Eugen4 commented Dec 14, 2024

Yes, it is correct. 12 degrees.

My code is almost the same as your example

#include <Arduino.h>

#include <VitoWiFi.h>
#include <SoftwareSerial.h>
const int sRX = D1; // software RX on D2(GPIO 4)
const int sTX = D2; // software TX on D1(GPIO 5)



EspSoftwareSerial::UART swSer(sRX, sTX);

// optolink on softwareserial, logging output on hardware UART

VitoWiFi::VitoWiFi<VitoWiFi::VS2> vitoWiFi(&swSer);
bool readValues = false;
uint8_t datapointIndex = 0;
uint8_t roomTemperature = 20;
bool writeRoomTemp = false;

VitoWiFi::Datapoint datapoints[] = {
  VitoWiFi::Datapoint("T0", 0x5525, 2, VitoWiFi::div10),
  VitoWiFi::Datapoint("T1", 0x0810, 2, VitoWiFi::div10),
  VitoWiFi::Datapoint("T2 A1M1", 0x2306, 1, VitoWiFi::noconv),
  VitoWiFi::Datapoint("T3 A1M1", 0x2307, 1, VitoWiFi::noconv),  
  VitoWiFi::Datapoint("T4 M2", 0x3306, 1, VitoWiFi::noconv),
  VitoWiFi::Datapoint("T5 M2", 0x3307, 1, VitoWiFi::noconv),
  VitoWiFi::Datapoint("T6 M3", 0x4306, 1, VitoWiFi::noconv),
  VitoWiFi::Datapoint("T7 M3", 0x4307, 1, VitoWiFi::noconv)
 
};

void setRoomTemp(uint8_t value) {
  roomTemperature = value;
  writeRoomTemp = true;
}

void onResponse(const VitoWiFi::PacketVS2& response, const VitoWiFi::Datapoint& request) {
  // raw data can be accessed through the 'response' argument
  Serial.print("Raw data received:");
  const uint8_t* data = response.data();
  for (uint8_t i = 0; i < response.dataLength(); ++i) {
    Serial.printf(" %02x", data[i]);
  }
  Serial.print("\n");

  // the raw data can be decoded using the datapoint. Be sure to use the correct type
  Serial.printf("%s: ", request.name());
  if (request.converter() == VitoWiFi::div10) {
    float value = request.decode(response);
    Serial.printf("%.1f\n", value);
  } else if (request.converter() == VitoWiFi::noconv) {
    float value = request.decode(response);
    // alternatively, we can just cast response.data()[0] to bool
    //Serial.printf("%s\n", value);
    Serial.printf("%f\n", value);
  }
}

void onError(VitoWiFi::OptolinkResult error, const VitoWiFi::Datapoint& request) {
  Serial.printf("Datapoint \"%s\" error: ", request.name());
  if (error == VitoWiFi::OptolinkResult::TIMEOUT) {
    Serial.print("timeout\n");
  } else if (error == VitoWiFi::OptolinkResult::LENGTH) {
    Serial.print("length\n");
  } else if (error == VitoWiFi::OptolinkResult::NACK) {
    Serial.print("nack\n");
  } else if (error == VitoWiFi::OptolinkResult::CRC) {
    Serial.print("crc\n");
  } else if (error == VitoWiFi::OptolinkResult::ERROR) {
    Serial.print("error\n");
  }
}

void setup() {
  delay(1000);
  Serial.begin(74880);
  Serial.print("Setting up vitoWiFi\n");

  vitoWiFi.onResponse(onResponse);
  vitoWiFi.onError(onError);
  vitoWiFi.begin();

  Serial.print("Setup finished\n");
}

void loop() {
  static uint32_t lastMillis = 0;
  if (millis() - lastMillis > 60000UL) {  // read all values every 60 seconds
    lastMillis = millis();
    readValues = true;
    Serial.println("readValues = true;");
    datapointIndex = 0;
  }

  if (readValues) {

  	Serial.print("Reading. Index = ");
  	Serial.println(datapointIndex);
    if (vitoWiFi.read(datapoints[datapointIndex])) {
      ++datapointIndex;
    } else Serial.println("NOT vitoWiFi.read");
    if (datapointIndex == 8) {
      readValues = false;
      Serial.println("readValues = false;");
    }
  }

  vitoWiFi.loop();
}

The second question: is this a normal output? A lot of NOT vitoWiFi.read, but all datapoints (raw data) has been read correctly

state 3 --> 4
readValues = true;
Reading. Index = 0
reading packet OK
state 4 --> 5
Reading. Index = 1
NOT vitoWiFi.read
state 5 --> 6
Reading. Index = 1
NOT vitoWiFi.read
state 6 --> 7
Reading. Index = 1
NOT vitoWiFi.read
state 7 --> 8
Reading. Index = 1
NOT vitoWiFi.read
Reading. Index = 1
NOT vitoWiFi.read
Reading. Index = 1
NOT vitoWiFi.read
rcv: 0x06
state 8 --> 9
Reading. Index = 1
NOT vitoWiFi.read
Reading. Index = 1
NOT vitoWiFi.read
Reading. Index = 1
NOT vitoWiFi.read
Reading. Index = 1
NOT vitoWiFi.read
state 9 --> 10
Raw data received: bd ff
T0: -6.7
Reading. Index = 1
reading packet OK
state 10 --> 4
Reading. Index = 2
NOT vitoWiFi.read
state 4 --> 5
Reading. Index = 2
NOT vitoWiFi.read
state 5 --> 6
Reading. Index = 2
NOT vitoWiFi.read
state 6 --> 7
Reading. Index = 2
NOT vitoWiFi.read
state 7 --> 8

@bertmelis
Copy link
Owner

Yes, it is correct. 12 degrees.

So the response is correct.

It comes down to matching the response to the right output formatting. You could distinguish by datapoint name or by datapoint address:

void onResponse(const VitoWiFi::PacketVS2& response, const VitoWiFi::Datapoint& request) {
  // raw data can be accessed through the 'response' argument
  Serial.print("Raw data received:");
  const uint8_t* data = response.data();
  for (uint8_t i = 0; i < response.dataLength(); ++i) {
    Serial.printf(" %02x", data[i]);
  }
  Serial.print("\n");

  // Now we have different methods of printing the value.
  Serial.printf("%s: ", request.name());
  if (request.address() == 0x2306) {  // you might want to include all relevant addresses here?
    Serial.printf("%u\n", response.data()[0]);
    return;
  }
  if (request.converter() == VitoWiFi::div10) {
    float value = request.decode(response);
    Serial.printf("%.1f\n", value);
    return;
  }
  if (request.converter() == VitoWiFi::noconv) {
    float value = request.decode(response);
    // alternatively, we can just cast response.data()[0] to bool
    //Serial.printf("%s\n", value);
    Serial.printf("%f\n", value);
    return;
  }
}

@Eugen4
Copy link
Author

Eugen4 commented Dec 15, 2024

@bertmelis, thanks alot. I will try this soon.

@bertmelis
Copy link
Owner

Alternatively, you define the datapoints outside the array. Then you create an array of pointers to the datapoints.

VitoWiFi::Datapoint T0("T0", 0x5525, 2, VitoWiFi::div10);
VitoWiFi::Datapoint T1("T1", 0x0810, 2, VitoWiFi::div10);
VitoWiFi::Datapoint T2_A1M1("T2 A1M1", 0x2306, 1, VitoWiFi::noconv);

VitoWiFi::Datapoint* datapoints[] = {
  T0, T1, T2
}; 

Then you have to dereference the pointer when reading/writing the datapoint:

vitoWiFi.read(datapoints[datapointIndex])
// becomes
vitoWiFi.read(*datapoints[datapointIndex])

In the callback you can check using pointer/address equality.

if (&request == &T0 ||
    &request == &T1) {
  // div10 conversion, display float
} else if (&request == & T2_A1M1) {
  // noconv, display int
}

@Eugen4
Copy link
Author

Eugen4 commented Dec 24, 2024

@bertmelis thank you for support, I was able to read 1byte data.

Do I need to change something in following code to write data?

if (writeRoomTemp1) {
    if (vitoWiFi.write(datapoints[1], Temperature1)) { // this section for 1byte noconv
      writeRoomTemp1 = false;
    }
  }
if (writeRoomTemp2) {
    if (vitoWiFi.write(datapoints[2], Temperature2)) { / // this section for 2byte div10
      writeRoomTemp2 = false;
    }
  }

@bertmelis
Copy link
Owner

Consult the table in the README: https://github.com/bertmelis/VitoWiFi?tab=readme-ov-file#conversion-types

A 1-byte noconv datapoint can be written to by using an uint8_t. A 2-byte div10 datapoint expects a float.

So in your code snippet, Temperature1 needs to be uint8_t and Temperature2 needs to be float.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants