I recently purchased the HMC5883L I2C compass module. The first thing I did was run the I2C scanner to confirm the address was 0D and to make sure it was communicating. So I know the module is talking to the Nano but the results it gives in the serial monitor are all zeros for X,Y,Z. I can pull the SDA or SCL wire and the numbers peg out then return to zero's when I land the wire back.
so I'm pretty sure its not a communication issue. I also tried the Adafruit_Sensor.h &
Adafruit_HMC5883_U.h libraries.
The "Magsensor" sketch runs and gives the unique ID an and other info from the chip so I know that it can communicate that info to the Nano. However the magsensor sketch never gives the x, y, z info. It seems to stop after running the setup and displaying the HMC5883 module information*.(unique ID#, Driver ver.#, Name, etc...* So I went back to the simple sketch that only uses the "wire" library and I get the same results......well now I get the values for x, y, z updated but they are always zero.
I bought 2 of the same HMC5883L's from different vendors, they are pinned out opposite but both are address 0D and both give all zero's for x, y, z.
I'm stumped and thought somebody may be able to help
thanks in advance..........
hope I did this right, this is only my second post
#include <Wire.h> //I2C Arduino Library
#define addr 0x0D //I2C Address for The HMC5883
void setup()
{
Serial.begin(9600);
Wire.begin();
Wire.beginTransmission(addr); //start talking
Wire.write(0x02); // Set the Register
delay(100);
Wire.write(0x00); // Tell the HMC5883 to Continuously Measure
Wire.endTransmission();
}
void loop()
{
int x,y,z; //triple axis data
//Tell the HMC what regist to begin writing data into
Wire.beginTransmission(addr);
Wire.write(0x03); //start with register 3.
Wire.endTransmission();
//Read the data.. 2 bytes for each axis.. 6 total bytes
Wire.requestFrom(addr, 6);
if(6<=Wire.available()){
x = Wire.read()<<8; //MSB x
x |= Wire.read(); //LSB x
z = Wire.read()<<8; //MSB z
z |= Wire.read(); //LSB z
y = Wire.read()<<8; //MSB y
y |= Wire.read(); //LSB y
}
Please use code tags, not quotes, when posting code. If you have questions, read the "How to use this forum" post.
Please post a link to the exact module you purchased, post the "Magsensor" code that you used (using code tags) and a copy of the output that appears on the serial monitor.
[quote]
[color=#7E7E7E]/***************************************************************************[/color]
[color=#7E7E7E] This is a library example for the HMC5883 magnentometer/compass[/color]
[color=#7E7E7E] Designed specifically to work with the Adafruit HMC5883 Breakout[/color]
[color=#7E7E7E] http://www.adafruit.com/products/1746[/color]
[color=#7E7E7E] [/color]
[color=#7E7E7E] *** You will also need to install the Adafruit_Sensor library! ***[/color]
[color=#7E7E7E] These displays use I2C to communicate, 2 pins are required to interface.[/color]
[color=#7E7E7E] Adafruit invests time and resources providing this open source code,[/color]
[color=#7E7E7E] please support Adafruit andopen-source hardware by purchasing products[/color]
[color=#7E7E7E] from Adafruit![/color]
[color=#7E7E7E] Written by Kevin Townsend for Adafruit Industries with some heading example from[/color]
[color=#7E7E7E] Love Electronics (loveelectronics.co.uk)[/color]
[color=#7E7E7E] [/color]
[color=#7E7E7E] This program is free software: you can redistribute it and/or modify[/color]
[color=#7E7E7E] it under the terms of the version 3 GNU General Public License as[/color]
[color=#7E7E7E] published by the Free Software Foundation.[/color]
[color=#7E7E7E] [/color]
[color=#7E7E7E] This program is distributed in the hope that it will be useful,[/color]
[color=#7E7E7E] but WITHOUT ANY WARRANTY; without even the implied warranty of[/color]
[color=#7E7E7E] MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the[/color]
[color=#7E7E7E] GNU General Public License for more details.[/color]
[color=#7E7E7E] You should have received a copy of the GNU General Public License[/color]
[color=#7E7E7E] along with this program. If not, see <http://www.gnu.org/licenses/>.[/color]
[color=#7E7E7E] ***************************************************************************/[/color]
#include <[color=#CC6600]Wire[/color].h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>
[color=#7E7E7E]/* Assign a unique ID to this sensor at the same time */[/color]
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);
[color=#CC6600]void[/color] displaySensorDetails([color=#CC6600]void[/color])
{
sensor_t sensor;
mag.[color=#CC6600]getSensor[/color](&sensor);
[color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color]([color=#006699]"------------------------------------"[/color]);
[color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color] ([color=#006699]"Sensor: "[/color]); [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color](sensor.[color=#CC6600]name[/color]);
[color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color] ([color=#006699]"Driver Ver: "[/color]); [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color](sensor.[color=#CC6600]version[/color]);
[color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color] ([color=#006699]"Unique ID: "[/color]); [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color](sensor.sensor_id);
[color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color] ([color=#006699]"Max Value: "[/color]); [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color](sensor.max_value); [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color]([color=#006699]" uT"[/color]);
[color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color] ([color=#006699]"Min Value: "[/color]); [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color](sensor.min_value); [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color]([color=#006699]" uT"[/color]);
[color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color] ([color=#006699]"Resolution: "[/color]); [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color](sensor.resolution); [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color]([color=#006699]" uT"[/color]);
[color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color]([color=#006699]"------------------------------------"[/color]);
[color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color]([color=#006699]""[/color]);
[color=#CC6600]delay[/color](500);
}
[color=#CC6600]void[/color] [color=#CC6600][b]setup[/b][/color]([color=#CC6600]void[/color])
{
[color=#CC6600][b]Serial[/b][/color].[color=#CC6600]begin[/color](9600);
[color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color]([color=#006699]"HMC5883 Magnetometer Test"[/color]); [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color]([color=#006699]""[/color]);
[color=#7E7E7E]/* Initialise the sensor */[/color]
[color=#CC6600]if[/color](!mag.[color=#CC6600]begin[/color]())
{
[color=#7E7E7E]/* There was a problem detecting the HMC5883 ... check your connections */[/color]
[color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color]([color=#006699]"Ooops, no HMC5883 detected ... Check your wiring!"[/color]);
[color=#CC6600]while[/color](1);
}
[color=#7E7E7E]/* Display some basic information on this sensor */[/color]
displaySensorDetails();
}
[color=#CC6600]void[/color] [color=#CC6600][b]loop[/b][/color]([color=#CC6600]void[/color])
{
[color=#7E7E7E]/* Get a new sensor event */[/color]
sensors_event_t event;
mag.getEvent(&event);
[color=#7E7E7E]/* Display the results (magnetic vector values are in micro-Tesla (uT)) */[/color]
[color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color]([color=#006699]"X: "[/color]); [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color](event.magnetic.x); [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color]([color=#006699]" "[/color]);
[color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color]([color=#006699]"Y: "[/color]); [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color](event.magnetic.y); [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color]([color=#006699]" "[/color]);
[color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color]([color=#006699]"Z: "[/color]); [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color](event.magnetic.z); [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color]([color=#006699]" "[/color]);[color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color]([color=#006699]"uT"[/color]);
[color=#7E7E7E]// Hold the module so that Z is pointing 'up' and you can measure the heading with x&y[/color]
[color=#7E7E7E]// Calculate heading when the magnetometer is level, then correct for signs of axis.[/color]
[color=#CC6600]float[/color] heading = [color=#CC6600]atan2[/color](event.magnetic.y, event.magnetic.x);
[color=#7E7E7E]// Once you have your heading, you must then add your 'Declination Angle', which is the 'Error' of the magnetic field in your location.[/color]
[color=#7E7E7E]// Find yours here: http://www.magnetic-declination.com/[/color]
[color=#7E7E7E]// Mine is: -13* 2' W, which is ~13 Degrees, or (which we need) 0.22 radians[/color]
[color=#7E7E7E]// If you cannot find your Declination, comment out these two lines, your compass will be slightly off.[/color]
[color=#CC6600]float[/color] declinationAngle = 0.22;
heading += declinationAngle;
[color=#7E7E7E]// Correct for when signs are reversed.[/color]
[color=#CC6600]if[/color](heading < 0)
heading += 2*[color=#006699]PI[/color];
[color=#7E7E7E]// Check for wrap due to addition of declination.[/color]
[color=#CC6600]if[/color](heading > 2*[color=#006699]PI[/color])
heading -= 2*[color=#006699]PI[/color];
[color=#7E7E7E]// Convert radians to degrees for readability.[/color]
[color=#CC6600]float[/color] headingDegrees = heading * 180/M_PI;
[color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color]([color=#006699]"Heading (degrees): "[/color]); [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color](headingDegrees);
[color=#CC6600]delay[/color](500);
}
[/quote]
I hope I loaded this sketch correct. Sorry about the last one, I should have read the forum rules first. Duh.
Here are the results from the serial monitor when I run this "magsensor" sketch.
I just cut and pasted it from the serial monitor, I hope that's ok.
serial monitor output:
HMC5883 Magnetometer Test
Sensor: HMC5883
Driver Ver: 1
Unique ID: 12345
Max Value: 800.00 uT
Min Value: -800.00 uT
Resolution: 0.20 uT
Here is the link to the module I bought on Ebay.
Both modules repond to the I2C scanner with the address 0D
/***************************************************************************
This is a library example for the HMC5883 magnentometer/compass
Designed specifically to work with the Adafruit HMC5883 Breakout
http://www.adafruit.com/products/1746
*** You will also need to install the Adafruit_Sensor library! ***
These displays use I2C to communicate, 2 pins are required to interface.
Adafruit invests time and resources providing this open source code,
please support Adafruit andopen-source hardware by purchasing products
from Adafruit!
Written by Kevin Townsend for Adafruit Industries with some heading example from
Love Electronics (loveelectronics.co.uk)
This program is free software: you can redistribute it and/or modify
it under the terms of the version 3 GNU General Public License as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***************************************************************************/
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>
/* Assign a unique ID to this sensor at the same time */
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);
void displaySensorDetails(void)
{
sensor_t sensor;
mag.getSensor(&sensor);
Serial.println("------------------------------------");
Serial.print ("Sensor: "); Serial.println(sensor.name);
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" uT");
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" uT");
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" uT");
Serial.println("------------------------------------");
Serial.println("");
delay(500);
}
void setup(void)
{
Serial.begin(9600);
Serial.println("HMC5883 Magnetometer Test"); Serial.println("");
/* Initialise the sensor */
if(!mag.begin())
{
/* There was a problem detecting the HMC5883 ... check your connections */
Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");
while(1);
}
/* Display some basic information on this sensor */
displaySensorDetails();
}
void loop(void)
{
/* Get a new sensor event */
sensors_event_t event;
mag.getEvent(&event);
/* Display the results (magnetic vector values are in micro-Tesla (uT)) */
Serial.print("X: "); Serial.print(event.magnetic.x); Serial.print(" ");
Serial.print("Y: "); Serial.print(event.magnetic.y); Serial.print(" ");
Serial.print("Z: "); Serial.print(event.magnetic.z); Serial.print(" ");Serial.println("uT");
// Hold the module so that Z is pointing 'up' and you can measure the heading with x&y
// Calculate heading when the magnetometer is level, then correct for signs of axis.
float heading = atan2(event.magnetic.y, event.magnetic.x);
// Once you have your heading, you must then add your 'Declination Angle', which is the 'Error' of the magnetic field in your location.
// Find yours here: http://www.magnetic-declination.com/
// Mine is: -13* 2' W, which is ~13 Degrees, or (which we need) 0.22 radians
// If you cannot find your Declination, comment out these two lines, your compass will be slightly off.
float declinationAngle = 0.22;
heading += declinationAngle;
// Correct for when signs are reversed.
if(heading < 0)
heading += 2*PI;
// Check for wrap due to addition of declination.
if(heading > 2*PI)
heading -= 2*PI;
// Convert radians to degrees for readability.
float headingDegrees = heading * 180/M_PI;
Serial.print("Heading (degrees): "); Serial.println(headingDegrees);
delay(500);
}
OK, I think I got it this time. I was using the "post to forum" in the arduino sketch edit section, and then pasting THAT to the forum with code tags. I think I should have just cut and pasted the sketch then add the Code Tags on the forum.
Yes, the "copy for forum" button on the Arduino IDE doesn't work.
I don't see a problem with the code, but there is this comment on the eBay link that is worrisome:
Note: It is Domestic Chip HMC5883, the program is not compatible with the original imported chip program, we can provide Matching routine !
This suggests that the Chinese knockoff chip is not compatible with code that expects it to behave like the Honeywell sensor. The module also does not have 3->5V level shifters on the I/O lines. Sometimes that is OK but often not.
The Adafruit HMC5883L model does have level shifters, and if it doesn't work with their software, they are likely to be willing to help you out.
Then it's probably a compatibility issue. As for The 3v to 5v level shifters, if the chip is operating at 3.3v that means it's I2c buss is at 3.3v? The arduino is using 5v on the I2c data lines?....thus a chip/Device that operates at 3.3v will have a 3.3v I2c SDA, SCL.
Or is the i2c voltage levels for SDA & SCL the same between 3.3 and 5v devices?
If the i2c scanner can detect an adress wouldn't that mean that the data lines are operating and the problem is more likely in the registers and how the information gets called for by the arduino, or somthing to that effect.
Basically I mean, if the arduinio can read the adress then the i2c data buss is working correctly but the 5838 is not issuing the correct information.
It's what I get for buying the cheapest on ebay...lol
I'll do some good research and probably order another.
I kind of went through the same thing with 3.2 in touch screens and the URTOUCH Library. I thought for sure that it was something I was doing but the code was good. Three touchscreens later I found one that worked. I got my money refunded for the two that didn't work but I spent so much time second-guessing myself when it was a falty hardware issue......a repeated falty hardware issue.
Sorry for the multiple periods,
Thanks for all your help. I really do appreciate the guidance. And attention to detail, awesome.
Got nobody else to ask so it means alot
Or is the i2c voltage levels for SDA & SCL the same between 3.3 and 5v devices?
No. the I2C lines are high impedance with pullup resistors, which means that the voltage level is set by whatever pullups are active.
This can be safe for 3.3V to 5V connections if you have pullups to 3.3V, but people often destroy 3.3V chips by connecting them to a 5V Arduino with pullups to 5V.
The fact that the I2C Address Scanner works says that the chip is probably not damaged. But my interpretation of the eBay comment is that the Chinese knockoff does not respond to the same commands as a genuine HMC5883L chip.
You could ask the seller for the correct code, and that might be enlightening for others with the same problem. I would not use that module, though.
Yes, I got one of those modules as well. I ordered one from ebay that said 'original honeywell', but when it arrived it was marked as a QMC5883L, and these do indeed have I2C address 0xD. My ebay seller had copied a description text that said 'ask me for the routine to drive this chip', but couldn't actually supply it.....
I googled around for the chip specification and wrote a library to drive that chip, see attachments if they come through, where I've enclosed an example sketch and a library along with the chip spec. (the .cpp and .h file should go in libraries/QMC5883L). Note: I've only tested the library with the Uno and pro-mini and haven't tested the interrupt driven/data ready acquisition modes.
Although the chip works, it seems less sensitive and stable than the original to me, but I haven't played around with all the over-sampling and measurement rate settings as it only arrived on the slow boat from China yesterday. Contrary to one of the other comments on this thread, mine is 5V tolerant (because the spec says so and because its still working after having 5V applied).
Sorry, there was a mistake in that sketch due to me not knowing the difference between East and West. When an observer faces East the North pole moves in a westerly direction relative to the observer. The updated sketch corrects this (I tested it in the garden last night - it works outside OK), and also makes it clear in which direction to mount the sensor (Y,X) so the results are as expected and not 90degrees out.
The attached sketch corrects this and I've updated the library comments so its now much clearer that its for the QMC5883L not the HMC5883L because they are, as we now know, completely different in their register layout.
... and finally, that last sketch was confusing where it said
// Values are accessed like so:
int MilliGauss_OnThe_XAxis = scaled.XAxis; // (or YAxis, or ZAxis)
because its returning Gauss not MilliGauss
// Values are accessed like so:
int Gauss_OnThe_XAxis = scaled.XAxis; // (or YAxis, or ZAxis)
Thank you so much Andy (old_fogey) we had the same issues and just want to confirm that your code worked a treat for the modules we bought off eBay.
Cheers!