BMM150地磁感器

简介

该传感器也可与六轴MEMS(3轴加速度+3轴陀螺仪)配对使用以获得一个9自由度惯性测量单元。
该传感器是专为指南针应用设计的三轴数字地磁传感器,具有低功耗(170uA)低噪(0.3-1.4uT)低温漂(±0.01%/K)、高分辨率(0.3uT)和高指针准确度(误差最大±2.5°@30uT水平磁场分量@25°C)的特点。BMM150能提供绝对空间方向上的运动矢量,该产品可与六轴IMU(三轴加速度+三轴磁力计)搭配使用以获得一个9自由度姿态传感器的效果。
BMM150还非常适合用于无人机这样的飞行项目中,轻便小巧的板子不会附加任何重量和占用体积,精准的空间方向可为无人机提供正确航向。

特性

  • 低功耗
  • 低噪声
  • 精度高
  • 精致小巧

应用场景

  • 无人机
  • 指南针/电子罗盘
  • 室内/室外导航
  • 头部运动追踪
  • 增强现实
  • 倾斜补偿的电子地图

技术规格

undefined

  • 供电电压:3.3V
  • 温度范围:-40~85°C
  • 数字接口:I2C/SPI
  • 可编程中断:2个中断引脚
  • 分辨率:0.3uT
  • 零B漂移:±40uT/±2uT(软件优化后)
  • 非线性:< 1%FS
  • 磁力测量范围:±1300μT (x,y轴) ±2047μT (z轴)
  • 平均功耗:170 μA (低功耗模式) / 500 μA (正常模式)
  • 低噪声:0.3-1.4uT
  • 精度:30uT水平磁场分量 ±2.5°
  • 启动时间:3ms

引脚说明

undefined

序号 丝印 功能描述
1 VCC 3.3V电源输
2 SCK 时钟线
4 SDI SPI、I2C数据线(输入)
5 SDO SPI、I2C数据线(输出)
6 CS SPI 片选线、I2C接地
7 PS 选择通讯协议
8 DRDY 数据收发准备状态
9 INT 中断引脚

注意:

  • 所有数据输出电压均为3.3V
  • 只能接入3.3V电压

不同通信方式连线提示:

- I2Cl连接:0x13是默认地址

undefined

  • 在使用magDrdyInterrupt时DRDY接中断,INT不接

- SPI连接

undefined

注意:使用SPI连线时PS引脚要接地

- 中断引脚连接

主板 默认连接引脚
Leonardo D3
Micro:bit P0
ESP32/ESP8266/ARDUINO_SAM_ZERO(M0) D7
Raspberry Pi GPIO25
  • 在使用中断时才接中断引脚 其他状态下不接

M0使用教程

请按接线图所示将传感器与M0(或其它主板)相连接即可。

这里使用的是默认地址0x13

准备

关于如何安装库文件,点击链接

