MPU6050 -- Motor Noise

Hi all,

I have been struggling with successfully reading yaw values from an MPU6050 using Jeff Rowberg's I2Cdevlib-MPU6050 "MPU6050_DMP6." I am trying to run 4 DC brushed motors using Pololu's G2 high-power motor driver (Pololu G2 High-Power Motor Driver 18v17) in locked-antiphase operation, while reading from an MPU6050 in I2C, both using a Teensy 4.1. There is a GND line, DIR line, and PWM line that control the motor driver. I send 0 or 1 to the PWM line to either deactivate or activate the motor driver, and I send analogWrite 0-128 for clockwise rotation or analogWrite 128-256 for anti-clockwise rotation in the DIR line in 100KHz. The motor is powered in 12V from the battery, the Teensy is powered in 5V from the battery through a voltage regulator, and MPU6050 is powered in 3.3V from the Teensy.

The problem is that whenever I turn on the motors using a switch, my MPU6050's values become either erratic or freeze immediately. The faster I run the motors, the MPU6050 freezes faster. It is quite obvious that the problem is electromagnetic interference from my motors since my MPU6050 works absolutely fine without my motors running.

I have tried connecting all the components to an Arduino Mega, but the MPU6050 was not fixed. However, when I disconnect the battery source to the Teensy (via the voltage regulator), AND when I disconnect the motor DIR, GND, and PWM lines and connect those three lines to an Arduino Mega, no matter how close the mainboard, Teensy, and MPU6050 are to the 4 motors, the MPU6050 works absolutely fine; my hardware connection is fine.
When I connect the three motor driver lines to my Teensy but not the battery source, there is still some noise; the MPU6050 freezes in 15-30 seconds when motors are MAX speed. When I connect the motor driver lines to an Arduino Mega and the battery source to the Teensy, my MPU6050 immediately freezes.
I have deduced that the noise is mainly from the battery source and motor driver lines.

Can anybody provide some advice on what I could do to eliminate this problem?

Thanks in advance, and I apologize for the lengthy description.

Here is my code (for the Teensy):

#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif

/* define motor driver pins */
#define motorPWM1 2
#define motorPWM2 3
#define motorPWM3 4
#define motorPWM4 5
#define motorDIR1 6
#define motorDIR2 7
#define motorDIR3 8
#define motorDIR4 9

/* MPU6050 program*/
MPU6050 mpu1(0x68);

#define INTERRUPT_PIN1 25
bool dmpReady1 = false;  // set true if DMP init was successful
bool dmpReady2 = false;
uint8_t mpu1IntStatus;   // holds actual interrupt status byte from MPU
uint8_t mpu2IntStatus;
uint8_t devStatus1;      // return status after each device operation (0 = success, !0 = error)
uint8_t devStatus2;
uint16_t packetSize1;    // expected DMP packet size (default is 42 bytes)
uint16_t packetSize2;
uint8_t fifoBuffer[64];  // FIFO storage buffer
Quaternion q;            // [w, x, y, z]         quaternion container
VectorInt16 aa;          // [x, y, z]            accel sensor measurements
VectorInt16 aaReal;      // [x, y, z]            gravity-free accel sensor measurements
VectorInt16 aaWorld;     // [x, y, z]            world-frame accel sensor measurements
VectorFloat gravity;     // [x, y, z]            gravity vector
float ypr1[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector
float ypr2[3];
double yaw;
volatile bool mpu1Interrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady1() {
  mpu1Interrupt = true;
}


void setup() {
  /* setup for MPU6050 */
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
  Wire.begin();
  Wire.setClock(400000);
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
  Fastwire::setup(400, true);
#endif

  Serial.begin(115200);
  mpu1.initialize();
  pinMode(INTERRUPT_PIN1, INPUT);
  devStatus1 = mpu1.dmpInitialize();
  mpu1.setXGyroOffset(-136);
  mpu1.setYGyroOffset(142);
  mpu1.setZGyroOffset(-14);
  mpu1.setZAccelOffset(1213);

  if (devStatus1 == 0 && devStatus2 == 0) {
    mpu1.setDMPEnabled(true);
    attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN1), dmpDataReady1, RISING);
    mpu1IntStatus = mpu1.getIntStatus();
    dmpReady1 = true;
    dmpReady2 = true;
    packetSize1 = mpu1.dmpGetFIFOPacketSize();
  } else {
    Serial.print(F("DMP Initialization failed (code "));
  }

  /* setup for motor drivers (LAP) */
  pinMode(motorPWM1, OUTPUT);
  pinMode(motorPWM2, OUTPUT);
  pinMode(motorPWM3, OUTPUT);
  pinMode(motorPWM4, OUTPUT);
  
  pinMode(motorDIR1, OUTPUT);
  pinMode(motorDIR2, OUTPUT);
  pinMode(motorDIR3, OUTPUT);
  pinMode(motorDIR4, OUTPUT);
  
  analogWriteFrequency(motorDIR1, 100000); //PWM is 100KHz 
  analogWriteFrequency(motorDIR2, 100000);
  analogWriteFrequency(motorDIR3, 100000);
  analogWriteFrequency(motorDIR4, 100000);
}


void loop() {
  /* MPU6050 */
  if (!dmpReady1) return;
  if (mpu1.dmpGetCurrentFIFOPacket(fifoBuffer)) {
    mpu1.dmpGetQuaternion(&q, fifoBuffer);
    mpu1.dmpGetGravity(&gravity, &q);
    mpu1.dmpGetYawPitchRoll(ypr1, &q, &gravity);
  }
  yaw = (ypr1[0] * 180 / M_PI); //get yaw value from MPU6050
  Serial.print("yaw; ");
  Serial.println(yaw);

  /* motor 1 */
  digitalWrite(motorPWM1, HIGH);
  analogWrite(motorDIR1, 0);

  /* motor 2 */
  digitalWrite(motorPWM2, HIGH);
  analogWrite(motorDIR2, 0);

  /* motor 3 */
  digitalWrite(motorPWM3, HIGH);
  analogWrite(motorDIR3, 0);

  /* motor 4 */
  digitalWrite(motorPWM4, HIGH);
  analogWrite(motorDIR4, 0);
}

The MPU-6050 is noisy, outdated, and your MPU-6050 might not be a real MPU-6050. It is probably on a module and that module might have the wrong values for a capacitor or a voltage regulator that lowers the voltage for the MPU-6050 below 3.3V. Your MPU-6050 has already 5 problems on its own.

The I2Cdev library has bugs, it uses the I2C Wire library in the wrong way, and some say that its calculations do not even calculate the right thing. It will work a little with a Arduino Uno, but your Teensy might not like that library. That means there are already 3 problems with that library.

You did not mention how long the wires are, what the pullup resistors are, if you use a cable, how the ground wires are running, and so on. I suppose there are at least 5 problems with that.
Perhaps you need to lower the I2C speed to 100kHz. You might have to isolate both circuits with opto-couplers.

That means there are at least 13 problems that you have to fix.
Please show a photo with the wires and give a link to your MPU-6050 module and make a drawing that shows how everything is powered.

Hi, thanks for the fast reply.

These are images of my mainboard PCB and wiring. Everything is powered by a 12V battery: the battery powers a voltage regulator which drops the 12v voltage down to 5v to the Teensy. The motor driver receives 3.3V logic from the Teensy and receives 12v motor operating voltage from the battery. My SCL line is about 10cm, and my SDA line is about 9cm.

I do use a USB cable to read Serial from the Teensy and also power the Teensy and other components with the battery.
This is the sensor I am using: https://www.amazon.com/Gy-521-MPU-6050-MPU6050-Sensors-Accelerometer/dp/B008BOPN40/ref=sr_1_4?keywords=MPU-6050&qid=1639833893&sr=8-4



Hi,
Thanks for the images.
Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Your tracks for power are very thin, in particular the 12V for the motor.
Also they lack 0.1uF bypass capacitors across the 12V, 3V3 and 5V tracks.

It is hard to trace but does the motor 12V supply connect on the PCB then to the motor controllers, and not just routed directly to the motor controllers.

Thanks... Tom... :grinning: :+1: :coffee: :australia:

MPU-6050 modules

Those are the crappiest modules that money can buy.
They cost 1 or 2 dollars: https://www.aliexpress.com/item/714775852.html
If you apply 3.3V to VCC, then the MPU-6050 runs at a lower voltage because of the voltage regulator. I think the blue wire is 5V, so if you power the MPU-6050 module with 5V, then it is okay.

Pullup resistors

It seems that the Teensy 4.1 has no pullup resistors. Both your modules might have 2k2 pullup resistors to 3.3V (or an other value, please read the resistors values) and you have added 4k7.
Total pullup = 4k7 // 2k2 // 2k2 = 891 Ω.
The sink current for SDA and SCL = 3.3V / 891 Ω = 3.7 mA.
The maximum is 3mA, so your I2C bus is not according to the I2C bus standard.

