Choosing motors for the Sketcher robot
In a previous post, I discussed my plan to construct a small robot capable of drawing shapes on paper. To achieve this, precise control over the robot's trajectory is essential. In order to keep the robot simple and cost-effective, I have decided not to employ any sensors for position tracking. Instead, the robot will operate with an open-loop control system, relying on the motors' operation to infer its position through a process known as "dead reckoning". However, it is important to note that with this method, errors are accumulating over time, resulting in the robot's trajectory diverging from the intended path.
In an effort to minimize these errors to an extend, I chose to use stepper motors to drive the wheels.
Stepper motors move in discrete steps, rather than continuously rotating like a conventional motor. This allows for precise control over the motor's rotation. Since the motor is directly connected to the wheel, the travel distance can be calculated based on the number of steps taken by the motor. For example, if the wheel has a circumference of 10 cm and the motor takes 100 steps to complete one revolution, then each step corresponds to a travel distance of 0.1 cm. We can use this information to determine how many steps are needed to move the robot a certain distance.
Uncertainties
Of course, even with stepper motors, there are always uncertainties that affect the robot's trajectory. There are various sources of uncertainty, such as wheel slippage, uneven surfaces, mechanical imperfections, and more. These uncertainties introduce small errors in the robot's position estimation. While these errors may be negligible on their own, they accumulate over time and can result in a significant deviation from the intended position. These errors are particularly significant when they affect the robot's orientation. Even a slight deviation in orientation can cause the robot to veer off course. In the context of this project, this deviation will cause the shapes to be distorted and, in the long run, they will not resemble the intended shape.
We can visualize this by building a simple python code that plots the robot's trajectory. We will give a series of movement commands to the robot, which will execute sequentially. Each command consists of the steps that each motor has to take. For calculating the robot's position and orientation I used the forward kinematics equation provided in this paper. I should note, that this is not a simulator and uncertainties were added randomly on each motor, just to demonstrate the effect of uncertainties on the robot's trajectory. I will not be using this code further in the project, but it is a good way to visualize the problem.
We will have the robot draw a house shape with an X in the middle as an experiment. On the first run, there are no uncertainties on the motors, so they move exactly as instructed. On the five subsequent runs, uncertainties are added. The video below shows the results.
As shown in the video, the house shape is recognizable, but distorted. Since uncertainty is added randomly, the results are different each time, some better that others. As mentioned, the longer the robot is moving, the more errors accumulate leading to worse results.
My goal is for the robot to be able to draw this house shape. If this happens I will consider this a success. I believe it is a reasonable goal. There are 7 turns (which is my main concern for inaccuracies) which I don't expect to throw the robot off track too much. But I will find out soon, after building the robot and testing it in real life.
Motor control
The motor I chose to use is 28byj-48. The price is very low, it has a small factor, and requires low currents from a 5V source. The torque is quite limited, but with a small modification it can be increased significantly. I went ahead and applied this modification on both motors.
I will use the A4988 driver to control each stepper motor. This allows to easily drive the motor by using two signals, STEP and DIRECTION. The STEP signal is used to move the motor one step, while the DIRECTION signal is used to control the direction of rotation. This way the driver is responsible for generating the necessary signals to drive the motor, simplifying the control process. I connected the pins 1A, 1B, 2A, 2B to the motor, powered pin VMOT with 5V and pin VDD with 3.3V. I used the 3V3 pin of ESP32 devkit board to power VDD.
Next I wrote the following code to test the motor's operation. The move_motor
function toggles the step signal at certain interval. Every time the step signal toggles, the motor makes one step. The interval between the toggles is what determines the speed of rotation.
from machine import Pin
import time
SPEED_FAST = 0.002
SPEED_SLOW = 0.008
DIR_CLOCKWISE = 1
DIR_ANTICLOCKWISE = 0
motor_step = Pin(14, Pin.OUT)
motor_dir = Pin(27, Pin.OUT)
motor_enable = Pin(12, Pin.OUT)
motor_enable.value(0)
motor_dir.value(0)
def move_motor(steps, direction, speed):
motor_dir.value(direction)
motor_enable.value(0)
for i in range(steps):
motor_step.value(not motor_step.value())
time.sleep(speed)
motor_enable.value(1)
move_motor(1000, DIR_CLOCKWISE, SPEED_FAST)
move_motor(1000, DIR_CLOCKWISE, SPEED_SLOW)
move_motor(1000, DIR_ANTICLOCKWISE, SPEED_SLOW)
move_motor(1000, DIR_ANTICLOCKWISE, SPEED_FAST)
while True:
pass
The code worked as expected, moving the motor back and forth. As shown in the code, the motor moves clockwise at a fast speed (relative term since the motor is inherently slow), then continues slowly, then reverses direction to anti-clockwise and turns slowly, and finally speeds up before finally stopping.
Now that we verified that the motor works as expected, the next step is to start putting together the hardware on a chassis and make it move around!