关于如何使用Firebeetle Board-M0,点击链接

  /*!
   *  @brief 软件复位,软件复位后先恢复为挂起模式,而后恢复为睡眠模式,suspend mode下不能软件复位
   */
  void softReset(void);

  /*!
   *  @brief 设置传感器的执行模式
   *  @param op mode
   *    BMM150_POWERMODE_NORMAL      // normal mode  正常的获得地磁数据的模式
   *    BMM150_POWERMODE_FORCED      // forced mode  单次测量,测量完成后,传感器恢复sleep mode
   *    BMM150_POWERMODE_SLEEP       // sleep mode   用户可以访问所有寄存器,不能测量地磁数据
   *    BMM150_POWERMODE_SUSPEND     // suspend mode 此时传感器cpu不工作,无法执行任何操作,用户只能访问控制寄存器 BMM150_REG_POWER_CONTROL的内容
   */
  void setOperationMode(uint8_t opMode);

  /*!
   *  @brief 获取传感器的执行模式
   *  @return result 返回字符串为传感器的执行模式
   */
  String getOperationMode(void);

  /*!
   *  @brief 设置预置模式,使用户更简单的配置传感器来获取地磁数据
   *  @param presetMode
   *    BMM150_PRESETMODE_LOWPOWER      // 低功率模式,获取少量的数据 取均值
   *    BMM150_PRESETMODE_REGULAR       // 普通模式,获取中量数据 取均值
   *    BMM150_PRESETMODE_ENHANCED      // 增强模式,获取大量数据 取均值
   *    BMM150_PRESETMODE_HIGHACCURACY  // 高精度模式,获取超大量数据 取均值
   */
  void setPresetMode(uint8_t presetMode);

  /*!
   *  @brief 设置获取地磁数据的速率,速率越大获取越快(不加延时函数)
   *  @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 获取配置的数据速率 单位:HZ
   *  @return rate
   */
  uint8_t getRate(void);

  /*!
   *  @brief 获取x y z 三轴的地磁数据
   *
   *  @return 地磁的数据的结构体,单位:微特斯拉(uT)
   */
  sMagData getGeomagneticData(void);

  /*!
   *  @brief 获取罗盘方向
   *
   *  @return 罗盘方向 (0° - 360°)
   *          0° = North, 90° = East, 180° = South, 270° = West.
   */
  float getCompassDegree(void);

  /*!
   *  @brief 使能或者禁止数据准备中断引脚
   *         使能后有数据来临DRDY引脚跳变
   *         禁止后有数据来临DRDY不进行跳变
   *         高极性:高电平为活动电平,默认为低电平,触发中断时电平变为高
   *         低极性:低电平为活动电平,默认为高电平,触发中断时电平变为低
   *  @param modes
   *      DRDY_ENABLE       // 使能DRDY
   *      DRDY_DISABLE      // 禁止DRDY
   *  @param polarity
   *      POLARITY_HIGH     // 高极性
   *      POLARITY_LOW      // 低极性
   */
  void setDataReadyPin(uint8_t modes, uint8_t polarity=POLARITY_HIGH);

  /*!
   *  @brief 获取数据准备的状态,用来判断数据是否准备好
   *
   *  @return status
   *      true  数据准备好了
   *      false 数据没有准备好
   */
  bool getDataReadyState(void);

 /*!
   *  @brief 使能x y z 轴的测量,默认设置为使能,禁止后xyz轴的地磁数据不准确
   *
   *  @param channelX
   *      MEASUREMENT_X_ENABLE       // 使能 x 轴的测量
   *      MEASUREMENT_X_DISABLE      // 禁止 x 轴的测量
   *  @param channelY
   *      MEASUREMENT_Y_ENABLE       // 使能 y 轴的测量
   *      MEASUREMENT_Y_DISABLE      // 禁止 y 轴的测量
   *  @param channelZ
   *      MEASUREMENT_Z_ENABLE       // 使能 z 轴的测量
   *      MEASUREMENT_Z_DISABLE      // 禁止 z 轴的测量
   */
  void setMeasurementXYZ(uint8_t channelX = MEASUREMENT_X_ENABLE, uint8_t channelY = MEASUREMENT_Y_ENABLE, uint8_t channelZ = MEASUREMENT_Z_ENABLE);

  /*!
   *  @brief 获取 x y z 轴的使能状态
   *  @return result 返回字符串为使能的状态
   */
  String getMeasurementStateXYZ(void);

  /*!
   *  @brief 设置阈值中断,当某个通道的地磁值高/低于阈值时触发中断
   *         高极性:高电平为活动电平,默认为低电平,触发中断时电平变为高
   *         低极性:低电平为活动电平,默认为高电平,触发中断时电平变为低
   *  @param modes
   *      LOW_THRESHOLD_INTERRUPT      // 低阈值中断模式
   *      HIGH_THRESHOLD_INTERRUPT     // 高阈值中断模式
   *  @param  threshold
   *             阈值,默认扩大16倍,例如:低阈值模式下传入阈值1,实际低于16的地磁数据都会触发中断
   *  @param polarity
   *      POLARITY_HIGH     // 高极性
   *      POLARITY_LOW      // 低极性
   */
  void setThresholdInterrupt(uint8_t modes, int8_t threshold, uint8_t polarity);

  /*!
   *  @brief 设置阈值中断,当某个通道的地磁值高于/低于阈值时触发中断
   *     当产生中断时,INT引脚电平产生跳变
   *     高极性:高电平为活动电平,默认为低电平,触发中断时电平变为高
   *     低极性:低电平为活动电平,默认为高电平,触发中断时电平变为低
   *  @param modes
   *      LOW_THRESHOLD_INTERRUPT  // 低阈值中断模式
   *      HIGH_THRESHOLD_INTERRUPT // 高阈值中断模式
   *  @param channelX
   *      INTERRUPT_X_ENABLE       // 使能 x 轴高阈值中断
   *      INTERRUPT_X_DISABLE      // 禁止 x 轴高阈值中断
   *  @param channelY
   *      INTERRUPT_Y_ENABLE       // 使能 y 轴高阈值中断
   *      INTERRUPT_Y_DISABLE      // 禁止 y 轴高阈值中断
   *  @param channelZ
   *      INTERRUPT_Z_ENABLE       // 使能 z 轴高阈值中断
   *      INTERRUPT_Z_DISABLE      // 禁止 z 轴高阈值中断
   *  @param  threshold
   *             阈值,默认扩大16倍,例如:传入 1 的阈值,实际高于/低于16的地磁数据都会触发中断
   *  @param polarity
   *      POLARITY_HIGH     // 高极性
   *      POLARITY_LOW      // 低极性
   */
  void setThresholdInterrupt(uint8_t modes, uint8_t channelX, uint8_t channelY, uint8_t channelZ, int8_t threshold, uint8_t polarity);

  /*!
   *  @brief 获取发生阈值中断的数据
   *  @return 返回存放地磁数据的结构体,结构体存放三轴当数据和中断状态,
   *    xyz轴的数据为 NO_DATA 时,未触发中断
   *    String state 存放状态二进制数据的字符串
   *    uint8_t value 存放状态二进制的原始值,数据格式如下
   *    bit0 is 1 代表x轴发生了中断
   *    bit1 is 1 代表y轴发生了中断
   *    bit2 is 1 代表z轴发生了中断
   *    ------------------------------------
   *    | bit7 ~ bit3 | bit2 | bit1 | bit0 |
   *    ------------------------------------
   *    |  reserved   |  0   |  0   |  0   |
   *    ------------------------------------
   */
  sThresholdData getThresholdData(void);

  /*!
   *  @brief 传感器自测,返回值表明自检结果
   *
   *  @param mode:
   *      BMM150_SELF_TEST_NORMAL              // 普通自测,测试X,Y,Z轴是否连接,是否短路
   *      BMM150_SELF_TEST_ADVANCED            // 高级自测,测试z轴数据的准确性
   *
   *  @return result 返回的字符串为自测的结果
   */
  String selfTest(uint8_t testMode);


