Author Topic: Serial protocol Checksum calculation  (Read 5993 times)

0 Members and 1 Guest are viewing this topic.

Offline Precious RoyTopic starter

  • Contributor
  • Posts: 18
  • Country: nl
Serial protocol Checksum calculation
« on: October 19, 2016, 07:08:05 am »
Hello,

I am working on reading out a scale via a serial connection, my English is not to good and i dont understand the explanation they give in the datasheet.
i was wondering can any of you explain how to do the checksum in simple English.

Code: [Select]
/*
??????????????????????????????????????????????????????????????
|STX|Status|Net Weight|Gross Weight|Peak Weight|ETX|Check|EOT|
??????????????????????????????????????????????????????????????
  1 |  2   |    3     |     4      |     5     | 6 |  7  | 8

  1 = Start of transmission, 1 Byte
  2 = Status of scale, 1 Byte
  3 = Net weight of the scale, 6 Bytes
  4 = Gross weight of scale, 6 Bytes
  5 = Peak weight of scale, 6 bits
  6 = End of text, 1 byte
  7 = Checksum is the ASCII encoding of the two hexadecimal digits, 2 byte
  8 = End of transmission, 1byte

  Checksum = 2 ASCII control characters calculated considering the characters between STX and ETX excluded.
  The control value is obtained by executing the operation of XOR (or exclusive) of the 8-bit ASCII codes of
  the characters considered. The result is a character that is expressed in hexadecimal with 2 digits that can
  take values from "O" to "9" and "A" to "F".
*/

I got my explanation form a different data sheet that i can not find on the web, but i do not understand ether of them.
Datasheet http://www.prisma.co.il/upload/DAT400DeviceNetmanual0.7(1).pdf Page 20
« Last Edit: October 19, 2016, 07:14:54 am by Precious Roy »
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: Serial protocol Checksum calculation
« Reply #1 on: October 19, 2016, 07:17:14 am »
How would you like to see the reply? In code? Do you have any test messages you can share?

It seems pretty simple - XOR the byte values of all the characters between STX and ETX characters, and output that as two hexidecimal digits.
and output that as two hexidecimal digits.

STX is ASCII code 2, ETX is code 3 and EOT is code 4.

« Last Edit: October 19, 2016, 07:20:33 am by hamster_nz »
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline Precious RoyTopic starter

  • Contributor
  • Posts: 18
  • Country: nl
Re: Serial protocol Checksum calculation
« Reply #2 on: October 19, 2016, 07:23:26 am »
yes thats what i was thinking but the checksum is 2 bytes and the amount of bytes between STX and ETX is 1+6+6+6 = 19 witch is not divisible by 2.

so that means i am not understanding what they want me to do.

Edit:
it does not mater how i get it, i can post the code i have at the moment but it is really simple. i do not have a sample of the output, but if you really need it i can write some code to get it.
Code: [Select]
/*
??????????????????????????????????????????????????????????????
|STX|Status|Net Weight|Gross Weight|Peak Weight|ETX|Check|EOT|
??????????????????????????????????????????????????????????????
  1 |  2   |    3     |     4      |     5     | 6 |  7  | 8

  1 = Start of transmission, 1 Byte
  2 = Status of scale, 1 Byte
  3 = Net weight of the scale, 6 Bytes
  4 = Gross weight of scale, 6 Bytes
  5 = Peak weight of scale, 6 bits
  6 = End of text, 1 byte
  7 = Checksum is the ASCII encoding of the two hexadecimal digits, 2 byte
  8 = End of transmission, 1byte

  Checksum = 2 ASCII control characters calculated considering the characters between STX and ETX excluded.
  The control value is obtained by executing the operation of XOR (or exclusive) of the 8-bit ASCII codes of
  the characters considered. The result is a character that is expressed in hexadecimal with 2 digits that can
  take values from "O" to "9" and "A" to "F".
*/
enum ScaleStatus
{
STABLE = 'S', // Stable weight
MOVING = 'M', // Moving weight
OVER = 'O', // Over capacity
UNKOWN  = 'E' // Can not be detected
};

const byte STX = 0; //1
const byte Status = 1; //1
const byte Net = 2; //6
const byte Gross = 8; //6
const byte Peak = 14; //6
const byte ETX = 20; //1
const byte Checksum = 21; //2
const byte EOT = 23; //1


void ProcessTimeString(char* ScaleString)
{
if (ScaleString[EOT] != '\0' && ScaleString[EOT + 1] == '\0') //should be 24 chars
{
//checksum

//status
m_Status = (ScaleStatus)ScaleString[Status];

char tmp[6]; // 6 last char is end of string, 5 because i am ignoring the 100liko digit

//net
memset(tmp, '0/', 6);
memcpy(tmp, ScaleString + Net + 1, 5);
m_Weight = atoi(tmp);

//gross
memset(tmp, '0/', 6);
memcpy(tmp, ScaleString + Gross + 1, 5);
m_GrossWeight = atoi(tmp);

//peak
memset(tmp, '0/', 6);
memcpy(tmp, ScaleString + Peak + 1, 5);
m_PeakWeight = atoi(tmp);
}
}
« Last Edit: October 19, 2016, 07:35:41 am by Precious Roy »
 

Offline Rerouter

  • Super Contributor
  • ***
  • Posts: 4694
  • Country: au
  • Question Everything... Except This Statement
Re: Serial protocol Checksum calculation
« Reply #3 on: October 19, 2016, 07:34:09 am »
I would imagine you have to pad 1 value, so AA becomes 00AA or AA00 if its uneven
 

Offline Precious RoyTopic starter

  • Contributor
  • Posts: 18
  • Country: nl
