Go Down

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

Freddan

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

robtillaart

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)

Freddan

#2
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>

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

robtillaart


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

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)


Rob Tillaart

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

Freddan

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  :)
/Fred

AWOL

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

cyberteque

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


cyberteque

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?

robtillaart

#8
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)

robtillaart

@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 :)  Let me know.


Rob Tillaart

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

Senso

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

robtillaart

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