样例代码1-获取配置状态(getAllState.ino)

  • 选择getAllState.ino

  • 烧录程序
 /*!
  * @file  getAllState.ino
  * @brief 获取所有的配置状态,自测状态,软件复位后传感器可以从正常模式变为为睡眠模式
  * @n 实验现象 传感器的配置信息打印在串口上,自测信息打印在串口上
  * @copyright   Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
  * @licence     The MIT License (MIT)
  * @author      ZhixinLiu(zhixin.liu@dfrobot.com)
  * @version     V0.4
  * @date        2021-04-21
  * @get         from https://www.dfrobot.com
  * @url         https://github.com/dfrobot/DFRobot_BMM150
  */
#include "DFRobot_BMM150.h"

//When using I2C communication, use the following program to construct an object by DFRobot_BMM150_I2C
/*!
 * @brief Constructor 
 * @param pWire I2C controller
 * @param I2C address
 *        i2c 地址选择,CS,SDO引脚连接1代表高电平,0代表低电平,4 种组合为 
 *          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
 */
DFRobot_BMM150_I2C bmm150(&Wire, I2C_ADDRESS_4);

//When using SPI communication, use the following program to construct an object by DFRobot_BMM150_SPI
#if defined(ESP32) || defined(ESP8266)
  #define BMM150_CS D3
#elif defined(__AVR__) || defined(ARDUINO_SAM_ZERO)
  #define BMM150_CS 3
#elif (defined NRF5)
  #define BMM150_CS 2  //The corresponding silkscreen on the development board is the pin of P2
#endif
/*!
 * @brief Constructor 
 * @param cs Chip selection pinChip selection pin
 *        spi连接方法
 *        (SDO<-->MISO)    (SDI<-->MOSI)
 *        (SCK<-->SCK)     (PS<--> GND)
 *        (CS<-->CS 可自定义引脚)
 */
//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!");

  /**!
   * 传感器自测,返回的字符串表明自检结果
   * mode:
   *  BMM150_SELF_TEST_NORMAL              // 普通自测,测试X,Y,Z轴是否连接,是否短路
   *  BMM150_SELF_TEST_ADVANCED            // 高级自测,测试z轴数据的准确性
   */
  Serial.println(bmm150.selfTest(BMM150_SELF_TEST_NORMAL));

  /**!
   * 设置传感器的执行模式
   * opMode:
   *   BMM150_POWERMODE_NORMAL  // normal mode  正常的获得地磁数据的模式
   *   BMM150_POWERMODE_FORCED  // forced mode  单次测量,测量完成后,传感器恢复sleep mode
   *   BMM150_POWERMODE_SLEEP   // sleep mode   用户可以访问所有寄存器,不能测量地磁数据
   *   BMM150_POWERMODE_SUSPEND // suspend mode 此时传感器cpu不工作,无法执行任何操作,
   *                                            用户只能访问控制寄存器 BMM150_REG_POWER_CONTROL的内容
   */
  bmm150.setOperationMode(BMM150_POWERMODE_NORMAL);

  /**!
   * 设置预置模式,使用户更简单的配置传感器来获取地磁数据
   * presetMode:
   *   BMM150_PRESETMODE_LOWPOWER      // 低功率模式,获取少量的数据 取均值
   *   BMM150_PRESETMODE_REGULAR       // 普通模式,获取中量数据 取均值
   *   BMM150_PRESETMODE_ENHANCED      // 增强模式,获取大量数据 取均值
   *   BMM150_PRESETMODE_HIGHACCURACY  // 高精度模式,获取超大量数据 取均值
   */
  bmm150.setPresetMode(BMM150_PRESETMODE_HIGHACCURACY);

  /**!
   * 设置获取地磁数据的速率,速率越大获取越快(不加延时函数)
   * 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
   */
  bmm150.setRate(BMM150_DATA_RATE_30HZ);

  /**!
   * 使能xyz轴的测量,默认设置为使能不需要配置,禁止后获取xyz轴的地磁数据不准确
   * 如果想配置更多参数请参考.h文件中的 setMeasurementXYZ() 函数
   */
  bmm150.setMeasurementXYZ();

  /**!
   * 获取配置的数据速率 单位:HZ
   */
  uint8_t rate = bmm150.getRate();
  Serial.print("rate is "); Serial.print(rate); Serial.println(" HZ");
  
  /**!
   * 获取 x y z 轴的使能状态,返回字符串为使能的状态
   */
  Serial.println(bmm150.getMeasurementStateXYZ());
  
  /**!
   * 获取传感器的执行模式,返回字符串为传感器的执行模式
   */
  Serial.println(bmm150.getOperationMode());
  
  /**!
   * 软件复位,软件复位后先恢复为挂起模式,而后恢复为睡眠模式,suspend mode下不能软件复位
   */
  bmm150.softReset();    // After software reset, resume sleep mode, (Suspended mode cannot be reset)
}

void loop() 
{
  /**!
   * 获取传感器的执行模式,返回字符串为传感器的执行模式
   */
  Serial.println(bmm150.getOperationMode());
  delay(1000);
}

结果

样例代码2-获取三轴地磁数据、罗盘角度(getGeomagneticData.ino)

  • 选择getGeomagneticData.ino

4

  • 烧录程序
 /*!
  * @file  getGeomagneticData.ino
  * @brief 获取三轴地磁数据,获取罗盘角度
  * @n "罗盘角度",罗盘方向逆时针旋转到地理北方的夹角大小
  * @n 实验现象 xyz三轴的地磁数据和罗盘角度打印在串口上
  * @copyright   Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
  * @licence     The MIT License (MIT)
  * @author      ZhixinLiu(zhixin.liu@dfrobot.com)
  * @version     V0.4
  * @date        2021-04-21
  * @get         from https://www.dfrobot.com
  * @url         https://github.com/dfrobot/DFRobot_BMM150
  */
#include "DFRobot_BMM150.h"

//When using I2C communication, use the following program to construct an object by DFRobot_BMM150_I2C
/*!
 * @brief Constructor 
 * @param pWire I2C controller
 * @param I2C address
 *        i2c 地址选择,CS,SDO引脚连接1代表高电平,0代表低电平,4 种组合为 
 *          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
 */
DFRobot_BMM150_I2C bmm150(&Wire, I2C_ADDRESS_4);

//When using SPI communication, use the following program to construct an object by DFRobot_BMM150_SPI
#if defined(ESP32) || defined(ESP8266)
  #define BMM150_CS D3
#elif defined(__AVR__) || defined(ARDUINO_SAM_ZERO)
  #define BMM150_CS 3
#elif (defined NRF5)
  #define BMM150_CS 2  //The corresponding silkscreen on the development board is the pin of P2
#endif
/*!
 * @brief Constructor 
 * @param cs Chip selection pinChip selection pin
 *        spi连接方法
 *        (SDO<-->MISO)    (SDI<-->MOSI)
 *        (SCK<-->SCK)     (PS<--> GND)
 *        (CS<-->CS 可自定义引脚)
 */
//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!");

  /**!
   * 设置传感器的执行模式
   * opMode:
   *   BMM150_POWERMODE_NORMAL  // normal mode  正常的获得地磁数据的模式
   *   BMM150_POWERMODE_FORCED  // forced mode  单次测量,测量完成后,传感器恢复sleep mode
   *   BMM150_POWERMODE_SLEEP   // sleep mode   用户可以访问所有寄存器,不能测量地磁数据
   *   BMM150_POWERMODE_SUSPEND // suspend mode 此时传感器cpu不工作,无法执行任何操作,
   *                                            用户只能访问控制寄存器 BMM150_REG_POWER_CONTROL的内容
   */
  bmm150.setOperationMode(BMM150_POWERMODE_NORMAL);

  /**!
   * 设置预置模式,使用户更简单的配置传感器来获取地磁数据
   * presetMode:
   *   BMM150_PRESETMODE_LOWPOWER      // 低功率模式,获取少量的数据 取均值
   *   BMM150_PRESETMODE_REGULAR       // 普通模式,获取中量数据 取均值
   *   BMM150_PRESETMODE_ENHANCED      // 增强模式,获取大量数据 取均值
   *   BMM150_PRESETMODE_HIGHACCURACY  // 高精度模式,获取超大量数据 取均值
   */
  bmm150.setPresetMode(BMM150_PRESETMODE_HIGHACCURACY);

  /**!
   * 设置获取地磁数据的速率,速率越大获取越快(不加延时函数)
   * 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
   */
  bmm150.setRate(BMM150_DATA_RATE_10HZ);

  /**!
   * 使能xyz轴的测量,默认设置为使能不需要配置,禁止后获取xyz轴的地磁数据不准确
   * 如果想配置更多参数请参考.h文件中的 setMeasurementXYZ() 函数
   */
  bmm150.setMeasurementXYZ();
}

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);
}

