I get 8 byte serial response from sensor in hex like : 77 07 00 81 12 26 45 71
Where bytes (5 to 7) 12 26 45 are the value of the sensor -226.45 (02 26 46 is positive 226.46)
How to parse that as a float/int ?
I get 8 byte serial response from sensor in hex like : 77 07 00 81 12 26 45 71
Where bytes (5 to 7) 12 26 45 are the value of the sensor -226.45 (02 26 46 is positive 226.46)
How to parse that as a float/int ?
You already did parse it, mentally. So there is no mystery about how to do it logically. Have you written any code yet?
BTW, the format is a form of BCD, binary coded decimal. It is not hexadecimal. I say, "a form" because of the convention of using one digit for the sign.
aarg:
You already did parse it, mentally. So there is no mystery about how to do it logically.
The mental parsing is transformed into physical parsing for the OP as he is a newbie.
#include<SoftwareSerial.h>
SoftwareSerial mySerial(3, 4); //SRX = 3, STX = 4
bool flag = false; //decides that 4-byte preamble has been detected
byte myData[4];
int j = 0;
void setup()
{
Serial.begin(9600);
mySerial.begin(9600);
}
void loop()
{
byte n = mySerial.available(); //to check if a data byte has come from sensor
if (flag == false) //4-byte preamble is notyet detected
{
if ( n == 4) //4-byte preamble is detected
{
for (int i = 0; i < 4; i++)
{
myData[i] = mySerial.read();
//Serial.print(myData[i], HEX);
}
Serial.println();
Serial.println("========");
long x = (long)myData[0] << 24 | (long)myData[1] << 16 | (long)myData[2] << 8 | (long)myData[3];
Serial.print(x, HEX);
if (x == 0x77070081) //checking if received 4-byte preamble matched with known preamble
{
Serial.println();
Serial.println("Preamble found.");
flag = true;
}
}
}
else
{
byte x = mySerial.read();
if (x != 0x71)
{
myData[j] = x; //save received sensor data until 0x71 (terminating byte) is detected
j++;
}
else
{
float z = (myData[0] & 0x0F) * 100.00 + (myData[1] >> 4 & 0x0F) * 10.0 + (myData[1] & 0x0F) * 1.00
+ (myData[2] >> 4 & 0x0F) * 0.1 + (myData[2] & 0x0F) * 0.01; //converting sensor's BCD data into float number
if ((myData[0] & 0xF0) == 0x10)
{
Serial.print("-"); //printing minus sign
}
Serial.print(z, 2); //shows sensor data with 2-digit precision
j = 0;
flag = false;
}
}
}
My idea was similar but converted the number to a series of strings
At that point you could do a string comparison on the first 8 characters to see if they match 77070081, then check to see if the next char is a 1 or 0 and then converts the next part of the string to a number and then save it as a float dividing by 100 for the decimal point and multiplying by -1 if necessary. Might be shorter but I've heard that converting strings is not always reliable.
you could also skip the 1 or 0 check and do:
if(value >= 1000){
value *= -1;
value = value/100;
}
Does anyone know if this would be bad practice?
The programmer has to decide how he is going to interpret the incoming data bytes coming from the OP's sensor. I have this interpretation based on which the sketch of Post#2 is developed and tested using 2 UNOs.
1st four bytes (77 07 00 81) are binary bytes.
Next three bytes (12 26 45) are BCD coded (Post#1) sensor data bytes; where, upper nibble of first byte (12) is the sign mark (1 means: minus and 0 means: +).
Last one byte (71) is a binary byte.
Well , atleast the code below is working ![]()
static const int RXPin = 16, TXPin = 17;
static const uint32_t Baud = 9600;
int incomingByte[8] ;
int x = 0;
float Value=0.00 ;
void setup() {
Serial.begin(115200);
Serial2.begin(Baud, SERIAL_8N1, RXPin, TXPin);
}
void loop() {
while (Serial2.available() > 0) {
incomingByte[x] = Serial2.read();
int Valueplus=(incomingByte[4]/16);
int Value100=(incomingByte[4] %16);
int Value10=(incomingByte[5]/16*10)+(incomingByte[5] %16);
float Value01=(incomingByte[6]/16*10)+(incomingByte[6] %16);
if (Valueplus==1) {
Value=-1*((Value100*100)+Value10+(Value01/100)) ;
} else {
Value=(Value100*100)+Value10+(Value01/100) ;
}
x=x+1;
}
Serial.println();
Serial.print("Value, ");
Serial.print(Value);
delay(200);
x=0;
}
sahti:
Well , atleast the code below is working
...until you happen to receive more than 8 characters and the program starts writing data beyond the bounds of incomingByte[], into undefined memory locations. Crash! There is no bounds checking on the index, 'x'.
aarg:
...until you happen to receive more than 8 characters and the program starts writing data beyond the bounds of incomingByte[], into undefined memory locations. Crash! There is no bounds checking on the index, 'x'.
Right, working on it.
I need to ask the data from the sensor.
Basically now what i should get back + Bit [1] on the answer tells me the the length of the answer. Last bit is checksum.
Not doing any military grade equipment here, althought the sensor looks like it.
sahti:
Basically now what i should get back + Bit [1] on the answer tells me the the length of the answer. Last bit is checksum.
I see no code at all that has anything to do with the length. What do you mean?
sahti:
Well , atleast the code below is working
static const int RXPin = 16, TXPin = 17;
If you are using Serial2 Port of MEGA, then RX2 = DPin-17 and TX2 = DPin-16. Therefore, your codes can't work with RX2 = DPin-16 and TX2 = DPin-17.
GolamMostafa:
If you are using Serial2 Port of MEGA, then RX2 = DPin-17 and TX2 = DPin-16. Therefore, your codes can't work with RX2 = DPin-16 and TX2 = DPin-17.
working on ESP32 .
sahti:
working on ESP32 .
I have executed your codes on my MEGA as receiver and NANO as simulated sensor. You sketch seems to be working as it is giving the right value (-226.45) for the incoming data bytes of: : 77 07 00 81 12 26 45 71. Are you detecting the preamble -- 77 07 00 81? Are you checking the terminating byte - 71? Checked for different preamble and terminating byte; the output value is still correct. This means that your sketch are not checking the preamble and terminating byte. Is it good? Please, adjust your codes to take care of preamble and terminating byte and post the revised codes. I have not found your codes to have crashed as predicted in Post#6.

MEGA Receiver Codes borrowed from OP:
//static const int RXPin = 16, TXPin = 17;
static const uint32_t Baud = 9600;
int incomingByte[8] ;
int x = 0;
float Value = 0.00 ;
void setup()
{
Serial.begin(9600);
Serial2.begin(9600);//(Baud, SERIAL_8N1, RXPin, TXPin);
}
void loop()
{
while (Serial2.available() > 0)
{
incomingByte[x] = Serial2.read();
int Valueplus = (incomingByte[4] / 16);
int Value100 = (incomingByte[4] % 16);
int Value10 = (incomingByte[5] / 16 * 10) + (incomingByte[5] % 16);
float Value01 = (incomingByte[6] / 16 * 10) + (incomingByte[6] % 16);
if (Valueplus == 1)
{
Value = -1 * ((Value100 * 100) + Value10 + (Value01 / 100)) ;
}
else
{
Value = (Value100 * 100) + Value10 + (Value01 / 100) ;
}
x = x + 1;
}
Serial.println();
Serial.print("Value, ");
Serial.print(Value);
delay(200);
x = 0;
}
Simulated Sensor Codes:
#include<SoftwareSerial.h>
SoftwareSerial mySerial(3, 4); //SRX = 3, STX = 4
byte myData[] = {0x77, 0x07, 0x00, 0x81, 0x12, 0x26, 0x45, 0x71};
void setup()
{
Serial.begin(9600);
mySerial.begin(9600);
}
void loop()
{
mySerial.write(myData, sizeof(myData));
delay(1000);
}

GolamMostafa:
I have executed your codes on my MEGA as receiver and NANO as simulated sensor. You sketch seems to be working as it is giving the right value (-226.45) for the incoming data bytes of: : 77 07 00 81 12 26 45 71. Are you detecting the preamble -- 77 07 00 81? Are you checking the terminating byte - 71? Checked for different preamble and terminating byte; the output value is still correct. This means that your sketch are not checking the preamble and terminating byte. Is it good? Please, adjust your codes to take care of preamble and terminating byte and post the revised codes. I have not found your codes to have crashed as predicted in Post#6.
Well, my problem in the beginning was how to make float out of the incoming 4 bytes of data not the calculation and check the incoming data. That's an easy task if i need it ..