Gravity: BMM150 Triple Axis Magnetometer Wiki - DFRobot

1. Introduction

BMM150 is a low-power and low-noise 3-axis geomagnetic sensor from Bosch for compass applications. It allows measurements of the magnetic field and compass angle in three perpendiculars within a measuring range of ±1300uT on X and Y axis and ±2047uT on Z axis.
On the small and lightweight board, there is a 2-bit DIP switch for I2C address setup, and 4 addresses are available. Based on Bosch's proprietary FlipCore technology, the performance and features of BMM150 are carefully tuned and thus can offer absolute spatial orientation without calibration, perfectly matching the requirements of all 3-axis mobile applications such as robot navigation & positioning, electric compass, electric map, navigation or augmented reality.

2. Features

3. Application

4. Pinout

XG

Pin Description
VCC DC3.3V-5V
GND Ground
SCL I2C Clock Line
SDA I2C Data Line
INT Interrupt Pin

I2C Addresses

Name A0 A1 Address
ADDRESS_1 0 0 0X10
ADDRESS_2 0 1 0X11
ADDRESS_3 1 0 0X12
ADDRESS_4 1 1 0X13

5. Specification

6. Dimension

7. Tutorial

7.1 Hardware Requirements

7.2 Software Requirements

7.3 Connection Diagram

LIANXIAN

Gravity: I2C BMM150 Module: VCC (to) ESP32-E Microcontroller: 3V3

Gravity: I2C BMM150 Module: GND (to) ESP32-E Microcontroller: GND

Gravity: I2C BMM150 Module: SCL (to) ESP32-E Microcontroller: SCL

Gravity: I2C BMM150 Module: SDA (to) ESP32-E Microcontroller: SDA

7.4 Sample Code

Sample Code List

Sample Code 1 - Get config status(getAllState.ino)

#include "DFRobot_BMM150.h"

DFRobot_BMM150_I2C bmm150(&Wire, I2C_ADDRESS_4);
/*i2c Address select, that CS and SDO pin select 1 or 0 indicates the high or low respectively. There are 4 combinations: 
 *I2C_ADDRESS_1 0x10  (CS:0 SDO:0)
 *I2C_ADDRESS_2 0x11  (CS:0 SDO:1)
 *I2C_ADDRESS_3 0x12  (CS:1 SDO:0)
 *I2C_ADDRESS_4 0x13  (CS:1 SDO:1) default i2c address */


#define BMM150_CS D3


void setup() 
{
  Serial.begin(115200);
  while(!Serial);
  while(bmm150.begin()){
    Serial.println("bmm150 init failed, Please try again!");
    delay(1000);
  } Serial.println("bmm150 init success!");

  Serial.println(bmm150.selfTest(BMM150_SELF_TEST_NORMAL));//The returned character string indicates the self test result

  bmm150.setOperationMode(BMM150_POWERMODE_NORMAL);//Normal mode

  bmm150.setPresetMode(BMM150_PRESETMODE_HIGHACCURACY);// High-accuracy mode

  bmm150.setRate(BMM150_DATA_RATE_30HZ);//30HZ

  bmm150.setMeasurementXYZ();//Default config of X-, Y-, and Z-axis

  uint8_t rate = bmm150.getRate();//Get the configured data rate
  Serial.print("rate is "); Serial.print(rate); Serial.println(" HZ");

  Serial.println(bmm150.getMeasurementStateXYZ());

  /**!
   * Get the sensor operation mode, return the sensor operation mode as character string
   */
  Serial.println(bmm150.getOperationMode());

  bmm150.softReset();  //Software reset  
}

void loop() 
{

  Serial.println(bmm150.getOperationMode());
  delay(1000);
}

Result

Burn sample code, and serial prints the current config status of the sensor.

Sample Code 2 - Get 3-axis geomagnetic data & compass angle(getGeomagneticData.ino)

#include "DFRobot_BMM150.h"

DFRobot_BMM150_I2C bmm150(&Wire, I2C_ADDRESS_4);

/*i2c Address select, that CS and SDO pin select 1 or 0 indicates the high or low respectively. There are 4 combinations: 
 *I2C_ADDRESS_1 0x10  (CS:0 SDO:0)
 *I2C_ADDRESS_2 0x11  (CS:0 SDO:1)
 *I2C_ADDRESS_3 0x12  (CS:1 SDO:0)
 *I2C_ADDRESS_4 0x13  (CS:1 SDO:1) default i2c address */

//When using SPI communication, use the following program to construct an object by DFRobot_BMM150_SPI

#define BMM150_CS D3


//DFRobot_BMM150_SPI bmm150(/*cs = */BMM150_CS);