结果

样例代码3-准备中断功能(magDrdyInterrupt.ino)

  • 选择magDrdyInterrupt.ino

  • 烧录程序
 /*!
  * @file  magDrdyInterrupt.ino
  * @brief 数据准备中断,当数据地磁数据准备好了触发DRDY中断(DRDY中断可以由软件和硬件判断是否产生了中断)
  * @n 实验现象 xyz三轴的地磁数据打印在串口上,单位微特斯拉 (uT)
  * @n 实验现象 DRDY引脚在产生中断后电平跳变触发主控中断,得到地磁数据
  * @copyright   Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
  * @licence     The MIT License (MIT)
  * @author      ZhixinLiu(zhixin.liu@dfrobot.com)
  * @version     V0.3
  * @date        2021-04-13
  * @get         from https://www.dfrobot.com
  * @url         https://github.com/dfrobot/DFRobot_BMM150
  */
#include "DFRobot_BMM150.h"

//When using I2C communication, use the following program to construct an object by DFRobot_BMM150_I2C
/*!
 * @brief Constructor 
 * @param pWire I2C controller
 * @param I2C address
 *        i2c 地址选择,CS,SDO引脚连接1代表高电平,0代表低电平,4 种组合为 
 *          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
 *          DRDY 连接到主控的中断引脚 pin 上
 */
DFRobot_BMM150_I2C bmm150(&Wire, I2C_ADDRESS_4);

//When using SPI communication, use the following program to construct an object by DFRobot_BMM150_SPI
#if defined(ESP32) || defined(ESP8266)
  #define BMM150_CS D3
#elif defined(__AVR__) || defined(ARDUINO_SAM_ZERO)
  #define BMM150_CS 3
#elif (defined NRF5)
  #define BMM150_CS 2  //The corresponding silkscreen on the development board is the pin of P2
#endif
/*!
 * @brief Constructor 
 * @param cs Chip selection pinChip selection pin
 *        spi方法
 *        (SDO<-->MISO)    (SDI<-->MOSI)
 *        (SCK<-->SCK)     (PS<--> GND)
 *        (CS<-->CS 可自定义引脚)
 *        (DRDY<-->pin DRDY连接到主控的中断引脚pin上)
 */
//DFRobot_BMM150_SPI bmm150(/*cs = */BMM150_CS);

