HMC5883L Compass Outputting Things I Do Not Understand

Hello, I am participating in a contest, details don't really matter but I need to use the compass to make the robot return to a certain heading when required. Using an arduino mega wires and the HMC5883L I managed to do this.

However I need to have everything in a PCB and decided to use the Teensy 4.1 as I didn't have to change my code much. I wired everything, HMC5883L's SDA going to pin 18 on the Teensy, and the HMC5883L's SCL going to pin 19 on the Teensy and I upload the code (same code that worked perfectly on the Arduino Mega), and I get values ranging from 112.9 to 112.41. Not at all the degrees I was hoping for.

The values also repeat at certain places. For example you may get 112.13 when the robot is facing me but get it again when its a bit more to the right for instance. Garbage values. I've spent the last 90 mins on this but haven't been able to crack it. If anyone can help, it would be much appreciated!

My code:

// Including appropriate libraries
#include <math.h>
#include <Arduino.h>
#include <Wire.h>
#include <HMC5883L_Simple.h>

// Compass
HMC5883L_Simple Compass;

void setup() {
  Wire.setSCL(19);
  Wire.setSDA(18);
  Wire.begin();
  Compass.SetSamplingMode(COMPASS_SINGLE);
  Compass.SetScale(COMPASS_SCALE_130);
  Compass.SetOrientation(COMPASS_HORIZONTAL_X_NORTH);
}

void loop() {
  Serial.println(Compass.GetHeadingDegrees());
}

Output from the above code:
Screenshot 2023-07-01 154840

Also I have checked my PCB design, everything is how it should be. I doubt it's an issue with that. If you would still like to see it I'd be happy to provide, it's just a bit messy.

Thank you again.

Then the PCB design becomes the prime suspect! With all technical problems which you cannot solve by yourself, a common reason is that the problem is where you believe it cannot be.

Did you prototype the PCB design before it was manufactured?

I did with the Mega, not the Teensy. I'd assume the connections would be the same no?

No. They might be. But don't assume they will be!

Wire Arduino Library, connecting I2C (TWI) devices to Teensy (pjrc.com)
He's showing as default, 17 sda and 16 scl; and recommends external pull-ups (vs. weak internal pull-ups).

GitHub - Richard-Gemmell/teensy4_i2c: An I2C library for the Teensy 4. Provides slave and master mode.

I think they should be the same, as it s SDA SCL connections. I am using different pins. I checked everything with a multimeter, they are receiving what they should be receiving. I'd love to be wrong though as I'd have a way to fix it!

Following your link, it says 18 and 19 are defaults for SDA and SCL for the teensy 4.1. I may be looking at the wrong thing.
Screenshot 2023-07-01 165251

And I focussed in on 'Wire 1'.
OK.
You're getting fishy numbers for a reason.
Is it too close to something where it was more in the clear before?

Not really, in the circuit before it was just as close to the mega as it is now the teensy. The motors I'm using now are a bit more powerful but they are very far from it so the effect would be negligible.

To see if your compass is working at all and to check the calibration, print out the X and Y magnetic field values when you rotate the sensor 360 degrees on a horizontal, non magnetic surface, with Z vertical.

A plot of those values should be an approximate circle centered on the origin, if the compass is properly calibrated.

Capture

If not, then calculating the compass heading from those values will fail with unpredictable results.

Note: the above plot has an elliptical shape due to an off-axis error, which can rather easily be corrected.

1 Like

The data sheet says ...

and a 12-bit ADC that enables 1° to 2° compass heading accuracy.

so any figures after the decimal point are suspect. "Garbage values."

Also its a magnetic compass so it will be affected by magnetic materials and magnetic fields nearby. Are you using permanent magnet motors?

I see okay. Any idea what to do if the values turn out to not plot a circle? Or is the module fried?

Yes, but I was using a permanent magnet motor in my previous design, and they are reasonably far apart so I doubt it's the cause.

Any idea what to do if the values turn out to not plot a circle?

Calibrate the magnetometer. The best procedure is described in this tutorial: Tutorial: How to calibrate a compass (and accelerometer) with Arduino | Underwater Arduino Data Loggers

Practical example for a difficult case is here: https://forum.pololu.com/t/correcting-the-balboa-magnetometer/14315

If you have a simple magnetic compass you can easily find out. Bear in mind when the motors are in use their magnetic properties will change.

Hello everyone, I hope you are all still awake. I have the QMC5883L. I am trying to do what I thought would be super simple. I was planning to use the Azimuth reading to steer the car. I don't care about the absolute direction, I only care about the relative change in the direction. So, for example, if the azimuth is 90 deg, then the car starts to veer slightly, and the azimuth changes to 92, great, then I can adjust...at least that was my plan. So, this is why I also thought I DO NOT NEED TO CALIBRATE.
However, I get the strangest results, which I've attached 6 pics to help visually. The sensor is mounted to the car.

  1. If I rotate the sensor physically (by hand, ie. around the loose screw that is holding the board), the azimuth changes seem to change very nicely and is close, if not exactly what I want (i.e. 90 degree rotation is about 90 degree azimuth change).
  2. However, If I do the exact same thing by turning the car instead, the azimuth BARELY changes (i.e. azimuth changes by only about 5 degrees or so) !? What the heck is that? Has anyone experienced anything like this, and any advice? I've also attached the code





type or paste code here
//#include <Wire.h>
#include <MechaQMC5883.h>

MechaQMC5883 qmc;

void setup() {
//  Wire.begin();
  Serial.begin(9600);
  qmc.init();
  //qmc.setMode(Mode_Continuous,ODR_200Hz,RNG_2G,OSR_256);
}

void loop() {
  int x, y, z;
  int azimuth;
  int delta, temp1, temp2;
  //float azimuth; //is supporting float too
  qmc.read(&x, &y, &z,&azimuth);
  //azimuth = qmc.azimuth(&y,&x);//you can get custom azimuth
  Serial.print("x: ");
  Serial.print(x);
  Serial.print(" y: ");
  Serial.print(y);
  //Serial.print(" z: ");
  //Serial.print(z);
  Serial.print(" a1: ");
  Serial.print(azimuth);
  temp1 = azimuth;
  //Serial.print(" temp1");
  //Serial.print(temp1);
  delay(100);
  qmc.read(&x, &y, &z,&azimuth);
  Serial.print(" a2: ");
  Serial.print(azimuth);
  temp2 = azimuth;
  //Serial.print(" temp2");
  //Serial.print(temp2);

  delta = temp2 - temp1;
  Serial.print(" delta: ");
  Serial.print(delta);
  Serial.println();
  delay(100);
}

These are values when the car is facing one direction (le'ts call it 185 deg).
image

I physically rotate the car 90 degrees, (program is still running, no other changes) and These are values.
image
The Azimuth barely changed at all, makes no sense to me.

Now, remember the 185 degree. So, from that position, instead of rotating the car 90 degrees, I rotate the sensor (on the screw), by 90 degrees. And, we get what we expect, the Azimuth changed to around 260 degrees (~90 degrees). I'm doing this all by hand, so it isn't going to be exactly 90. The point is: Azimuth updates fine when the sensor rotates. Azimuth doesn't when the car rotates.
image

Azimuth changes correctly. Anyone know why??????????????????????

Magnetometers don't work out of the box as compasses. They always need to be calibrated, especially when placed near motors and current carrying wires.

Calibrate the sensor in place and you should be fine.

even if I only care about relative changes? I only care that the angle changes.

It is not working now, correct?

It DOES work, when I rotate the sensor itself (not the car). It DOES NOT work, if I rotate the car. It's almost the exact same thing. In first case, when I rotate the sensor about 90, I get about 90. With the car, I rotate it about 90 and I get about 5 or less. And the sensor is attached to the car, like in the pictures.