SD write interference with MPU9250 accelerometer ??

I am working on a major project for rocket telemetry and I've stumbled on a strange conflict between an SD Card (on SPI) and a MPU9250 accelerometer (on I2C). These are both connected to an Arduino Mega 2560 board mounted on a custom shield. There is nothing else on the SPI bus and there is a small BMP180 pressure sensor also on I2C.

In general, everything works perfect, except when I sample the accelerometer from the MPU9250, immediately following an SD Card write to disk. When I sample following a write to disk I occasionally get random garbage from the accelerometer. The code and variables used for each device is completely isolated, so I suspect something much lower level is going on. If I add a 50ms delay after the SD Card write then the MPU is happy and never reports an anomaly. This could be a fix, but on my project, when a rocket launches I need to rapidly capture acceleration and log it to the SD without missing a beat.

The SD Card ( and the MPU9250 ( are mounted next to each other on the shield. I even put the SD card on a separate power line and regulator from a LiPo battery to see if that would help (it did not).

My SD logging code opens files on startup, so the "offending" writes that cause the MPU to go crazy don't include file open or file close.

Has anyone heard of an SD write interfering with an accelerometer?

A SD memory card is 3.3V and the Arduino Mega 2560 is 5V. Your SD module has a level shifter. That should work fine.

The Arduino Mega 2560 board is the only Arduino board with 10k pullup resistors to 5V for SDA and SCL. Your MPU-9250 module connects SDA and SCL directly to the MPU-9250 chip. That is not okay. Use a level shifter.

The new Arduino boards use a SAMD21 ARM M0+ processor at 3.3V, then you don't have all these problems with 5V and 3.3V.

Thanks Koepel. My SD reader has a built in level shifter, but not the MPU. Now I’m going to go back and look at all of my modules/interfaces.

I’m using a serial TTY radio and GPS. Both are 3.3V tx/rx. Both are working fine, but I suspect the Mega is pushing 5V. Can anyone confirm the standard voltage on Serial1 and Serial2 for the Mega? I see that the Due uses 3.3v and the Uno 5V, but I can’t seem to confirm the TTY voltage for the Mega.

The Serial pins on the Arduino Mega 2560 are 5V. Those pins are directly connected to the ATmega2560 microcontroller which runs at 5V.

Reading a 3.3V input for the serial RX is almost never a problem. But it pushes the 5V TX level into the TTY and GPS. Some devices are 5V tolerant. Some devices are even 5V tolerant without any mention in the datasheet.

A very simple solution is for example to limit the current to 1mA with a resistor in the TX line. 5V - 3.3V / 1mA = 1700 Ω, that means a resistor of 1k8 to 10k.

The ATmega2560 can output 40mA per pin. That is a lot. When pushing 5V into a 3.3V chip via a TX pin, it is not 40mA, but it might be enough to damage some chips.

Many new sensors are not very tolerant. The 10k pullup to 5V on the Arduino Mega 2560 board can be enough to lift the voltage level of a 3.3V sensor via SCL and SDA to damage it.

I added level shifters to the I2C SDA and SCL on the MPU9250 and I added them to the TX and RX on the GPS and the Serial TTL radio.

Adding the level shifters has substantially improved the MPU issue related to SD writes, but not eliminated it altogether. I used to get a crazy reading about 1 in 10 reads followed by a SD write with no delay following the write. Now I get a crazy reading about 1 in 100 reads followed by a write. Also, before I had to use a 27ms delay following a write to the SD Card to fully eliminate the issue. Now I can fully eliminate the issue with a 10ms delay. So, the level shifters definitely helped a lot, but odd that I still get the issue. 10ms is manageable for my project and I've got a load of software filters to detect anomalies, but it still makes me question the integrity of the sensor.

I was also getting some odd lock-ups with the CPU before the shifters when the radio antenna was near the Arduino. I am using strong radios (2W), so I assumed I was getting too much RF interference on pins or directly to the CPU on transmit. The shifters appear to have fixed or substantially fixed this issue, as well. thanks!

How long are the wires of the I2C bus ? Or are they in a cable ?

With level shifters the voltage levels match and the I2C bus is more tolerant for electrical noise. However 1 in 100 is really bad, that is not reliable. It should be no errors at all, or perhaps 1 in a million or so.

The impedance of the I2C bus can be lowered to make it more reliable. The maximum pulldown current for the I2C bus is specified as 3 mA. When you combine all pullup resistors on the I2C bus, both at the 5V and the 3.3V side, then you can calculate the current that is needed to pull the SDA or SCL low. You can also write a sketch that does a Wire.begin() and nothing else to keep the I2C bus idle. Then measure the shortcut current of SDA to GND and of SCL to GND.

If you have used bidirectional levels shifters (ment for the I2C bus) in RX and TX signals, those signals have become a lot weaker. For example the TX signal is 40 mA super strong. A bidirectional level shifter with 10k pullup resistors has a high level that is 0.33 mA strong. That means the signal has become 121 times weaker.

Can you try some shielding ?

The I2C components are on a custom shield directly mounted to the Arduino, so the wires are less than 1-2” max from component to pin.

I did a lot more testing. With a small 10ms delay following SD writes my setup is bulletproof running for eight hours straight...sampling, writing to SD occasionally, transmitting on the radio, etc. The sampling is at 50Hz, so that is as close to perfect as I can get over eight hours. Adding the level shifters also seemed to fix the radio interference causing lock-ups. I was prepared to build a faraday cage around the Arduino, but now it seems like I don’t need to.

I’ll put an oscilloscope on the pins and see if anything looks unusual during radio transmission.



As far as I know, I2C operates with "open collector," which means that only the pull-up resistors will provide some power, so why use an adapter in that field?

I'm trying to use an MPU-6050 to analyze a vibrating table that operates at about 55Hz, but it has a lot of noise, because it is an old equipment with too many gaps in the couplings, so just reading the accelerometer does not provide clean data.

Are you using any data processing, like FFT, PSD etc?

Wow. that is a high resolution application for an accelerometer. In my experience the accelerometer, gyro, and manometer in my MPU9250 is very noisy. I am using the accelerometer/gyro combination to calculate rocket tilt and g forces on the way up, but I really only need an accurate sample about every 100ms. Even if I go 500ms without a good sample it isn't the end of the world. Sampling at 55hz should be possible on a fast processor Arduino, since the sensor can sample thousands of times a second. I am using the DMP built into the MPU9250 and quaternion filters. It takes about 30 seconds of sampling to get accurate, but then it is super accurate for me.

Depending on your application, you also likely need to calibrate the accelerometer. There are a lot of examples to run and get the off-sets required. I calibrated my manometer for another application and what I did was just write a program to output the x,y,z to the monitor (comma delimited) and then I rotated it around in circles for a minute. I then pasted the x,y,z data into excel and graphed it. it was super obvious when I visualized the data to see how best to calibrate the offsets.

Can an MPU9250 (or IMU6050) be reset without cycling the VCC?

I am 99.9% stable with my rocket telemetry project, but I still have a nagging issue with the MPU9250. When I let the rig sit on a launch pad for 30 minutes, sampling the accelerometer every 10ms, the MPU code stops working randomly about every 10 minutes in. The issue always coincides with a radio send, so I suspect RF interference that is just impacting the MPU board or a power pulse that messes with the MPU.

I have not narrowed down the specific code issue, since I cannot repeat it on the bench and it only happens when my rig (antennas, batteries, all other components) are assembled. My function to check the MPU/DMP and set the ac.x,ac.y, ac.z values (and calculate tilt) either doesn't run (status != 0x02) or runs but sets the same value every time. So, what I see in my logs is the same x,y,z values for every read after the problem occurs. I am handling for FIFO overflows and reseting FIFO regularly when things get busy.

I am traveling now, so I can't instrument the code and narrow down the issue, but one thought I had was to just test for the same value 10 times in a row (~100ms) and if the x,y,z were the same then reset the MPU9250. This is crude, but might be easier than trying to shield everything from the 2watt transmitter. A software reset would presume the sensor still has a pulse. I could work out a hardware reset on VCC, but that adds more complexity. I need something like a watchdog timer, but for just one sensor, since the Arduino and all the other sensors, radio, SD, etc. are working just fine when the problem occurs.