void setup() 
{
  Serial.begin(115200);
  while(!Serial);
  while(bmm150.begin()){
    Serial.println("bmm150 init failed, Please try again!");
    delay(1000);
  } Serial.println("bmm150 init success!");

  bmm150.setOperationMode(BMM150_POWERMODE_NORMAL);//Normal mode

  bmm150.setPresetMode(BMM150_PRESETMODE_HIGHACCURACY);//High-accuracy mode

  bmm150.setRate(BMM150_DATA_RATE_10HZ);//10HZ

  bmm150.setMeasurementXYZ();//Default config of X-, Y-, and Z-axis
}

void loop()
{
  sBmm150MagData_t magData = bmm150.getGeomagneticData();
  Serial.print("mag x = "); Serial.print(magData.x); Serial.println(" uT");
  Serial.print("mag y = "); Serial.print(magData.y); Serial.println(" uT");
  Serial.print("mag z = "); Serial.print(magData.z); Serial.println(" uT");

  /* float type data*/
  //Serial.print("mag x = "); Serial.print(magData.xx); Serial.println(" uT");
  //Serial.print("mag y = "); Serial.print(magData.yy); Serial.println(" uT");
  //Serial.print("mag z = "); Serial.print(magData.zz); Serial.println(" uT");
  float compassDegree = bmm150.getCompassDegree();
  Serial.print("the angle between the pointing direction and north (counterclockwise) is:");
  Serial.println(compassDegree);
  Serial.println("--------------------------------");
  delay(100);
}

Result

Burn sample code, and serial prints the geomagnetic data and compass angle obtained by the sensor.

Sample Code 3 - Threshold interrupt function(thresholdInterrupt.ino)

#include "DFRobot_BMM150.h"

DFRobot_BMM150_I2C bmm150(&Wire, I2C_ADDRESS_4);

/*i2c Address select, that CS and SDO pin select 1 or 0 indicates the high or low respectively. There are 4 combinations: 
 *I2C_ADDRESS_1 0x10  (CS:0 SDO:0)
 *I2C_ADDRESS_2 0x11  (CS:0 SDO:1)
 *I2C_ADDRESS_3 0x12  (CS:1 SDO:0)
 *I2C_ADDRESS_4 0x13  (CS:1 SDO:1) default i2c address */

#define BMM150_CS D3


volatile uint8_t interruptFlag = 0;
void myInterrupt(void)
{
  interruptFlag = 1;    // interrupt flag
  #if defined(ESP32) || defined(ESP8266)||defined(ARDUINO_SAM_ZERO)
    detachInterrupt(13);   //Connect to pin INT
  #else
    detachInterrupt(0);   
  #endif
}

void setup() 
{
  Serial.begin(115200);
  while(!Serial);
  while(bmm150.begin()){
    Serial.println("bmm150 init failed, Please try again!");
    delay(1000);
  } Serial.println("bmm150 init success!");

  bmm150.setOperationMode(BMM150_POWERMODE_NORMAL);//Normal mode

  bmm150.setPresetMode(BMM150_PRESETMODE_HIGHACCURACY);//High-accuracy mode

  bmm150.setRate(BMM150_DATA_RATE_10HZ);//rate of 10HZ

  bmm150.setMeasurementXYZ();//Default config of X-, Y-, and Z-axis

  bmm150.setThresholdInterrupt(LOW_THRESHOLD_INTERRUPT, 0, POLARITY_LOW);//trigger interrupt when below threshold

  #if defined(ESP32) || defined(ESP8266)||defined(ARDUINO_SAM_ZERO)

  pinMode(/*Pin */13 ,INPUT_PULLUP);//Low-polarity pull-up output
  attachInterrupt(/*interput io*/13, myInterrupt, LOW);

  pinMode(/*Pin */2 ,INPUT_PULLUP);

  attachInterrupt(/*Interrupt No*/0, /*function*/myInterrupt ,/*state*/LOW );//Set pin interrupt
  #endif

}

void loop() 
{
  if(interruptFlag == 1){
    sBmm150ThresholdData_t threshold = bmm150.getThresholdData();
    if(threshold.x != NO_DATA){
      Serial.print("mag x = "); Serial.print(threshold.x); Serial.println(" uT");
    }
    if(threshold.y != NO_DATA){
      Serial.print("mag y = "); Serial.print(threshold.y); Serial.println(" uT");
    }
    if(threshold.z != NO_DATA){
      Serial.print("mag z = "); Serial.print(threshold.z); Serial.println(" uT");
    }
    Serial.println();
    interruptFlag = 0;
    #if defined(ESP32) || defined(ESP8266)||defined(ARDUINO_SAM_ZERO)
      attachInterrupt(13, myInterrupt, LOW);
    #else
      attachInterrupt(0, myInterrupt ,LOW);
    #endif
  }
  delay(100);
}

