Go Down

Topic: Magnetometer MicroMag 3 on Arduino Due (Read 571 times) previous topic - next topic

miqbal

Hi everyone

I'm trying to get my magnetometer working on my Due, I'm getting output but I don't think its correct. Like the X Y and Z axis numbers fluctuate even when the compass isn't moving. I'm beginning to believe this magnetometer is garbage even though it was expensive!

Here is what I have so far:

Code: [Select]
//initialise analog pins to 0
int an1, an2, an3 = 0;

void setup() {
//open serial at 19200 baud
  Serial.begin(19200);
}

void loop() {
read_analog_pins();
}

void read_analog_pins() {

  an1 = analogRead(0);
  delay(5);

  an2 = analogRead(1);
  delay(5);

  an3 = analogRead(2);
  delay(5);

  Serial.print("x = ");
  Serial.print(an1,DEC);
  delay(500);

  Serial.print(" ");
  Serial.print("y = ");
  Serial.print(an2,DEC);
  delay(500);

  Serial.print(" ");
  Serial.print("z = ");
  Serial.println(an3,DEC);
  delay(500);
}


So then I started google searching and found this:

http://wiring.org.co/learning/basics/magneticfield.html

But this also doesn't work. Like when I run the code it uploads just fine (you have to declare int WLED = 1; and add #include <Arduino.h> in order for it to run properly in the Arduino IDE) I really am stuck here guys, any help will be much appreciated

miqbal

So I found this other sketch which looks like it would work but I'm getting incorrect output of just -1,-1,-1 idk what I'm doing wrong? Maybe my connections??

http://cwwang.com/2008/02/20/micromag-3-axis/

Code: [Select]
//heading calcuations added from Daniel's processing code to get a heading value of 0-3600 in Arduino
//edited by Che-Wei Wang
//tested on MICROMAG 3-AXIS V1.00
//clockwise rotation is positive

//Original Arduino code for controlling a MicroMag3 magnetometer through SPI
//by Daniel Soltis

#define SCLK 7 //the clock to pulse (#1 on breakout)
#define MISO 6 //master in, slave out (#2 on breakout)
#define MOSI 5 //master out, slave in (#3 on breakout)
#define SSNOT 4 //when low, the device is enabled (#4 on breakout)
#define DRDY 3 //this is low after a reset, high when data is ready (#5 on breakout)
#define RESET 2 //this needs to be toggled low-high-low before each measurement (#6 on breakout)

#include <math.h>

int x = 0;
int y = 0;
int z = 0;
int heading = 0;

float readaxis(int _axis);
int getHeading(float x, float y, float z);


void setup(){
  Serial.begin(9600);

  pinMode(SSNOT, OUTPUT);
  pinMode(RESET, OUTPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(DRDY, INPUT);
  pinMode(SCLK, OUTPUT);

  //i could just ground this line, but this at least marks it as
  //something that one could change if needed
  digitalWrite(SSNOT, LOW);
}

void loop(){

  x=readaxis(0);
  y=readaxis(1);
  z=readaxis(2);
  getHeading(x,y,z);

}

void send_bit(int _high){

  //this sends the bit on the rising edge of the clock

  digitalWrite(MOSI, _high);
  delay(2);
  digitalWrite(SCLK, HIGH);
  delay(2);
  digitalWrite(SCLK, LOW);
  delay(2);
}

int receive_bit(){

  //this receives the data on the falling edge of the clock

  digitalWrite(SCLK, HIGH);
  delay(2);
  int bit = digitalRead(MISO);
  delay(2);
  digitalWrite(SCLK, LOW);
  delay(2);
  return bit;
}

float readaxis(int _axis){
  //this function sends eight bits, waits until the data is ready
  //and receives 16 bits

    //pulse the reset
  digitalWrite(RESET, LOW);
  delay(2);
  digitalWrite(RESET, HIGH);
  delay(2);
  digitalWrite(RESET, LOW);
  delay(2);

  //send the command byte

  //this sends data that we are not in debug mode
  //and sets the amount of time to read the magnetic sensors (the ASIC period)
  //as /2048
  send_bit(LOW);
  send_bit(HIGH);
  send_bit(HIGH);
  send_bit(LOW);
  send_bit(LOW);
  send_bit(LOW);

  //the last two bits select the axis
  if (_axis == 0){ //x axis
    send_bit(LOW);
    send_bit(HIGH);
  }
  else if (_axis == 1){ //y axis
    send_bit(HIGH);
    send_bit(LOW);
  }
  else{ //z axis
    send_bit(HIGH);
    send_bit(HIGH);
  }

  //wait until the drdy line is high
  while (digitalRead(DRDY) == LOW){
    //wait
    //Serial.println("waiting");
  }
  //Serial.println("data!");

  long runningtotal = 0;

  //receive the results and tally them up as they come in

  //the leftmost bit signs the number as positive or negative
  long sign = receive_bit();

  //the remaining bits need to be translated from individual bits into an integer
  for (int i = 14; i >= 0; i = i - 1){
    long thisbit = receive_bit();
    thisbit = thisbit << i;
    runningtotal = runningtotal | thisbit;
  }

  if (sign == 1){
    runningtotal = runningtotal - 32768;
  }

  //this sends the data over the serial line, as a string separated by commas
  if (_axis == 0){
    x = runningtotal;
    Serial.print(x,DEC);
    Serial.write(44);
  }
  else if (_axis == 1){
    y = runningtotal;
    Serial.print(y,DEC);
    Serial.write(44);
  }
  else{
    z = runningtotal;
    Serial.print(z,DEC);
    Serial.write(44);
  }
  return runningtotal;
}

int getHeading(float x, float y, float z){
  int heading=0;
  if (x==0 && y<0) heading=900.0;
  if(x==0 && y>0) heading=2700.0;
  if (x < 0) heading = (PI - atan(y/x))/TWO_PI*3600.0;
  if (x > 0 && y < 0) heading = (-1*atan(y/x))/TWO_PI*3600.0;
  if (x > 0 && y > 0) heading = (2.0*PI - atan(y/x))/TWO_PI*3600.0;
  Serial.print("heading: ");
  Serial.println(int(heading));
  return heading;
}



But the output I'm getting is:

Code: [Select]
Connected to /dev/tty.usbmodem1421 at 9600
0,-1,-1,heading: 900
-1,-1,-1,heading: 1350
-1,-1,-1,heading: 1350
-1,-1,-1,heading: 1350



I have wired my compass to my due as stated here except Vdd is connected to 3.3 NOT 5v on the Due.

http://ardadv.blogspot.com/2012/03/using-micromag3-with-arduino-and-jump.html


I would appreciate any feedback or suggestions


MarkT

All those delays in the bit-bashing should be 1 microsecond, not 2 milliseconds - the chip
can clock upto 1MHz.

MEMS magnetometers are noisy, you need lots of low-pass filtering to
get anything reasonably stable.  Try a cut-off frequency of 0.3 Hz or so at
first.  That means sample at the nyquist rate for the device and digitally
filter the result.
[ I won't respond to messages, use the forum please ]

miqbal

If anybody can answer this they would be my hero, this would answer a lot of questions: how can I tell if my compass is bad?

I know this is a very broad question but say I test out the compass and even when outside I get random numbers generated, the X values jump from 400 to 560 and the Y values jump from -100 to -300, etc. What could be causing this? How do I know my compass is bad? What potential things should I look at, any sort of tests could I do?

I read up about calibration but could someone tell me how to calibrate?

Here's what I have much simpler and easier from CWWang's solution :
Code: [Select]
// Do not remove the include below
#include "magnetometer_due.h"

//initialise analog pins to 0
int an1, an2, an3 = 0;

void setup() {
//open serial at 19200 baud
  Serial.begin(19200);
}

void loop() {
read_analog_pins();
}


void read_analog_pins() {

  an1 = analogRead(0);
  delay(5);

  an2 = analogRead(1);
  delay(5);

  an3 = analogRead(2);
  delay(5);

  Serial.print("x= ");
  Serial.print(an1,DEC);
  delay(500);

  Serial.print(" ");
  Serial.print("y= ");
  Serial.print(an2,DEC);
  delay(500);

  Serial.print(" ");
  Serial.print("z= ");
  Serial.println(an3,DEC);
  delay(500);
}


And this is the output I am getting:
Code: [Select]
x=400 y=-120 z=200
x=480 y=-120 z=460
x=520 y=-220 z=210
x=610 y=-200 z=200
x=400 y=-520 z=300


This output makes no sense...

Any help or suggestions will be very much appreciated, thanks

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!

Arduino
via Egeo 16
Torino, 10131
Italy