Arduino Uno resetting after robot runs a few moments

First off, this robot is my son's science fair project. His question was "How fast can a robot solve a maze?". He has told his teacher that he built the robot, and that I (his father) have written the coding for the robot. He gave his in class report on a failed experiment, even telling them that the robot had problems and was unable to complete the experiment, and the teacher thought his project was good enough that they selected him to go to the area science fair even though the robot was not functioning properly. I have spent the last three weeks trying (unsuccessfully) to get it to work without resetting in the middle of things. I have decided to ask for help, since it appears this problem is beyond me..

Our robot works (to a point) in that it drives forward until it detects an obstacle, then it sweeps the infrared sensor array (using a servo) to detect a clear path. It then rotates to that heading, and continues forward.

The problem I am having is that the robot would just stop with no apparent reason. I added a bunch of serial output from the robot so that we could see what was happening, and it looks like the setup() routine is being called when the robot just stops. This would indicate to me that the microprocessor is being reset somehow - I'm not sure what would cause that. Sometimes the robot resets after the first sweep of the servo, sometimes it can make 2 or three decisions before it resets.

Hardware wise, I am running the arduino, a motor control shield, bluetooth serial adaptor, and the servo all from a 7.2V 2200mAh LiPo battery pack, connected to an LM7805 voltage regulator giving +5V to the VCC on the arduino. The motors are 4.5V motors, connected to tank treads, and the servos are Tower Pro MG-90S servos on a pan/tilt assembly. I am not really using the tilt servo and have even disconnected it to see if that made any difference (it didn't).

I am including a copy of the code that runs the robot, in hopes that someone smarter than myself can point out where I may have gone wrong so that we can get this robot running before he has to present on Friday.
(The source code exceeds the limits of the message post, so I have included a link to the file in my dropbox)

Any help would be appreciated.

1 Like

Since SRAM is often the most constrained resource you can easily run out of it (which will cause a crash and usually a reset).

One easy way to conserve SRAM space is to keep printed string constants in FLASH. By default, all normal string constants are moved from FLASH to SRAM before the sketch is started.

If you change, for example,

Serial.println("Set left motor speed..");

to

Serial.println(F("Set left motor speed.."));

the string constant will be left in FLASH and printed directly from there.

You can save some more space by making the 'vals' array in scanEye() a byte array. That will save 32 bytes. Just use "analogRead() / 4" to reduce the readings to byte size.

I made the changes that you suggested, and reduced the length of some of the string constants that were being printed out. I didn't realize they were SRAM hogs..

However, it does not seem to have changed the problem. :disappointed_relieved:

Any further suggestions?

Add extra supply decoupling capacitors. The motor generates interference that resets the processor.

Grumpy_Mike:
Add extra supply decoupling capacitors. The motor generates interference that resets the processor.

Where do I add the capacitors, and what value should I use?

Currently, the battery connects to a LM7805 voltage regulator, then the servos and the VCC of the arduino board are connected to the regulated side. The motor controller is on a shield, and uses VCC from the arduino to power the motors, which are 4.5v motors from a Tamiya tank tread kit.

When running in manual mode - the robot never resets I can tell it to do anything I want to - turn, go forward, scan the eye, etc.. and it does not reset. Only when running in automatic mode does the processor reset, which is why I thought originally that the problem must be software related, since the reset doesn't happen in manual mode - I thought that the motors were not causing problems. I am probably wrong on this...

When running in manual mode - the robot never resets

New information.
In which case it is probbly your software that is at fault. Probbly running out of SRAM.

alphamale:

Grumpy_Mike:
Add extra supply decoupling capacitors. The motor generates interference that resets the processor.

When running in manual mode - the robot never resets

Open mouth, insert foot..

Of course as soon as I post this, I get it to do a reset while running in manual mode as well. It seems that the resets are somehow linked to startup of the DC motors. Not every time, but sometimes when the robot first starts to move, or changes direction (especially if the motor is experiencing higher than normal load - I hadn't ever tried it on an inclined surface before tonight..), the reset is occurring. The motor shield has a 100uF 35V capacitor from VCC to GND, do I need to increase this? Or do I need to add a capacitor from the regulated side of the LM7805 to GND? (If the latter, how big?)

I can disconnect the motor shield VCC from the arduino VCC. If I did this, would it help the problem to give the arduino the full 7.4V from the battery and let it's own internal regulator handle the microprocessor board, and let the 7805 I have power the motor shield and servos?

Currently, the battery connects to a LM7805 voltage regulator, then the servos and the VCC of the arduino board are connected to the regulated side.

Even though you're using small servos, it's not a good idea to power them from the
Arudino 5V v.reg, first, due to current considerations, and secondly due to motor
noise from the servos possibly disrupting the Arduino.

You could power the servos from your 7.2V battery using a series diode or two, 1N400X,
to drop the voltage.

Secondly, can you indicate which Arduino board, motor shield, and motors you're using.
How much motor current? It's not uncommon for uC boards to glitch when run off the
same battery as the motors, etc. Some people do this, but usually use so-called brown-out
ckts = a diode on Vin followed by a "large" value electrolytic ahead of the v.reg.

Thirdly, under certain conditions, your motors might be resetting the Arduino. I might
first try disconnecting the servos, and powering the Arduino from a 2nd battery to see
if that fixes the problem.

Some shields may not be designed as well as they should be. IE, you need bypass cap and
a LARGE electrolytic at the point where the battery attaches to the shield to prevent
large voltage swings due to motor current fluctuations. This would be my first guess as
the problem. See, Main Capacitor section here,

http://www.4qdtec.com/pwm-01.html

Fourthly, at first glance your code looks good, and I don't see anything obvious, although
I would modularize the loop() function to make it easier to read. I doubt your code is
exceeding even 2KBytes of RAM, but there is a way to measure this. [someone knows how].

Fifthly, I'm not familiar with ServoTimer2 library, but tracked it down. For one thing,
you're passing floats to funtion ServoTimer2::write(int pulsewidth), which accepts ints.

https://code.google.com/p/arduino-ppm-servo/

I would either cast the parameter as an int, or just use * 11 / 2, instead of 5.5, rather
than relying on the compiler to do the type conversion invisibly.

1 Like

Thanks for all the help, looks like it was a power issue after all. I took the VCC from the motor shield and arduino and seperated them, giving th arduino 7.4V straight from the battery, and fed the motor shield through my other LM7805 regulator. Now my servos and motor shield are powered from one LM7805 (with a heatsink on it) and the arduino powers itself. The robot ran around for almost 10 minutes without a glitch. I appreciate you guys for pointing me in the right direction and giving me some pointers that will undoubtedly make the code more efficient.

Problem is (for now) solved.

1 Like

Yeah, the other thing I forgot to mention was "star grounding", but you basically discovered
the idea on your own, ;-).
http://www.lh-electric.net/tutorials/gnd_loop.html