element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Members
    Members
    • Benefits of Membership
    • Achievement Levels
    • Members Area
    • Personal Blogs
    • Feedback and Support
    • What's New on element14
  • Learn
    Learn
    • Learning Center
    • eBooks
    • STEM Academy
    • Webinars, Training and Events
    • More
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • More
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • More
  • Products
    Products
    • Arduino
    • Dev Tools
    • Manufacturers
    • Raspberry Pi
    • RoadTests & Reviews
    • Avnet Boards Community
    • More
  • Store
    Store
    • Visit Your Store
    • Choose Another Store
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
Sensors
  • Technologies
  • More
Sensors
Blog ROHM Magnetometer Sensor BM1422AGMV
  • Blog
  • Sensor Forum
  • Documents
  • Events
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Sensors requires membership for participation - click to join
Blog Post Actions
  • Subscribe by email
  • More
  • Cancel
  • Share
  • Subscribe by email
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Jan Cumps
  • Date Created: 23 Nov 2018 2:34 PM Date Created
  • Views 1511 views
  • Likes 8 likes
  • Comments 27 comments
  • RoadTest
  • rohm
  • road_test
Related
Recommended

ROHM Magnetometer Sensor BM1422AGMV

Jan Cumps
Jan Cumps
23 Nov 2018

I'm Road Testing the Rohm SensorShield-EVK-003 (Arduino Compatible) and the sensors that come with it.

In this post, the Geo Magnetic Sensor BM1422AGMVBM1422AGMV.

 

The Sensor Shield ecosystemSensor Shield ecosystem is ROHM's test bed for their sensors. It's an Arduino form shield with a number of slots.

The small evaluation boards for their sensors plug into that board.

For each of the sensors, there's an example sketch available.

For this blog post, I'm testing the Magnetometer sensor that comes with the kit.

 

Evaluation Board

 

This tiny PCB contains the sensor, required bypass capacitors, optional footprints for i2c pull-ups and a jumper to change the address of the sensor.

 

The sensor comes in a QFN  package.

 

The datasheet does not explain the physical constructions.

But it's safe to assume that there are 3 sensors on board. Each physically mounted in one of the 3 axis.

 

The quote below - from (deprecated) android documentation - shows how the axis are interpreted in a smartphone.

  • Azimuth (degrees of rotation about the -z axis). This is the angle between the device's current compass direction and magnetic north. If the top edge of the device faces magnetic north, the azimuth is 0 degrees; if the top edge faces south, the azimuth is 180 degrees. Similarly, if the top edge faces east, the azimuth is 90 degrees, and if the top edge faces west, the azimuth is 270 degrees.
  • Pitch (degrees of rotation about the x axis). This is the angle between a plane parallel to the device's screen and a plane parallel to the ground. If you hold the device parallel to the ground with the bottom edge closest to you and tilt the top edge of the device toward the ground, the pitch angle becomes positive. Tilting in the opposite direction— moving the top edge of the device away from the ground—causes the pitch angle to become negative. The range of values is -180 degrees to 180 degrees.
  • Roll (degrees of rotation about the y axis). This is the angle between a plane perpendicular to the device's screen and a plane perpendicular to the ground. If you hold the device parallel to the ground with the bottom edge closest to you and tilt the left edge of the device toward the ground, the roll angle becomes positive. Tilting in the opposite direction—moving the right edge of the device toward the ground— causes the roll angle to become negative. The range of values is -90 degrees to 90 degrees.

source: developer.android.com

 

Firmware

 

What surprised me is that the example available from the ROHM website is better than what's on github.

The downloadable one supports a trigger when data is available from the magnetometer.

That's a useful demo for this device and it is interesting for Arduino education.

The Software registers the trigger, and based on the mode of the device attaches that trigger on the falling or rising edge.

image source: BM1422AGMV datasheet

 

I'm quoting from both sketch and library.

Copyright (c) 2017 ROHM Co.,Ltd.

Please check the - very liberal - copyright notice in the source files.

 

Here's the trigger handler. It's defined in the sketch.

void bm1422agmv_isr(void)
{
  bm1422agmv.set_drdy_flg();
}

 

The trigger is attached in the Setup() method in the sketch.

BM1422AGMV bm1422agmv(BM1422AGMV_DEVICE_ADDRESS_0E);
// ...
void setup() {
// ...
  Wire.begin();
  rc = bm1422agmv.init();
// ...

  bm1422agmv.isr_func(0, bm1422agmv_isr);
}

 

We see the constructor and three methods used from the ROHM library BM1422AGMV.

You can check out the C++ code in the zip file you downloaded from ROHM website.

I'll show some extracts from them, with focus on the steps happening:

 

Constructor

#define BM1422AGMV_DEVICE_ADDRESS_0E   (0x0E)    // 7bit Addrss

BM1422AGMV::BM1422AGMV(int slave_address)
{
  _device_address = slave_address ;
}

 

init()

byte BM1422AGMV::init(void)
{
// ...

  _drdy_flg = 0;

  rc = read(BM1422AGMV_WIA, &reg, sizeof(reg));
// ...

  if (reg != BM1422AGMV_WIA_VAL) {
// ...
  }

  // Step1
  reg = BM1422AGMV_CNTL1_VAL;
  rc = write(BM1422AGMV_CNTL1, &reg, sizeof(reg));
// ...

  // Check 12bit or 14bit
  buf[0] = (BM1422AGMV_CNTL1_VAL & BM1422AGMV_CNTL1_OUT_BIT);
  if (buf[0] == BM1422AGMV_CNTL1_OUT_BIT) {
    _sens = BM1422AGMV_14BIT_SENS;
  } else {
    _sens = BM1422AGMV_12BIT_SENS;
  }
  delay(1);
// ...

  buf[0] = (BM1422AGMV_CNTL4_VAL >> 8) & 0xFF;
  buf[1] = (BM1422AGMV_CNTL4_VAL & 0xFF);
  rc = write(BM1422AGMV_CNTL4, buf, sizeof(buf));
// ...
  // Step2
  reg = BM1422AGMV_CNTL2_VAL;
  rc = write(BM1422AGMV_CNTL2, &reg, sizeof(reg));
// ...

  // Step3

  // Option
  reg = BM1422AGMV_AVE_A_VAL;
  rc = write(BM1422AGMV_AVE_A, &reg, sizeof(reg));
// ...

  return (rc);
}

 

 

isr_func()

void BM1422AGMV::isr_func(int int_num, void func(void))
{
  if (BM1422AGMV_CNTL2_VAL & BM1422AGMV_CNTL2_DRP) {
    attachInterrupt(int_num, func, RISING);
  } else {
    attachInterrupt(int_num, func, FALLING);
  }
}

 

In the loop() method, the sketch gets data from the sensor.

void loop() {
  byte rc;
  float mag[3];

  rc = bm1422agmv.get_val(mag);
  if (rc == 0) {
    Serial.print(F("BM1422AGMV XDATA="));
    Serial.print(mag[0], 3);
    Serial.println("[uT]");
    Serial.print(F("BM1422AGMV YDATA="));
    Serial.print(mag[1], 3);
    Serial.println("[uT]");
    Serial.print(F("BM1422AGMV ZDATA="));
    Serial.print(mag[2], 3);
    Serial.println("[uT]");
    Serial.println();
  }
  delay(500);
}

 

Here are the library functions used:

 

get_val()

byte BM1422AGMV::get_val(float *data)
{
  byte rc;
  unsigned char val[6];
  signed short mag[3];
  rc = get_rawval(val);
  if (rc != 0) {
    return (rc);
  }
  mag[0] = ((signed short)val[1] << 8) | (val[0]);
  mag[1] = ((signed short)val[3] << 8) | (val[2]);
  mag[2] = ((signed short)val[5] << 8) | (val[4]);
  convert_uT(mag, data);
  return (rc);  
}

 

