MPU6050 & teensy 3.1 problem

Status
Not open for further replies.

JV88

Member
I am using my teensy 3.1 to read data from the MPU6050. After I upload it, it reads out the data fine, but when I unpower it and put the power back on it reads only zeros. This does not happen with my arduino nano, the nano always reads the values fine. I have also used external pull ups between SDA, SCL and 3.3V, I tried 2k2, 4k7 and 10k resistors but it didn't help. I then bought another teensy 3.1 but the same problem occurs with this new board. I also have two different MPU6050 breakout boards: the gy-521 and the SEN-11028 from sparkfun, my teensy has the same problem with both of them.
The strange thing is that it does work but only if I load the program, not when just putting the power back on. I also tested the difference between USB and an external power source but no luck there. Occasionally when the program does run it suddenly stops reading the data, also re-uploading the program sometimes takes many tries because before it runs. This does not happen with other programs.

I use the I2C and MPU6050 library of Jeff Rowberg, I tested with the MPU6050_raw.ino file. My teensy's are the black edition (probably not very relevant).
 
@JV88
Using the gy-521 board, I tested the MPU6050_raw.ino from Jeff Rowberg's library example, and can confirm the same issue.
Serial monitor returns after disconnecting & reconnecting usb cable to Teensy 3.1:
Code:
a/g:	0	0	0	0	0	0

I think it is to do with when the device gets initialised.
Code:
accelgyro.initialize();
if you copy that to within the void loop, you can unplug & plug your usb cable and the values are not zerod.

Hopefully, that gives you something to investigate.

Did you manage to get the MPU6050_DMP.ino example working with Teensy 3.1 interrupts pin?
I tried adding, this code to the //INTERRUPT DETECTION ROUTINE, but no joy:
Code:
pinMode(0, INPUT);
attachInterrupt (0, dmpDataReady, RISING);//I tried RISING or CHANGE
all I get in the Serial monitor is:
Code:
Initializing I2C devices...
Testing device connections...
MPU6050 connection successful

Send any character to begin DMP programming and demo: 
Initializing DMP...
Enabling DMP...
Enabling interrupt detection (Teensy external interrupt 0)...
DMP ready! Waiting for first interrupt...
Just in case anyone else is inteested, Jeff's Docs & Library info are here:
http://www.i2cdevlib.com/devices/mpu6050#source
 
If you have to use the DMP, Jeff Rowberg's library is the only game in town. If you just want the properly calibrated and scaled data out, I have an Arduino sketch here https://github.com/kriswiner/MPU-6050 that runs well on the Teensy 3.1. It uses the Wire.h library since I was having problems with an older version of i2c.h. I have run Jeff's sketches and they work fine on an Arduino, I've just never tried them on the Teensy 3.1 yet.
 
Thanks onehorse, that works straight out the box with Teensy 3.1.
I think I may pick up a Nokia screen, as I see you added output functions too.

This link may interest you, a video showing combined/filtered gyro & accel data to help with gyro drift:
https://www.youtube.com/watch?v=qmd6CVrlHOM

There is an .ino file for setting up the serial output, and a .pde processing file to visualise the data (at end of article link below).
With a Teensy 3.1 you may need to change the portIndex in ShowGY521Data.pde to your corresponding serial port
http://www.geekmomprojects.com/gyroscopes-and-accelerometers-on-a-chip/
I can get the pde to load and read the accel, but the gyro data is zeroed.
Code:
DEL:0.0030000#ACC:-88.38,-0.75,0.00#GYR:0.00,0.00,0.00#FIL:-3.54,-0.03,0.00

I have never really using processing before, but even having a half working example, is pretty cool.
 
Thanks for the video link. I have seen this before but could not get the processing sketch to work for me. I might try it again.
Jeff Rowberg's sketch is great since the Invensense IP DMP has an algorithm for outputting pitch, roll, and YAW without a magnetometer reference datum. I think they just use a synthetic magnetic vector. I will try this myself to see if I can get it to work.
I have been spending most of my time getting sensor fusion output from the MPU-9150, MPU-9250, and LSM9DS0. These have embedded magnetometers making true 9DoF sensor fusion possible and, with the open-source Madgwick and Mahony filtering algorithms, efficient and easy to implement.
What is interesting and not totally surprising is that the filter update rates depend on processor speed. With a 3.3V 8 MHz Pro Mini I can get filter update rates of ~150 to 200 Hz. But with the Teensy 3.1 I can get update rates of 1 kHz, which is just about optimum for gyro and accelerometer ODRs of 200 Hz. ALL HAIL TEENSY!
 
@onehorse - I remember reading somewhere that most people who got the Teapot demo working did so with Processing 1.5.1.
 
I have Processing 2, which I have used for some Trinket demos but I haven't spent any time learning how to use it well. I am using an old laptop that runs Windows XP and will be buying a replacement soon with Windows 7; I will wait till then to worry about getting the Teapot demo working.

On another note, I added Madgwick's IMU sensor fusion algorithm to my MPU-6050 Arduino sketch and it matches the MPU-6050 DMP output by producing Yaw, Pitch, and Roll without a magnetic reference. Of course, the yaw drifts but it is not too bad, only about half a degree per minute. This is about the same as I measured using Jeff Rowberg's sketch that gets the Yaw, Pitch, and Roll from the proprietary DMP Invensense algorithm. It can't be too different from Madgwick's; they all do about the same thing just differing in the gradient calculation of the error term.

I was able to run both my sketch without the DMP and Jeff Rowberg's sketch with the DMP on the Teensy 3.1. I verified that I can specify any pin on the Teensy as interrupt; I chose pin 12 and the sketch worked well. I have noticed though that often after a few minutes the DMP overflows or something and Rowberg's sketch stops. I haven't delved deeper to understand what's happening or to try to fix it.
 
Just reference notes for anyone reading:

I'm reading four MPU6050 accelerators on a Teensy 3.1 using three wires (+power); I wired two of the boards to be on i2c address 0x69 (the other two came wired for address 0x68), ran the same I2C0 SCL to all of them, and used the pin muxing to flip SDA between pins 17 and 18 (so a pair of MPU6050's at 0x68 and 0x69 on each SDA).
This works fine; also the MPU6050 works fine with 1Mhz I2C (use "I2C0_F = 8;").

I dispensed with the MPU6050 interrupt lines because you can poll the chips quite easily. I run them at 50hz update currently.

Also I recommend anyone starting out to use Jeff Rowberg's DMP code rather than the raw values; it's much more convenient. His code is based on invensene's V2.1 DMP code; there's also a newer version Arduino DMP library out there http://www.kauailabs.com/robotics/k...ense-mpu-60509150-driver-to-arduino-platform/ which uses a later version (5.1) of the DMP microcode; not tried it yet.

Finally I found MPU6050 modules on ebay (from US seller) for $3.68+(combinable) shipping from "nyplatform". Bargain!

BTW I'm using 100-ohm series resistors on the I2C lines out of the teensy to avoid ringing
 
Last edited:
I wired two of the boards to be on i2c address 0x69 (the other two came wired for address 0x68), ran the same I2C0 SCL to all of them, and used the pin muxing to flip SDA between pins 17 and 18 (so a pair of MPU6050's at 0x68 and 0x69 on each SDA).

Let me see if I have this straight; you have two pairs of MPU6050 sensors addressed 0x68 and 0x69 on one of either SDA0 on pin 18 and SDA1 on pin 17, all hooked up to SCL0 on pin 19. Then you mux between the two sensor addresses and the SDA0 and SDA1 to get four independently addressable MPU6050s on the same Teensy 3.1? Sweet set up. Do you use the i2c_t3.h library to toggle between SDA0 and SDA1? Or how do you do this in the program?
 
Yes; exactly that. I just added a "busSelect" uint8 to Jeff Rowberg's MPU6050 C++ class (which uses the regular Wire i2c lib on Teensy) and dropped in this:


void MPU6050::select()
{
uint32_t pinConfig0 = (PORT_PCR_MUX(2)|PORT_PCR_ODE|PORT_PCR_SRE|PORT_PCR_DSE); //i2c, output, slew rate (slow), drive strength (high)
uint32_t pinConfigOff = PORT_PCR_MUX(0); //analog (off)

//pin 17(B1)=SDA(1), pin18(B3)=SDA(0), pin19(B2)=SCL (both)
CORE_PIN16_CONFIG = pinConfigOff; //b0 scl not used
CORE_PIN19_CONFIG = pinConfig0; //b2 scl used for both
if(busSelect)
{
CORE_PIN17_CONFIG = pinConfig0; //b1 sda
CORE_PIN18_CONFIG = pinConfigOff; //b3 off
}
else
{
CORE_PIN17_CONFIG = pinConfigOff; //b1 off
CORE_PIN18_CONFIG = pinConfig0; //b3 sda
}
}

Then I just have an array of four MPU6050 objects (tweaked the constructor to take busSelect and a unitId argument also) , with different i2c addresses and busSelects kinda like this


#define NUM_MPUS 4
MPU6050 mpus[4]={ MPU6050(0x68,0,0) , MPU6050(0x69,0,1), MPU6050(0x68,1,2) , MPU6050(0x69,1,3) };

..and just call mpu->select on each one before init'ing them and reading them. It's pretty much what you'd expect.

Am just poking at more indepth hackery to use nonblocking (irq and/or DMA) to read them. I'm really hacking and slashing this stuff cos I've got a ton of things to do and it's barely a few weeks until it's Time To Get Dusty... :)
 
Last edited:
mpuread.jpg
This is it polling the "Interrupt" register on the four devices (and repeating) you see it hits up 0x68 and 0x69 on SCL+SDA1 then the same on SCL+SDA2. In this case all the fifo's are empty. This capture was running at 400khz, also in practice you wouldn't bother polling all the time if you know data is only coming @50hz, but you see what I mean.
 
Excellent! I will try something similar with i2c_t3.h. I bought a bunch of the GY-521 for $2 from Amazon.com; I am selling them on Tindie but I might keep four and try this multiplex approach. I really want to do this with multiple MPU9250 hanging on the same Teensy 3.1. I think two should be easy, but your method shows that up to six should be possible; there is an SDA/SCL pin pair on the back pads too.
 
Well yeah you can go crazy; I scored a handful of CMOS dual 4:1 analog mux's (74HC4052) as a backup solution; one of these this would let you mux each of the teensy SDA pins four times giving you up to 16 MPU6050's (two SDA outputs, muxed 4 ways, two MPUs on each one); the issue then might become too many pullups (one in each module) on the single very-fanned-out SCL line so maybe either mux it in the teensy (I was saving pins) or add an external 4:1 mux for SCL too.

...It'd be a little pointless also :)

I'm just doing four sensors cos I have two hands and two feet :) I'm also saving my teensy pins because I might be driving 16 channels of WS2812B's at the same time (and sensing battery voltage and reading IR remote control and, etc etc)
 
Last edited:
Hi, I hope someone can help me. I have a MPU6050 connected to a Teensy 3.1, change the interrupt pin to 15. I am using DMP, for a moment send the correct data, but then locks up and stops transmitting. Any idea what can be happening ?. Thanks
 
Try removing the interrupt check and just polling the interrupt register to see when data is ready. That should narrow it down to where the problem is (i.e. is it an i2c problem). I'm using four MPUs without interrupts and it works fine for hours.
 
Works fine; you're just reading the FIFO.

a) Configure MPU in DMP mode (e.g. at 50hz output rate, whatever you need see DMP setup code) - assuming you're using 6DOF each packet is 42 bytes (forget exactly)
b) Every 50hz (or faster) read one byte from "PU6050_RA_INT_STATUS", check bit 1, if set (data ready) read 42 bytes from FIFO.
c) That's it. If you poll too slowly you'll miss packets and the fifo will fill up eventually (then bit 4 will be set in INT_STATUS); you could read the fifo size register to see if you have more than one packet in the fifo and read two if that happens. If you poll too fast it's not a problem.

If you get junk data it's likely because you're not aligned to each 42 byte chunk in the fifo, i.e. the 42 bytes you read are half of one packet and half the next one; just clear the fifo before you start. This is not usually a problem.

I'm running four MPUs with only three wires as described above, and no interrupt lines (just SCL/SDA) and reading them continuously round-robin with code that runs off the cpu's i2c interrupt (so non-blocking); it works fine. (see https://www.youtube.com/watch?v=KzE-fCionf0 this is running in that configuration)
 
Thank you very much DrTune for your contribution. Now run well. Something very strange is that I found a teensy 3.0 runs perfectly without modification.
 
I wanted to add this information in case it is useful to someone, the time when the interrupt is triggered for different values ​​of mpu.setRate ()

0 -> 6 ms
5 -> 12 ms
9 -> 20 ms
10-> 21.6 ms
20-> 41.6 ms
 
Excellent! I will try something similar with i2c_t3.h. I bought a bunch of the GY-521 for $2 from Amazon.com; I am selling them on Tindie but I might keep four and try this multiplex approach. I really want to do this with multiple MPU9250 hanging on the same Teensy 3.1. I think two should be easy, but your method shows that up to six should be possible; there is an SDA/SCL pin pair on the back pads too.
onehorse, did you ever get the mux'ing to work with i2c_t3. I had this working with just a single MPU6050 (0x68 or 0x69) on each bus/channel (using top and back pads) but when I add two (both 0x68 and 0x69) or another I2C device none of the MPU6050's will ACK - the others will though (e.g. OBDII, temp, etc.).
I'm suspecting my code and or setup but wanted to check.
 
Status
Not open for further replies.
Back
Top