Mecanum wheel robots are fascinating because they have an unusual freedom of movement in every direction. M5Stack produces the "RoverC", which is controlled by an M5StickC (ESP32) and is therefore very easy to program. There are examples with a remote control, but I wanted to create a solution where you can program movement sequences from a mobile phone or a PC. The idea was to create a kind of game where the robot has to be controlled around a number of obstacles. But not with a remote control, but rather by programming movement commands via Bluetooth.
Due to the mecanum wheels, the RoverC can move in any direction without turning (The control of the wheels is explained in detail further below):
A commanded value for a specific direction causes the rover to move in that direction for a defined time. This allows a sequence of movements to be programmed by a sequence of directional values. That sounds complicated, but it is quite simple.
ExampleLets say that the following arena is given and that the rover has to be navigated from start to finish:
To reach the target without driving against the obstacles, the following movement sequence can be programmed:
0 45 90 180 135 90 0 0
The motion sequence can be programmed on the Rover via a Bluetooth serial Terminal which is available for Smartphones or PC.
And this is how the programmed motion looks like:
Establishing a Bluetooth serial connection with an ESP32 is quite simple:
Just include the BluetoothSerial.h header file and define an BluetoothSerial object:
#include <BluetoothSerial.h>
// the Bluetooth serial object
BluetoothSerial SerialBT;
uint64_t chipid;
char chipname[256];
Then, you will need a name for the Bluetooth device. This can be taken from the Chip ID of the ESP. With this ID the BluetoothSerial can be started and immediately it waits for a connection from a client.
// create the Bluetooth ID
//The chip ID is essentially its MAC address(length: 6 bytes)
chipid = ESP.getEfuseMac();
sprintf( chipname, "M5StickC_%04X", (uint16_t)(chipid >> 32));
// start Bluetooth
if(SerialBT.begin(chipname))
tb_display_print_String("[OK] Bluetooth Init\n");
else
tb_display_print_String("[ERR] Unable to start Bluetooth!\n");
Side note: The code uses my tb_display library to easily create text output on the M5StickC.
Within the state machine, the program waits for incoming characters from the Bluetooth Serial interface. The characters are collected, and each time a space character is received, the value that was sent is stored as a command. An asterisk character (or a timeout of 5 seconds) terminates the receive mode and starts the motion sequence.
while(SerialBT.available()){
int data = SerialBT.read();
// only numbers
if(isDigit(data)){
read_String += (char)data;
}
// space is the delimiter between direction codes
if(data == ' ' || (data == '*' && read_String != "")){
int value = read_String.toInt();
if(value >=0 && value <= 360){
code_queue_add(value);
}
read_String = "";
}
// * is the start command for the motion sequence
if(data == '*'){
tb_display_print_String("\n-START-\n");
process_state = ps_run_program;
}
}
To save the commands a <int> queue from the standard C++ library was used. This is located in a separate.h and.cc file to avoid conflicts with the namespace.
// define the queue object
std::queue<int> Command_queue;
During the motion sequence, the top element is fetched from the queue as the new command until the queue is empty:
// proceed all commands out of the queue
// code_queue_get() returns false if the queue is empty
while(code_queue_get(&value)){
snprintf(String_buffer, sizeof(String_buffer), "--> %i\n", value);
tb_display_print_String(String_buffer);
// The function move_rover() also includes the acceleration.
// Therefore it can take a different amount of time to proceed.
move_rover(value, 50);
// let the rover move for 250ms (excluding the acceleration phase)
delay(250);
}
rover_stop();
tb_display_print_String("\n-FINISH-\n");
How to connect to the RobotFirst, download and install a Bluetooth Serial Terminal App on your PC or Smartphone.
Then, you need to pair your device with the M5StickC like you will do with any other Bluetooth device:
Now, you can start the Bluetooth Serial Terminal, connect to the Robot and send Movement commands separated by spaces and with an asterisk at the end of the list.
When rotating forward, a normal wheel produces a force that points exactly in the direction of travel. Due to the arrangement of the individual drums, a mecanum wheel produces a force that is directed diagonally forward at 45 degrees. Same for backward rotations as shown in the following picture:
For the whole RoverC the layout is as follows:
What we need now is a function that calculates the values for the four motor speeds based on the desired direction of movement and the desired speed. To do this, we have to break down the desired direction of movement into the components vx and vy:
If we now look again at the resulting force directions of the wheels in relation to the base coordinate system, we can calculate the required speed for each motor:
And that's it. The only thing left to consider is an acceleration ramp for the motors. If you switch the motors directly from 0 to 100, the robot will jump and definitely lose its track. In the code, a simple ramp function accelerates the rover slowly, so that it stays better on the lane.
FeedbackI hope you enjoy the rover and this code can prove to be useful to some of you. Feel free to message me here if you have questions or comments.
Enjoy!
Regards,
Hans-Günther
Comments