Go Down

Topic: Compass HMC6352 in Continous Mode anyone who got it working? (Read 2410 times) previous topic - next topic


I have not seen anyone who has got the HMC6352 to work in continous mode.

Getting it to run in in Query Mode where you first initiate a reading with the "A" command was fairly easy.
(After some initial TWI issues)

I try to initiate the compass as follows:


with the following defines:
#define COMPASS_1_WRITE_ADDRESS         0x21
#define COMPASS_1_READ_ADDRESS           0x21   
#define CMD_CONTINOUS_20HZ                  0x72
#define CMD_CONTINOUS_10HZ                  0x52
#define CMD_CONTINOUS_10HZ_NORES       0x42

Anyone who can share code working for continous mode?


PLease post your whole code so people with such a sensor can help.
and please use the # button to tag code appropiate.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)


Mar 30, 2011, 07:22 pm Last Edit: Apr 03, 2011, 11:22 am by Freddan Reason: 1
Here comes the code.

Again...Getting my data by sending "A" and then ask for the result works fine.
Now I just want to step it up a bit and let the compass sample so all I have to do is ask for the result.
The idea is to have a compass sending data via the Arduino 2560 board autonomously on Serial1 which goes to my PC. On the PC I run my robot SW which is done in C#.
(I know .... probably overkill to have the 2560 to do this simple task but thats how it is done today :-) )

Code: [Select]

#include <avr/io.h>
#include <MsTimer2.h>
#include <Wire.h>

#define __AVR_ATmega2560__
#define F_CPU 16000000UL
#define UBRR1H  // Used for Serial1 routines

#define COMPASS_1_WRITE_ADDRESS 0x21 // The addess is normally 0x42 but shifted >> 1 to get right format for wire lib
#define COMPASS_1_READ_ADDRESS 0x21   // The addess is normally 0x43 bin 0100 0011 but shifted >> 1 -> 0010 0001 also 0x21 ???? to get right format for wire lib
#define CMD_WRITE_TO_EEPROM      'w'
#define CMD_READ_FROM_EEPROM      'r'
#define CMD_READ_FROM_RAM_REGISTER            'g'
#define CMD_ENTER_SLEEP_MODE      'S'
#define CMD_EXIT_SLEEP_MODE      'W'
#define CMD_SAVE_OP_MODE_TO_EEPROM            'L'
#define CMD_CONTINOUS_20HZ 0x72
#define CMD_CONTINOUS_10HZ 0x52

#define RAM_ADRESS_OPERATIONAL_MODE     0x7F //0x74
#define RAM_ADRESS_OUTPUT_MODE          0x4E

const byte MEASUREMENT_RATE_1HZ   = 0x00;
const byte MEASUREMENT_RATE_5HZ   = 0x20;
const byte MEASUREMENT_RATE_10HZ  = 0x40;
const byte MEASUREMENT_RATE_20HZ  = 0x60;

const byte PERIOD_RESET_SET_ON     = 0x10;
const byte PERIOD_RESET_SET_OFF    = 0x00;

const byte OP_MODE_STANDBY         = 0x00;
const byte OP_MODE_QUERY           = 0x01;
const byte OP_MODE_CONTINUOUS      = 0x02;
const byte OP_MODE_NOT_ALLOWED     = 0x03;


unsigned int GlobCompassData[4]={0x55,00,00,00}; //Startbyte always 55 , 2 data bytes and a checksum is added when data is read.

// Init Compass1 to a mode where it sends data at TBDHz
void InitCompass1()

//Only one of the two below is used


void GetCompass1Dir()

byte val = 0;
byte data[2];
int deg, j, frac, compassdatavalid, checksum;


 Wire.requestFrom(COMPASS_1_READ_ADDRESS, 2);
 j = 0;
char c = Wire.receive();
   data[j] = c;
 Serial.print("Total Byte count");
// ADD checksum at the end
checksum = GlobCompassData[0];
for(j = 1; j < 3; j++){
  checksum ^= GlobCompassData[j];
   Serial.print(" DataByte One: ");
Serial.print(GlobCompassData[1], HEX);
Serial.print("    DataByte two: ");
Serial.println(GlobCompassData[2], HEX);
   Serial.print(" heading = ");
frac = data[0]*256 + data[1];
deg = frac / 10;
frac = frac - deg * 10;
Serial.println("NO DATA RECIEVED");

// Timer2int called at 10HZ
void Timer2interrupt()
 static boolean output = HIGH;
 digitalWrite(13, output);
 output = !output;

void setup()
 pinMode(13, OUTPUT);
 MsTimer2::set(500,Timer2interrupt); // 200ms period gives a call at 2Hz to get the compass direction. The compass is internally sampled at 10Hz and average
 InitCompass1; // Set up the compass for automode  

void loop()
    Serial1.print("Compass data: Command Byte:");
    Serial1.print(GlobCompassData[0], HEX);
    Serial1.print("  First Byte: ");
    Serial1.print(GlobCompassData[1], HEX);
    Serial1.print("  Second Byte: ");
    Serial1.print(GlobCompassData[2], HEX);
    Serial1.print("   Checksum:");
    Serial1.println(GlobCompassData[3], HEX);

Last Edit ..jus removed some swedish out of the code...


Thats a lot of code (even without the Swedish :)

A quick scan revealed in setup():


that should be


as it is a function call.

If you press CTRL-T in the IDE the autoformatter re-indents the code, makes it more readable (for me)

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)


