Giter VIP home page Giter VIP logo

micropython-mpu9x50's Introduction

As of now, this repo holds:

  • vector3d - a vector class for IMU devices
  • imu - a base class for MPU9x50 devices. Supports the MPU6050.
  • mpu9150 - a class for the MPU9150
  • mpu9250 - a class for the MPU9250

vector3d will eventually be spun out to serve as common starting point for other imu-device drivers.
Documentation for the MPU9150/MPU6050 can be found here.

Module mpu9250

mpu9250 is a micropython module for the InvenSense MPU9250 sensor. It measures acceleration, turn rate and the magnetic field in three axes.
Breakout board: Drotek, Sparkfun

The MPU9250 has a number of advantages over the MPU9150 (which has manufacturing status "not recommended for new designs"). The magnetometer is capable of continuous operation, updating at 100Hz. It supports separate filters for accelerometer and gyro. And the breakout board is cheaper. It also supports SPI however this driver assumes an I2C connection.

Introduction

The MPU9250 is a dual chip module, with the magnetometer provided by an AsahaiKASEI AK8963 chip. In consequence the coordinate system of the magnetometer is not aligned with that of the other components. This driver corrects this so that the axes of each instrument correspond with those of the accelerometer.

Since the driver is likely to be used with the sensor fusion module the orientation of the sensor relative to the vehicle is significant. The Madgwick algorithm assumes x is orientated towards the front of the vehicle, y is left-right, and z is down. To accommodate cases where the sensor is mounted orthogonally to this orientation, support is provided for inverting and transposing axes. The driver returns vehicle-relative coordinates.

Wiring the sensor to the pyboard

The MPU9250 chip does not support 5V operation however the Drotek board has a voltage regulator so can be powered from 3.3V or 5V.

pyboard mpu9250
VIN 3V3
GND GND
SCL SCL
SDA SDA

Quickstart

Example assuming an MPU9250 connected to 'X' I2C interface on the Pyboard:

from mpu9250 import MPU9250
imu = MPU9250('X')
print(imu.accel.xyz)
print(imu.gyro.xyz)
print(imu.mag.xyz)
print(imu.temperature)
print(imu.accel.z)

Modules

To employ the driver it is only necessary to import the mpu9250 module and to use the MPU9250 class.

mpu9250

MPU9250
Class for the MPU9250 sensor.
MPUException
This will be raised in the event of an I2C error. It is derived from the Python OSError.

imu

InvenSenseMPU
Base class for InvenSense inertial measurement units.

vector3d

Vector3d
Class for a 3D vector. This is documented here.

MPU9250 Class

The class has various properties returning Vector3d instances. The principal properties of the Vector3d are x, y and z returning the vector's components and xyz which returns a 3-tuple of the components (x, y, z). It also supports calibration and conversion to vehicle relative coordinates.

Methods

MPU9250() The constructor supports the following arguments

  1. side_str 'X' or 'Y' (mandatory) defines the I2C interface in use. Alternatively an initialised I2C object may be passed.
  2. device_addr 0 or 1 (optional) Two devices may be used with addresses determined by the voltage on the AD0 pin. If only one device is used, this argument may be None when the device will be automatically detected.
  3. transposition (optional) Enables axes to be transposed (see below).
  4. scaling (optional) Enables axes to be inverted (see below).

The defaults for transposition and scaling will cause the driver to return sensor-relative results.

wake()
wakes the device

sleep()
sets the device to sleep mode

get_accel_irq()
get_gyro_irq()
get_mag_irq()
These methods are somewhat experimental. They are capable of being called from within an interrupt callback and update the integer properties only of the relevant Vector3D object. Currently writing nontrivial MicroPython interrupt callbacks is something of a black art as it can be unclear when the heap is likely to be invoked causing an exception.

Principal Properties

sensors
Returns three Vector3d objects, accelerometer, gyro and magnetometer.

accel_range integer 0 to 3 read/write
Returns or sets the current accelerometer range: this determines the accelerometer full scale range as per the table below. Note that the x, y, z values from the driver are scaled to units of g regardless of the range selected. Range affects only the full scale capability and resolution.

Range Value (+-g)
0 2
1 4
2 8
3 16

gyro_range integer 0 to 3 read/write
Determines the gyro full scale range as per the table below. Note that the x, y, z values from the driver are scaled to units of degs/s regardless of the range selected. Range affects only the full scale capability and resolution.

