Introduction: SnappyXO Precise Mover Robot

Make your Arduino robot go straight for a specified distance or twist to a specified angle using the PreciseMovement Arduino library.

The robot needs a rolling ball caster or equivalent to minimize friction while twisting.

You can tell the robot to go forward to a specified distance or twist to a specified angle. The program determines its position using dead reckoning. Since the position estimates rely only on the wheel velocity, slippage will induce considerable error. The designer of the robot should be careful to minimize the risk of slippage.

This has been tested to work with the SnappyXO robot.

Step 1: Tutorial Location Changed

The tutorial has been moved to the page below. This tutorial is no longer maintained.

Step 2: Build the SnappyXO Differential Drive Robot

The PreciseMovement library that we will be using is only compatible with differential drive robots. You can choose to use other 2 wheel drive robots.

Step 3: Connect the Electronics

For the standard SnappyXO Optical Encoder:

D0 (encoder output) -> Arduino Digital Pin

VCC -> Arduino 5V


Motor and Arduino Power:

The motor power source should be adequate for the motors your using. For the SnappyXO kit, 4AA batteries are used for the motor power and 9V battery for the Arduino power. Make sure that they all have a common GND.

Step 4: Install PreciseMovement Arduino Library

Step 5: Code

Arduino Code:

These parameters require adjustment. Other parameters labeled recommended on the code can be adjusted for better performance.

  • Check and set the motor pins under ARDUINO PINS.
  • Set LENGTH and RADIUS.
    • LENGTH is the distance from the left wheel to the right wheel.
    • RADIUS is the radius of the wheel.
  • Set PULSES_PER_REV, which is the number of pulses the encoder outputs for one wheel revolution.
    • Note this is different from the number of pulses the encoder outputs for one motor shaft revolution unless the encoders are connected to read directly from the wheel shaft.
    • PULSES_PER_REV = (pulses per one revolution of motor shaft) x (gear ratio)
  • Set STOP_LENGTH if you see that the robot is overshooting after the forward movement.
    • The robot will stop once the estimated position is STOP_LENGTH away from the target. Thus, the STOP_LENGTH, is the approximate distance required for the robot to come to a stop.
  • PID parameters
    • KP_FW: This is the proportional component of the forward motion. Increase this until the robot goes straight. If you can't get it to go straight by tuning this, then the hardware is likely at fault. (eg. wheel misalignment, etc)
    • KP_TW: This is the proportional component of the twisting motion PID. Simply start from a low value and increase this until the twist speed, or the angular velocity of the robot while twisting, is fast enough, but does not cause overshoot. To make observations, you can have the robot alternate from 0 to 90 and back by inserting the following in the loop function.

Place this in loop to tune KP_FW:


Place this in loop to alternate from 0 to 90 to tune KP_TW:

mover.twist(90); // Twist 90 CW


mover.twist(-90) // Twist 90 CCW


Note that in order to actually twist the angular velocity at TARGET_TWIST_OMEGA, the KI_TW also needs to be tuned since a proportional controller will never settle to the exact target. However, it's not necessary to twist at that exactly angular velocity. The angular velocity just needs to be slow enough.

Step 6: How It Works

If you're curious about how it works read on.

The forward movement is kept straight using the pure pursuit algorithm on a straight line path.
More on Pure Pursuit:

The twist PID controller tries to keep the twist angular velocity at TARGET_TWIST_OMEGA. Note that this angular velocity is the angular velocity of the entire robot not the wheels. Only one PID controller is used and the output is the PWM write speed of both the left and right motors. Dead reckoning is done to compute the angle. Once the angle reaches the error threshold, the robot stops.