Well... I just gave up on this.
I have looked at the oscillsocope screen over and over and cannot figure out why I cant read out the values after initiating the compass.
I am starting to believe that I must write som more commands when initating the compass.....but I have no idea which...

Instead I am now using my oscilloscope to trim and run the Command "A" and read data at 20Hz.
Then I will do the Low Pass filtering on my PC instead.....

Simple ....Yes.... but it works  :)


Well... I just gave up on this.
I have looked at the oscillsocope screen over and over and cannot figure out why I cant read out the values after initiating the compass.

Did you read robtillart's comment about the compass not being intialised?
I think your test program is too complicated - I'd simplify, forget the timer.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.


This is how I got mine to work when I first got it.

Code: [Select]
#include <Wire.h>
int HMC6352Address = 0x42;
// This is calculated in the setup() function
int slaveAddress;
int ledPin = 13;
boolean ledState = false;
byte headingData[2];
int i, headingValue;
void setup()
// Shift the device's documented slave address (0x42) 1 bit right
// This compensates for how the TWI library only wants the
// 7 most significant bits (with the high bit padded with 0)
slaveAddress = HMC6352Address >> 1;   // This results in 0x21 as the address to pass to TWI
pinMode(ledPin, OUTPUT);      // Set the LED pin as output
void loop()
  // Flash the LED on pin 13 just to show that something is happening
  // Also serves as an indication that we're not "stuck" waiting for TWI data
  ledState = !ledState;
  if (ledState) {
  // Send a "A" command to the HMC6352
  // This requests the current heading data
  Wire.send("A");              // The "Get Data" command
  delay(10);                   // The HMC6352 needs at least a 70us (microsecond) delay
  // after this command.  Using 10ms just makes it safe
  // Read the 2 heading bytes, MSB first
  // The resulting 16bit word is the compass heading in 10th's of a degree
  // For example: a heading of 1345 would be 134.5 degrees
  Wire.requestFrom(slaveAddress, 2);        // Request the 2 byte heading (MSB comes first)
  i = 0;
  while(Wire.available() && i < 2)
    headingData[i] = Wire.receive();
  headingValue = headingData[0]*256 + headingData[1];  // Put the MSB and LSB together
  Serial.print("Current heading: ");
  Serial.print(int (headingValue / 10));     // The whole number part of the heading
  Serial.print(int (headingValue % 10));     // The fractional part of the heading
  Serial.println(" degrees");

Basically it's just the example code modified to work on a mega.


Then I got my RTC, MPL115A1, SparkFun huge LCD with serial back pack.
I added a keypad as well, but the finished unit probably wont use it.
It works but the big LCD is proving to be a hassle to house/mount.


If you have a look at the LCD closely you can see the barometer output is bogus! It wasn't hooked up.

How the hell do I put photo's here or circuits or drawings?


Apr 04, 2011, 10:02 pm Last Edit: Apr 04, 2011, 10:04 pm by robtillaart Reason: 1
use the button under the italic button to get [ img] and [ /img] tags (without spaces) and

place the URL to the image in between. The URL must end with a real image file I guess, that could cause the flickr files to fail.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)


Got my hmc6352 sensor last week, wrote a library for it which is still in Beta. Also made a simple config sketch to set modes and do a EEPROM dump etc. However when put the hmc in continuous mode it "got mad" values in EEPROM and RAM completely made no sense anymore and I could not reset it for two days. It was working in continuous mode as I could get (uncallibrated) readings at 20 times per second.

I finally got it back to standby mode by a separate sketch that kept on writing to EEPROM the right value and then I pulled the 5V plug.

If you are interested in a "continuous" experiment please send me a PM than I will mail the BETA version. I have to do more tests before publishing the library (but some other projects scream for attention :)  Let me know.

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)


Do you know that that sensor is a 3.3v part do you?


From datatsheet - Low Voltage Operation (2.7 to 5.2V)  - so the Arduino 5V should not harm it ...
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Go Up