Range Value +- degs/sec
0 250
1 500
2 1000
3 2000

temperature float read only
Returns the chip temperature in degrees celcius

accel Vector3d instance read only
Returns the Vector3d holding the current accelerometer data. Units are g.

gyro Vector3d instance read only
Returns the Vector3d holding the current gyro data. Units degrees/s.

mag Vector3d instance read only
Returns the Vector3d holding the current magnetometer data. As configured by this driver the MPU9250 reads the magnetometer at 10mS intervals. Units are uT (microtesla).

Accessing a Vector3d instance x, y, z or xyz properties will cause the device to be read and will return the latest data. In the case of the magnetometer, if it is accessed, and then accessed again within 10mS and before the unit has had a chance to update, the old data will be returned and a counter MPU9250.mag_stale_count will be incremented. The counter will be cleared the first time fresh data is acquired and read.

In the event that the most recent data read by the magnetometer is in error the Vector3d instance will return the most recent valid data and increment mag_stale_count. A high value of mag_stale_count (or any nonzero value if the read rate is below 100Hz) suggests an error condition.

mag_stale_count integer read only
As described above: a count of the number of consecutive times in the curent sequence of reads that the driver has returned out-of-date values.

accel_filter_range integer 0 to 7 read/write
The digital low pass filter enables the effect of vibration to be reduced in the accelerometer readings. The following table gives the approximate bandwidth and delay for the filter.

value bw(Hz) Delay(mS)
0 460 1.94
1 184 5.8
2 92 7.8
3 41 11.8
4 20 19.8
5 10 35.7
6 5 66.96
7 460 1.94

Note: in my testing option 7 produced garbage.

gyro_filter_range integer 0 to 7 read/write

The digital low pass filter enables the effect of vibration to be reduced in the gyro readings. The following table gives the approximate bandwidth and delay for the filter.

value bw(Hz) Delay(mS)
0 250 0.97
1 184 2.9
2 92 3.9
3 41 5.9
4 20 9.9
5 10 17.85
6 5 33.48
7 3600 0.17

See "Other MPU9250 properties" below.

Use in interrupt callbacks

MicroPython interrupt callbacks prohibit the use of the heap, which rules out a number of standard Python techniques including exception handling and the use of floating point. Currently it is not always evident whether code will use the heap, so any use of these techniques should be considered experimental. The following MPU9250 methods provide access to the device where this must be performed in a callback.

get_accel_irq()
get_gyro_irq()
get_mag_irq()
These methods read the device and update the integer values of the Vector3D objects only. These values hold unscaled values direct from the device so coordinates are device relative and no calibration, correction or scaling is applied.

Note that the scaling factors of the accelerometer and gyro depend only on the range selected, hence these can be hard coded in the callback. To get the most accurate readings from the magnetometer the factory-set corrections should be applied. These are in the property mag_correction but being floating point values cannot be used in a callback. Options (depending on application) are to apply them outside the callback, or convert them to scaled integers in initialisation code.

See tests/irqtest.py for example code.

Other MPU9250 properties

passthrough Boolean read/write
sets passthrough mode. It is activated (True) by default. This needs to be activated to enable the magnetometer interface to be linked to the SDA, SCL pads.

sample_rate 8 bit integer read/write
Determines the update rate of the sensor registers. Values should be in range 0 to 255. The update rate is given by rate = Internal_Sample_Rate / (1 + sample_rate). It is not clear, given the subset of functionality supported by this driver, why you might want to change this from the zero default.

mag_correction float 3-tuple
Holds factory-set magnetometer correction values.

chip_id
The ID of chip (113) is hardcoded on the sensor. Reading this property will test the communications with the IMU by reading this value which is returned to the user. A ValueError will be raised if the value is incorrect.

mpu_addr
I2C adress of the accelerometer and the gyroscope.

mag_addr
I2C adress of the magnetometer.

timeout
Timeout for I2C operations.

Exception handling

Incorrect values such as

imu = MPU9250('Z')

will raise a ValueError with a meaningful error message.
When any communication with the IMU takes place it is possible for the I2C bus to lock up. This is normally a consequence of hardware failure such as the device being connected incorrectly or leads being too long. In this instance a custom MPUException will be raised with a dscriptive message. This is derived from Python's OSError: the user may trap either in the hope of continuing operation. In my experience this seldom works: if the I2C bus locks up a power cycle is required to clear it.

