Pololu 3pi Robot User Manual
Page 40
• Increasing the line-following speed.
• Improving the line-following PID constants.
• Increasing turning speed.
• Identifying situations where the robot has gotten lost.
• Adjusting the speed based on what is coming up; e.g. driving straight through an ‘S’ at full speed.
The following video shows a 3pi prototype—it only has one blue power LED, but it is otherwise functionally identical
to the final version—that we programmed to compete in LVBots Challenge 4.0. The code is more advanced (and
complicated) than the sample maze-solving code we have just provided. Improvements over the sample program
include a higher base running speed with better-tuned line-following PID constants, faster and smoother turns, and
increased speed on long straight segments.
When we were trying to improve the 3pi’s maze performance, our first step was to improve its line-following ability
by better tuning the PID constants as we slowly increased the robot’s maximum speed, and our second step was to
improve the turns to be faster and smoother. Very quickly, however, we noticed that further speed improvement was
being limited by the intersections. If the robot was moving too quickly when it hit them, it would invariably screw
up somewhere. Going slowly enough to survive the intersections led to unnecessarily slow driving on long straight
segments, however.
Our solution was to time the length of every segment the robot encountered during the learning phase. The code
would reset the timer at an intersection and then stop it when the 3pi hit the following intersection. As the program
stored an array of visited intersections, it also stored the segment times in a parallel array, producing something like:
{ L, S, S, R, L, ... }
{ 3, 3, 6, 5, 8, ... }
The top array gives the action performed at each visited intersection (L = turned left, S = went straight, R = turned
right), and the bottom array gives the amount of time spent driving along the segment that directly led to that
intersection. The units of the segment times were chosen to provide numbers that can allow the robot to meaningfully
differentiate between longer and shorter segments but that never exceed 255 for any segment in the maze. This second
restriction means that the values can be stored in an array of unsigned chars (i.e. each segment’s time takes up just
one byte of memory), which helps keep memory usage down. The ATmega168 has just 1024 bytes of RAM, so it’s
important that applications like this store data in an efficient way that leaves enough room for the stack, which is also
stored in RAM. A good rule of thumb is to leave 300 – 400 bytes of RAM available for the stack and data used by
the Pololu AVR library (or more if you have some deeply nested functions or functions with a lot of local variables).
Note that the ATmega328 has 2048 bytes of RAM, which gives you a bit more room for your data.
Once the 3pi has learned the maze, the maze-driving algorigthm is essentially:
1. If the robot is going straight at the next intersection, drive the current segment at high speed; don’t even
worry about slowing down until we know we have an intersection coming up that will require a turn.
2. Otherwise, drive the current segment at high speed until time T has elapsed, at which point slow back down
to normal speed until the next intersection is reached.
The value T is computed from a function that uses the previously measured segment “length”. For short segments, T
is negative and the 3pi just drives the entire segment at normal speed. For longer segments, T is positive and causes
the 3pi to drive most of the segment at high speed before slowing down just in time to handle the intersection safely.
We came up with a function for T on paper and then ran a series of tests to get the various constants right.
Pololu 3pi Robot User's Guide
© 2001–2014 Pololu Corporation
8. Example Project #2: Maze Solving
Page 40 of 63