Git Product home page Git Product logo

marksherstan / mpu-6050-9250-i2c-compfilter Goto Github PK

View Code? Open in Web Editor NEW
88.0 2.0 23.0 10.12 MB

MPU6050/9250 I2C and SPI interface. Sensor fusion using a complementary filter yields sensor Euler angles and is implemented in five different languages.

License: GNU General Public License v3.0

MATLAB 8.77% C++ 34.68% Python 35.15% JavaScript 4.47% HTML 0.21% Makefile 0.37% C 16.35%
arduino raspberry-pi imu mpu6050 mpu9250 visualization sensor nodejs p5js filter

mpu-6050-9250-i2c-compfilter's Introduction

MPU-6050 and MPU-9250 I2C or SPI Complementary Filter

Testing different methods to interface with a MPU-6050 or MPU-9250 via I2C or SPI. All methods feature the extraction of the raw sensor values as well as the implementation of a complementary filter for the fusion of the gyroscope and accelerometer to yield an angle(s) in 3 dimensional space.

Registry Maps and Sensitivity Values

Values retrieved below come from the MPU-6050 and MPU-9250 registry maps and product specifications documents located in the \Resources folder. Configure the gyroscope on 0x1B and the accelerometer on 0x1C as per data sheets with the following values (the MPU-6050 and MPU-9250 are interchangeable and all registries are the same):

Accelerometer Sensitivity Gyroscope Sensitivity Hexadecimal Binary
+/- 2g 16384 +/- 250 deg/s 131 0x00 00000000
+/- 4g 8192 +/- 500 deg/s 65.5 0x08 00001000
+/- 8g 4096 +/- 1000 deg/s 32.8 0x10 00010000
+/- 16g 2048 +/- 2000 deg/s 16.4 0x18 00011000

The slave address is b110100X which is 7 bits long. The LSB bit of the 7 bit address is determined by the logic level on pin AD0. This allows two sensors to be connected to the same I2C bus. When used in this configuration, the address of one of the devices should be b1101000 (pin AD0 is logic low) and the address of the other should be b1101001 (pin AD0 is logic high). Communication will typically take place over the 0x68 register.

Ensure that the proper logic (3.3V vs 5V) is being used so you do not fry your sensor

Use

Arduino

Connect the sensor to the microcontroller as outlined below.

  • VCC --> 5V or 3.3V based on specific breakout board and logic levels
  • GND --> GND
  • SDA and SCL pins located in table below:
Board SDA Pin SCL Pin
Uno A4 A5
Mega2560 20 21
Leonardo 2 3
Due 20 21

Upload the main.ino sketch and observe the values in the serial port or serial plotter. The calibrateGyro.ino sketch can be used to retrieve the offset values which can be directly placed into the main.ino sketch to eliminate the need for calibration every time the microcontroller is started up. Note that this is at the cost of performance as the sensors drift over time and between uses.

MATLAB

Connect an Arduino using the same wiring as outlined above. Run MATLAB\I2C\main.m and observe the values in the command line. MATLAB is extremely slow when using an Arduino/I2C connection.

A faster method is to read data through a serial connection. Using the same wiring connection, upload the sketch in Visualizer\arduinoSketch to the Arduino board. Adjust any desired parameters as outlined below in the MATLAB\serial\main.m file. Run and observe the values in the command line.

% Set up the class
gyro = 250;                       % 250, 500, 1000, 2000 [deg/s]
acc = 2;                          % 2, 4, 7, 16 [g]
tau = 0.98;                       % Time constant
port = '/dev/cu.usbmodem14101';   % Serial port name

RPi (Python)

Connect your IMU sensor to 5V or 3.3V based on specific breakout board and ground to ground. Refer to the pinout of your board using pinout.xyz and match SDA and SCL accordingly.

Setup as described here. First enter sudo raspi-config and enable SPI and I2C. Reboot the Pi.

Edit the modules file using sudo nano /etc/modules and ensure i2c-bcm2708 and i2c-dev are both in the file. Reboot again.

