Pages: [1]   Go Down
Author Topic: Compass HMC6352 in Continous Mode anyone who got it working?  (Read 1229 times)
0 Members and 1 Guest are viewing this topic.
Sweden
Offline Offline
Newbie
*
Karma: 0
Posts: 8
What could be more fun a Saturday night than sending "Hello World" to a robot display??
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

  Wire.beginTransmission(COMPASS_1_WRITE_ADDRESS);
  Wire.send(CMD_WRITE_TO_RAM_REGISTER);             
  Wire.send(RAM_ADRESS_OPERATIONAL_MODE);         
  Wire.send(CMD_CONTINOUS_10HZ_NORES);            
  Wire.endTransmission();

with the following defines:
#define COMPASS_1_WRITE_ADDRESS         0x21
#define COMPASS_1_READ_ADDRESS           0x21   
#define CMD_WRITE_TO_RAM_REGISTER      'G'
#define CMD_CONTINOUS_20HZ                  0x72
#define CMD_CONTINOUS_10HZ                  0x52
#define CMD_CONTINOUS_10HZ_NORES       0x42
#define RAM_ADRESS_OPERATIONAL_MODE   0x74

Anyone who can share code working for continous mode?
thanks/Fred
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12487
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Rob Tillaart

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

Sweden
Offline Offline
Newbie
*
Karma: 0
Posts: 8
What could be more fun a Saturday night than sending "Hello World" to a robot display??
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#include <avr/io.h>
#include <MsTimer2.h>
#include <Wire.h>

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

//COMPASS
#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_WRITE_TO_RAM_REGISTER  'G'
#define CMD_READ_FROM_RAM_REGISTER            'g'
#define CMD_ENTER_SLEEP_MODE      'S'
#define CMD_EXIT_SLEEP_MODE      'W'
#define CMD_UPDATE_BRIDGE_OFFSETS  'O'
#define CMD_ENTER_USER_CALIBRATION_MODE      'C'
#define CMD_EXIT_USER_CALIBRATION_MODE        'E'
#define CMD_SAVE_OP_MODE_TO_EEPROM            'L'
#define CMD_GET_DATA_COMPENSATE_AND_CALCULATE_NEW_HEADING  'A'
#define CMD_CONTINOUS_20HZ 0x72
#define CMD_CONTINOUS_10HZ 0x52
#define CMD_CONTINOUS_10HZ_NORES 0x42

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

//OPERATIONAL_MODE = MEASUREMENT_RATE || OP_MODE
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;


#define MAX_NO_OF_READINGS_IN_FILTER  50

// GLOBAL VARIABLES
static boolean COMPASSTIME,COMPASSDATAVALID;
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()
{
  
 Wire.beginTransmission(COMPASS_1_WRITE_ADDRESS);
 Wire.send(CMD_WRITE_TO_RAM_REGISTER);            
 Wire.send(RAM_ADRESS_OPERATIONAL_MODE);

//Only one of the two below is used
  Wire.send(CMD_CONTINOUS_10HZ_NORES);
//  Wire.send(MEASUREMENT_RATE_1HZ || PERIOD_RESET_SET_ON || OP_MODE_CONTINUOUS);


  Wire.endTransmission();
}

void GetCompass1Dir()
{

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

 
  //Wire.beginTransmission(COMPASS_1_WRITE_ADDRESS);
  //Wire.send(CMD_GET_DATA_COMPENSATE_AND_CALCULATE_NEW_HEADING);
  //Wire.endTransmission();
  //delay(70);

  Wire.requestFrom(COMPASS_1_READ_ADDRESS, 2);
  j = 0;
  COMPASSDATAVALID=false;
  while(Wire.available())
  {
char c = Wire.receive();
    Serial.println(c,HEX);
    data[j] = c;
    GlobCompassData[j+1]=c;
    j++;
    COMPASSDATAVALID=true;
}
  Wire.endTransmission();
  Serial.print("Total Byte count");
    Serial.println(j,HEX);
// ADD checksum at the end
checksum = GlobCompassData[0];
for(j = 1; j < 3; j++){
   checksum ^= GlobCompassData[j];
}
GlobCompassData[3]=checksum;
  
  
  if (COMPASSDATAVALID)
  {
    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.print(deg);
Serial.print(".");
Serial.println(frac);
  }
  else
  {
Serial.println("NO DATA RECIEVED");
  }
}

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

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
  MsTimer2::start();
  Serial.begin(19200);
  Serial1.begin(19200);
  Wire.begin();
  delay(100);
  InitCompass1; // Set up the compass for automode  
  
}

void loop()
{
   if (COMPASSTIME)
   {
     GetCompass1Dir();
     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);
COMPASSTIME=false;    
   }
}


Last Edit ..jus removed some swedish out of the code...
« Last Edit: April 03, 2011, 04:22:48 am by Freddan » Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12487
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Thats a lot of code (even without the Swedish smiley

A quick scan revealed in setup():

  InitCompass1;   

that should be

  InitCompass1();

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)


Logged

Rob Tillaart

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

Sweden
Offline Offline
Newbie
*
Karma: 0
Posts: 8
What could be more fun a Saturday night than sending "Hello World" to a robot display??
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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  smiley
/Fred
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 241
Posts: 24480
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.
Logged

"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.

field road, jupiter creek
Offline Offline
Sr. Member
****
Karma: 3
Posts: 349
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
#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
Serial.begin(57600);
pinMode(ledPin, OUTPUT);      // Set the LED pin as output
Wire.begin();
}
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) {
    digitalWrite(ledPin,HIGH);
  }
  else
  {
    digitalWrite(ledPin,LOW);
  }
  // Send a "A" command to the HMC6352
  // This requests the current heading data
  Wire.beginTransmission(slaveAddress);
  Wire.send("A");              // The "Get Data" command
  Wire.endTransmission();
  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();
    i++;
  }
  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(".");
  Serial.print(int (headingValue % 10));     // The fractional part of the heading
  Serial.println(" degrees");
  delay(500);
}

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

Logged

field road, jupiter creek
Offline Offline
Sr. Member
****
Karma: 3
Posts: 349
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.


http://www.flickr.com/photos/32926550@N07/5225844507/
http://www.flickr.com/photos/32926550@N07/5225845443/
http://www.flickr.com/photos/32926550@N07/5225846865/

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?

* tricorder_V1.pde (15.72 KB - downloaded 1 times.)
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12487
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
« Last Edit: April 04, 2011, 03:04:03 pm by robtillaart » Logged

Rob Tillaart

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

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12487
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@Fred
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 smiley  Let me know.


Logged

Rob Tillaart

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

Portugal
Offline Offline
God Member
*****
Karma: 5
Posts: 962
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12487
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Rob Tillaart

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

Pages: [1]   Go Up
Jump to: