Magnetic field sensor help pls? (wont print data into serial monitor)

hello :D,

Could i get some help. i just got this micromag 3-axis magnetic field sensor and i cant figure out why the code wont work. this code was provided as an example. i copied the wiring diagram and everything. im using an arduino uno. ive check the connections atleast 20 times. it wont print the data in the serial monitor. i wanted the data of x, y, z and the heading of the magnetic field to be shown in the serial monitor. Right now it does nothing.

Code from:MagneticField \ Learning \ Wiring

int SCLKpin = 8;     // magnetometer pin 1
int MISOpin = 9;     // magnetometer pin 2
int MOSIpin = 10;    // magnetometer pin 3
int SSNOTpin = 11;   // magnetometer pin 4
int DRDYpin = 12;    // magnetometer pin 5
int RESETpin = 13;   // magnetometer pin 6
int x = 0;        // magnetic field x axis
int y = 0;        // magnetic field y axis
int z = 0;        // magnetic field z axis
int heading = 0;  // magnetic field heading

void setup()
{
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);  // turn ON the board LED for diagnostics only
  digitalWrite(LED_BUILTIN, HIGH);
  pinMode(SSNOTpin, OUTPUT);
  pinMode(RESETpin, OUTPUT);
  pinMode(MOSIpin, OUTPUT);
  pinMode(SCLKpin, OUTPUT);
  pinMode(MISOpin, INPUT);
  pinMode(DRDYpin, INPUT);
  digitalWrite(SSNOTpin, LOW);
}

void loop()
{
  x = readAxis(0);  // read the x-axis magnetic field value
  y = readAxis(1);  // read the y-axis magnetic field value
  z = readAxis(2);  // read the z-axis magnetic field value
  heading = getHeading(x, y, z);  // calculates the magnetic field heading
  Serial.print("x: ");
  Serial.print(x, DEC);
  Serial.print("y: ");
  Serial.print(y, DEC);
  Serial.print("z: ");
  Serial.print(z, DEC);
  Serial.print("heading: ");
  Serial.print(heading, DEC);
  delay(20000);  // next reading in 20 seconds
}


// specific commands for the sensor

void sendBit(int bit)
{
  // send the bit on the RISING edge of the clock
  digitalWrite(MOSIpin, bit);
  delay(2);
  digitalWrite(SCLKpin, HIGH);
  delay(2);
  digitalWrite(SCLKpin, LOW);
  delay(2);
}

int receiveBit()
{
  // receive the data on the FALLING edge of the clock
  digitalWrite(SCLKpin, HIGH);
  delay(2);
  int bit = digitalRead(MISOpin);
  delay(2);
  digitalWrite(SCLKpin, LOW);
  delay(2);
  return bit;
}

float readAxis(int axis)
{
  // send eight bits, wait until the data is ready then receive 16 bits

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

  // send the command byte
  // set the time to read the magnetic sensors (ASIC period) as /2048
  sendBit(LOW);
  sendBit(HIGH);
  sendBit(HIGH);
  sendBit(LOW);
  sendBit(LOW);
  sendBit(LOW);

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

  // wait until the DRDY line is high
  while (digitalRead(DRDYpin) == LOW)
  {
  }

  long total = 0;

  // receive result
  // the leftmost bit mark the number as positive or negative
  long sign = receiveBit();

  // the remaining bits are converted to an integer
  for (int i = 14; i >= 0; i = i - 1)
  {
    long thisbit = receiveBit();
    thisbit = thisbit << i;
    total = total | thisbit;
  }

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

  // set and return the appropriate variable
  if (axis == 0)
  {
    x = total;
  }
  else if (axis == 1)
  {
    y = total;
  }
  else
  {
    z = total;
  }
  return total;
}

int getHeading(float x, float y, float z)
{
  float heading = 0;
  if ((x == 0) && (y < 0))
    heading = PI / 2.0;
  if ((x == 0) && (y > 0))
    heading = 3.0 * PI / 2.0;
  if (x < 0)
    heading = PI - atan(y / x);
  if ((x > 0) && (y < 0))
    heading = -atan(y / x);
  if ((x > 0) && (y > 0))
    heading = 2.0 * PI - atan(y / x);
  return  int(degrees(heading));
}

Please never say that. It's frustrating for those who want to help you.

Always describe what actually happens when the code runs and what you wanted or expected to happen.

oh sorry, it wont print the data in the serial monitor. i wanted the data of x, y, z and the heading of the magnet to be shown in the serial monitor. Right now it does nothing.

Nothing at all?

Do you have the correct baud rate setting in serial monitor to match your code?

Add some extra Serial.println() commands like Serial.println("Exiting setup()"), Serial.println("Entering loop()") and similar to your code to help diagnose what is going on.

yes i do have correct baud setting. its set to 9600.

#include <SPI.h>

int SCLKpin = 13;    // SCK pin of Arduino Uno connected to magnetometer pin 1
int MISOpin = 12;    // MISO pin of Arduino Uno connected to magnetometer pin 2
int MOSIpin = 11;    // MOSI pin of Arduino Uno connected to magnetometer pin 3
int SSNOTpin = 10;   // SS (Slave Select) pin of Arduino Uno connected to magnetometer pin 4
int DRDYpin = 9;     // Data Ready pin of Arduino Uno connected to magnetometer pin 5
int RESETpin = 8;    // Reset pin of Arduino Uno connected to magnetometer pin 6

int x = 0;            // Magnetic field x-axis
int y = 0;            // Magnetic field y-axis
int z = 0;            // Magnetic field z-axis
int heading = 0;      // Magnetic field heading