With the sensor correctly wired enter the following in the command line.

sudo apt-get install i2c-tools python-smbus
sudo i2cdetect -y 1

Which should yield the table below (possible to have the value 0x69) verifying a proper connection:

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --  

Once verified run python3 main.py to observe the values.

9 DOF MPU-9250 RPi (Python) Madgwick Filter

Follow the same setup guide as in the RPi (Python) section, however an MPU-9250 must be used.

The code is based on Kriswiner's C++ MPU-9250 library located here and Sebastian Madgwick's open source IMU and AHRS algorithms located here. To run the program navigate to the \9DOF directory and run python3 main.py.

Before running the program and sensor fusion algorithms the magnetometer must be calibrated. Uncomment the second line below and the program will walk you through all the required steps. Once values have been retrieved enter them in lines three and four below.

# Calibrate the mag or provide values that have been verified with the visualizer
# mpu.calibrateMagGuide()
bias = [282.893, 300.464, -91.72]
scale = [1.014, 1.054, 0.939]
mpu.setMagCalibration(bias, scale)

To verify the results of the calibration refer to the two articles located here and here. Place the values from the calibration into data.txt and magCalVisualizer.py and magCalSlider.py as described in the program guide during calibration. The magCalVisualizer.py and magCalSlider.py script will provide all the required plots to aid in verifying the results as well as interactive sliders to optimize values.

Note that the magnetometer can either be read as a slave or in direct mode. Both methods exist with slave being the default mode.

Node.js and p5.js Visualizer

Connect an IMU device as outlined in the Arduino section. Upload the sketch located in Visualizer/arduinoSketch. This sketch simply transmits the raw byte data from the sensor over a serial connection.

Next, install the required packages by performing these steps:

cd MPU-6050-9250-I2C-CompFilter/render
npm install

Edit the file main.js file located in Visualizer/render to set the correct serial port and any other parameters of interest.

// Customize these values
const serialPortName = 'COM4';
const serialBaud = 9600;
var tau = 0.98;
var gyroScaleFactor = 65.5;
var accScaleFactor = 8192.0;
var calibrationPts = 250;

Once all the values are customized start the serial port server by navigating to Visualizer/render and entering:

node main.js

In your default browser enter localhost:3000 and the visualizer should be running.

Ensure to hold the IMU device still until an object appears on the screen. This is the program performing a calibration for gyroscope offset.

STM32

See full instructions and example code at https://github.com/MarkSherstan/STM32-MPU6050-MPU9250-I2C-SPI. Support for:

  • I2C using CPP
  • I2C using C
  • SPI using CPP (MPU-9250 only)
  • SPI using C (MPU-9250 only)

C++ Library

A generic C++ library was written that can be used on a variety of hardware. Refer to the Arduino or Raspberry Pi example in the CPP_library directory to get an idea of how to use the library.

For the Arduino example ensure to add the library to your Arduino IDE or put the mpuXX50.h and mpuXX50.cpp in the same folder as your *.ino.

For the Raspberry Pi you may need to run the following commands before using the Makefile.

sudo apt-get install libi2c-dev
sudo apt-get install i2c-tools
sudo apt-get update

sudo i2cdetect -y 0
//or
sudo i2cdetect -y 1

Upon setting up the class with the I2C address of the sensor and defining the read and write functions the library has the capability to.

  • Perform WHO_AM_I sensor self check
  • Set the resolution of the accelerometer and gyroscope
  • Perform, set, and return gyroscope calibration values
  • Return raw sensor values, calibrated sensor values, and complementary fused values yielding sensor attitude - roll, pitch, and yaw (yaw will drift over time)

Future Ideas

  • Add quaternion angle representation
  • Kalman filter (custom lib)
  • C Library
  • General clean up
  • Use updated hardware

mpu-6050-9250-i2c-compfilter's People

Contributors

marksherstan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

mpu-6050-9250-i2c-compfilter's Issues

madgwickFilter params

Hi Mark!