volatile uint8_t interruptFlag = 0;
void myInterrupt(void)
{
  interruptFlag = 1;    // 中断标志
  detachInterrupt(0);   // 禁止中断
}

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!");

  /**!
   * 设置传感器的执行模式
   * opMode:
   *   BMM150_POWERMODE_NORMAL  // normal mode  正常的获得地磁数据的模式
   *   BMM150_POWERMODE_FORCED  // forced mode  单次测量,测量完成后,传感器恢复sleep mode
   *   BMM150_POWERMODE_SLEEP   // sleep mode   用户可以访问所有寄存器,不能测量地磁数据
   *   BMM150_POWERMODE_SUSPEND // suspend mode 此时传感器cpu不工作,无法执行任何操作,
   *                                            用户只能访问控制寄存器 BMM150_REG_POWER_CONTROL的内容
   */
  bmm150.setOperationMode(BMM150_POWERMODE_NORMAL);

  /**!
   * 设置预置模式,使用户更简单的配置传感器来获取地磁数据
   * presetMode:
   *   BMM150_PRESETMODE_LOWPOWER      // 低功率模式,获取少量的数据 取均值
   *   BMM150_PRESETMODE_REGULAR       // 普通模式,获取中量数据 取均值
   *   BMM150_PRESETMODE_ENHANCED      // 增强模式,获取大量数据 取均值
   *   BMM150_PRESETMODE_HIGHACCURACY  // 高精度模式,获取超大量数据 取均值
   */
  bmm150.setPresetMode(BMM150_PRESETMODE_HIGHACCURACY);

  /**!
   * 设置获取地磁数据的速率,速率越大获取越快(不加延时函数)
   * 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
   */
  bmm150.setRate(BMM150_DATA_RATE_10HZ);

  /**!
   * 使能xyz轴的测量,默认设置为使能不需要配置,禁止后获取xyz轴的地磁数据不准确
   * 如果想配置更多参数请参考.h文件中的 setMeasurementXYZ() 函数
   */
  bmm150.setMeasurementXYZ();

  /**!
   * 使能或者禁止数据准备中断引脚,
   *   使能后有数据来临DRDY 引脚电平发生变化
   *   禁止后有数据来临DRDY 引脚电平不变
   *   高极性:高电平为活动电平,默认为低电平,触发中断时电平变为高
   *   低极性:低电平为活动电平,默认为高电平,触发中断时电平变为低
   * modes:
   *   DRDY_ENABLE       // 使能DRDY
   *   DRDY_DISABLE      // 禁止DRDY
   * polatily:
   *   POLARITY_HIGH     // 高极性
   *   POLARITY_LOW      // 低极性
   */
  bmm150.setDataReadyPin(DRDY_ENABLE, POLARITY_LOW);

  #if defined(ESP32) || defined(ESP8266)||defined(ARDUINO_SAM_ZERO)
  /**!
    根据设置的DADY引脚极性选择
      INPUT_PULLUP    // 低极性,设置13号引脚为上拉输入
      INPUT_PULLDOWN  // 高极性,设置13号引脚为下拉输入
    interput io
      All pins can be used. Pin 13 is recommended
  */
  pinMode(/*Pin */13 ,INPUT_PULLUP);
  attachInterrupt(/*interput io*/13, myInterrupt, LOW);
  #else
  /**!    The Correspondence Table of AVR Series Arduino Interrupt Pins And Terminal Numbers
   * ---------------------------------------------------------------------------------------
   * |                                        |    Pin       | 2  | 3  |                   |
   * |    Uno, Nano, Mini, other 328-based    |--------------------------------------------|
   * |                                        | Interrupt No | 0  | 1  |                   |
   * |-------------------------------------------------------------------------------------|
   * |                                        |    Pin       | 2  | 3  | 21 | 20 | 19 | 18 |
   * |               Mega2560                 |--------------------------------------------|
   * |                                        | Interrupt No | 0  | 1  | 2  | 3  | 4  | 5  |
   * |-------------------------------------------------------------------------------------|
   * |                                        |    Pin       | 3  | 2  | 0  | 1  | 7  |    |
   * |    Leonardo, other 32u4-based          |--------------------------------------------|
   * |                                        | Interrupt No | 0  | 1  | 2  | 3  | 4  |    |
   * |--------------------------------------------------------------------------------------
   */

  /**!    The Correspondence Table of micro:bit Interrupt Pins And Terminal Numbers
   * ---------------------------------------------------------------------------------------------------------------------------------------------
   * |             micro:bit                       | DigitalPin |P0-P20 can be used as an external interrupt                                     |
   * |  (When using as an external interrupt,      |---------------------------------------------------------------------------------------------|
   * |no need to set it to input mode with pinMode)|Interrupt No|Interrupt number is a pin digital value, such as P0 interrupt number 0, P1 is 1 |
   * |-------------------------------------------------------------------------------------------------------------------------------------------|
   */
  /**!
       根据设置的DADY引脚极性选择
      INPUT_PULLUP    // 低极性,设置2号引脚为上拉输入
   */
  pinMode(/*Pin */2 ,INPUT_PULLUP);

  /**!
    设置引脚为中断模式
    // Open the external interrupt 0, connect INT1/2 to the digital pin of the main control:
      function
        callback function
      state
        LOW            // 当引脚为低电平后产生中断,进入interrupt函数
  */
  attachInterrupt(/*Interrupt No*/0, /*function*/myInterrupt ,/*state*/LOW );
  #endif
}

void loop() 
{
  /**!
   * 获取数据准备的状态,用来判断数据是否准备好(软件获取数据准备的状态)
   * status:
   *   true  数据准备好了
   *   false 数据没有准备好
   */
  /*
  if(bmm150.getDataReadyState()){
    sMagData 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");
    Serial.println();
  }
  */

  /**!
    当DRDY io口产生了中断,获取地磁数据(硬件获取数据准备的状态)
    重新使能中断
  */  
  if(interruptFlag == 1){
    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");
    Serial.println();
    interruptFlag = 0;
    attachInterrupt(0, myInterrupt ,LOW);
  }
  delay(100);
}

结果

3

样例代码4-阈值中断功能(thresholdInterrupt.ino)

  • 选择thresholdInterrupt.ino

  • 烧录程序
 /*!
  * @file  thresholdInterrupt.ino
  * @brief 设置高于/低于阈值触发中断,当相应轴的中断产生时数据会打印在串口上
  * @n 实验现象 当xyz轴的地磁数据大于/小于设定的阈值时,三轴的地磁数据打印在串口上,单位:微特斯拉 (uT)
  * @n 实验现象 INT引脚在产生中断后电平跳变触发主控中断,得到地磁数据
  * @copyright   Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
  * @licence     The MIT License (MIT)
  * @author      ZhixinLiu(zhixin.liu@dfrobot.com)
  * @version     V0.4
  * @date        2021-04-21
  * @get         from https://www.dfrobot.com
  * @url         https://github.com/DFRobot/DFRobot_BMM150
  */
#include "DFRobot_BMM150.h"

//When using I2C communication, use the following program to construct an object by DFRobot_BMM150_I2C
/*!
 * @brief Constructor 
 * @param pWire I2C controller
 * @param I2C address
 *        i2c 地址选择,CS,SDO引脚连接1代表高电平,0代表低电平,4 种组合为 
 *          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
 *          INT 连接到主控的中断引脚pin上
 */
DFRobot_BMM150_I2C bmm150(&Wire, I2C_ADDRESS_4);

//When using SPI communication, use the following program to construct an object by DFRobot_BMM150_SPI
#if defined(ESP32) || defined(ESP8266)
  #define BMM150_CS D3
#elif defined(__AVR__) || defined(ARDUINO_SAM_ZERO)
  #define BMM150_CS 3
#elif (defined NRF5)
  #define BMM150_CS 2  //The corresponding silkscreen on the development board is the pin of P2
#endif
/*!
 * @brief Constructor 
 * @param cs Chip selection pinChip selection pin
 *        spi连接方法
 *        (SDO<-->MISO)    (SDI<-->MOSI)
 *        (SCK<-->SCK)     (PS<--> GND)
 *        (CS<-->CS 可自定义引脚)
 *        (INT<-->pin INT连接到主控的中断引脚pin上)
 */
//DFRobot_BMM150_SPI bmm150(/*cs = */BMM150_CS);

volatile uint8_t interruptFlag = 0;
void myInterrupt(void)
{
  interruptFlag = 1;    // 中断标志
  #if defined(ESP32) || defined(ESP8266)||defined(ARDUINO_SAM_ZERO)
    detachInterrupt(13);   // 禁止中断
  #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!");

  /**!
   * 设置传感器的执行模式
   * opMode:
   *   BMM150_POWERMODE_NORMAL  // normal mode  正常的获得地磁数据的模式
   *   BMM150_POWERMODE_FORCED  // forced mode  单次测量,测量完成后,传感器恢复sleep mode
   *   BMM150_POWERMODE_SLEEP   // sleep mode   用户可以访问所有寄存器,不能测量地磁数据
   *   BMM150_POWERMODE_SUSPEND // suspend mode 此时传感器cpu不工作,无法执行任何操作,
   *                                            用户只能访问控制寄存器 BMM150_REG_POWER_CONTROL的内容
   */
  bmm150.setOperationMode(BMM150_POWERMODE_NORMAL);

  /**!
   * 设置预置模式,使用户更简单的配置传感器来获取地磁数据
   * presetMode:
   *   BMM150_PRESETMODE_LOWPOWER      // 低功率模式,获取少量的数据 取均值
   *   BMM150_PRESETMODE_REGULAR       // 普通模式,获取中量数据 取均值
   *   BMM150_PRESETMODE_ENHANCED      // 增强模式,获取大量数据 取均值
   *   BMM150_PRESETMODE_HIGHACCURACY  // 高精度模式,获取超大量数据 取均值
   */
  bmm150.setPresetMode(BMM150_PRESETMODE_HIGHACCURACY);

  /**!
   * 设置获取地磁数据的速率,速率越大获取越快(不加延时函数)
   * 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
   */
  bmm150.setRate(BMM150_DATA_RATE_10HZ);

  /**!
   * 使能xyz轴的测量,默认设置为使能不需要配置,禁止后获取xyz轴的地磁数据不准确
   * 如果想配置更多参数请参考.h文件中的 setMeasurementXYZ() 函数
   */
  bmm150.setMeasurementXYZ();

  /*!
   * 设置阈值中断,当某个通道的地磁值高/低于阈值时触发中断
   * 高极性:高电平为活动电平,默认为低电平,触发中断时电平变为高
   * 低极性:低电平为活动电平,默认为高电平,触发中断时电平变为低
   * modes:
   *   LOW_THRESHOLD_INTERRUPT      // 低阈值中断模式,低于阈值时触发中断
   *   HIGH_THRESHOLD_INTERRUPT     // 高阈值中断模式,高于阈值时触发中断
   * threshold  //阈值范围,默认扩大16倍,例如:低阈值模式下传入阈值1,实际低于16的地磁数据都会触发中断
   * polarity:
   *   POLARITY_HIGH     // 高极性
   *   POLARITY_LOW      // 低极性
   * 如果想使用更多参数请参考.h文件中的 setThresholdInterrput() 函数
   */
  bmm150.setThresholdInterrupt(LOW_THRESHOLD_INTERRUPT, 0, POLARITY_LOW);

  #if defined(ESP32) || defined(ESP8266)||defined(ARDUINO_SAM_ZERO)
  /**!
    根据设置的INT引脚极性选择
      INPUT_PULLUP    // 低极性,设置13号引脚为上拉输入
      INPUT_PULLDOWN  // 高极性,设置13号引脚为下拉输入
    interput io
      All pins can be used. Pin 13 is recommended
  */
  pinMode(/*Pin */13 ,INPUT_PULLUP);
  attachInterrupt(/*interput io*/13, myInterrupt, LOW);
  #else
  /**!    The Correspondence Table of AVR Series Arduino Interrupt Pins And Terminal Numbers
   * ---------------------------------------------------------------------------------------
   * |                                        |    Pin       | 2  | 3  |                   |
   * |    Uno, Nano, Mini, other 328-based    |--------------------------------------------|
   * |                                        | Interrupt No | 0  | 1  |                   |
   * |-------------------------------------------------------------------------------------|
   * |                                        |    Pin       | 2  | 3  | 21 | 20 | 19 | 18 |
   * |               Mega2560                 |--------------------------------------------|
   * |                                        | Interrupt No | 0  | 1  | 2  | 3  | 4  | 5  |
   * |-------------------------------------------------------------------------------------|
   * |                                        |    Pin       | 3  | 2  | 0  | 1  | 7  |    |
   * |    Leonardo, other 32u4-based          |--------------------------------------------|
   * |                                        | Interrupt No | 0  | 1  | 2  | 3  | 4  |    |
   * |--------------------------------------------------------------------------------------
   */

  /**!    The Correspondence Table of micro:bit Interrupt Pins And Terminal Numbers
   * ---------------------------------------------------------------------------------------------------------------------------------------------
   * |             micro:bit                       | DigitalPin |P0-P20 can be used as an external interrupt                                     |
   * |  (When using as an external interrupt,      |---------------------------------------------------------------------------------------------|
   * |no need to set it to input mode with pinMode)|Interrupt No|Interrupt number is a pin digital value, such as P0 interrupt number 0, P1 is 1 |
   * |-------------------------------------------------------------------------------------------------------------------------------------------|
   */
  /**!
    根据设置的INT引脚极性选择
      INPUT_PULLUP    // 低极性,设置2号引脚为上拉输入
   */
  pinMode(/*Pin */2 ,INPUT_PULLUP);

  /**!
    设置引脚为中断模式
    // Open the external interrupt 0, connect INT1/2 to the digital pin of the main control:
      function
        callback function
      state
        LOW            // 当引脚为低电平后产生中断,进入interrupt函数
  */
  attachInterrupt(/*Interrupt No*/0, /*function*/myInterrupt ,/*state*/LOW );
  #endif

}

void loop() 
{
  /**!
   * 获取发生阈值中断的数据,和中断的状态 (软件获取数据准备的状态)
   *    返回存放地磁数据的结构体,结构体存放三轴当数据和中断状态,
   *    xyz轴的数据为NO_DATA时未触发中断
   *    如果想查看中断状态请查看.h文件
   */
  /*
  sThresholdData 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();
  */

  /**!
    当INT io口产生了中断,获取阈值中断的数据(硬件获取阈值中断的状态)
  */
  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);
}

结果

树莓派使用教程

准备

接线图

  • 将模块与树莓派按照连线图相连。I2C地址默认为0x13.

安装驱动

  1. 启动树莓派的I2C接口。如已开启,可跳过该步骤。
    打开终端(Terminal),键入如下指令,并回车:
    sudo raspi-config

然后用上下键选择“ 5 Interfacing Options ”, 按回车进入,选择 “ P5 I2C ”, 按回车确认“ YES ”即可。重启树莓派主控板。

  1. 安装Python依赖库与git,树莓派需要联网。如已安装,可跳过该步骤。
    在终端中,依次键入如下指令,并回车:
  sudo apt-get update
  sudo apt-get install build-essential python-dev python-smbus git
  1. 下载BMM150驱动库。在终端中,依次键入如下指令,并回车:
  cd Desktop
  git clone https://github.com/DFRobot/DFRobot_BMM150

样例代码

样例代码1-获取配置状态(get_all_state.py)

  • 在终端中,键入如下指令并回车,运行样例代码:
  cd DFRobot_BMM150/python/raspberrypi/examples
  cd get_all_state
  python get_all_state.py

结果

get all state

样例代码2-获取三轴地磁数据、罗盘角度(get_geomagnetic_data.py))

  • 在终端中,键入如下指令并回车,运行样例代码:
  cd DFRobot_BMM150/python/raspberrypi/examples 
  cd get_geomagnetic_data
  python get_geomagnetic_data.py

结果

get_geomagnetic_data

样例代码3-准备中断功能(data_ready_interrupt.py)

  • 在终端中,键入如下指令并回车,运行样例代码:
  cd DFRobot_BMM150/python/raspberrypi/examples
  cd data_ready_interrupt
  python data_ready_interrupt.py.py

结果

data_ready_interrupt

样例代码4-阈值中断功能(threshold_interrupt.py)

  • 在终端中,键入如下指令并回车,运行样例代码:
  cd DFRobot_BMM150/python/raspberrypi/examples
  cd threshold_interrupt
  python threshold_interrupt.py

结果

threshold_interrupt

常见问题

还没有客户对此产品有任何问题,欢迎通过qq或者论坛联系我们!

更多问题及有趣的应用,可以 访问论坛 进行查阅或发帖。

更多

原理图

3D文件

CAD文件

数据手册

一键下载所有资料

DFshopping_car1.png DFRobot商城购买链接