Motor interference and decoupling capacitors

Hi all,

I'm making a self-balancing robot. Using:

Wiring is pretty simple:

  • the sensor has 2 pins to the Uno 3.3V, gnd to arduino gnd and SCL/SDA to A4/A5. I didn't connect the interrupt pin on the IMU because I use raw sensors readings.
  • Motor driver shield on top the Arduino, motor supply on the screw terminals of the shield, motors connected to their terminals on the shield.

Here is my problem: when motors are not powered (battery disconnected) the Uno reads the sensor just fine. When I connect the motors, the Arduino hangs randomly. Sometimes after 2 seconds, sometimes several minutes. Generally the hangs happen when the robot is very tilted / when the motors spin fast / when the motors reverse suddenly and often. When it hangs the motors keep spinning at the last speed they were at. The robot is balancing OK and when it's balancing it doesn't hang or after several minutes.

I searched what could cause the hangs. I checked the available RAM at various points in the code using this little function

int availableMemory() {
    // Use 1024 with ATmega168
    int size = 2048;
    byte *buf;
    while ((buf = (byte *) malloc(--size)) == NULL);
        free(buf);
    return size;
}

and using some "Serial.print(availableMemory());" at different places in the code.

Everywhere I have around 1300 bytes free so that's not the problem.

I debugged with Serial prints to check where the hangs happen. They always happen when reading sensor data.

So I'm 99% sure now that it's due to the motors creating noise/interference in the circuit, which in turn causes problems with sensor data acquisition through I2C, which causes the hangs. I don't understand I2C very well so that's as far as I could diagnose :slight_smile:

I then proceeded to read how to prevent interference from the motors. I'm already running separate power supplies for motors/motor driver and Arduino.

I added 3 decoupling caps (0.1 uF) on each motor, from terminals to case and between terminals. It seems to help somehow, the robot is a bit more stable it seems so that would mean sensor readings are less noisy. However it didn't reduce the hangs.

Here are my questions:

  1. I read that I should add decoupling caps on the power supply line. I'm not sure how to do that exactly. Do I solder caps between +V and GND wires coming from the battery? Do I do it on both batteries?

  2. Can I add a decoupling cap on the sensor? Sensor has 2 pins to Arduino 3.3V, 1 pin to Arduino ground and the 2 SCL/SDA pins. Should I add a cap between the VCC and GND pins? And if so do the caps need to be as close to the sensor as possible?

  3. About connecting batteries grounds. I assumed that the grounds are already connected through the shield and that it's enough. But should I connect the batteries grounds elsewhere?

  4. I saw some people added a logic level converter from the sensor to the Arduino however I couldn't find details. I assume it's used to up the SCL/SDA lines to 5V. Could that help?

Many thanks, sorry about the long post, I really want to get advice before doing anything stupid :slight_smile:

More capacitors seldom hurt. Add a large capacitor (>100µF) across the supply to the motor.

You can add more capacitance to the board input of the sensor, yes - maybe add a 10µF across the Vcc/GND pins.

Another thing you could try is reducing the pullup resistance of the I²C lines - add some smaller (say 1K?) resistors between SDA and Vcc, and SCL and Vcc. That would help to reduce the impact of noise on the digital lines.

All that and put a cap(bipolar) over the motor terminals as well.

My guess about the cause of the hangs is that the I²C messages are getting corrupted, and the Arduino is waiting an infinite amount of time for a message to complete that has corrupted. I don't think there's any kind of time-out facility on the Arduino I²C driver.

Reducing the I²C pull-up resistance should help fix that.

Thanks a lot for the quick answers! I'll try reducing the pullup resistance of the I2C lines and adding a cap on the motors supply, and see how it goes. Thanks again.

The cap across the motor terminals will reduce high frequency noise from the
brushes, but don't add any capacitors between motor terminals and case, that
just makes the motor case a radiator of interference. You can add a ground wire
to the case. Make sure the high current wiring is all twisted pair and doesn't contain
large loops that could radiate flux.

Never share ground wires between high current parts of the circuit and the sensors.

This means that the grounds of the Arduino and the motor driver should meet once, so
that you have a star-ground from that point. In particular if you ground the motor
case from the high current side of the circuit, it must not be connected to signal
ground of the encoder.

MarkT:
The cap across the motor terminals will reduce high frequency noise from the
brushes, but don't add any capacitors between motor terminals and case, that
just makes the motor case a radiator of interference. You can add a ground wire
to the case. Make sure the high current wiring is all twisted pair and doesn't contain
large loops that could radiate flux.

Never share ground wires between high current parts of the circuit and the sensors.

This means that the grounds of the Arduino and the motor driver should meet once, so
that you have a star-ground from that point. In particular if you ground the motor
case from the high current side of the circuit, it must not be connected to signal
ground of the encoder.

I agree with all of that and would add: If you are using an actual Arduino rather than a stanadlone system, then I suggest you use one of the Arduino ground pins to connect the sensor ground, and a different Arduino ground pin to connect the Arduino to everything else (power, motor drivers etc.).

How are you powering the Arduino: from the same power supply as the motors, or a different one? If it's the same power supply, then you need to be careful with the power supply wiring too, and you may need to filter the power input to the Arduino.

