×

Please see all COVID-19 updates here as some shipments may be delayed due to CDC safety and staffing guidelines. If you have an order or shipping question please refer to our Customer Support page. For technical questions please check out our Forums. Thank you for your continued support.

Joe P2

Member Since: December 3, 2009

Country: United States

  • We ran into problems reading ABS_POS on an Arduino board, too. The problem seems to be in the dSPIN_Param function in file dSPIN_support.ino.

    C silently converts types shorter than int to int prior to any arithmetic operations. Ints in Arduino are 16 bits, so the left shift operations on the bytes returned by dSPIN_Xfer don't work as intended with 16 bit ints.

    Consider how dSPIN_Param handles the first byte returned from dSPIN_Xfer:

    if (byte_len == 3) {
        ret_val |= dSPIN_Xfer(...) < < 16;
    }
    

    dSPIN_Xfer returns a byte, and it is silently converted into a signed, 16 bit int, and then it is left shifted 16 bits. A 16 bit value shifted left 16 bits is 0. So the most significant byte of the ABS_POS is effectively ignored. Surprise #1.

    The next byte is handled the same way, except it's shifted left 8 bits, but this also causes an unexpected result. Suppose dSPIN_Xfer returns 0x80. It's first converted to an int (0x0080), then shifted left 8 bits (0x8000). But this is now a negative value in a (signed, 16 bit) int. So when it's converted to an unsigned long to be OR'd with ret_val, it's converted to 0xFFFF8000. Surprise #2.

    The solution that worked for us was to explicitly cast the value returned by dSPIN_Xfer to an unsigned long. This forces the conversion of the 8 bit byte to a 32 bit value, which is long enough to handle the left shifts properly.

    ret_val |= (unsigned long)dSPIN_Xfer(...) < < 16;
    ...
    ret_val |= (unsigned long)dSPIN_Xfer(...) < < 8;
    ...
    ret_val |= (unsigned long)dSPIN_Xfer(...);
    

    (It's not strictly needed in the last case, but I like consistency.)

    I suspect the original code was written for a system that used 32 bit ints, on which the left shifts would have worked as intended.

    I hope Sparkfun will change the example sketch to save other from this subtle bit of C behavior.

No public wish lists :(