Converting float back to single hex bytes[SOLVED]

I'm working on a little project to get data from Acuity Battery Monitoring System from Curtis. I'm receiving all the data that I need correctly and converting the values to show the actual battery voltage, current and temperature. I want to mock this code on an Uno because the unit is on site and I need to work from home on it, So the idea is to make a mock up unit so I can carry on working on the project at home as I need to add or stuff and send this data to a server.
Master unit will be an EPS32 and slave ( Acuity mock).

My aim is to send the exact same data format that I get form the Acuity Battery Monitoring from the uno through canbus to the master, My thoughts/idea is where I can adjust the decimal value the convert it back into the exact data format.

So the 2 first bytes 0XB6 and 0XB0 once converted reads 29.98, I want to adjust the 29 and convert it back to HEX format before sending it back out onto the canbus.

The code below is a working sample data coming in with known values where I convert it to a readable format.

uint32_t identifier = 426; //olny get data from this address
uint16_t voltage = 0;
byte rx_frame[8] = {0XB6, 0X0B, 0XC5, 0X01, 0XC5, 0X0B, 0XB1, 0X00};//incoming data from  Acuity Battery Monitoring Systembattery monitor
int16_t current = 0, temperature = 0;
float voltagefloat = 0, currentfloat = 0, temperaturefloat = 0;

void setup() {

  // start Serial communication
  Serial.begin(9600);
  voltage = (rx_frame[1] << 8) + rx_frame[0]; //convert to decimal
  current = (rx_frame[3] << 8) + rx_frame[2]; //convert to decimal
  temperature = (rx_frame[5] << 8) + rx_frame[4];//convert to decimal
  voltagefloat = voltage * 0.01; // value to times by
  currentfloat = current * 0.01; // value to times by
  temperaturefloat = temperature * 0.01; // value to times by
  Serial.print("Voltage = ");
  Serial.print(voltagefloat);
  Serial.print(" , Current = ");
  Serial.print(currentfloat);
  Serial.print(" , temperature = ");
  Serial.println(temperaturefloat);



}

void loop() {

}

So the question is how do I convert the flaot back to HEX format like this

0XB6, 0X0B, 0XC5, 0X01, 0XC5, 0X0B, 0XB1, 0X00

uint16_t value = fValue * 100;
uint8_t lowB = value;
uint8_t highB = value >> 8;

Looks like the data is sent as 16-bit integers, little endian, with the integers representing the value in hundredths. What are the last two bytes used for?

Hi sorry I forgot to attach a picture of the data format.
byte 1&2 are battery voltage,byte 3&4 are battery current,byte 5&6 are temperature byte 7 not used and byte 8 is the state of discharge(SoC).
Yes tehy are 16 bit integer.

I've looked at tried your code, And just working on the voltage side of things first and this is what I get from the serial port.

Voltage = 29.98 , Current = 4.53 , temperature = 30.13
 , LOW BYTE HEX = B6
 , HIGH BYTE HEX = B
 , LOW BYTE INT = 182
 , HIGH BYTE INT = 11

latest code:


uint32_t identifier = 426; //olny get data from this address
uint16_t voltage = 0;
byte rx_frame[8] = {0XB6, 0X0B, 0XC5, 0X01, 0XC5, 0X0B, 0XB1, 0X00};//incoming data from battery monitor
int16_t current = 0, temperature = 0;
float voltagefloat = 0, currentfloat = 0, temperaturefloat = 0;

void setup() {

  // start Serial communication
  Serial.begin(9600);
  voltage = (rx_frame[1] << 8) + rx_frame[0]; //convert to decimal
  current = (rx_frame[3] << 8) + rx_frame[2]; //convert to decimal
  temperature = (rx_frame[5] << 8) + rx_frame[4];//convert to decimal
  voltagefloat = voltage * 0.01; // value to times by
  currentfloat = current * 0.01; // value to times by
  temperaturefloat = temperature * 0.01; // value to times by
  Serial.print("Voltage = ");
  Serial.print(voltagefloat);
  Serial.print(" , Current = ");
  Serial.print(currentfloat);
  Serial.print(" , temperature = ");
  Serial.println(temperaturefloat);
 uint16_t value = voltagefloat *100;
 uint8_t lowb= value ;
 uint8_t highb = value >>8;
 Serial.print(" , LOW BYTE HEX = ");
  Serial.println(lowb,HEX);
  Serial.print(" , HIGH BYTE HEX = ");
  Serial.println(highb,HEX);
  Serial.print(" , LOW BYTE INT = ");
  Serial.println(lowb);
  Serial.print(" , HIGH BYTE INT = ");
  Serial.println(highb);
 


}

void loop() {

}

So that looks correct bu how can I add those to a char to send out the correct format like 0XB6 and 0X0B so that I can get to then send it over Canbus lines

Thanks
Steve

Since the data is in a nice binary format that is compatible with the UNO, I would not mess with converting the individual bytes. Define a struct that matches the data structure, manipulate the values in that, and send the struct to the CAN bus.

byte rx_frame[8] = {0XB6, 0X0B, 0XC5, 0X01, 0XC5, 0X0B, 0XB1, 0X00};//incoming data from battery monitor

struct {
  uint16_t voltage;
  int16_t current;
  int16_t temperature;
  uint8_t unused;
  uint8_t stateOfCharge;
} pdo1;

void setup() {

  // start Serial communication
  Serial.begin(9600);

  memcpy(&pdo1, rx_frame, sizeof(pdo1));
  
  Serial.print("Voltage = ");
  Serial.print(pdo1.voltage / 100.0);
  Serial.print(" , Current = ");
  Serial.print(pdo1.current / 100.0);
  Serial.print(" , temperature = ");
  Serial.print(pdo1.temperature / 100.0);
  Serial.print(" , state of charge = ");
  Serial.print(pdo1.stateOfCharge);
  Serial.println('%');

  //print hex values
  uint8_t* ptr = (uint8_t*)&pdo1;
  for (size_t i = 0; i < sizeof(pdo1); i++) {
    if (*ptr < 0x10) Serial.print('0');
    Serial.print(*ptr, HEX);
    Serial.print(' ');
    ptr++;
  }
  Serial.println();

  //change values
  pdo1.voltage = 30.01 * 100.0;
  pdo1.current = 7.91 * 100.0;
  pdo1.temperature = 25.62 * 100.0;

  Serial.print("Voltage = ");
  Serial.print(pdo1.voltage / 100.0);
  Serial.print(" , Current = ");
  Serial.print(pdo1.current / 100.0);
  Serial.print(" , temperature = ");
  Serial.print(pdo1.temperature / 100.0);
  Serial.print(" , state of charge = ");
  Serial.print(pdo1.stateOfCharge);
  Serial.println('%');

  //print hex values
  ptr = (uint8_t*)&pdo1;
  for (size_t i = 0; i < sizeof(pdo1); i++) {
    if (*ptr < 0x10) Serial.print('0');
    Serial.print(*ptr, HEX);
    Serial.print(' ');
    ptr++;
  }
  Serial.println();

  //probable way to send data to the can bus
  //CAN.write((uint8_t*)&pdo1, sizeof(pdo1));

}

void loop() {

}

Thank you David, This works a treat and is far more elegant way of doing it and easy to understand and follow.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.