Demo of calibration

>>> from  mpu9250 import MPU9250
>>> a = MPU9250('x')
>>> a.mag.cal
(0, 0, 0)
>>> import pyb
>>> sw = pyb.Switch()
>>> a.mag.calibrate(sw) # User rotates unit about each axis then presses the Pyboard switch
>>> a.mag.cal
(35.30567, 18.92022, -9.428905)
>>>

micropython-mpu9x50's People

Contributors

jonathanfoster avatar peterhinch avatar turbinenreiter 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

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

micropython-mpu9x50's Issues

Porting to ESP32 anyone?

Hi
I was about to write my own implementation for the mpu6050 and 9250, when I came across this nice library :)

As the title says, anyone working on a port to the esp32. Maybe a port to esp8266? Guess that would work on the esp32 too.

Side note. Anyone tested this on the mpu6050 for the accelerometer / gyro ?

Adding support for FIFO buffer

The MPU family has a built-in 1024 FIFO which can be set up to read in data from the thermometer, gyroscopes, and accelerometer.

I've been working on building support for that feature, but don't know the ins and outs of memory management or this module yet, so I'd figured I'd mention the project here in case anyone wants to help.

Working branch here.

MPU9255 support?

Excuse me,have you test whether it would work on MPU9255 or not?sry4my poor English...

How fast we can read data from the sensor

A lot of example that i saw always using the sleep function on each reading, is it possible to not using the sleep function?, and if it is necessary to use, what is the shortest time to sleep?.

BTW, I am using mp6050 with class MPU6050 in imu.py file

Error while using imu.py on Pi Pico

Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "mpu6050.py", line 84, in __init__
TypeError: can't convert str to int

imu.py: Cant convert str to int

Hello,

I try to use the MP6050 with the Pico so I use the file "imu.py", which i renamend to "mpu6050.py" on my pico.
When I create a new object with: "mpu = MPU6050('x')" I get the error "cant convert str to int" on the 83th line.
When I the use thsi command: "mpu = MPU6050(1)". So I replace the sring with an int, I get the error: "Invalid I2C instance"
What value do I have to enter there?

is DMP support?

if using DPM, derectory read quaternion numbers.
will it be supported?

i can't use mpu6050 by ur module as the demo.

ๅ›พ็‰‡
i had tested the the code:
`from imu import MPU6050

imu = MPU6050('Y')
print(imu.accel.xyz)
print(imu.gyro.xyz)
print(imu.temperature)
print(imu.accel.z)`
i connnected "X9" and "X10" for "SCL" and ""SDA".
but always :MPUException: I2C failure when communicating with IMU.
Thank you for help!

INT pin?

ANy suggestions how to use this library utilising INT pin on MPU 9250?
I would like to use Motion Detection notifications - how can I receive them?
image

Lopy Migration

Hi
I have done the Lopy porting on my fork but i see acceleration at zero values all the time
any suggestion ?

Magnetometer wrong values and freezes esp32

HI. I'm back :-)

I've started testing with the mpu9250. Both the standard 9DOF and the newer 10DOF.

The x and z values for the mag vector is frozen. They might very rarely make a blip, but then right back to the frozen value.

i2c = I2C(-1, scl, sda, freq=400000)

imu = MPU9250(i2c)

sens = imu.sensors
while True:
     print(sens[2].xyz)
     print("mag_stale_count: {}".format(imu.mag_stale_count))
     utime.sleep_ms(200)

yields this result when I'm constantly moving the sensors around

(-0.1869141, -14.58692, 0.2244141)
mag_stale_count: 0
(-0.1869141, -14.58692, 0.2244141)
mag_stale_count: 1
(-0.1869141, -7.405664, 0.2244141)
mag_stale_count: 0
(-0.1869141, -3.815039, 0.2244141)
mag_stale_count: 0
(-0.1869141, -3.815039, 0.2244141)
mag_stale_count: 1
(-0.1869141, -14.58692, 0.2244141)
mag_stale_count: 0
(-0.1869141, -46.90254, 0.2244141)
mag_stale_count: 0
(-0.1869141, -7.405664, 0.2244141)
mag_stale_count: 0
(-0.1869141, -7.405664, 0.2244141)
mag_stale_count: 0
(-0.1869141, -29.39824, 0.2244141)
mag_stale_count: 0
(-0.1869141, -7.405664, 0.2244141)
mag_stale_count: 0
(-0.1869141, -3.815039, 0.2244141)
mag_stale_count: 0
(-0.1869141, -3.815039, 0.2244141)
mag_stale_count: 0

