DCloud
July 7, 2017, 10:03am
1
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
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..
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++)
DCloud
July 10, 2017, 12:08pm
8
@ 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
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.
DCloud
July 10, 2017, 3:36pm
11
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
Thank you guys