I2C and noise

There are no wires and there is a ground plane ? That is very good. Is there any GND current from a motor reaching the pcb board ?

Decoupling capacitors

Please show a schematic.
Where are your 100nF decoupling capacitors ?
With normal electrolytic capacitors at certain voltage regulators, you might have created a noise generator.

Conclusion

It is not so bad. I think you underestimate how much noise the motor drivers and the motors make. If you could see the noise, then the whole project would light up like a Christmas tree up to a foot / 30cm around it. The noise goes directly through the air and via the wires. A single small tiny ground wire is enough to create an enormous amount of noise in the whole pcb board.
Maybe you have to redesign the project and keep the high power away from the low power.
Maybe you should encapsulate the pcb board in metal.
Maybe optocouplers are needed.
Maybe normal modern sensors with a normal library will also help.

Hi Tom, thanks for your reply.

This is the schematics of the mainboard PCB (I only included the parts with the motor driver and I2C lines).
Are the "tracks for power" that you refer to the red and black power wires that go to the motor driver's motor operating voltage and the motors? Also, where should I put the 0.1uF bypass capacitors across my 12v, 3.3v, and 5v tracks?
The 12v battery supply connects to the motor operating supply in the motor driver. The 12v battery supply also connects to the 5v voltage regulator, which gives 5v voltage to the Teensy. The Teensy's ground is the same as the motor driver's logic ground. The Teensy operates the motor driver using digital and analog PWM pins.

Hi Koepel, thanks for your reply.

No there is no GND current from the motor directly reaching the PCB board. Just that the motor driver logic GND is shared with Teensy's GND and the motor driver's 12V operating voltage GND is the same GND as the voltage regulator's GND, which drops the 12V to 5V to the Teensy.
Can you please specify why the 100uF electrolytic capacitors can be a noise generator, and why I should use 100nF capacitors instead for the voltage regulator's input and output?
How can I keep the high power away from the low power?
I am thinking of putting optocouplers to the PWM and DIR lines of my motor drivers that connect to my Teensy's digital and analog pins, but what should I do for my battery source wires that seemingly produce the most damage to my MPU?

Thank you very much for your valuable advice.

On this forum we often say that the problem is in the part that someone is not showing.
Is that the whole schematic of the board ?

Can you fix the schematic ?
MD_PWM4 is connected to GND, PWM is connected to GND and the other MD connector is not clear how it is connected.

I see that you use a Pololu module for the 5V : https://www.pololu.com/category/261/d36v28fx-step-down-voltage-regulators
That is good. It has all the decoupling capacitors already on the module.
Some voltage regulators need low ESR capacitors or else they start oscillating at a high frequency.
A electrolytic capacitor has a higher impedance for high frequencies. The 100nF ceramic capacitors can deal with high frequency noise.

I'm not sure about the battery power. I have no clear view how the power wires are running in your project. Maybe you need a very large electrolytic capacitor the reduce voltage drops. Maybe a star-ground will help if you don't have that yet.
Grounding is a skill/craftsmanship on its own.

Hi Koepel, thanks for your reply.

I apologize for the schematic; I just updated it to the full version above :slight_smile:

I will try adding 100nF capacitors next to both vin and vout tomorrow.
Also, which accelerometer and gyroscope module that can measure yaw values do you recommend? Where should I put this large capacitor at what value?

These are how my power wires are running my project. The illustration is really messy, I apologize for that.

Thanks very much.

The ground current that just went through the motor has two paths to return to the battery. One path is via the MD module to the negative pole of the battery, the other path is via the MD module, to the Teensy board, to the battery.
It depends on many things which path the current will choose. You may not assume that the ground current will select the big wires.

In this schematic, the MPU-6050 module is powered by 3.3V. The MPU-6050 gets is voltage from the voltage regulator, that is lower than 3.3V, and thus that is not optimal.

Why do you have two MPU-6050 sensors ? I'm used to see a sensor in the center of such a project.

Hi Koepel, thanks for your reply.

I have tried using 5v instead of 3.3V with the MPU6050 and replaced the 100uF capacitors with 0.1uF capacitors on the voltage regulator's vin and vout; however, the issue persists. Now that I connected the MPU6050 with 5V, how many ohms should my pullup resistors be?

I am using 2 MPU-6050s because I want to use the average yaw value of the two for more accurate measurements.

Finally, do you mean that the motor gnd current can go from motor--> MD logic --> teensy --> regulator --> battery?

Thank you very much for the advice.

I wrote about 5 problems with your MPU-6050 module and you solved only one by applying 5V to VCC.
When using two MPU-6050 modules, you have doubled the trouble.
Fix a problem by reducing things that can go wrong, not by doubling the trouble.
I asked to read the values of the pullup resistors on your MPU-6050 modules, because the photo was not detailed enough.

Yes, that might happen. It depends on many things, but a GND current can decide to take the long path with the small wires.

Are you trying to solve your problem by fixing each problem step by step ? After 10 posts, you have fixed only one problem by applying 5V to VCC of the MPU-6050 module, but there are still more than 10 problems to go. That means we will need 100 posts to get closer to a working project.

Why would you allow that your beautiful project has the crappiest sensor that money can buy, and it might not even be a real MPU-6050.

Hi Koepel, thanks for your reply.

The pullup resistors on my MPU6050 modules are 2.2K ohms.
Do you recommend any real MPU-6050s? All the MPU6050s I can find are from Amazon. Or should I just ditch the MPU-6050 and try different IMU sensors?

Regarding the I2CdevLib, I have tried different MPU-6050 libraries (both on Teensy and Arduino) but none of them work because the sensor values freeze after turning on the motors. So I do not think there is a big issue with the code or library I am using.

Even with other sensors it will freeze, because the I2C bus has some serious noise problems.

Ditch the MPU-6050. It is no longer made.
Ditch the I2Cdev library, it might work with a Uno, but I really don't like it together with the Teensy 4.1.

The processor on the Teensy board seems to be in the middle of the project, perhaps you can glue the sensor somewhere near the processor with hot glue (also called hot-snot).

Solve the GND current issue. I mentioned a "star-ground", have you investigated what that is ?
Wrap the controller module in copper foil and ground the foil to a GND that is close to the GND of the Teensy board, or to the star-ground.
Maybe the noise enters via the power supply wires and a LC filter is needed for the 12V and maybe for the GND as well.

Perhaps you have to use optocouplers to the motor controllers.

Then you may still have to fix the I2C bus.
Select pullup resistors so that the sink current is between 1mA and 3mA.
Maybe you should ditch the I2C bus as well. The SPI bus is a stronger bus (a lot stronger). See if the ADXL345 suits you, is that only a accelerometer ? The LSM6DS3 is accelerometer + gyro.

You could do a test, suppose that you can fix the problem by solving the GND current issue. Then you know that you are on the right track and choosing a better sensor with the SPI bus will make it even better.

First obvious observation is that the MPU6050 pcb is very close to the motors and their magnetic fields, so may be picking up directly induced voltages. Sensitive electronics should be far from the motors. A steel screen between the motors and electronics could mitigate this by shielding from changing magnetic fields.

The high current wire already seems to be twisted pair which is good, but sheer proximity of the motors and their high current winding to the microcontroller (a cm or so?) and sensors may be the underlying issue - especially with a 3.3V microcontroller which is very sensitive to noise (industrial controllers typically use 24V signalling expressly to reduce noise sensitivity in high EMI environments and would typically have a shielded enclosure for the sensitive control board)

Can you place the control electronics in a steel or at least metal shielded box?

Your motors appear to have EMI-reducing ceramic capacitors (blue) across the terminals (even 1nF can significantly reduce EMI from the brush sparking). Its important these caps aren't too large or too small in value - too large and current spikes are generated from the H-bridges charging the caps, too small and they won't attenuate RFI much - some experimentation might be needed.

1 Like

Hi Koepel and MarkT, thank you for your replies.

I will test out your provided possible solutions on my own and post any questions or updates soon.

Thank you very much for the advice.

Hi Koepel,

Thank you for your suggestions!
I solved the issue by replacing the MPU6050 with a bno055 from Adafruit.
Now the bno055 does not freeze or produce erratic values even when the motor is rotating at max speed for several minutes, which is enough for my project.
Thank you very much.

I'm glad it is working :smiley:

Adafruit BNO055 : https://www.adafruit.com/product/2472
Schematic : https://learn.adafruit.com/assets/24546

It has 10k pullup on both side of the level shifter, that make a pullup of 5k. You could add some extra pullup to lower the impedance of the I2C bus.
You don't need that level shifter, and it makes the I2C bus weaker. Well, anything is better than a fake MPU-6050 I suppose.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.