Checksum calculation leading to crash (dividing by 0)

Hi there,

I have run into my first real problem trying to code a way of checking the data then comparing my calculated checksum to the UART received checksum value.

According to the manufacturer's datasheet, the equation is as follow:

Check value=(invert( Byte1+Byte2+...+Byte7/Byte24))+1

Attempting to run this code ends in a system crash, as Byte24 is always 0, and I am trying to divide by it.

Maybe I am missing some knowledge on what they actually mean? I tried searching the forum previously and found no similar problem, so forgive me if this has been explained before.

Here is my code in question (all serial prints are for debugging):

  if(mySerial.available()>0) {                          // Checks is there's any data in buffer 
    int byteLength = mySerial.available();
    Serial.println(byteLength);
    int preCheckData[byteLength];
    for (int i = 0; i < byteLength; i++) {    // Updates data from the sensor module to the table
      preCheckData[i] = mySerial.read();
    };
    int chkSum = (~(preCheckData[1]+preCheckData[2]+preCheckData[3]+preCheckData[4]+preCheckData[5]+preCheckData[6]+preCheckData[7]/preCheckData[24])+ 1);
    Serial.println(String(checkSum)); // Crashes at this point when calculating chkSum
    
    limitListener(); Serial.println(preCheckData[25]);
  }  

Device: Wemos D1 Mini

Hi, @Bobertsawesome
Welcome to the forum.

Please read the post at the start of any forum , entitled "How to use this Forum".

This will help with advice on how to present your code and problems.

The link shows you how to post your code in a scrolling window.

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

1 Like

This is not very clear but is an attempt to describe the two separate check digits, one for the command and one for the returned data.

Command:
Check value=(invert( Byte1+Byte2+...+Byte7))+1

Returned Data:
Check value=(invert( Byte1+Byte2+...+Byte24))+1

1 Like

what guarantees you that this is not null ?
you don't even know if you read 25 bytes from the Serial port

Arrays are 0 indexed! if your array has a size of 25, the last index is 24.

I think it's a typo or a "Chinglish" translation problem.

Looking at the datasheet, the command format example given shows the following data bytes:

0xFF 
0x86 
0x00 0x65 
0x00 0x36 
0x00 0x96 
0x01 0x9A 
0x00 
0x02 0xFD 
0x00 0x28 
0x00 0x28 
0x00 0x05 
0x00 0x20 
0x00 0x50 
0x00 0x00

If you add all of these up you get 0x0515. Add 0x01 to get 0x0516. To that, add the check byte 0xEA and you get 0x0600. The LSB (0x00) is what matters; as long as it's zero (0x00) your message is good.

So a checksum algorithm might be:

uint8_t preCheckData[] = 
    {
        0xFF,           //0     start
        0x86,           //1     reserved
        0x00, 0x65,     //2     PM1.0
        0x00, 0x36,     //4     PM2.5
        0x00, 0x96,     //6     PM10
        0x01, 0x9A,     //8     CO2
        0x00,           //10    VOC
        0x02, 0xFD,     //11    Temperature
        0x00, 0x28,     //13    Humidity
        0x00, 0x28,     //15    CH2O
        0x00, 0x05,     //17    CO
        0x00, 0x20,     //19    Ozone (O3)
        0x00, 0x50,     //21    NO2
        0x00, 0x00,     //23    reserved
        0xEA            //25    checksum
        
    };

void setup( void )
{
    Serial.begin(115200);
    
    uint16_t sum = 1;
    for( uint8_t i=0; i<(sizeof(preCheckData)/sizeof(preCheckData[0])); i++ )
        sum = sum + preCheckData[i];
    if( (sum & 0xff) == 0x00 )
    {
        Serial.println( "Message is good." );
        
    }//if
    else
    {
        Serial.println( "Message is bad." );
        
    }//else
    
}//setup

void loop( void )
{
}//loop

Maybe this only works for this particular message but it's worth a try.

1 Like

That is not exactly the way I have understood it. From the example you've quoted, byte0, the fixed start byte (0xFF), should be omitted (or fixed at 0x0). The only bytes required are byte1 through to byte24. That is this rather cryptically written Check value=(invert( Byte1+Byte2+...+Byte24))+1 which says how the check digit is constructed, not (necessarily) the best way to check it.

You've seen that it is a standard mod 256 check digit so simply adding up all the digits, including the check digit, should yield 0x0, which it does. You can also do it all in a uint8_t variable and it simply rolls over.

1 Like

Fair enough.

This worked perfectly, and I tested with a simulated wrong byte where I confirmed it was rejected. I'll have to read up on why that is the checksum and how you came to that calculation, but I appreciate the help in the right direction.

So yes, I assume it was just a weird way to write the checksum? I assume people well versed in reading and interpreting byte comms would recognize what they truly mean.

Meh. Just "not very good" documentation, using a symbol ("/") with both a mathematical (division) and a textual ("or") interpretation.

1 Like

To be fair the product is intended for industrial and product implementation, so I can forgive them for not spelling it out haha.