We've now reached the point where all the separate components of the rover can come together to form something greater than the sum of its parts. The chassis is required as a physical platform for mounting our hardware such as motors and of course the EDP which holds the brains of the rover - the mbed. After this we saw the quadrature encoders give us control over the position of the wheels, and the PID controller allowed us to control the speed of the wheel. The inertial measurement and orientation filter also allowed us to determine what direction we were facing and we could use this to make precise turns.
Now we are able to pull in all of this functionality into a single application.

(The five simple states of the rover)
The original rover class simply consisted of the RS-EDP Brushed Motor Control Application Module Library which was used to drive the motors in open loop; that is without any feedback from sensors. This was required to get things up and running and convince myself I could control the motors with the brushed motor module.
As different components were finished, new functionality such as moving precise distances was added, and interrupt routines were created to ensure appropriate action was taken along the way to achieving a set goal.
However, as the functionality increased, so did the complexity and soon all sorts of interrupt routines were required for rotating, position control, velocity control, reading intertial sensors and so on. The current structure was becoming far too bloated and certainly wasn't scalable, not only for the immediate future but also in terms of extending the class itself to different applications.
Instead the idea of a state machine was introduced. Instead of having lots of different interrupts requiring servicing in different methods, there would be one main interrupt routine that would take action appropriate to the state the rover was in. This would greatly reduce complexity by having similar code in the same place, and also make the whole system a lot more extensible through the easy addition of new states.
At the moment the rover only implements five basic states: 1. Moving Forward, 2. Moving Backward, 3. Rotating Clockwise, 4. Rotating Counter-Clockwise, 5. Stationary These five primitives can used one after the other to allow the rover to navigate simple paths. In the future new states such as Following Line or Avoiding Obstacles could be introduced to further enhance the rover's applications.
The following represents an overview what happens in main method of the rover application class; a link to full source code listings will be presented in the next blog post.
1. Initialization
- Create a Rover object setting the appropriate pins for PWM, brake and direction on the motor control application modules
- The Rover class will initialize the motor control application modules in its constructor, as well as setting up two PID controllers (one for the left and right motors respectively) with tuning parameters that are #defined in the Rover header file. Class attributes used for internal calculations will be initialized, along with the quadrature encoder interfaces for each wheel.
- The final part of the constructor sets the state to Stationary, and sets up ticker interrupts to log orientation and position data, and perform the appropriate state action.
2. Reading Commands
- The movment commands are contained in a simple text file on the mbed, with statements such as "move forward 3000", "turn right 90". The main method parses these commands and calls the appropriate method in the Rover class which enters the appropriate state.
3. State Based Action
The main method waits until the Rover has returned to a Stationary state before issuing the next command. The Rover calls the method which takes state based action from a ticker interrupt about 100 times per second.
3.1 Moving Forward and Backward
Upon entering the Moving Forward or Moving Backward state, a position set point is set for how many pulses the encoders should detect before the Rover moved the desired distance. Each iteration of the state action interrupt causes the Rover to update the PID controllers' process variables to perform velocity control on the motors. After the Rover reaches the set point it returns to the Stationary state.
3.2 Rotating Clockwise and Counter-Clockwise
The rotating states are similar to the Moving Forward/Backward states - they receive a heading set point to hit which is checked with the current heading as measured by the IMU. Velocity control is still used to control the motors although now they are running in opposite directions to cause rotation and they also run much slower to ensure the angle turned isn't overshot by rotating too fast and missing readings from the IMU.
3.3 Stationary
This is the simplest state to service - we just do nothing and wait to receive a new command which will put us into the right state!
My next post will wrap things, presenting conclusions, source code and a video of the rover in action. A final post will be made after this with supporting documents such as a bill of materials, schematics etc.
Other posts in this series:
1. Introduction
2. Chassis
3. Quadrature encoders
4. PID velocity control
5. Inertial measurement unit
6. Rover State Machine
7. Conclusion
8. Technical Details