2
\$\begingroup\$

So I'm interfacing an arduino with a Melexis temperature sensor, and it's going okay--aside from the fact that I can't seem to get the CRC check to work.

I've gotten read operations to complete successfully (although my software ignores the packet error code) but I have tried a lot of implementations of CRC8 to check the PEC byte to no avail. The code block I am using now came from OneWire:

uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len)
{
    uint8_t crc = 0;

    while (len--) {
        uint8_t inbyte = *addr++;
        for (uint8_t i = 8; i; i--) {
            uint8_t mix = (crc ^ inbyte) & 0x01;
            crc >>= 1;
            if (mix) crc ^= 0x8C;
            inbyte >>= 1;
        }
    }
    return crc;
}

I rewrote it to consider just the one byte:

int smbCRC(int message) {

    uint8_t crc = 0;

  uint8_t inbyte = message & 0xFF;
  for (uint8_t i = 8; i; i--) {
    uint8_t mix = (crc ^ inbyte) & 0x01;
    crc >>= 1;
    if (mix) crc ^= 0x8C;
    inbyte >>= 1;
  }

    return crc;
}

But its CRC does not match that of the MLX datasheet (Figure 8 from here for example). When I print an int with its CRC8 like so:

int message = 0x3aD2;
lcd.print(String(message,HEX) + " " + String(smbCRC(message),HEX));

I get back "3ad2 eb", though the datasheet says the correct PEC is 0x30. Where am I going wrong? It seems like this could be caused by a bad implementation of CRC or bad assumptions on my part about the CRC input, and I'm not sure where to start troubleshooting.

\$\endgroup\$
  • \$\begingroup\$ Why are you restricting smbCRC() to the one byte, while sending it more than one byte? \$\endgroup\$ – TimH - Codidact Dec 12 '13 at 22:06
  • \$\begingroup\$ I don't know much about CRCs, but it looks to me like "polynomial X8+X2+X1+1" doesn't match your XOR value of 0x8C... Not sure what to suggest, though. Best of luck! \$\endgroup\$ – TimH - Codidact Dec 12 '13 at 22:29
  • \$\begingroup\$ Possibly a helpful link. OK, I'll be quiet now... ;-) \$\endgroup\$ – TimH - Codidact Dec 12 '13 at 22:41
  • \$\begingroup\$ As you are passing 2 bytes in (0x3AD2) and your CRC function only works on one byte at a time you will get the wrong answer. Your crc function could be changed to take the crc seed as a function parameter, which would allow multiple calls. \$\endgroup\$ – David Dec 13 '13 at 6:17
  • \$\begingroup\$ There are many things which can be "tweaked" in a CRC implementation: the polynomial, the initial state, even the byte order and the bit order are non-intuitive sometimes. This link has everything you need to know in a reasonably readable form: zlib.net/crc_v3.txt \$\endgroup\$ – Martin Thompson Dec 13 '13 at 9:27
2
\$\begingroup\$

The code you have above is a polynomial of x8 + x5 + x4 + 1. I thought it looked familiar and I just checked some code and it's what the Dallas 1-wire devices use, so I guess you've found some code written for those devices (as also implied from the class name).

The x8 + x2 + x1 + 1 this device requires is also known as CRC-8-CCITT. There's a problem with your modified code but revert back to the first version and try changing 0x8C to 0xE0. There's a table of them on Wikipedia under polynomial representations of cyclic redundancy checks.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

It has become clear to me at this point that everything that could go wrong, has.

I used a calculator to figure out exactly what was being considered by the CRC examples in the figures in the datasheet, and discovered that the command, address, AND data were all part of the calculation. So problem one was that I was not supplying enough data to the algorithm.

For Figure 8, the whole packet was 0xb407b5d23a -> 0x30

For Figure 9, the whole packet was 0xb42207c8 -> 0x48

I am currently distracted by a different project at work but I will update this answer soon!

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.