Reading HEX from serial and using it

Hi everyone, currently I’m attempting to understand how to read from the serial monitor, for example if “read 0x00, 0x01” is sent. I understand character arrays that’s not the problem, what I’m confused about is reading 0x00 and 0x01 from here. How can I take the characters from the character array that make up this hex number and then store it as a hex number?

void loop() {
  // put your main code here, to run repeatedly:
  if(Serial.available() > 0){
    recvWithEndMarker();
  }
  if(receivedChars[0] == 'r'){
    startAddress = receivedChars[5];
    endAddress = receivedChars[8];
    for(int i = startAddress; i <= endAddress; ++i){
      data = EEPROM.read(i);
      Serial.print(data, DEC);
      Serial.print(" ");
    }
    Serial.println();
  }
  else if(receivedChars[0] == 'w'){
    startAddress = receivedChars[6];
    int i = 9;
    int j = 0;
    while(receivedChars[i] != NULL){
      data = receivedChars[i];
      EEPROM.write(startAddress, data);
      i += 2;
      j++;
    }
    Serial.print(j);
    Serial.print(" bytes of data beginning at ");
    Serial.print(startAddress);
    Serial.print(" successfully");
    Serial.println();
  }
  memset(receivedChars, 0, sizeof(receivedChars));
}

Here’s the code I’ve done.

Thanks!

I don't see anything in the code snippet you posted that relates to your question. You need to post an example of what is in the array receivedChars[] before you start trying to parse it.

Also explain how the data in the example is intended to be used.

And please post the complete program in your next reply (or attach the .ino file if it is big)

...R

If receiveWithEndMarket() is Robin's code, it is non-blocking.

You do not necessarily get the full data in one go; it might very well be that you only receive the 'r'. Use the newData flag to determine if you have received a full message. And next parse it; Robin's examples contain a parse example using strtok(); your approach will also work if you do it properly using strchr() to find the comma and replace it with the nul terminator.

You can use strtoul to convert the text 0x00 to the number 0x00

What I receive in the serial monitor will always be of the format “read 0x00, 0x00” where the two 0x00 are some hex number. What I’m trying to do is take these two hex numbers and use them to read from EEPROM where the first number is where to start reading, and the second number is where to stop reading.

I’ve figured out at this point that the first number IS stored from receivedChars[5] through [8], but I’m still unsure how to take these character and store them as a single hex number.

Here’s my full code.

#include <EEPROM.h>

const byte numChars = 20;
char receivedChars[20];
int startAddress;
int endAddress;
byte data;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  while(!Serial){
    //wait for connection
    Serial.println("waiting for serial port connection");
  }
  Serial.println("successful connection");
}

void loop() {
  // put your main code here, to run repeatedly:
  if(Serial.available() > 0){
    recvWithEndMarker();
  }
  if(receivedChars[0] == 'r'){
    //read 0x00, 0x00
    char hex1[2] = {receivedChars[7], receivedChars[8]};
    char hex2[2] = {receivedChars[13], receivedChars[14]};
    startAddress = receivedChars[5];
    endAddress = receivedChars[8];
    for(int i = startAddress; i <= endAddress; ++i){
      data = EEPROM.read(i);
      Serial.print(data, DEC);
      Serial.print(" ");
    }
    Serial.println();
  }
  else if(receivedChars[0] == 'w'){
    startAddress = receivedChars[6];
    int i = 9;
    int j = 0;
    while(receivedChars[i] != NULL){
      data = receivedChars[i];
      EEPROM.write(startAddress, data);
      i += 2;
      j++;
    }
    Serial.print(j);
    Serial.print(" bytes of data beginning at ");
    Serial.print(startAddress);
    Serial.print(" successfully");
    Serial.println();
  }
  memset(receivedChars, 0, sizeof(receivedChars));
}

void recvWithEndMarker() {
  //reset buffer
  memset(&receivedChars, 0, 20);

  //create variables
  static byte ndx = 0;
  char endMarker = '\n';
  char rc;
  delay(500);

  //while data is available read
  while (Serial.available() > 0) {
    rc = Serial.read();

    //if the end then stop
    if (rc != endMarker) {
      receivedChars[ndx] = rc;
      ndx++;
      if (ndx >= numChars) {
        ndx = numChars - 1;
      }
    }
    
    else {
      receivedChars[ndx] = '\0'; // terminate the string
      ndx = 0;
    }
  }
}

andyg223: What I receive in the serial monitor will always be of the format "read 0x00, 0x00" where the two 0x00 are some hex number.

Can you send the data as read,0,0 where the '0's represent decimal numbers - for example read, 10, 37. That will make the parsing much easier because you can use atoi() to convert the "37" into an integer. There is a parse example in Serial Input Basics

(You could actually send read 10 37 where 'space' is used as the delimiter rather than a comma. But comma separated values (CSV) is a very common system)

I believe the somewhat more complex strtol() function can convert hex values to long but there does not seem to be an int version.

You would also make life simpler for yourself if you just send 'r' rather than "read".

...R

unfortunately it needs to be in that exact format

You don't need an int version of strtol; simply assign the result to an int variable.

sterretje:
You don’t need an int version of strtol; simply assign the result to an int variable.

Yes. I should have said that, I was just trying to prevent the OP wasting time looking for an int version.

…R

I appreciate looking out for me needing to do extra work :stuck_out_tongue:

I tried using strtol with the example “read 0x31, 0x40” but when I’m setting it to ints, they are printing out as being 31 and 4031, any reason why that may be?

here’s where I’m using strtol

if(receivedChars[0] == 'r'){
    //read 0x00, 0x00
    const char hex1[2] = {receivedChars[7], receivedChars[8]};
    const char hex2[2] = {receivedChars[13], receivedChars[14]};
    startAddress = (int)strtol(hex1, NULL, 0);
    endAddress = (int)strtol(hex2, NULL, 0);

Two digits from your incoming message don't fit in a two character array; you need space for a terminating nul character.

That fixed it!