Pico Bot
Having recently discovered the new Raspberry Pi Pico W microcontroller (see my recent article), I was curious to learn how much of a mobile robot’s control and navigation code a Pico W might be able to manage. As a first step, I did a quick internet search and was thrilled to find this collision avoidance robot project by Dan McCreary. I built it and found it to be as advertised. Definitely very inexpensive and certainly simple enough to be an excellent project for a young student to explore using the Pico on a mobile robot. But its collision avoidance behavior is very primitive and it’s not able to drive in a straight line, owing to the subtle variations in friction between the 2 wheel motors. Yes, it’s true. The differential drive configuration (2 wheels, coaxially positioned) despite its popularity because of its simplicity of control and its ability to make very tight turns, has one big disadvantage: In order to drive straight, the two wheels need to be running at exactly the same speed. Unfortunately, this is not something that the cheap DC motors we typically use in our robotics projects are able to do well.
My goal for this project is to build a simple mobile robot that uses the Pico W’s capabilities to:
- improve on the performance of the collision avoidance robot
- enhance the ability to control it
However, the performance and control will certainly not be as elaborate and sophisticated as this DIY ROS robot which mimics the capabilities of a robotic vacuum cleaner, including the ability to draw its own map!
The mobile robot of this project has these goals:
- Includes a web-server that publishes a control interface accessible from any web browser through a WiFi connection.
- Has a 2-wheel differential drive configuration, incorporating a gear-motor with integral encoder at each wheel.
- Using the encoders, it “knows” where it is by keeping track of its own pose (its location coordinates and its angular orientation).
- Also using the encoders, it is capable of driving straight from a starting position to a destination position, stopping at a precise distance.
- Using its pose awareness, it can make precise turns to a goal angle.
- The project is easily extensible, allowing more sensors to be added and the ability to program new, more complex behaviors.
Now let’s explore how our mobile robot will accomplish these goals.
Adding Encoders to the motor shafts
As mentioned above, when we apply a voltage to a DC motor, we don’t know exactly what speed it will run at. This is because each motor has its own intrinsic friction characteristics. In order for our mobile robot to be able to drive straight forward and back, we must insure that the right and left motors are running at exactly the same speed. So in order to know the speed of each motor, a rotary encoder is installed on each motor. The encoder is comprised of a small magnetic disk mounted on the motor shaft. The disk has 11 salient magnetic poles around its perimeter. A fixed hall sensor is mounted near the disk and is triggered by each passing magnetic pole. (Actually, by using 2 hall sensors spaced 90 degrees apart, the encoder is able to distinguish which direction the disk is rotating.) By counting the ticks being generated by the encoders on each motor, it is a simple matter to calculate both pose and speed.
Odometry
Keeping track of the number of ticks generated by the right and left encoders allows the robot to keep track of its pose. (We assume that the robot hasn’t gotten stuck somewhere and is just “spinning its wheels”.)
Motor Speed Control using P I D feedback from encoders
We can also keep track of the rate of the encoder pulses, allowing us to calculate the speed of the motor, which we can then compare to the desired speed. If the actual speed is slower that the desired speed, we increase the voltage to the motor. If it is too fast, we decrease the voltage. This is the P term of what is known as a P I D closed loop feedback controller. It’s similar to the way the cruise control on your car works.
A P I D controller applies 3 distinct terms of trim to the motor voltage in order to achieve optimum performance.
- P (proportional) Adjusts voltage in proportion to the speed error.
- I (integral) Adjusts voltage in proportion to the integral of the speed error. This is the term that overcomes the sustained effect of friction causing a motor to run too slowly.
- D (derivative) Adjusts voltage in proportion to the derivative of the speed error. This term helps to prevent over-correction when error value is changing very quickly.
P I D + C controller
The P I D controller was successful in getting the mobile robot to drive in a straight line, but as the motors came up to speed, one of them can sometimes manage to get to speed sooner. As a result, the robot will drive in a direction slightly toward the side of the wheel that came up to speed more slowly. To correct this, I added a 4th term, C, to the controller to urge the difference in the accumulated counts of the 2 encoders toward zero.
- C (count difference) Adjusts voltage in proportion to the count difference between the two encoders.
The Python code
The Python code that runs on the Pico needs to be attentive to several things that are going on at once, so we have to make sure that these different tasks can all cooperate and that one task doesn’t hog the Pico when another task need its urgent attention. For example, the hall sensors of the encoders need to be connected to pins that can interrupt anything else that the Pico happens to be doing. Those pulses are coming at a rate of several thousand per second and we don’t want to miss a single one of them. Also, there are 2 forever loops running simultaneously:
- The web server is constantly listening for incoming web requests for the robot to do something.
- The main robot control loop is running at a rate of 10 times per second. Inside this loop we are checking the encoder values, calculating the robot’s current pose and controlling the motor speeds.
The MicroPython uasyncio module is used to set up these 2 tasks to run concurrently, cooperatively relinquishing the processor’s time while the other works through critical sections of code.
The Control Screen
I decided to use this 5-Button screen used by Christopher Barnatt in his Pi Pico W WiFi Controlled Robot. It’s simple and intuitive.
The Hardware
Mechanically, the heart of the Picobot is a pair of Wheel / Motor assemblies which I purchased from AliExpress. The motors have a 56:1 gearbox which seems just right when driving them with a 12 V LiPo battery. Also on the bottom is the L298N motor driver board. In addition to driving the motors with PWM signals from the Pico, it has a 5V power supply that provides power to the encoders and the Pico.
On the top, there is just the Pico W and an On/Off switch. I’m leaving space to put more gizmos on in the future. Meanwhile, if you want to dig deeper, there is more detail in my project notes at my GitHub repository.