Firmware - focusrobotics/explorer GitHub Wiki
Motor Controller Firmware Architecture
Controller
The controller class is instanced by the top level program and manages input from the top level computer (the raspberry pi). I've implemented two controllers at this point, the first one understands the protocol for a bluetooth joystick app that I could run on my tablet and is called JoystickCtl. The second controller is intended to be used with the Raspberry Pi and reads JSON formatted messages from the serial port. It's called JsonCtl.
Robot Program
The controller can have one or more robot program classes that it manages. The reason to do things this way is that the controller could interpret certain commands to choose which program to run so that a user can have a simple remote control program to position the robot and then switch to a semi-autonomous or maybe just more complex program for testing. This seemed like an easier way to debug as I was writing more and more complicated code in the microcontroller.
The robot program has a virtual base class (RPBase) and then a couple implementations. (RPManual and RPManualMotion so far) The common base class is so that the controller class can treat any robot program instance the same as it switches between them and not have to know the details of each one.
Motor
There is a motor control base class with multiple derived classes. This is because the motor control class has to know the details of the motor driver board and I've used this firmware for a couple different robots, each with different motor driver boards. MotorPair is the base class and AFMS_MotorPair is the derived class to control the Adafruit motor controller while VNH5019_MotorPair works with the Pololu motor driver board that I'm actually using for Explorer.
The RPManual robot program class only uses the MotorPair class. All it does is take control inputs from the user interface and turn them into motor power values. It ignores the higher level encoder and motion/PID control classes below and would ignore bump and IR sensors which I intend to integrate later.
Encoder
The encoder class just counts ticks from the encoders on each wheel. I probably will switch that to using a base class and derived classes as well because different robots use different encoders and different microcontroller can track the encoders in different ways, sometimes with polliing for value changes, sometimes with interrupts, and sometimes with dedicated hardware.
Odometry
The Odometry class combines tick counts from the encoder with physical information about the robot (wheel diameter, configuration, baseline) and time information to calculate velocity, acceleration, and relative x/y position from an arbitrary starting point.
Motion
The motion class uses a PID controller and odometry information to create more accurate robot movements. When it is in use it drives the motor class directly so that motor power is varied based on actual velocity so that velocity can be kept constant regardless of the surface or incline that the robot is navigating.
Build and Run
PIO setup
STM32F411
Mega 2560
Resources
Encoder
I want to have a very accurate encoder for this project so that I can make use of the odometry for SLAM and other things. The motors have a built in quadrature encoder and I want the firmware to make use of it. The stm32 has hardware support for quadrature encoders and I want to use that (when I have switched to the stm32) but I haven't done that before so I might take multiple steps to get there. Here is on page on just using normal ISRs to deal with quadrature encoders in stm32: https://electronics.stackexchange.com/questions/99915/stm32-rotary-encoder-with-hardware-interrupts