get_rawval()

byte BM1422AGMV::get_rawval(unsigned char *data)
{
// ...
  // Step4
  reg = BM1422AGMV_CNTL3_VAL;
  rc = write(BM1422AGMV_CNTL3, &reg, sizeof(reg));

  while(_drdy_flg == 0) {
    delayMicroseconds(100);
  };
  _drdy_flg = 0;

  rc = read(BM1422AGMV_DATAX, data, 6);
// ...
  return (rc);
}

 

convert_uT

void BM1422AGMV::convert_uT(signed short *rawdata, float *data)
{
  // LSB to uT
  data[0] = (float)rawdata[0] / _sens;
  data[1] = (float)rawdata[1] / _sens;
  data[2] = (float)rawdata[2] / _sens;
}

 

Here you see how the read from the sensor works in collaboration with the data ready flag and the interrupt.

 

Measurements

 

A few measurements, first flat on the table, with the text on the sensor PCB facing:

North:

BM1422AGMV XDATA=1.208[uT]
BM1422AGMV YDATA=-0.375[uT]
BM1422AGMV ZDATA=-76.875[uT]

South:

BM1422AGMV XDATA=-26.333[uT]
BM1422AGMV YDATA=-24.333[uT]
BM1422AGMV ZDATA=-79.417[uT]

East:

BM1422AGMV XDATA=-28.917[uT]
BM1422AGMV YDATA=-4.042[uT]
BM1422AGMV ZDATA=-80.917[uT]

West:

BM1422AGMV XDATA=1.333[uT]
BM1422AGMV YDATA=-26.708[uT]
BM1422AGMV ZDATA=-78.083[uT]

 

And here pointing the board up and down:

Up West:

BM1422AGMV XDATA=-49.875[uT]
BM1422AGMV YDATA=-41.667[uT]
BM1422AGMV ZDATA=-25.625[uT]

Down West:

BM1422AGMV XDATA=32.375[uT]
BM1422AGMV YDATA=-29.333[uT]
BM1422AGMV ZDATA=-20.542[uT]

 

i2c Traffic

 

I've captured the traffic of a measurement sequence. Here you can see the effects of the following lines of code:

  rc = read(BM1422AGMV_DATAX, data, 6);

It generates an address write, then 6 blocks of char size data returning.

You may recognise this address on line 3:

#define BM1422AGMV_DATAX              (0x10)

 

I've also measured the impact of moving the sensor in increments of 22°. I'll post them if there's interest.

 

Related blog
ROHM Temperature Sensor BD1020HFV
ROHM Magnetometer Sensor BM1422AGMV
ROHM Hall Sensor BD7411G
ROHM Colour Sensor BH1749NUC
ROHM Colour Sensor BH1749NUC - part 2: Other Firmware Libraries
ROHM Ambient Light and Proximity Sensor RPR-0521RS
Anonymous

Top Comments

  • Jan Cumps
    Jan Cumps over 3 years ago in reply to genebren +3

    I don't know yet how to write the full review. There's so many diverse things here that reporting on all of them isn't straightforward in a single post.

    My current idea is to continue writing…

  • kulky64
    kulky64 over 3 years ago +3

    Have you tried to calibrate out hard and soft iron interference? Because from your data it seems there is some present. If you are in Belgium you should be getting total magnetic field of around 49 uT…

  • Jan Cumps
    Jan Cumps over 3 years ago in reply to kulky64 +3

    There is an iron molecule in my neighbourhood

