Reading In a HEX cmd and output interger

Hello,

I am currently working on a project that takes in the following Hex command via UART (9600 baud):
{0xAA,0xAA,0x12,0x02,0x00,0x03,0xAA,0x64,0x05,0x00,0xF9,0x00,0x03,0x44,0x08,0x39,0x85,0x03,0xFF,0xFF,0xFF,0xC1}

I am then looking to parse though the message and change the bolded byte to an integer to send via BT to my phone.

I am able to read in all of the message if I send it like (AAAA12020003AA640500F900034408398503FFFFFFC1) in the serial monitor, but when I go to send via hex using dock-lock I run into some problems.

In the below code what do I need to do to be able to read in and store the HEX command and then correctly go through it as this really only works with a charstring from serial monitor. Sorry if this is a dumb/easy question I am very new to arduino.

const byte numChars = 64;
char receivedChars[128];
int DataRec = 0;

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  // Serial = USB to computer for sniffing
  Serial.begin(9600);
  // Serial1 = BT serial through HM-10 Module
  Serial1.begin(9600);
  Serial.println("Arduino is ready");
}

// the loop routine runs over and over again forever:
void loop() {
 recvWithEndMarker();
 showNewData();
 sendBTData();
}

void recvWithEndMarker() {
 static byte ndx = 0;
 char endMarker = '\n';
 char rc;
  while (Serial.available() > 0 && DataRec == false) {
   rc = Serial.read();
   if (rc != endMarker) {
    receivedChars[ndx] = rc;
    ndx++;
    if (ndx >= numChars) {
     ndx = numChars - 1;
    }
   }
   else {
    receivedChars[ndx] = '\0'; // terminate the string
    ndx = 0;
    DataRec = 1;
  }
 }
}

void showNewData() {
 if (DataRec == 1) {
 Serial.print("This just in ... ");
 Serial.println(receivedChars);
 DataRec = 2;
 }
}

void sendBTData(){
  if (DataRec == 2){
   int var = receivedChars[10] + receivedChars[11];
   Serial.print("Heart Rate is ...");
   Serial.print(receivedChars[10],HEX);
   Serial.print(",");
   Serial.println(var,DEC);
   DataRec = 0;
  }
}

You say that you run into problems. What are the problems?

"Send via hex" is a confusing statement. When the byte value 170 is sent, that is what is sent. In decimal it is 170, in hex it is 0xAA, and in binary it is 0b10101010.

Mk1888 Thank you for your response! When I used Docklight with a hex command saved so I can easily send, I do not receive the acknowledgement of This just in in the window like I do during the use of serial monitor.

@Robin2 Update I have adjusted your code slightly and am not always getting stuck at the print out of Start 1 detected…

I always know my command with come in as 0xAAAA so I want to detect that before adding my data into the 18 byte message I am going to parse through. Is there something I am doing wrong?

The stare and end marker code is slightly modified to look for the double start bytes then processes for length not an end byte.

const byte numChars = 64;
byte receivedChars[numChars];

int newData = 0;

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  // Serial = USB to computer for sniffing
  Serial.begin(9600);
  // Serial1 = BT serial through HM-10 Module
  Serial1.begin(9600);
  Serial.println("Arduino is ready");
}



// the loop routine runs over and over again forever:
void loop() {
    recvWithStartEndMarkers();
    showNewData();
    sendBTData();
}

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    byte startMarker = 0xAA;
    byte rc;
 
 // if (Serial.available() > 0) {
    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (ndx < 18) {
              Serial.print("Creating Array ... ");
                receivedChars[ndx] = rc;
                ndx++;
                Serial.println(ndx,DEC);
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = 1;
            }
        }
        else if (rc == startMarker) {
          Serial.print("Start 1 detected ... ");
          rc = Serial.read();
          if(rc == startMarker){
            Serial.print("Start 2 detected ... ");
            recvInProgress = true;
          }
        }
    }
}

1. Is this hex command:{0xAA,0xAA,0x12,0x02,0x00,0x03,0xAA,0x64,0x05,0x00,0xF9,0x00,0x03,0x44,0x08,0x39,0x85,0x03,0xFF,0xFF,0xFF,0xC1} always contain fixed number of bytes (22)?

2. Is the target byte (here: 0xAA) always at index position 6?

3. Are these 6 bytes: 0xAA,0xAA,0x12,0x02,0x00,0x03 always fixed valued?

@GolamMostfa

  1. Yes that is correct.

  2. Yeah but the value will change from 0x00 to 0xFF depending on what the sensor reads.

  3. Just the AA AA the third byte is the payload length in the event of a future change.

Thank you for helping out!

Please, provide me the full answer for the following question.

  1. Are these 6 bytes: 0xAA,0xAA,0x12,0x02,0x00,0x03 always fixed valued?

You have said that:
1st 2 bytes (0xAA, 0xAA) are fixed.
What's about 0x12: Does it change?
What's about the rest-- 0x02,0x00,0x03 ?

@GolamMostafa

Sorry only the first 0-1 are fixed, 3 is pay load length, 4 is always 0x02, 5 varies from 00-FF, 6 is always 0x03.

Did not mean to cause confusion.

So, will it be alright --

To design a sketch that will look for consecutive 0xAA and 0xAA; if found, next 20 bytes would be received and saved in an array named **byte myData**and then the integer value of myData[6] would be written to (soft) UART/BT device?

@GolamMostafa that would be more than helpful!

These are sketches (tested using UNO and MEGA).

UNO-Hex Command Simulator.

#include<SoftwareSerial.h>
SoftwareSerial SUART(2, 3);
byte myCode[] = 
{
  0xAA, 0xAA, 0x12, 0x02, 0x00, 0x03, 0xAA, 0x64, 0x05, 0x00, 0xF9,
  0x00, 0x03, 0x44, 0x08, 0x39, 0x85, 0x03, 0xFF, 0xFF, 0xFF, 0xC1
};

void setup()
{
  Serial.begin(9600);
  SUART.begin(9600);
}

void loop()
{
  for ( int i = 0; i < sizeof(myCode); i++)
  {
    SUART.write(myCode[i]);
    Serial.print(myCode[i], HEX);
  }
  Serial.println();
  delay(2000);
}

MEGA -- Receiver (myData[6] is written o UART2 of MEGA)

bool flag = false;
byte myData[20];
byte myCode[2];

void setup()
{
  Serial.begin(9600);
  Serial1.begin(9600);
  Serial2.begin(9600);
}

void loop()
{
  byte n = Serial1.available();
  if (flag == false)
  {
    if (n == 2)
    {
      myCode[0] = Serial1.read();
      myCode[1] = Serial1.read();
    }
    int x = (int)myCode[0] << 8 | (int)myCode[1];
    if (x == 0xAAAA)
    {
      flag = true;
      Serial.println("Preamble found.");
    }
  }
  else
  {
    Serial1.readBytes(myData, 20);
    Serial.println("Sending target value to UART2.");
    Serial2.print(myData[6], DEC); //AA = 170 will be sent as: 31, 37, 30
    Serial.println(myData[6], DEC);
    flag = false;
    Serial.println("=====================");
  }
}

smR.png

smR.png

@GolamMostafa , this is working great there is a slight issue in regards to the first time I send the message over it looks like it responds with 5 for the value even though it is 170 command. I then send the message for a second time in which it then responds correctly.

Is there something I need to do to flush the buffer of junk beforehand?

@GolamMostafa okay I have a better under standing what is happening. With the code below this is what output I am seeing, there seems to be something weird were the index of the array are being read differently (ie with out without the preamble).

Arduino is Ready

I then send the HEX Command. This is what prints out serially.

myCode 0 = AA
myCode 1 = AA
Preamble found.
Sending target value as.
5

(repeats every 100ms)
Preamble found.
Sending target value as.
5

Preamble found.
Sending target value as.
5

Preamble found.
I then send the command again.
Sending target value as.
170

myCode 0 = FF
myCode 1 = FF
(The loop then stops outputting)

To me it seems the index is being shifted 2 bytes since 0x05 is position 4 instead of 6 in the first one, but the second time the command is sent it is looking correctly at position 6.

bool flag = false;
byte myData[20];
byte myCode[2];
int newData = 0;

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  // Serial = USB to computer for sniffing
  Serial.begin(9600);
  // Serial1 = BT serial through HM-10 Module
  Serial1.begin(9600);
  Serial.println("Arduino is ready");
}



// the loop routine runs over and over again forever:
void loop() {
    recData();
    sendBTData();
}

void recData() {
  byte n = Serial.available();
  if (flag == false)
  {
    if (n == 2)
    {
      myCode[0] = Serial.read();
      Serial.print("myCode 0 = ");
      Serial.println(myCode[0],HEX);
      myCode[1] = Serial.read();
      Serial.print("myCode 1 = ");
      Serial.println(myCode[0],HEX);
    }
    int x = (int)myCode[0] << 8 | (int)myCode[1];
    if (x == 0xAAAA)
    {
      flag = true;
      Serial.println("Preamble found.");
    }
  }
  else
  {
    Serial.readBytes(myData, 20);
    Serial.println("Sending target value as.");
    Serial.println(myData[6], DEC);
    flag = false;
    Serial.println("=====================");
    delay(100);
  }
}

void sendBTData(){
  if (newData == 2){
   newData = 0;
  }
}

The MEGA's sketch of Post#10 suffers from few flaws which are: the missing codes to reset the arrays; reading wrong target value which should be from myData[4] and not from myData[6]. This is the corrected sketch. It can be easily figured out from Fig-2 why the value 5 (= myData[6]) was appearing on the Serial Monitor. Thanks to Serial Monitor/IDE -- a fantastic debugging tool.

bool flag = false;
byte myData[20];
byte myCode[2];

void setup()
{
  Serial.begin(9600);
  Serial1.begin(9600);
  Serial2.begin(9600);
}

void loop()
{
  byte n = Serial1.available();
  if (flag == false)
  {
    if (n == 2)
    {
      myCode[0] = Serial1.read();
      myCode[1] = Serial1.read();
    }
    int x = (int)myCode[0] << 8 | (int)myCode[1];
    if (x == 0xAAAA)
    {
      flag = true;
      Serial.println("Preamble found.");
      memset(myCode, 0, 2);
    }
  }
  else
  {
    Serial1.readBytes(myData, 20);
    for(int i=0; i<20; i++)
    {
      byte x = myData[i];
      if(x <0x10)
      {
        Serial.print('0');  //prints leading zeo of a byte
      }
      Serial.print(myData[i], HEX);
    }
    Serial.println();
    Serial.println("Sending target value to UART2.");
    Serial2.print(myData[4], DEC); //AA = 170 will be sent as: 31, 37, 30
    Serial.println(myData[4], DEC);
    flag = false;
    memset(myData, 0, 20);
    Serial.println("=====================");
  }
}

smk1.png
Figure-2:

smk1.png

Thank you for looking into that for me from my comments. I tried debugging with memset and could not get it quite like you have it now so thank you.

I am wondering if you could explain the line of code byte manipulation wise so I can understand this better in the future!

    int x = (int)myCode[0] << 8 | (int)myCode[1];
    if (x == 0xAAAA)

sykotikk23:
I am wondering if you could explain the line of code byte manipulation wise so I can understand this better in the future!

    int x = (int)myCode[0] << 8 | (int)myCode[1];

if (x == 0xAAAA)

1. Given that:

myCode[0] = 0xAA;
myCode[1] = 0xAA;

2. Each of the above quantity of Step-1 is of 8-bit. We want to place them side-by-side to get 16-bit (b15 - b0); where, myCode[0] will occupy upper 8-bit position (b15 - b8) and myCode[1] will occupy lower 8-bit positio (b7 - b0) (Fig-1).
make16-bit.png
Figure-1:

3. The above task of Step-2 can be done in this way:
(1) Shift myCode[0] to the left by 8-bit positions about a buffer of 16-bit size for which we have this code: (int)myCode[0]<<8. Now, we have: 0XAA00.

(2) Add or (arithmetic OR) the 16-bit value of Step-3 with myCode[1] (0xAA) after placing the later in a 16-bit buffer (0x00AA) for which we have this code: (int)myCode[1]; as a result, we get: 0XAA00 + 0x00AA (0xAA00 | 0x00AA) = 0xAAAA. (int)myCode[1] is read as: cast 8-bit variable myCode[1] to occupy 16-bit space.

(3) When Step-3 and Step-4 are combined, we get:

int x = (int)myCode[0]<<8 | (int)myCode[1];  // x  0xAAAA

4. Meaning of: if(x == 0xAAAA)
Checking whether x is equal to 0xAAAA or not.

make16-bit.png