Read a specific hex byte from a data packet

What I'm trying to do is take in a scoreboard signal that sends data packets in hex values and read a specific byte, then perform certain functions depending on the value of that byte. Here are a couple of sample data packets.
55 AA 01 11 05 EA 22 BF BF 86 86 DB DB CF CF E6 E6 ED ED 87 87 FF FF 4E
55 AA 02 11 05 DA 22 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 DE
55 AA is always the start of a new packet and the 3rd byte is the address. I would like to only read packets with an address of 01. So in the examples, the second packet would be ignored. What I'm wanting to do is read the 8th byte of the data packet and serial print a certain value depending on what that value is. Any help would be great. Thanks!

Post the code where you begin to try to attempt this.

If only to show us how you come to possess these alleged data packets.

Seems like you have to read the packet in any case to know if you didn't have to.

a7

I don't have any code yet but here is where I got the sample packet from.

Read a full packet and analyse it. Once you have found the header in a received packet, check the next byte; ignore the (already received packet) if it's not 0x01.

How are the data packets sent?

Do you request them?
Are they sent out at periodic intervals?
Are they sent when data on the scoreboard changes?

Reading serial input with a preamble and a fixed number of bytes is a simple extension of the serial reading techniques shown in Robin2's tutorial.
https://forum.arduino.cc/t/serial-input-basics-updated/382007

First you need to understand and then tell us what you mean by "hex values". That's something newbies always get wrapped around the axle over. "Hex" only make since if you're talking about a human-readable representation ... typically when the data is transported in ASCII format. Is that the case with this scoreboard signal? Otherwise, if the data is transported as raw binary, there is no concept of "hex", it's just binary data.

The packets are automatically sent from the scoreboard controller multiple times a second.

The controller transmits the data as 0x55, 0xAA, 0x01, 0x11, 0x05 etc. Using a basic serial monitor just shows a bunch of random stuff but if I have a serial monitor set to read it as hex then the incoming data looks similar to the sample packet.

Yes but. Without seeing how you receive these, or plan to, it's hard to help.

The problem is trivially easy several ways. It's all now in the details, which are yet lacking.

a7

Not really an answer. Is the data signal ASCII Hex or binary? It sounds like the latter, but you need to know for sure and understand the difference.

It's converted to TTL on the receive end and comes is on the receive pin of the UART where I can do a serial read.

It is binary signal.

So "hex" has absolutely nothing to do with it. As @sterretje said, you can monitor the incoming bytes for the start of frame. Once found, read the entire frame into an array of uint8_t. You can then process it anyway you like.

you might benefit from studying state machines. Here is a small introduction to the topic: Yet another Finite State Machine introduction

here is an idea for the code. The function get8thByte() awaits data on the Serial port and checks for a special sequence using explicit steps for each magic value 0x55 0xAA and 0x01. Once you have received those 3 values, you are in the last state where you await patiently for the 8th byte and return it and flag that you got a hit (by returning true)

The code below is meant for testing, so instead of 0x55 0xAA and 0x01, the code expects A, B and C as characters. so if you type some garbage ABC00008000000xyzHello whatever in the Serial monitor, the code will tell you I got 0x38 (which is the ASCII code for '8' which was the 8th byte starting from ABC).

bool get8thByte(byte &val) {
  const byte magic1 = 'A'; // replace with 0x55
  const byte magic2 = 'B'; // replace with 0xAA
  const byte magic3 = 'C'; // replace with 0x01

  static enum {WAITING_55, WAITING_AA, WAITING_01, WAITING_8th_BYTE} state = WAITING_55;
  static byte count = 0;

  if (Serial.available() == 0) return false;

  byte r = Serial.read();
  switch (state) {
    case WAITING_55:
      if (r == magic1) state = WAITING_AA;
      break;
    case WAITING_AA:
      if (r == magic2) state = WAITING_01;
      else if (r != magic1) state = WAITING_55;
      break;
    case WAITING_01:
      if (r == magic3) {
        state = WAITING_8th_BYTE;
        count = 3; // we already read 3 bytes succesfully
      } else if (r == magic1) state = WAITING_AA;
      else state = WAITING_55;
      break;
    case WAITING_8th_BYTE:
      if (++count == 8) {
        val = r;
        state = WAITING_55;
        return true;
      }
      break;
  }
  return false;
}

void setup() {
  Serial.begin(115200);
  Serial.println(F("Ready"));
}

void loop() {
  byte value;
  if (get8thByte(value)) {
    Serial.print(F("I got 0x"));
    if (value < 0x10) Serial.write('0');
    Serial.println(value, HEX);
  }
}

2 Likes

I've lost count of how many state machine packet receivers / decoders I've designed and coded during the past 40 years :slight_smile:
@semmons3 I couldn't agree more with what post #14 says. I did almost post something similar earlier, but didn't have the time to explain so well.

Have you monitored the data transmission long enough to be sure the message length is always the same number of bytes?

Your page in How do I continuously serial print last string of data received on Uno? - #7 by semmons3 says you can't assume that 0x55 0xAA is always the start of a packet. since it could be part of the packet.. For instance a packet for address 0x55 that happens to be 0xAA characters long would start 0x55AA55AA...

1 Like

sure, ideally the code would read a frame, validate the checksum etc.. the doc is clear on this

That code worked perfectly for what I'm trying to do. Thank you!

Glad to hear but it’s not 100% safe you might get false positives if you are unlucky