
LSM9DSO Debugging
Backstory
Recently I have kicked my job search into high gear. That means I have lots of phone interviews, coding challenges, and other pre-screen tasks to complete. Usually these pre-screens are not meant to be extremely hard. They are just hard enough to eliminate all the people who are not close to being technically strong enough. One company asked me to integrate a common microcontroller development board (STM32F4 Discory board) with a common hobbyist sensor (Adafruit LSM9DSO IMU breakout board). Both of these items have a lot of support to the point of being nearly idiot proofed.... nearly idiot proof
It came as a considerably worry to me that after hours of debugging my Discovery Board absolutely would not play nice with the IMU. This was not supposed to be hard; I was even allowed to use ANY resource online. I had decided to start by forking Brian Cair's port of the Arduino library for the LSM9DSO to the STM32F4. It had all the pin and register definitions as well as the functions I would need. Unfortunately it only had SPI support and the challenge called for an I2C based solution.
Debugging Steps
Like always things don't work when you start and you slowly remove all the possible problems. Here are a short list of things to check separated into groups :
Development Tools
- development environment is actually doing what you think it is (you are listening to the correct serial ports, your Makefile is including everything it should, etc..)
Board
- Ensure board is initialized properly (e.g. watchdog timers are fed)
On Board Peripheral
- Peripheral's clock powered and initialized correctly in MCU
Pin Configuration
- Pins routed to correct function within MCU (I2C in this case)
- Pins in correct mode for communication protocol (open drain in the case of I2C)
- Pull up/down resistors configured correctly (pull up in the case of I2C)
Protocol
- communication initialized properly (frequency, duty cycle, address length, etc..)
- messaging protocol followed exactly as data sheets describe (this can be particular hard without a logic analyzer)
Off Board Peripheral
- All control registers of the peripheral have been set properly (in this case each of the three sensors in the IMU are enabled, all three axes for each sensor are enabled, new readings are being taken continuously, etc...)
Physical
- Jumper wires connected to correct pins on peripheral
- Jumper wires connected to correct pins on microcontroller
- All jumper wires are engaging the pins well; there are no intermittent connections
- Wires pass continuity check
My goal is not necessarily to check all of these exhaustively. Rather I attempt to get things half working. At that point I can reason about the results to greatly reduce the number of things that could possibly still be wrong. Now you are left with a few weird bugs and behaviors, so you:
- power down and restart everything to see if the issue persists
- re-read the datasheet for anything you missed
- google the problem as best you can
Resolution
If you are unlucky you will have a problem with no clear solution. In my case everything worked except the accelerometer printed a constant value of X:-24539 Y: -24539 Z: 24539
. I was lucky to find someone with exactly my problem in a thread on sparkfun. He was using a different microcontroller, different code, and a different breakout board but somehow had the exactly the same problem. Not only was the accel reading constant, but it was X:-24539 Y: -24539 Z: 24539
. There was no solution in that thread, but there was a lead -- the LSM9DS0 is often very particular about the logic level shifting hardware that is used. After experimenting and reviewing the breakout board schematic the culprit was discovered!
While SDOG and SDOXM are usually outputs of the sensor, they become inputs when the chip is used for I2C rather than SPI. Although the board claims to be 5V tolerant, it does not account for this. Using a 5V input on these pins causes the sensor VDD to be significantly higher than the sensor's published maximum voltage. This does not seem to affect the magnetometer or gyroscope. Furthermore, it only affects the accelerometer when the board is powering up; if the sensor is first powered on at the nominal voltage, then later 5V is applied to SDOG or SDOXM everything continues to work normally. I guess that explains why this problem has not come up often enough to be noticed despite the large number of people using the board.
If you experience this problem do one of the following as a work around:
- use SPI
- use I2C but set SDOG and SDOXM to low and adjust the LSB of the addresses in your I2C calls appropriately
- use I2C with SDOG and SDOXM high by connecting them to a <3.6V supply (such as the 3.3V supply on the breakout board itself!)