void setup() {
  Serial.begin(9600);
  pinMode(SSNOTpin, OUTPUT);
  pinMode(RESETpin, OUTPUT);
  pinMode(MOSIpin, OUTPUT);
  pinMode(SCLKpin, OUTPUT);
  pinMode(MISOpin, INPUT);
  pinMode(DRDYpin, INPUT);
  digitalWrite(SSNOTpin, HIGH);  // Ensure SS is high initially (not selected)
  digitalWrite(RESETpin, LOW);   // Keep reset low initially
  
  // Debug prints
  Serial.println("Setup complete.");
}

void loop() {
  digitalWrite(SSNOTpin, LOW);  // Step 1: Bring SSNOT low
  Serial.println("Step 1: SSNOT pin set LOW");
  delayMicroseconds(10);        // Ensure SSNOT is stable low
  
  digitalWrite(RESETpin, HIGH); // Step 2: Pulse RESET high
  Serial.println("Step 2: RESET pin set HIGH");
  delayMicroseconds(10);        // Pulse width minimum 5us
  digitalWrite(RESETpin, LOW);  // Reset to low state
  Serial.println("Step 2: RESET pin set LOW");
  delayMicroseconds(10);        // Ensure RESET is stable low
  
  // Step 3: Send command byte (000000) and axis selection
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0)); // Start SPI transaction
  digitalWrite(SSNOTpin, LOW);  // Select the MicroMag3
  Serial.println("Step 3: MicroMag3 selected");

  SPI.transfer(0b00110000);     // Send command byte: 000000
  Serial.println("Step 3: Command byte sent");
  SPI.transfer(0b00000110);     // Send axis selection byte (for example, X-axis)
  Serial.println("Step 3: Axis selection sent");
  
  digitalWrite(SSNOTpin, HIGH); // Deselect the MicroMag3
  Serial.println("Step 3: MicroMag3 deselected");
  SPI.endTransaction();         // End SPI transaction

  // Small delay for stability
  delay(10);

  // Step 4: Wait for DRDY pin to go high indicating data is ready
  unsigned long startTime = millis();  // Record start time for timeout
  while (digitalRead(DRDYpin) == LOW) {
    // Wait until DRDY line is high or timeout
    if (millis() - startTime > 100) {  // Timeout after 100ms (adjust as necessary)
      Serial.println("Timeout waiting for DRDY to go HIGH");
      break;
    }
  }
  
  if (digitalRead(DRDYpin) == HIGH) {
    Serial.println("Step 4: DRDY pin is HIGH, data ready");

    // Step 5: Read data from MISO line
    SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0)); // Start SPI transaction
    digitalWrite(SSNOTpin, LOW);  // Select the MicroMag3
    Serial.println("Step 5: MicroMag3 selected for data read");

    // Shift out 16 bits of data from MicroMag3
    int sign = SPI.transfer(0);   // First bit is sign
    Serial.println("Step 5: First bit (sign) read");
    long total = 0;
    
    for (int i = 14; i >= 0; i--) {
      int thisbit = SPI.transfer(0);
      thisbit = thisbit << i;
      total = total | thisbit;
    }
    Serial.println("Step 5: 16 bits of data read");

    digitalWrite(SSNOTpin, HIGH); // Deselect the MicroMag3
    Serial.println("Step 5: MicroMag3 deselected");
    SPI.endTransaction();         // End SPI transaction

    // Interpret total as signed integer
    if (sign == 1) {
      total = total - 32768;
    }

    // Assign values based on axis
    x = total; // Assuming axis is predefined or calculated earlier
    y = total; // Replace with actual axis assignments
    z = total; // Replace with actual axis assignments

    // Calculate heading if needed
    heading = getHeading(x, y, z);

    // Print data or do further processing
    Serial.print("x: ");
    Serial.print(x);
    Serial.print(" y: ");
    Serial.print(y);
    Serial.print(" z: ");
    Serial.print(z);
    Serial.print(" heading: ");
    Serial.println(heading);
  }
  else {
    Serial.println("Data not ready within timeout period");
  }

  delay(20000);  // Next reading in 20 seconds
}

// Function to calculate heading
int getHeading(float x, float y, float z) {
  float heading = 0;

  if ((x == 0) && (y < 0))
    heading = PI / 2.0;
  if ((x == 0) && (y > 0))
    heading = 3.0 * PI / 2.0;
  if (x < 0)
    heading = PI - atan(y / x);
  if ((x > 0) && (y < 0))
    heading = -atan(y / x);
  if ((x > 0) && (y > 0))
    heading = 2.0 * PI - atan(y / x);

  return int(degrees(heading));
}

Output for serial monitor:

Setthin timeout period
: Axis selection sent
Step 3: MicroMag3 deselected
Timeout waiting for DRDY to go HIGH
Data not ready within timeout period
: Axis selection sent
Step 3: MicroMag3 deselected
Timeout waiting for DRDY to go HIGH
Data not ready within timeout period
Setup complete.
Step 1: SSNOT pin set LOW
Step 2: RESET pin set HIGH
Step 2: RESET pin set LOW
Step 3: MicroMag3 selected

This code is very different. There was no SPI library before.

I don't see SPI.begin() in setup().

Hi, @aspect612
Welcome to the forum.

Can you please post a link to data/specs of the sensor?

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:

Hello :D, @TomGeorge

Datasheet: https://www.sparkfun.com/datasheets/Sensors/MicroMag3%20Data%20Sheet.pdf

Wiring and Code:

Image:

i didnt copy the #include <SPI.h> before. sorry i kind of missed that part. and I changed the code only for it to debug.

The first code didn't use SPI library all all. It bit-banged comms with the sensor. Like I said, it was very different code, not simply something missed or changed for debugging.

Before I or anyone else wastes time helping you with the second code, it is going to completely change again?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.