CheckSum XOR

Hi all,

I need help on a checksum XOR calculation. This is the code.

String dataToParse;
char toCheck[20];
int incomingByte;
boolean checkS = true;
void setup() 
{
  // put your setup code here, to run once:
  Serial.begin(115200);
}

void loop() 
{
  // put your main code here, to run repeatedly:

   if (Serial.available() > 0)
      { 
    //   incomingByte = Serial.read();
     //  Serial.print("Byte Ricevuti: ");
     //  Serial.println(incomingByte,HEX);       
     //  dataToParse += incomingByte;           
      dataToParse = Serial.readString();
      Serial.print("ToCheckSum.:");
      Serial.println(dataToParse);
      Serial.print("");
      Serial.print("ToCheckLength.:");
      Serial.println(dataToParse.length());
      Serial.print("");
      dataToParse.toCharArray(toCheck,dataToParse.length()+1);
      Serial.print("ToCheckSum.:");
      Serial.println(dataToParse);
      Serial.print("");

      Serial.print("CheckSum.:");
      Serial.println(getCheckSum(toCheck));
      Serial.print("");
     }  
}
uint8_t getCheckSum(char *string)
{
  int XOR = 0;  
  for (int i = 0; i < strlen(string); i++) 
  {
    Serial.print("i.:");
    Serial.println(string[i]);
    Serial.print("");
    XOR = XOR ^ (string[i]);
  }
  dataToParse ="";
  return XOR;  
}

If i put on the input this : 000111031C93 the result should it be = 9C
based on this http://www.scadacore.com/field-tools/programming-calculators/online-checksum-calculator/
But my result is 122.
Don't understand what am I doing wrong..? :o :roll_eyes:

Thanks

You have to convert the incoming data from ascii to binary.

The bytes you are checksumming now are:

"0" = 0x30,
"0" = 0x30,
"0" = 0x30,
"1" = 0x31 etc...

What you should be checksumming is:

0x00, 0x01, 0x11, 0x03, 0x1C, 0x93

In your case, the length of the string is 12, but you want to turn that into 6 bytes.
So you should take 2 characters at time and convert those into a single byte.

  for (int i = 0; i < strlen(string);  i+= 2) // <-- increment by 2
  {
    Serial.print("i.:");
    Serial.println(string[i]);
    Serial.print("");

    // make single byte value out of 2 characters from the string...
    byte b1,b2,b;

    // First byte: hex to bin
    b1 = string[i];
    if (b1 >= 'a')
      b1 = b1 - 'a' + 10;
    else if (b1 >= 'A')
      b1 = b1 - 'A' + 10;
    else
      b1 -= '0';

    // Second byte: hex to bin
    b2 = string[i + 1];
    if (b2 >= 'a')
      b2 = b2 - 'a' + 10;
    else if (b2 >= 'A')
      b2 = b2 - 'A' + 10;
    else
      b2 -= '0';

    // Combine the two
    b = 0x10 * b1 + b2;

    XOR = XOR ^ b;
  }

(You might want to add some sanity checks, that all characters are hex (0..9, A..F), and that the string length is even.)

You should avoid using the String class because it can lead to memory corruption on a small computer. Instead, use null terminated C strings. You can use strtol() to convert hex digits to binary values.

@ Jobi-Wan I added your code but the result is different from what I got from the online calculator.

String dataToParse;
char toCheck[20];
int incomingByte;
boolean checkS = true;
void setup() 
{
  // put your setup code here, to run once:
  Serial.begin(115200);
}

void loop() 
{
  // put your main code here, to run repeatedly:

   if (Serial.available() > 0)
      { 
    //   incomingByte = Serial.read();
     //  Serial.print("Byte Ricevuti: ");
     //  Serial.println(incomingByte,HEX);       
     //  dataToParse += incomingByte;           
      dataToParse = Serial.readString();
      Serial.print("ToCheckSum.:");
      Serial.println(dataToParse);
      Serial.print("");
      Serial.print("ToCheckLength.:");
      Serial.println(dataToParse.length());
      Serial.print("");
      dataToParse.toCharArray(toCheck,dataToParse.length());
      int aaa = getCheckSum(toCheck);
      Serial.print("CheckSum.:");
      Serial.println(aaa);
      Serial.print("");      
      dataToParse ="";
     }  
}
uint8_t getCheckSum(char *string)
{
  int XOR = 0;  
  for (int i = 0; i < strlen(string);  i+= 2) // <-- increment by 2
  {
    Serial.print("i.:");
    Serial.println(string[i]);
    Serial.print("");

    // make single byte value out of 2 characters from the string...
    byte b1,b2,b;

    // First byte: hex to bin
    b1 = string[i];
    if (b1 >= 'a')
      b1 = b1 - 'a' + 10;
    else if (b1 >= 'A')
      b1 = b1 - 'A' + 10;
    else
      b1 -= '0';

    // Second byte: hex to bin
    b2 = string[i + 1];
    if (b2 >= 'a')
      b2 = b2 - 'a' + 10;
    else if (b2 >= 'A')
      b2 = b2 - 'A' + 10;
    else
      b2 -= '0';

    // Combine the two
    b = 0x10 * b1 + b2;

    XOR = XOR ^ b;
  }

  return XOR;  
}

If i put "3132333435" the result should be 31, and I got 4.

Cannot find what is wrong.. :drooling_face:

Thanks

DCloud:
If i put "3132333435" the result should be 31, and I got 4.

To test this, I added a couple of lines to the setup() function:

void setup() 
{
  // put your setup code here, to run once:
  Serial.begin(115200);
  byte cs = getCheckSum("3132333435");
  Serial.print("CS = 0x");
  Serial.println(cs,HEX);
}

And it tells me:

i.:3
i.:3
i.:3
i.:3
i.:3
CS = 0x31

Are you converting the hex digits to use for internal purposes anyway? It seems to me you would want to actually do something with the data. Then you can simply calculate a checksum on the array that you store the values in. The code for that is 10 times simpler.

The code provided by Dcloud convolves reading and checking, which (in an actual program instead of an example) should be two separate functions.

  for (int i = 0; i < strlen(string); i++)

Please don't run strlen each time you check the loop condition. It makes the electrons sad.

  for (int i = 0; string[i] != '\0'; i++)
  for (int i = 0; string[i]; i++)
int len = strlen(string);
for (int i = 0; i < len; i++)

@ aarg

Correct. From the serial input I need to do the XOR checksum.

@ Jobi-Wan Does it work if you put an input from the serial monitor? Using the code I pasted ( with your

checksum part)

Thanks

  • Make sure that dataToParse doesn't have line feed and/or character return at the end.
  • Make sure that toCheck has all of the characters in it and is zero terminated.

DCloud:
@ aarg

Correct. From the serial input I need to do the XOR checksum.

I think you missed my point. I'm saying you have the option of computing a checksum while you read input, or after you finish reading input. I consider it simpler and more straightforward to do the latter.

So guys,

now I get the correct value. This is the code

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

void loop() 
{
  // put your main code here, to run repeatedly:

   if (Serial.available() > 0)
      {           
      dataToParse = Serial.readString();
      Serial.print("ToCheckSum.:");
      Serial.println(dataToParse);
      Serial.print("");
      Serial.print("ToCheckLength.:");
      Serial.println(dataToParse.length());
      Serial.print("");
      char toCheck[dataToParse.length()];
      Serial.print("Size ToCheck.:");
      Serial.println(sizeof(toCheck));
      dataToParse.toCharArray(toCheck,dataToParse.length());
      byte aaa = getCheckSum(toCheck);
      Serial.print("CheckSum HEX.:");
      Serial.println(aaa,HEX);
      Serial.print("CheckSum DEC.:");
      Serial.println(aaa,DEC);
      Serial.print("");      
      dataToParse ="";
     }  
}
uint8_t getCheckSum(char *string)
{
  int XOR = 0;  
  for (int i = 0; string[i] != '\0';  i+= 2) // <-- increment by 2
  {
    Serial.print("i.:");
    Serial.println(string[i]);
    Serial.print("");

    // make single byte value out of 2 characters from the string...
    byte b1,b2,b;

    // First byte: hex to bin
    b1 = string[i];
    if (b1 >= 'a')
      b1 = b1 - 'a' + 10;
    else if (b1 >= 'A')
      b1 = b1 - 'A' + 10;
    else
      b1 -= '0';

    // Second byte: hex to bin
    b2 = string[i + 1];
    if (b2 >= 'a')
      b2 = b2 - 'a' + 10;
    else if (b2 >= 'A')
      b2 = b2 - 'A' + 10;
    else
      b2 -= '0';

    // Combine the two
    b = 0x10 * b1 + b2;

    XOR = XOR ^ b;
  }

  return XOR;  
}

My ( stupid ) error was on the (NL) on the serial monitor of the IDE :sleeping: :zipper_mouth_face: :smiley_cat:

Thank you guys :smiley: