Search code examples
protocolsdecodechecksumcrc

Checksum/CRC calculation


I am decoding a message sent by an wireless outdoor weather station. I have figured out what most of the protocol means except haven't been able to determine how to calculate the checksum. Here is what I've found so far:

 0100 0111 0110 0000 0111 0100 0011 0010 1110 0110
|----|---------|--------------|---------|---------|
 start   id         temp        humidity  checksum?

So in the above example the temperature was 11.6 degrees and 50% humidity. The "id" field changes to a "random" value when I replace the batteries in the outdoor transmitter. The last 8 bits only change when the id/temp/humidity changes so I'm fairly certain those are the checksum/crc bits.

Here are a bunch of different transmissions:

0100 1110 0101 0000 1001 0010 0011 0011 1010 0001
0100 1110 0101 0000 1001 0010 0011 0100 0011 0110
0100 0111 0110 0000 1001 0010 0011 0100 0110 1100
0100 0111 0110 0000 1001 0010 0011 0101 0101 1101
0100 0111 0110 0000 1001 0100 0011 0101 0000 0111
0100 0111 0110 0000 1001 0101 0011 0110 1010 0000
0100 0111 0110 0000 1001 1000 0011 0111 1101 0001
0100 0111 0110 0000 1010 1000 0011 0111 0110 0011
0100 0111 0110 0000 1010 1001 0011 0111 1001 0111
0100 0111 0110 0000 1010 1010 0011 0111 1011 1010
0100 0111 0110 0000 0111 0100 0011 0010 1110 0110
0100 0111 0110 0000 0111 0101 0011 0010 0001 0010
0100 0111 0110 0000 0111 0110 0011 0010 0011 1111

I'm not familiar with checksum/crc techniques, can anyone see what might be being used here or point me in a direction for how to determine this?


Solution

  • Hacked OK. Here's the C# code to generate the 5-th byte out of the previous 4 bytes.

    /// <summary>A variant of CRC-8</summary>
    /// <param name="data">Pass here the first 4 bytes of data, e.g. { 0x4E 0x50 0x92 0x33 }</param>
    /// <returns>The computed SRC value, e.g. 0xA1 for the data specified above.</returns>
    static byte src8( byte[] data )
    {
        byte res = 0;
        foreach( byte b in data )
        {
            byte val = b;
            for( int i = 0; i < 8; i++ )
            {
                byte tmp = (byte)( ( res ^ val ) & 0x80 );
                res <<= 1;
                if( 0 != tmp )
                    res ^= 0x31;
                val <<= 1;
            }
        }
        return res;
    }