Loading...
Pages: [1]   Go Down
Author Topic: Exceeding the maximum output data rate of the HMC5883L  (Read 359 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In the data sheet of the HMC5883L 3-axis compass the maximum output data rate is listed as 160 Hz when using single-measurement mode (interrupt driven sampling). I've written a simple arduino sketch using interrupts to only grab data when the device data ready pin has changed status, indicating the samples are ready. However, I've found that with my code I am able to sample at up to ~240 Hz. Will sampling at this rate for long durations damage the sensor? Why else would the listed maximum rate be so much lower than what I can achieve?

Here is my code where I've limited the sampling to 200 Hz :

Code:
#include <Wire.h>

#define MAG_ADDRESS ((char) 0x1E)
uint8_t mag_buffer[6];
int16_t mag_raw[3];

long start_time = 0;
long previous_time = 0;
long loop_duration = 0;

volatile boolean isDataReady = false;

void setup() {
  Serial.begin(115200);
  Serial.println("Initializing...");
 
  Wire.begin();

  configMag();
 
  attachInterrupt(13, magDataReady, RISING);
 
  previous_time = micros();
}


//interrupt function when mag DRDY pin is brought LOW
void magDataReady() {
  isDataReady = true;
}


void loop() {

  start_time = micros();
  loop_duration = start_time - previous_time;
 
  if(loop_duration >= 5000) {
    if(isDataReady) {
      isDataReady = false;
      readMag();
 
//      Serial.print(mag_raw[0], DEC); Serial.print(",");
//      Serial.print(mag_raw[1], DEC); Serial.print(",");
//      Serial.print(mag_raw[2], DEC); Serial.println();
      previous_time = start_time;
   
    }
    else {
      Serial.println("Missed one");
    }
  }
 
}


void configMag() {
  uint8_t mag_name;
 
  // make sure that the device is connected
  Wire.beginTransmission(MAG_ADDRESS);
  Wire.write((byte) 0x0A); // Identification Register A
  Wire.endTransmission();
 
  Wire.beginTransmission(MAG_ADDRESS);
  Wire.requestFrom(MAG_ADDRESS, 1);
  mag_name = Wire.read();
  Wire.endTransmission();
 
  if(mag_name != 0x48) {
    Serial.println("HMC5883L not found!");
    Serial.print(mag_name, HEX); Serial.println(" found, should be 0x48");
    delay(1000);
  }
 
  // Register 0x00: CONFIG_A
  // normal measurement mode (0x00) and 75 Hz ODR (0x18)
  Wire.beginTransmission(MAG_ADDRESS);
  Wire.write((byte) 0x00);
  Wire.write((byte) 0x18);
  Wire.endTransmission();
  delay(5);
 
  // Register 0x01: CONFIG_B
  // default range of +/- 130 uT (0x20)
  Wire.beginTransmission(MAG_ADDRESS);
  Wire.write((byte) 0x01);
  Wire.write((byte) 0x20);
  Wire.endTransmission();
  delay(5);
 
  // Register 0x02: MODE
  // continuous measurement mode at configured ODR (0x00)
  // possible to achieve 160 Hz by using single measurement mode (0x01) and DRDY
  Wire.beginTransmission(MAG_ADDRESS);
  Wire.write((byte) 0x02);
  Wire.write((byte) 0x01);
  Wire.endTransmission();
 
  delay(200);
 
}


// read 6 bytes (x,y,z magnetic field measurements) from the magnetometer
void readMag() {
 
  // multibyte burst read of data registers (from 0x03 to 0x08)
  Wire.beginTransmission(MAG_ADDRESS);
  Wire.write((byte) 0x03); // the address of the first data byte
  Wire.endTransmission();
 
  Wire.beginTransmission(MAG_ADDRESS);
  Wire.requestFrom(MAG_ADDRESS, 6);  // Request 6 bytes
  int i = 0;
  while(Wire.available())
  {
    mag_buffer[i] = Wire.read();  // Read one byte
    i++;
  }
  Wire.read();
  Wire.endTransmission();
 
  // combine the raw data into full integers (HMC588L sends MSB first)
  //           ________ MSB _______   _____ LSB ____
  mag_raw[0] = (mag_buffer[0] << 8) | mag_buffer[1];
  mag_raw[1] = (mag_buffer[2] << 8) | mag_buffer[3];
  mag_raw[2] = (mag_buffer[4] << 8) | mag_buffer[5];
 
  // put the device back into single measurement mode
  Wire.beginTransmission(MAG_ADDRESS);
  Wire.write((byte) 0x02);
  Wire.write((byte) 0x01);
  Wire.endTransmission();
 
}
Logged

Netherlands
Offline Offline
Tesla Member
***
Karma: 90
Posts: 9393
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Will sampling at this rate for long durations damage the sensor? Why else would the listed maximum rate be so much lower than what I can achieve?
it might heat up?
or there might be an internal calibration?
or time needed to settle the measurement?
or drift in accuracy?
or ...

Still very interesting to know this max speed.
Can you tell anything about the accuracy at max speed, is it less? ( don't know how to measure, on a fast servo perhaps?)

while(Wire.available())  => while(Wire.available() >0 && i < 6) // your array might explode smiley-wink
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Those are the kind of issues I had imagined, although I am mainly concerned about heating.

The quality of the measurements does decrease with the higher sampling frequencies. I don't really know how to measure the accuracy of the device, but I did record a few seconds of data while it was stationary. There is a noticeable increase in noise when sampling at 200 Hz, but not enough that it couldn't be filtered out. See for yourself:


P.S. Thanks for catching that potential infinite loop, I don't know how I missed that

[EDIT] Fixed the image link
« Last Edit: January 20, 2013, 09:05:27 am by drm0hr » Logged

Netherlands
Offline Offline
Tesla Member
***
Karma: 90
Posts: 9393
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

the image link is broken somehow

Quote
I don't know how I missed that
Everyone is blind for his/her own code,
and the chance the error would occur is very small otherwise test runs would have shown it .
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

Pages: [1]   Go Up
Print
 
Jump to: