MPU6050 IMU code works with Arduino but not TEENSY 4.0

Status
Not open for further replies.

Droid

Member
Hello everybody

I posted on this forum recently but I ran into another problem and figured it needed its own thread.
(https://forum.pjrc.com/threads/61755-TEENSY-4-0-reading-wrong-data-on-GY-521-MPU6050-Breakout-Board)

For the project I'm working on, I need to get pitch and roll data from an GY-521 IMU board. Once again, my code compiles nicely on an Arduino but once I switch over to Teensy it doesn't work. The pitch and roll values do not accurately represent what they are supposed to like how it is on an arduino. I tried experimenting with int16_t because that's what did the trick last time (and I have my suspicions that it's a similar issue) but I could not get it to give the correct values.

So what's happening is that the pitch and roll slowly increases but as soon as it hits 1, the values shoot up when I'm moving the IMU at a relatively constant rate.

Could someone explain how to successfully port over Arduino code to Teensy so that I do not run into this issue again?

My code is attached below. Please help, and thanks in advance!

View attachment main.cpp
 
This is very likely the problem.

Code:
  //Store accelerometer values and divide by 16384 as per the datasheet
  acc_x = (Wire.read() << 8 | Wire.read()) / 16384.0;
  acc_y = (Wire.read() << 8 | Wire.read()) / 16384.0;
  acc_z = (Wire.read() << 8 | Wire.read()) / 16384.0;

This code works only by mistake on 8 bit AVR. Consider that Wire.read() gives a number between 0 to 255. On a 32 bit processor, this equation can never give a negative number. It works on AVR because the math defaults to signed 16 bit integer, so the equation which should have resulted in 0 to 65535 becomes -32768 to +32767.

To make this work on Teensy 4.0, or any other 32 bit board, you need something like this:

Code:
  //Store accelerometer values and divide by 16384 as per the datasheet
  acc_x = (int16_t)(Wire.read() << 8 | Wire.read()) / 16384.0;
  acc_y = (int16_t)(Wire.read() << 8 | Wire.read()) / 16384.0;
  acc_z = (int16_t)(Wire.read() << 8 | Wire.read()) / 16384.0;
 
Hello Paul!

This worked! Thank you for your help, time, and explanation. This is greatly appreciated!
 
That code is assuming an order of evaluation for the operands to the '|' operator. Whats to stop a compiler calling the right-hand
Wire.read() call first?
 
Status
Not open for further replies.
Back
Top