Thanks again, much much appreciated.

@MarkT: I'll get rid of the caps on the motors cases.
@dc42 I have separate power supplies for Arduino and shield.

I'm not sure I fully uderstand grounds :smiley: should be pretty simple, I feel like an idiot.

I am indeed using an actual, original Arduino. As you know it has two ground pins, both are connected to the motor driver shield (because of how shields connect). Is that a bad thing? I assume these two ground pins are connected somewhere on the Arduino board.

One of these two ground pins is connected directly to the IMU ground pin and nothing else. The other one goes to a breadboard, giving ground to arduino battery and pots (used for PID tuning). Motor driver battery ground goes straight to the ground screw terminal of the driver shield.
Is that the correct way to do so?

If I want to ground the motors cases, where does it have to go to then? The "breadboard" ground? And if I add the encoders, same? But then it would means motors cases and encoder signal grounds are connected...

Like I said I'm a bit lost with grounds :slight_smile:

Thanks again guys!

It sounds to me that your grounding is OK. In particular, you have the IMU ground connected directly to an Arduino pin, not to the breadboard ground. As you are using a motor shield, you cannot (unfortunately) completely separate the signal and power grounds, short of soldering a ground wire to the back of the Arduino. So I suggest you follow MarkT's advice, specifically:

  • keep the area enclosed by the motor battery - motor shield - motors as small as possible, for example, by using twisted pair wires between the shield and the motors (hand-twisted wire is OK, no need for anything fancy)

  • if the motor shield does not already have one, add a large decoupling capacitor between the motor power supply terminals

Also, if the problem is indeed caused by the I2C interface hanging, then adding external pullup resistors on the I2C pins may help - as will keeping the I2C wires well away from the motor wires.

Uuhmm, something I don't understand.
Looking at various Arduino boards with a x10 loupe, it really looks to me as if all the board grounds are common?
It's possible to follow the traces under the 'ink' and they all seem to be interconnected. I used a multi meter on Mini (just in case I was wrong and meter votage 'broke' something) and it seems to verify this.
Anyway, if all the grounds are connected together on the board, why does it matter where you connect external grounds?
Sorry for the interuption

Indeed Crazypj that's what I don't get either :slight_smile:

Checking continuity with a multimeter, all grounds (driver supply, Arduino supply, the two gnd pins on arduino / shield) are all connected. The only way I can imagine of separating motor power and arduino grounds completely is to chop off the two headers under the shield that connect to the gnd headers on the Arduino. And then connect sensors ground and arduino power ground directly on the arduino pins (that is, inbetween arduino and shield).

But if I also undestand correctly the motors and arduino ground must be connected somewhere.

I don't know if the amount of material where you have a common ground between the motor voltage and Arduino will make a difference?
Unfortunately there is a lot I don't know about electronics :~
Do the motors spin down when you switch them off? could be they are acting as a DC generator? (350 rpm free speed + over 10,000 rpm motor shaft speed @ 29:1 reduction?)
I have some scrap copper pieces about 1-1/2" dia 1/16" thick @ 1-1/2"x 1/2"x 1/16" I use as grounding points (and heatsink, de-soldering, etc, etc :smiley: )

Success!

It doesn't hang anymore.

What I did (in sequence):

  • add a 0.1 uF cap between motors terminals, and one 1uF cap between each terminal and case: slight stability improvement but still hanged if robot was "shaking" too much / motors at or close to max PWM.

  • Took everything apart, repositioned motor power battery, shortened motors and battery leads a lot and twisted them; ran them around the chassis as far away from sensor as possible. Shortened I2C leads from sensor and twisted them. Took away the terminal-to-case caps.

Now it basically never hangs. I pushed the robot while balancing, grabbed it and shook it in all directions and generally made his life hard (sweet, sweet revenge) and when putting it back on the floor it resumed balancing. Did that multiple times and zero hangs.

Now on to add the encoders.

I can't thank you enough guys! You and this forum are amazing and I learned a lot today again :smiley:

I'm glad you got it working!

crazypj:
Uuhmm, something I don't understand.
Looking at various Arduino boards with a x10 loupe, it really looks to me as if all the board grounds are common?
It's possible to follow the traces under the 'ink' and they all seem to be interconnected. I used a multi meter on Mini (just in case I was wrong and meter votage 'broke' something) and it seems to verify this.
Anyway, if all the grounds are connected together on the board, why does it matter where you connect external grounds?
Sorry for the interuption

It matters because of the resistance of the connection between the wire and the ground pin, and the resistance and inductance of the wire. Current flowing through the connection and wire will cause a voltage drop across them due to the resistance, and changes in the current will cause a voltage to be niduced across the wire due to its inductance.

But in this case, it sounds like the main problem was mutual inductance between the motor circuit and some other part of the circuit (such as the wiring between the Arduino abd the sensor). The pulsating current in the motor wiring was creating a pulsating magnetic field, and this pulsating magnetic field was inducing a voltage either in the sensor-to-Arduino wiring or somewhere else. Using twisted pair largely eliminates the magnetic field produced by the wires, or the suceptibility of the wires to magnetic fields.

Just read this tread. Thanks a lot, it worked for me too :smiley: