convert Hex result of sensor to integer value

Hello,

I am interfaceing with an sensor over the Serial interface.

I have to send hex data to the sensor, to initiate the communication...

(0x55 0xAA 0x7E 0x02 0x4F 0x43 0x94 0x0E 0x0D)

Well so far I have managed to do it:

byte message[] = {0x55, 0xAA, 0x7E, 0x02, 0x4F, 0x43, 0x94, 0x0E, 0x0D };
Serial.write(message, sizeof(message));

This is the description of the answer of this device:

answer:

0x55 0xAA 0x7E 0x04 0x4F 0x43 MSB LSB SUM XOR 0x0D

Function: Query the measurement result

Description:

For example: return 11 bytes, where the first 7 and 8 are directly oxygen concentration, the measurement result = (high byte * 256 + low byte) / (10).

Byte SUM is the cumulative value of bits 4, 5, 6, 7, 8 bytes, and the tenth byte XOR is the exclusive-OR value of bits 4, 5, 6, 7, 8 bits. E.g

The return data is:

0x55 0xAA 0x7E 0x04 0x4F 0x43 0x03 0xB4 0x4D 0xBF 0x0D

Results (O2) = 0x03B4 (hexadecimal) = 948, the concentration value was 94.8%

Can someone help me write up the code to interpret the result?

0x55 0xAA 0x7E 0x04 0x4F 0x43 0x03 0xB4 0x4D 0xBF 0x0D
0x03 0xB4

I know that these two values represent the sensor data, that I am looking for, however I am clueless how I get a hold on that.

Thanks,

Andreas

    ((unsigned int) 0x03 << 8) |0xB4

however I am clueless how I get a hold on that.

You also seem clueless when it comes to reading directions. The stickies at the top of the forum, the ones that you were supposed to read BEFORE you blundered in here, say POST YOUR CODE.

You can't make use of the data until you prove you can read (the data).

Hi,

here is the code that I have so far:

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

int sensorValue = 0;

void setup() {
  Serial.begin(19200);    // Init serial to communicate with sensor.
  mySerial.begin(9600);   // Init softserial to communicate with other device.
}

void loop() {

  // Send message to sensor, which make it send back data.
  byte message[] = { 0x55, 0xAA, 0x7E, 0x02, 0x4F, 0x43, 0x94, 0x0E, 0x0D };
  Serial.write(message, sizeof(message));

  // Read the answer of the sensor.
  while (Serial.available()) {
    int readout = Serial.read();
   
    /*** Code to interpret HEX answer of the sensor.  ***/
    
  }

  // Send the extracted sensor value to other device over softserial.
  mySerial.println("[" + String(sensorValue) + "]");

  delay(2000);
}
SoftwareSerial mySerial(10, 11); // RX, TX

So, you have a mySerial connected to these pins. Post a picture of the mySerial that is connected, so we know what a mySerial looks like.

  // Send message to sensor, which make it send back data.  byte message[] = { 0x55, 0xAA, 0x7E, 0x02, 0x4F, 0x43, 0x94, 0x0E, 0x0D };
  Serial.write(message, sizeof(message));

Why isn't the sensor connected to the software serial instance, so you can use Serial to debug your code?

    int readout = Serial.read();
   
    /*** Code to interpret HEX answer of the sensor.  ***/
   
  }

You are not storing the data, or even printing it, so you have no proof that the sensor returns the data you think it does.

Hi all,

I have started this thread a bit unprepared - now I am back with more data better structure.

Step 1: check if communication with sensor works

I have used a USB to Serial device to connect to the sensor. The software to communicate between PC and sensor over serial is HTerm 0.8.1 beta.

The documentation says, to send 11 01 01 ED in Hex to the sensor, to get an answer with the sensor values.

This actually also happens.

As shown in the screenshot I receive in total 24 “characters” in Hex.

The red circle of the screenshot represents the oxygen value (I need this value as integer).

The blue circle of the screenshot represents the gas flow value (I need this value as integer).

This is an example of the supplier manual, how they calculate the values:

For example: a measurement result for the flow: 5L / min, O2 concentration: 94.8%. Then the returned result (O2) = 94.8% = 0x03B4

(Hexadecimal), (FLOW) = 5.0 L / min = 0x0032 (hexadecimal), the returned data is "16 09 01 03 B4 00 32 00 D2 00 00 25"

Conclusion:

The sensor behaves as detailed in the manual.

Step 2: try to connect to the sensor with an Arduino.

I have used this simple sketch to receive the sensor data with an Arduino and instantly repeat it over an soft serial to the PC.

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

void setup() {
  mySerial.begin(9600);   // Serial to send stuff to PC.
  Serial.begin(9600);     // Serial to communicate with sensor.
}

void loop() {

  // Query the sensor data.
  Serial.write(0x11);
  Serial.write(0x01);
  Serial.write(0x01);
  Serial.write(0xED);

  // Wait for the sensor to answer.
  delay(10);

  // Read the answer from the sensor.
  while (Serial.available()) {
    
    // Send the received data to PC.
    mySerial.write(Serial.read());
  }
  
  delay(1000);
}

It worked fine.

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

void setup() {
  mySerial.begin(9600);   // Serial to send stuff to PC.
  Serial.begin(9600);     // Serial to communicate with sensor.
}

void loop() {

  // Query the sensor data.
  Serial.write(0x11);
  Serial.write(0x01);
  Serial.write(0x01);
  Serial.write(0xED);

  delay(10);

  // Read the answer from the sensor.
  int i = 0;
  while (Serial.available()) {
    
    // Send the received data to PC.
    mySerial.write(Serial.read());

    i = i + 1;
  }

  mySerial.println("{" + String(i) + "}");
  
  delay(1000);
}

Just to be sure I checked next how often the while loop iterates, respectively how many bytes it receives – and it is 12 bytes – so everything is fine and dandy so far.

Step 3: convert the received data.

I have generated a byte array reading[11], which should contain the 12 byte sent by the sensor.

Instead of repeating the data to the softserial, I write the data to the byte array.

After the data was received I try to convert the byte array, which contains the hex values to integer, and there the problems start.

The oxygen value of 00 CD HEX should be 205 decimal, which means 20.5% oxygen, which is the atmospheric content of O2 – so the sensor is delivering the correct value only my math is failing.

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

byte reading[11];           // byte array where the Serial readings are stored.
int oxigen_concentration;   // Sensor value 1;
int flow_rate;              // Sensor value 2;

void setup() {
  mySerial.begin(9600);   // Serial to send stuff to PC.
  Serial.begin(9600);     // Serial to communicate with sensor.
}

void loop() {

  // Query the sensor data.
  Serial.write(0x11);
  Serial.write(0x01);
  Serial.write(0x01);
  Serial.write(0xED);

  delay(10);

  // Read the answer from the sensor.
  int i = 0;
  while (Serial.available()) {

    reading[i] = Serial.read();

    i = i + 1;
  }

  oxigen_concentration = reading[3] * 256 + reading[4];
  flow_rate = reading[5] * 256 + reading[6];

  mySerial.println(oxigen_concentration);
  mySerial.println(flow_rate);
  
  delay(1000);
}

The output is complete garbage...

Thanks a lot for your help.

bytearray.jpg

You're not waiting for all the data to arrive before you convert it.

How are you getting data from the Arduino to the PC? Most people would have connected the mysterious device to the SoftwareSerial instance pins, and used Serial for talking to the PC.

Is the mysterious device a TTL level device or an RS232 level device?

@AWOL...

You're not waiting for all the data to arrive before you convert it.

I dont think so, as the while loop exists after all 12 bytes are received.

When the calculation code is reached, all 12 bytes are already contained in the reading byte array.

// Query the sensor data.
Serial.write(0x11);
Serial.write(0x01);
Serial.write(0x01);
Serial.write(0xED);

delay(10);

// Read the answer from the sensor.
int i = 0;
while (Serial.available()) {

reading = Serial.read();

  • i = i + 1;*
  • }*

oxigen_concentration = reading[3] * 256 + reading[4];
flow_rate = reading[5] * 256 + reading[6];

  • mySerial.println(oxigen_concentration);*
  • mySerial.println(flow_rate);*
    @ PaulS: I totally agree with you, but still this is not the root of the conversion problem.
    In the beginning I had the impression that soft serial does not work to send the hex to the sensor, so I switched around - however I probably just had a wiring problem...
    Again, the communication part is not the root of the problem.
    Thanks,
    Andreas

When the calculation code is reached, all 12 bytes are already contained in the reading byte array.

There's nothing in the code you posted to indicate that.

  while (Serial.available()) {

    reading[i] = Serial.read();

    i = i + 1;
  }

Let's suppose, when the while loop starts, that there is just one byte in the serial buffer. It takes next to no time to copy that value, update an index to point to the next available character (there aren't any) and to increment i. So, the loop starts again, and there is no data. So, the while loop ends, and you've read one byte.

How many bytes do you then pretend are in the reading array?

byte reading[11];

This array is big enough for 11 readings, not 12.

@AWOL:

I have just realized, that at some occasions I get the correct resutl:

The correct result for the oxigen value would be 205...

This number does come often - so you meight be right...

How could I avoid this?

Thanks.

If you know you need twelve bytes, why don't you wait for twelve bytes to appear?

Hello all,

this sketch works fine now:

It was indeed as AWOL sayd, I had to increase the delay, that the message gets received completely.

thanks a lot.

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

byte reading[12];           // byte array where the Serial readings are stored.
int oxigen_concentration;   // Sensor value 1;
int flow_rate;              // Sensor value 2;

void setup() {
  mySerial.begin(9600);   // Serial to send stuff to PC.
  Serial.begin(9600);     // Serial to communicate with sensor.
}

void loop() {

  // Query the sensor data.
  Serial.write(0x11);
  Serial.write(0x01);
  Serial.write(0x01);
  Serial.write(0xED);

  delay(100);

  // Read the answer from the sensor.
  int i = 0;
  while (Serial.available()) {

    reading[i] = Serial.read();

    i = i + 1;
  }


  oxigen_concentration = (int)reading[3] * 256 + (int)reading[4];
  flow_rate = reading[5] * 256 + reading[6];
  
  mySerial.println(oxigen_concentration);
  mySerial.println(flow_rate);
    
  delay(1000);
}

Better still, get rid of the delay entirely, and read as many bytes as you need.

Make the array index a static variable, so it is NOT initialized to 0 every time loop() iterates.

Read the available data WITHOUT delay().

Only use the data when i is 11. Reset i to 0 after using the data.