The newer mpu9250 10DOF freezes randomly for a few seconds every 30 - 60 seconds or something like that.

Manually calling the

imu.mag.xyz

over and over again, yields the same result.

Have it running in C on an Arduino uno, and have no problems, so both sensors seems okay.

What am I doing wrong here?

Tilt Angle Question

Is there any easy way to quickly obtain the tilt angle of the sensor? Or just lots of manual calculations?

I'm a little new to this stuff, so apologies if this is a dumb question...

Random KeyboardInterrupt and ASCII disco

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "main.py", line 43, in run
  File "/lib/uasyncio/core.py", line 155, in run_forever
  File "/lib/uasyncio/core.py", line 110, in run_forever
  File "main.py", line 33, in send_data
  File "main.py", line 24, in get_data
  File "vector3d.py", line 103, in xyz
  File "imu.py", line 395, in _accel_callback
  File "imu.py", line 312, in accel_range
KeyboardInterrupt: 
>>> KK3K3K<lKlKlKKK3K3K<lKlKlKK<3K3K3K3lK<KK<KK3K3K<lKxKlKKK3K3K<lKlKlKK<,K3K3K3KlK<KK<KK3K3K<lKKHKK3KK<lKlKlKK<,K3K3K3KlK<KK<KK3K3K<lKlKlKK3K3K<lKlK

So this is a fun little thing. I'm running on an ESP32 and have a fast loop calling all sensor values of the MPU9265 (which is yet another version of the chip). Every once in a while, execution stops with above Traceback.

Anyone ever seen anything like this?

The line in the code where this happens is:

@property
def accel_range(self):
 """
Accelerometer range
Value:              0   1   2   3
for range +/-:      2   4   8   16  g
 """
    try:
        self._read(self.buf1, 0x1C, self.mpu_addr)
        ari = self.buf1[0] // 8 # this line throws up
    except OSError:
        raise MPUException(self._I2Cerror)

    return ari

I think this is gonna be a fun one.

/edit: It actually happens at random parts in the code.

Filter for magnetometer

I am trying to do some distance calculations for this project using the magnetometer.

But i always get a stale magnetic interference when the sensor is stationary.
I have tried several moving average algorithms. They improved the overall signal quite a bit.

But its still nowhere near what the project requires.

I have tried several magnets. Neodymium, speaker magnets, varying from little to high intensity and i am getting similar results..

Can you advise me on how can I implement a filter?

Bad chip ID retrieved with MPU-9250/6500

I'm using an MPU-9250/6500 and I get a "Bad chip ID retrieved: MPU communication failure" ValueError after initialization. My sensors chip ID is 0x73, but the MPU9250 class chip ID is set to 0x71.

I was able to work around the issue by simply setting the class chip ID before initialization.

MPU9250._chip_id = 0x73
imu = MPU9250(i2c)

The MPU-9250 register map does in fact list 0x71 as the default value for WHOAMI (see page 44), but there appears to be another variant of the sensor, the MPU-9255, that return 0x73 instead (page 44 of the MPU-9255 register map).

The real problem is I've got a MPU-9255 that's stamped as MPU-9250/6500. It appears others have run into the same issue as well (see miniben-90/mpu9250#13 and kriswiner/MPU9250#47).

It would be easy to make chip ID an init parameter, create a MPU9255 class, or just remove the exception from being thrown all together. I'm happy to submit a PR if either approach would work.

MPU exception during startup with RPi Pico

Hardware: Raspberry Pi Pico, MPU-6050

Error message:
Traceback (most recent call last):
File "", line 33, in
File "imu.py", line 105, in init
File "imu.py", line 159, in chip_id
MPUException: I2C failure when communicating with IMU

Suspected bug is in _read() class function. Why try cell is not used in chip_id, following error message is recorded:
Traceback (most recent call last):
File "", line 33, in
File "imu.py", line 105, in init
File "imu.py", line 157, in chip_id
File "imu.py", line 117, in _read
OSError: [Errno 5] EIO

Not sure if issue is with hardware or code

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.