Storing a HEX string from serial buffer

Hi, I am currently working on a project where I am communicating with a variable frequency drive using Modbus RTU. I have successfully written to the coils. I am now reading from the registers. I have send the command to read from the required register and successfully received a response which prints out to the serial monitor. What i cant seem to figure out is how to store the HEX string that is read by the serial monitor so I can remove the extra information and convert the returned value I need.

This is what I have so far, any help would be greatly appreciated.

#include <SoftwareSerial.h>
SoftwareSerial RS485(3, 2);   // RX, TX
byte message_SPD[] = {0x02, 0x03, 0x00, 0x01, 0x00, 0x01, 0xD5, 0xF9}; //MODBUS RTU QUERY COMMAND FOR SPEED REFERENCE


void setup() {

  Serial.begin(2400);
  RS485.begin(9600);

}

void loop() {

  RS485.write(message_SPD, sizeof(message_SPD));
  delay(20);
  byte byteCounter = 0;
  while(byteCounter < 7)
  {
    while(RS485.available())
    {
      Serial.print(RS485.read(),HEX); // When this prints out it looks like "2325DCFE8D" I need to be able to either store that value and then remove the 232 and FE8D then convert the remainder "5DC" to int16
      byteCounter++;
    }
  }
  Serial.println();
}

Save the packet to a packet buffer, then pick out the bytes you need explicitly.

  byte buffer [7] ;
  while (RS485.available () < 7)
  {}
  for (byte i = 0 ; i < 7 ; i++)
    buffer[i] = RS485.read () ;
  // now look at the relevant entries in buffer

It might be a good idea to make the code non-blocking too, but that’s a refinement.

They data is binary, not hex, you chose to print it out in hex.

Serial.print(RS485.read(),HEX); // When this prints out it looks like "2325DCFE8D" I need to be able to either store that value and then remove the 232 and FE8D then convert the remainder "5DC" to int16

Rubbish. Printing ONE byte will never result in 2325DCFE8D appearing anywhere.

It would appear that you are printing 23, 25, DC, FE, and 8D with no spaces between them.

If you stored the 5 bytes in an array, you could get the 4th, 5th, and 6th nibbles, and combine them into an int.

MarkT:
Save the packet to a packet buffer, then pick out the bytes you need explicitly.

  byte buffer [7] ;

while (RS485.available () < 7)
  {}
  for (byte i = 0 ; i < 7 ; i++)
    buffer[i] = RS485.read () ;
  // now look at the relevant entries in buffer




It might be a good idea to make the code non-blocking too, but that's a refinement.

They data is binary, not hex, you chose to print it out in hex.

Thanks for the quick response, but i’m still kinda new at the programming language. Would you mind explaining a little bit please.

The response from the VFD is in HEX or at least that is what the VFD manual says it will respond in. Sniffing the lines this is what is actually sent from the VFD 02 03 02 05 DC FE 8D, which contains the slave address, function code, not sure what the 3rd one is, the 4th and 5th is my returned value in HEX. 05 DC = 1500, then the last 2 are the CRC’s i believe.

EDIT: Okay so I used the buffers to store each part and i checked what was in the 4th and 5th and it is a value in decimal so buffer 3 = 5 buffer 4 = 220 which comes out to 5 DC in HEX which is what i needed. So how do i go about converting that into 1500?

Fooled by Serial.print :slight_smile: Serial.print omits leading zeroes and hence 0x02 followed by 0x03 looks like 23.

A way to prevent the possibility of misinterpretation is by adding an additional print statement (see below) or print each received byte on a new line.

    while(RS485.available())
    {
      Serial.print(RS485.read(),HEX); // When this prints out it looks like "2325DCFE8D" I need to be able to either store that value and then remove the 232 and FE8D then convert the remainder "5DC" to int16
      Serial.print(",");
      byteCounter++;
    }
  }

Okay so I used the buffers to store each part and i checked what was in the 4th and 5th and it is a value in decimal so buffer 3 = 5 buffer 4 = 220 which comes out to 5 DC in HEX which is what i needed. So how do i go about converting that into 1500? I know if you take the HEX values and convert them to UINT32 - Mid-Little Endian (CDAB) it will convert out to 1500.

 (buffer[4] << 8) || buffer [5]

MarkT:

 (buffer[4] << 8) || buffer [5]

This just gave me all 1’s

Mkinney88:
This just gave me all 1’s

Try bitwise OR instead:

(buffer[4] << 8) | buffer [5]

Doh, sorry, I've been writing Python all day and got the operator wrong!

thank you for all your help!!