Result

Burn sample code, rock the sensor to trigger threshold interrupt, and serial prints data change.

8. API Function

  /*!
   *  @brief Soft reset, restore to suspended mode after soft reset and then enter sleep mode, soft reset can't be implemented under suspend mode
   */
  void softReset(void);

  /*!
   *  @brief Set sensor operation mode
   *  @param op mode
   *    BMM150_POWERMODE_NORMAL      // normal mode  Get geomagnetic data normally
   *    BMM150_POWERMODE_FORCED      // forced mode  Single measurement, the sensor restores to sleep mode when the measurement is done.
   *    BMM150_POWERMODE_SLEEP       // sleep mode   Users can visit all the registers, but can’t measure geomagnetic data
   *    BMM150_POWERMODE_SUSPEND     // suspend mode At the time the sensor cpu doesn’t work and can’t implement any operation. Users can only visit the content of the control register BMM150_REG_POWER_CONTROL
   */
  void setOperationMode(uint8_t opMode);

  /*!
   *  @brief Get sensor operation mode
   *  @return result Return sensor operation mode as a character string
   */
  String getOperationMode(void);

  /*!
   *  @brief Set preset mode, make it easier for users to configure sensor to get geomagnetic data
   *  @param presetMode
   *    BMM150_PRESETMODE_LOWPOWER      // Low power mode, get a fraction of data and take the mean value.
   *    BMM150_PRESETMODE_REGULAR       // Regular mode, get a number of data and take the mean value.
   *    BMM150_PRESETMODE_ENHANCED      // Enhanced mode, get a plenty of data and take the mean value.
   *    BMM150_PRESETMODE_HIGHACCURACY  // High accuracy mode, get a huge number of data and take the mean value.
   */
  void setPresetMode(uint8_t presetMode);

  /*!
   *  @brief Set the rate of obtaining geomagnetic data, the higher, the faster (without delay function)
   *  @param rate
   *    BMM150_DATA_RATE_02HZ
   *    BMM150_DATA_RATE_06HZ
   *    BMM150_DATA_RATE_08HZ
   *    BMM150_DATA_RATE_10HZ  (default rate)
   *    BMM150_DATA_RATE_15HZ
   *    BMM150_DATA_RATE_20HZ
   *    BMM150_DATA_RATE_25HZ
   *    BMM150_DATA_RATE_30HZ
   */
  void setRate(uint8_t rate);

  /*!
   *  @brief Get the config data rate, unit: HZ
   *  @return rate
   */
  uint8_t getRate(void);

  /*!
   *  @brief Get the geomagnetic data of 3 axis (x, y, z)
   *
   *  @return Geomagnetic data structure, unit: (uT)
   */
  sMagData getGeomagneticData(void);

  /*!
   *  @brief Get compass degree
   *
   *  @return Compass degree (0° - 360°)
   *          0° = North, 90° = East, 180° = South, 270° = West.
   */
  float getCompassDegree(void);

  /*!
   *  @brief Enable or disable data ready interrupt pin
   *         After enabling, the DRDY pin jump when there's data coming.
   *         After disabling, the DRDY pin will not jump when there's data coming.
   *         High polarity: active on high, the default is low level, which turns to high level when the interrupt is triggered.
   *         Low polarity: active on low, default is high level, which turns to low level when the interrupt is triggered.
   *  @param modes
   *      DRDY_ENABLE       // Enable DRDY
   *      DRDY_DISABLE      // Disable DRDY
   *  @param polarity
   *      POLARITY_HIGH     // High polarity
   *      POLARITY_LOW      // Low polarity
   */
  void setDataReadyPin(uint8_t modes, uint8_t polarity=POLARITY_HIGH);

  /*!
   *  @brief Get the data ready status, determine whether the data is ready
   *
   *  @return status
   *      true  Data ready
   *      false Data is not ready
   */
  bool getDataReadyState(void);

 /*!
   *  @brief Enable the measurement at x-axis, y-axis and z-axis, default to be enabled. After disabling, the geomagnetic data at x, y, and z axis are wrong.
   *
   *  @param channelX
   *      MEASUREMENT_X_ENABLE       // Enable the measurement at x-axis
   *      MEASUREMENT_X_DISABLE      // Disable the measurement at x-axis
   *  @param channelY
   *      MEASUREMENT_Y_ENABLE       // Enable the measurement at y-axis
   *      MEASUREMENT_Y_DISABLE      // Disable the measurement at y-axis
   *  @param channelZ
   *      MEASUREMENT_Z_ENABLE       // Enable the measurement at z-axis
   *      MEASUREMENT_Z_DISABLE      // Disable the measurement at z-axis
   */
  void setMeasurementXYZ(uint8_t channelX = MEASUREMENT_X_ENABLE, uint8_t channelY = MEASUREMENT_Y_ENABLE, uint8_t channelZ = MEASUREMENT_Z_ENABLE);

  /*!
   *  @brief Get the enabling status at x-axis, y-axis and z-axis
   *  @return result Return enabling status as a character string
   */
  String getMeasurementStateXYZ(void);

  /*!
   *  @brief Set threshold interrupt, an interrupt is triggered when the geomagnetic value of a channel is beyond/below the threshold
   *         High polarity: active on high level, the default is low level, which turns to high level when the interrupt is triggered.
   *         Low polarity: active on low level, the default is high level, which turns to low level when the interrupt is triggered.
   *  @param modes
   *      LOW_THRESHOLD_INTERRUPT      // Low threshold interrupt mode
   *      HIGH_THRESHOLD_INTERRUPT     // High threshold interrupt mode
   *  @param  threshold
   *             Threshold, default to expand 16 times, for example: under low threshold mode, if the threshold is set to be 1, actually the geomagnetic data below 16 will trigger an interrupt
   *  @param polarity
   *      POLARITY_HIGH     // High polarity
   *      POLARITY_LOW      // Low polarity
   */
  void setThresholdInterrupt(uint8_t modes, int8_t threshold, uint8_t polarity);

  /*!
   *  @brief Set threshold interrupt, an interrupt is triggered when the geomagnetic value of a channel is beyond/below the threshold
   *     When an interrupt occurs, INT pin level will jump
   *     High polarity: active on high level, the default is low level, which turns to high level when the interrupt is triggered.
   *     Low polarity: active on low level, the default is high level, which turns to low level when the interrupt is triggered.
   *  @param modes
   *      LOW_THRESHOLD_INTERRUPT  // Low threshold interrupt mode
   *      HIGH_THRESHOLD_INTERRUPT // High threshold interrupt mode
   *  @param channelX
   *      INTERRUPT_X_ENABLE       // Enable high threshold interrupt at x-axis
   *      INTERRUPT_X_DISABLE      // Disable high threshold interrupt at x-axis
   *  @param channelY
   *      INTERRUPT_Y_ENABLE       // Enable high threshold interrupt at y-axis
   *      INTERRUPT_Y_DISABLE      // Disable high threshold interrupt at y-axis
   *  @param channelZ
   *      INTERRUPT_Z_ENABLE       // Enable high threshold interrupt at z-axis
   *      INTERRUPT_Z_DISABLE      // Disable high threshold interrupt at z-axis
   *  @param  threshold
   *             Threshold, default to expand 16 times, for example: if the threshold is set to be 1, actually the geomagnetic data below 16 will trigger an interrupt
   *  @param polarity
   *      POLARITY_HIGH     // High polarity
   *      POLARITY_LOW      // Low polarity
   */
  void setThresholdInterrupt(uint8_t modes, uint8_t channelX, uint8_t channelY, uint8_t channelZ, int8_t threshold, uint8_t polarity);

  /*!
   *  @brief Get the data when threshold interrupt occurred
   *  @return Returns the structure for storing geomagnetic data, the structure stores the data of 3 axis and interrupt status,
   *    The interrupt is not triggered when the data at x-axis, y-axis and z-axis are NO_DATA
   *    String state The storage state is binary data string
   *    uint8_t value The storage state is binary raw value, the data format are as follows:
   *    bit0 is 1 Indicate the interrupt occur at x-axis
   *    bit1 is 1 Indicate the interrupt occur at y-axis
   *    bit2 is 1 Indicate the interrupt occur at z-axis
   *    ------------------------------------
   *    | bit7 ~ bit3 | bit2 | bit1 | bit0 |
   *    ------------------------------------
   *    |  reserved   |  0   |  0   |  0   |
   *    ------------------------------------
   */
  sThresholdData getThresholdData(void);

  /*!
   *  @brief The sensor self test, the returned value indicate the self test result.
   *
   *  @param mode:
   *      BMM150_SELF_TEST_NORMAL              // Normal self test, test whether x-axis, y-axis and z-axis are connected or short-circuited
   *      BMM150_SELF_TEST_ADVANCED            // Advanced self test, test the data accuracy at z-axis
   *
   *  @return result The returned character string is the self test result
   */
  String selfTest(uint8_t testMode);

9. More Documents

SEN0529 STP 3D Model.rar

SEN0529 2D CAD Dimensions.rar

SEN0529 2D CAD Dimensions.pdf

SEN0529 Schematics.pdf

BMM150 Datasheet.pdf

10. FAQ

For any questions, advice or cool ideas to share, please visit the DFRobot Forum.