You did a good job ;) but looks like something wrong with madgwickFilter in 9DOF/main.py
mx = mpu.my and my = - mpu.mx
Please add notes to your code - i thought it was mistake
// Sensors x (y)-axis of the accelerometer is aligned with the y (x)-axis of the magnetometer;
// the magnetometer z-axis (+ down) is opposite to z-axis (+ up) of accelerometer and gyro!

You can also improve your code when read raw data:

  1. replace

for ii in range(7):
rawData.append(self.bus.read_byte_data(self.MPU9250_ADDRESS, self.EXT_SENS_DATA_00 + ii))
by "rawData = self.bus.read_i2c_block_data(self.MPU9250_ADDRESS, self.ACCEL_OUT, 14)"

  1. and add try/except block - sometime self.bus.read return error while try to read raw data

10 times same Madwickfilter calculation and compFilter not used

In the 9DOF main.py program loop on line 580 you are performing the Madwick filter calculation 10 times with the same sensor values but with a different deltat. Not clear why.

Also the compFilter method in your program is not used and it is not clear why it exists.

Why no accel cal?

main.py runs a gyro cal, but not an accelerometer cal.
Is there a reason?

I created one and get these results:

Calibrating accel with 1000 points. Do not move!
aX std:16.0 min:298 max:402
aY std:17.0 min:8212 max:8316
aZ std:102.0 min:-512 max:-2

Calibration complete
	X accel offset: 351.5
	Y accel offset: 8267.1
	Z accel offset: -237.2

but I haven't tried factoring the offset into processValues()

                # Subtract the offset calibration values for the accelerometers
                # self.ax -= self.aXcal
                # self.ay -= self.aYcal
                # self.az -= self.aZcal

Fixing "Slider() has no valstep parameter" error msg

In running magCalSlider.py on Dexter Industries Raspbian for Robots, I received the error:
Slider() has no valstep parameter

pip3 freeze | grep matplotlib reported matplotlib version 2.0.0
sudo pip3 install --upgrade matplotlib fixed the issue (upgraded to version 3.0.3)

(Can mark issue solved/complete.)

Note: AK8963 is set up as slave, not using direct access.

You are making reference to Kris Winer's C programs. Thank you for translating these to Python so I don't have to do it myself.

It is worth noting that on Kris' site the communication with the AK8963 normally is done using direct addressing on main AK8963 address 0C. The host reads the magnometer values directly from the AK8963. The 0C address is also visible with i2cdetect.

Only in a subfolder he explains and shows the setup with the AK8963 as slave, and this is what you are using in your Python programs. This does not work on my MPU9250 and I am not sure why. (maybe it only works for MPU6050?). I am going to change it back to direct communication.

I think it is worth making a note about this in your documentation.

bias applied incorrectly in magCalSlider and magCalVisualizer

In the main program magnetometer calibration routine the RAW magnetometer values are captured and the bias and scale factors are calculated.
The instructions say that the RAW values should be stored in data.txt and the bias and scale factor should then be defined in the two visualization programs. These will then display raw and corrected graphs.

In the main program : bias = RAWbias * scaleFactor * factorycalibration and scale=avgrange/axis-range
(where RAWbias=(maxRAW+minRAW)/2)

In the visualization programs however you are applying the bias to the RAW magnetometer values (retrieved from data.txt)
So you are subtracting a bias that is alread corrected with scalefactor and factorycalibration values from a RAW magnetometer value.
I think you should either subtract a raw bias from raw values or corrected bias from corrected values.

Also note that the scalefactor is calculated from RAW values but applied on corrected values. Since these are close to 1 anyway the impact is small.

That is why currently the magCalSlider each time requires further manual adjustment.

(notes :

  1. in the explanation of calibration by Kris Winer and the example routine he provides, you can see the variables mag_bias[ ] and dest1[ ] for the raw and corrected values respectively.
  2. also note that you bias correction in the main program (in the processvalues function) is correct. The error only exists in the visualization programs magCalSlider and magCalVisualizer

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.