Serial.read to array writes everything in one index

Hello everyone,

I'm new to this forum and also relatively new to arduino, so could really use some help here.

I'm trying to read a HEX code like "0xFA 0x21 0x10 0x01 0x01" from Serial.read() and store it in an array.
However, no matter how I tried it, I always get some garbage when displaying it with Serial.print().
While trying to find the problem, I noticed that, without any for loop, everything is stored in the first index of the array. I can also write the entire HEX code in one single char variable.
When using some sort of loop for storing every character in a different index of the array, I either get some mix of the HEX code with inverted questionmarks, or something like this: "00x0x10x120x120x12" when I send "0x12" through the serial monitor.

I'm using a Mega 2560, if that helps.

I also have nothing else going on around the Serial.read() function. This is the code:

char hex[5] = {'\0'};

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  if(Serial.available() > 0){
    for(byte i = 0; i < 4; i++){
      hex[i] = Serial.read();
    }
    for(byte i = 0; i < 4; i++){
      Serial.print(hex[i]);
    }
  }
}

In this instance, when I send 0x12, I get this response:
0⸮⸮⸮x⸮⸮⸮1⸮⸮⸮2⸮⸮⸮
⸮⸮⸮

Can someone help me with this problem?

Your code waits until there is a byte available on the Serial interface then saves 4 bytes to the array.

You should either be waiting for a character then when one is available writing it to the array and incrementing the index until you have read 4 characters or waiting until 4 characters are available before reading and storing them

Think about what you have coded!
If one byte is available, you read 4 bytes. How well will that work?
Paul

@jeyd
I think the tutorial Serial Input Basics were exactly written for you.

If you want the values of the hex bytes and not just the text, here is a sketch that will convert that kind of input to a list of bytes. Be sure to set your Serial Monitor line ending to "Newline".

In addition to space, you can use comma, tab, slash or most other characters to separate the values.

byte ByteValues[100];
int ByteIndex = 0;
bool InANumber = false;

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop()
{
  // put your main code here, to run repeatedly:
  if (Serial.available())
  {
    char c = Serial.read();

    if (c >= '0' && c <= '9')
    {
      // It is a digit
      if (InANumber)
      {
        ByteValues[ByteIndex] <<= 4;
        ByteValues[ByteIndex] += c - '0';
      }
    }
    else if (c >= 'A' && c <= 'F')
    {
      // It is a hex digit
      if (InANumber)
      {
        ByteValues[ByteIndex] <<= 4;
        ByteValues[ByteIndex] += c - 'A' + 10;
      }
    }
    else if (c >= 'a' && c <= 'f')
    {
      // It is a hex digit
      if (InANumber)
      {
        ByteValues[ByteIndex] <<= 4;
        ByteValues[ByteIndex] += c - 'a' + 10;
      }
    }
    else // not a hex digit
    {
      if (InANumber)
      {
        ByteIndex++;
        ByteValues[ByteIndex] = 0;
        InANumber = false;
      }

      // Numbers start with 0x or 0X.
      if (c == 'x' || c == 'X')
      {
        InANumber = true;
      }

      if (c == '\n')
      {
        // Newline (End of input)

// DEMONSTRATION, just prints the values
        for (int i = 0; i < ByteIndex; i++)
        {
          if (ByteValues[i] < 0x10)
            Serial.print('0'); // Add leading zero
          Serial.print(ByteValues[i], HEX);
        }
        Serial.println();
// END DEMONSTRATION
      }
    }
  } // End of if (SerialAvailable())
}

Thanks a lot to everybody. I figured it out now. Really dumb how I didn't notice that.

Thank you very much, this is exactly what i wanted to do.

I cleaned up the code a bit.

byte ByteValues[100];
int ByteIndex = 0;
bool InANumber = false;

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop()
{
  // put your main code here, to run repeatedly:
  if (Serial.available())
  {
    char c = Serial.read();
    static int number = 0;

    if (InANumber)
    {
      if (c >= '0' && c <= '9')
      {
        // It is a digit
        number <<= 4;
        number += c - '0';
      }
      else if (c >= 'A' && c <= 'F')
      {
        // It is a hex digit (upercase)
        number <<= 4;
        number += c - 'A' + 10;
      }
      else if (c >= 'a' && c <= 'f')
      {
        // It is a hex digit (lowercase)
        number <<= 4;
        number += c - 'a' + 10;
      }
      else // not a hex digit
      {
        // End of a number, store it.
        ByteValues[ByteIndex] = number;
        ByteIndex++;
        number = 0;
        InANumber = false;
      }
    }

    // Numbers start with 0x or 0X.
    if (c == 'x' || c == 'X')
    {
      number = 0;
      InANumber = true;
    }

    if (c == '\n')
    {
      // Newline (End of input)

      // vvvvvvv  DEMONSTRATION, just prints the values
      for (int i = 0; i < ByteIndex; i++)
      {
        if (ByteValues[i] < 0x10)
          Serial.print('0'); // Add leading zero
        Serial.print(ByteValues[i], HEX);
        Serial.print(' ');
      }
      Serial.println();
      // ^^^^^^^^ END DEMONSTRATION

      ByteIndex = 0;
      number = 0;
    }
  } // End of if (SerialAvailable())
}
1 Like