Parents
  • kulky64
    kulky64 over 3 years ago

    Have you tried to calibrate out hard and soft iron interference? Because from your data it seems there is some present. If you are in Belgium you should be getting total magnetic field of around 49 uT with inclination of 66 deg. You can check magnetic field data for your exact GPS location at:

    https://www.ngdc.noaa.gov/geomag-web/#igrfwmm

    From your data I'm getting total length of magnetic field vector ( =sqrt(x^2+y^2+z^2) ) from 48.3 uT to 87.1 uT.

    • Cancel
    • Up +3 Down
    • Reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 3 years ago in reply to kulky64

    Here’s the calculation:

     

    I can compare with a micro:bit.

    • Cancel
    • Up +2 Down
    • Reply
    • More
    • Cancel
  • kulky64
    kulky64 over 3 years ago in reply to Jan Cumps

    Then assuming properly identified and corrected hard and soft iron distortion you should be getting total length of magnetic field vector around 48.7558 uT in any orientation of the sensor.

    • Cancel
    • Up +2 Down
    • Reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 3 years ago in reply to Jan Cumps

    Here's an uncalibrated micro:bit facing

    north

    X:64 Y:16 Z:-1040

    south

    X:32 Y:32 Z:-1024

    • Cancel
    • Up +2 Down
    • Reply
    • More
    • Cancel
Comment
  • Jan Cumps
    Jan Cumps over 3 years ago in reply to Jan Cumps

    Here's an uncalibrated micro:bit facing

    north

    X:64 Y:16 Z:-1040

    south

    X:32 Y:32 Z:-1024

    • Cancel
    • Up +2 Down
    • Reply
    • More
    • Cancel
Children
  • Jan Cumps
    Jan Cumps over 3 years ago in reply to Jan Cumps

    micro:bit with total vector length calculation:

     

    X:48 Y:112 Z:-1024 Strength: 1031
    Vector: 1031.2245148366092

     

    • Cancel
    • Up +2 Down
    • Reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 3 years ago in reply to Jan Cumps

    With the ROHM sensor.

    South:

    BM1422AGMV XDATA=-29.000[uT]
    BM1422AGMV YDATA=-16.167[uT]
    BM1422AGMV ZDATA=-78.208[uT]
    BM1422AGMV VECTOR=84.964

     

    North:

    BM1422AGMV XDATA=0.542[uT]
    BM1422AGMV YDATA=-7.375[uT]
    BM1422AGMV ZDATA=-82.542[uT]
    BM1422AGMV VECTOR=82.872

     

    I changed the sketch to add the vector length, using kulky64 's calculation

    total length of magnetic field vector ( =sqrt(x^2+y^2+z^2) )

     

    #include <math.h>       /* sqrt, pow */
    // ...
        Serial.print(F("BM1422AGMV VECTOR="));
        Serial.print(sqrt(pow(mag[0], 2.0) + pow(mag[1], 2.0) + pow(mag[2], 2.0)), 3);  
    // ...

    • Cancel
    • Up +2 Down
    • Reply
    • More
    • Cancel
  • jc2048
    jc2048 over 3 years ago in reply to Jan Cumps

    I think you might be reading the accelerometer.

     

    My Microbit gives a fairly reasonable figure. It's a bit sensitive to the monitor and the laptop, so I had to hold it up in the air away from them both. Where I am in Britain is pretty much the same as Belgium, so it should be something around 48-49uT.

     

    • Cancel
    • Up +2 Down
    • Reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 3 years ago in reply to jc2048

    You are right. I definitely mixed up the sensors here ...

    • Cancel
    • Up +2 Down
    • Reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 3 years ago in reply to Jan Cumps

    X:23 Y:-28 Z:-31 Strength: 48

     

     

    With the ROHM sensor:

    BM1422AGMV XDATA=33.875[uT]
    BM1422AGMV YDATA=-27.792[uT]
    BM1422AGMV ZDATA=-28.625[uT]
    BM1422AGMV VECTOR=52.338

    • Cancel
    • Up +2 Down
    • Reply
    • More
    • Cancel
Element14

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2022 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • Facebook
  • Twitter
  • linkedin
  • YouTube