Pages: [1]   Go Down
Author Topic: Magnetometer MicroMag 3 on Arduino Due  (Read 383 times)
0 Members and 1 Guest are viewing this topic.
Sydney
Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
//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
Logged

Sydney
Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Logged

0
Offline Offline
Shannon Member
****
Karma: 206
Posts: 12156
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

[ I won't respond to messages, use the forum please ]

Sydney
Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
// 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:
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
Logged

Pages: [1]   Go Up
Jump to: