Go Down

Topic: Compass HMC6352 in Continous Mode anyone who got it working? (Read 2122 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.


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

Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

via Egeo 16
Torino, 10131