Re: Serial protocol Checksum calculation
« Reply #4 on: October 19, 2016, 07:37:11 am »
I guess but now the question is (it does not mention it so does that mean i need to test it out ?) do i begin with the  padding or  end with it ?
 

Offline Rerouter

  • Super Contributor
  • ***
  • Posts: 4694
  • Country: au
  • Question Everything... Except This Statement
Re: Serial protocol Checksum calculation
« Reply #5 on: October 19, 2016, 07:46:32 am »
could you post some example strings?

what value each byte contains in a valid message, it should not be hard to work back from there.
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: Serial protocol Checksum calculation
« Reply #6 on: October 19, 2016, 08:25:03 am »
My take on a sample message, and code to verify... note that STX, ETX and EOT are single character constants!

Code: [Select]
#include <stdio.h>
#include <string.h>

#define STX "\002"
#define ETX "\003"
#define EOT "\004"

static const char test_data[25] = STX "2333333444444555555" ETX "32" EOT;
static const char to_hex[16] = "0123456789ABCDEF";

static int verify_message(const char *message)
{
  unsigned char checksum = 0;
  char digit1, digit2;
  int i;

  /* Validate length */
  if(strlen(message) != 24) return 0;

  /* Validate STX */
  if(message[0]  != 2) return 0;
  /* Validate ETX */
  if(message[20] != 3) return 0;
  /* Validate EOT */
  if(message[23] != 4) return 0;

  /* Calculate the checksum (note STX and ETX are not included) */
  for(i = 1; i < 20; i++)
     checksum ^= message[i];

  /* Split into digits */
  digit1 = to_hex[checksum / 16];
  digit2 = to_hex[checksum & 0xF];
  printf("Calculated checksum is %c%c\n", digit1,digit2);

  /* Verify the digits */
  if(test_data[21] != digit1) return 0;
  if(test_data[22] != digit2) return 0;
  return 1;
}

int main (void)
{
  if(verify_message(test_data))
    printf("Verification passes\n");
  else
    printf("Verification FAILED\n");
  return 0;
}
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline Precious RoyTopic starter

  • Contributor
  • Posts: 18
  • Country: nl
Re: Serial protocol Checksum calculation
« Reply #7 on: October 19, 2016, 08:53:57 am »
so i got a sample message in binary form,
2,83,48,48,48,48,48,48,48,48,52,54,57,56,48,48,52,55,48,48,3,53,51,4,
-  S   0    0   0   0    0   0   0   0   4    6   9   8   0    0   4   7   0    0  -  check  -
it was rather hard to get in string because of the missing characters

Edit: hamster_nz i will test your code but first study up on what you ar doing :}
Edit 2: i had to change some formatting stuff but it works like a charm thanks you so much but could i ask you to elaborate on this part
Code: [Select]

digit1 = to_hex[checksum / 16];
digit2 = to_hex[checksum & 0x0F];

ar you getting the low and high part of the byte as in H 0000|0000 L
« Last Edit: October 19, 2016, 09:17:28 am by Precious Roy »
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: Serial protocol Checksum calculation
« Reply #8 on: October 19, 2016, 10:20:10 am »
could i ask you to elaborate on this part
Code: [Select]

digit1 = to_hex[checksum / 16];
digit2 = to_hex[checksum & 0x0F];

ar you getting the low and high part of the byte as in H 0000|0000 L

Yes, there is a little trap in that checksum has to be "unsigned char" or bad things may happen.

For example, if checksum is "signed char" and 0x80 (-128 decimal), then checksum/16 = -8, or 0xF8, and then it will try to access to_hex[-8], causing bad things.

Maybe I should have written it as follows to avoid those bad things...
Code: [Select]

digit1 = to_hex[(checksum / 16)&0xF];
digit2 = to_hex[checksum & 0x0F];
   

You could do the same transform programmatically to avoid the lookup table:
Code: [Select]

/* Split out the digits */
digit1 = (checksum / 16)&0xF;
digit2 = checksum & 0x0F;
/* Convert digits to ASCII characters */
digit1 += (digit1 > 9) ? 'A'-10 : '0';
digit2 += (digit2 > 9) ? 'A'-10 : '0';
   
But that is just fugly :D.

Using the lookup table shows the intent better, but it does introduce that possibility of maybe looking outside of the lookup table that should be guarded against.

Also, the lookup table removes the assumption that you are working in a character set where the digits and letters are sequential and leaves less magic to explain to those not familiar with ASCII codes.
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline amyk

  • Super Contributor
  • ***
  • Posts: 8258
Re: Serial protocol Checksum calculation
« Reply #9 on: October 19, 2016, 11:06:30 am »
Code: [Select]
  7 = Checksum is the ASCII encoding of the two hexadecimal digits, 2 byte
This is the key point, the checksum itself is a single byte but then gets converted into ASCII text format. So XOR together the 19 bytes, interpret the two checksum bytes as text representation of a hex byte, and then compare the resulting values.
 

Offline Precious RoyTopic starter

  • Contributor
  • Posts: 18
  • Country: nl
Re: Serial protocol Checksum calculation
« Reply #10 on: October 19, 2016, 12:46:43 pm »
 hamster_nz Thanks for al your help, together with amyk everything is clear, i am just left wondering why it is written down so confusing 20 more words and everything would of been fine
 

Offline bson

  • Supporter
  • ****
  • Posts: 2269
  • Country: us
Re: Serial protocol Checksum calculation
« Reply #11 on: October 19, 2016, 06:36:08 pm »
I too would think I misunderstood if I saw a suggestion to use xor to perform checksumming.  :palm:
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf