Go Down

Topic: HMC5883L library is incorrect while it work with Arduino Due (Read 4075 times) previous topic - next topic


I got the HMC5883L library from following web page.

I've tested it with Arduino Pro mini, it is OK.
But the result on Due is incorrect.
It seems not consider the 2's complement.

the attached image shows Due not consider 2's complement.
and following data come from I2C sniffer.
Code: [Select]

-------------------- Start to Monitor I2C / SMBus / PMBus Procotol --------------------
-------------------- All data will be monitored and display on screen -----------------
[S] 3C 02 00 [P]
[S] 3C 03 [P]
[S] 3D 00 F3 01 52 FF 82# [P]

for 2's complement, 0xFF82 should be -126 not 65410.

Could somebody tell me how to fix this issue?



If you post your sketch it could be easier to find the problem.

BTW at 99% your issue is caused by the different "int" size on the Arduino Due.

The Atmega based boards use int size of 16bit.
The Arduino Due runs a 32bit CPU where the int size is 32bit.


said that, you should consider the value 0xFF82 placed in 16 bit or 32 bit fields:

16 bit integer:  0xFF82 => -126
32 bit integer:  0x0000FF82 => 65410

note that in the 32 bit case the sign bit is 0 so the value displayed is the "correct" 65410.

The solution to your issue could be to use "int16_t" or "short" instead of "int".



Feb 25, 2013, 01:56 pm Last Edit: Feb 25, 2013, 02:06 pm by daniel666 Reason: 1
I confirm this.
In HMC5883L Library we read two's 8-bit registers ( MSB and LSB) and create from this16-bit signed int value by shift most significant byte by 8 and do inclusive OR with least significant byte:  
Code: [Select]
int value = (MSB << 8 ) | LSB;

Registers are stored in uint8_t (from <inttypes.h>) buffers.

As I understand what cmaglie said: an int type was 16-bits on other Arduino boards, so casting by shifting and OR was OK because sign bit was on right place.
Arduino Due using 32-bits integers so when we shift by 8 and do OR sign bit is 16 bit (not 32) and while casting we get wrong value ??  

I will try with 16-bits integers as cmaglie said but I want to know how to change it in correct (efficient) way ?

Edit: Changing int to int16_t works.

I propose to change

1. raw data types:
Code: [Select]

struct MagnetometerRaw
    int16_t XAxis;
    int16_t YAxis;
    int16_t ZAxis;

2. includes:
Code: [Select]
#include WProgram.h to
Code: [Select]
#include <Arduino.h> in HMC5883L.cpp

3. read and write methods of Wire library:

In HMC5883L.cpp change Wire.send to Wire.write and Wire.receive to Wire.read

Go Up