This wiki page will mainly discuss the top-layer code which is mostly contained within robot.c
.
The source code itself is divided into logical sections with the help of separate folders and files:
Control
Contains all the control-related code, about which more can be read in the Control section.FATFS
Middlewares
MTi
Is the library used to communicate with the IMU chip.oled
contains all the pages that can be displayed on the oled as well as two helper files. More info can be found at the oled pageperipherals
contains all the files needed in order to communicate with the elements in the robot like:Util
contains simple utility functions that are used throughout the top boardWirless
contains all the logic for interacting with the SX1280 chip, which is used for the wireless communicationiwdg.c
configures the watchdog timer, allowing the robot to reboot when it crashes.rem.c
handles the incoming REM packets that are coming over UART.robot.c
contains the main loop and all of the interrupts and times.A seperate page exist for the OLED
In wheels.c the low level code for the wheels is located. In here one can brake the wheels, which happens during bootup or when the robot is halting. If the wheels are not braking, the wheels speed can be set. This can either be done with setting PWM directly or giving a value between -1 and 1. The latter is preferred, as it is more readable. Besides setting the speed one can also compute the current wheel speed by reading the encoder located on each wheel.
This file that can more specifically be found in /Core/Src/top_board/robot.c
contains the main loop and the most important functions that are being used for all the tasks on the robot. Let's start with the initialization function
The void init()
function prepares the rest of the code and the hardware for operation. The most important steps that it takes are (in chronological order):
LEDs indicate different things, the table beneath shows what they mean during initialization.
LED # | |
---|---|
0 | Successfully read robot id & team |
1 | Finished playing beep-up tune and sending first log |
2 | Finished setting up control constants & booting up OLED screen |
3 | Initialized wireless communication |
4 | Initialized IMU |
5 | Finished playing tunes if in test-mode |
6 | Initialized MCP and checked if other boards are alive |
7 | Unused |
After the initialization has completed, the main loop located in void loop()
will start running. The most important steps that it takes are:
After initialization the LEDs indicate different things, than during initialization.
LED # | Definition |
---|---|
0 | Toggled every second, indicating that the robot is alive |
1 | On in case that the IMU is not yet calibrated |
2 | On when wheels are braking |
3 | On when halting |
4 | On if dribbler is on (not necessarily spinning) |
5 | On if SD card is initialized |
6 | Toggled every time the robot receives a REM packet |
7 | Toggled every time the top board receives a MCP packet |
Once a packet comes in, 4 conditions are checked. Namely, valid packet type, rem version, robot id, and payload size. If these are all correct the packet is stored. There are multiple checks to minimize the chance that random noise gets stored. After handling the incoming packet, an already prepared packet is immediately send back. This needs to be done ASAP as the basestation only has a certain amount of time per robot to communicate before trying with the next robot.
Although the datasheet for the SX1280/81 gives a range of 2.4GHz-2.5GHz, frequencies above 2.3GHz area also supported.
Once initialized, the robot will not drive under the following conditions: IMU not initialized or no packet received in the last 250ms. The exception on this are self-tests ran from the oled screen.
Every 100Hz the control loop is executed. In this loop the state estimation is updated, the wheel speed is calculated, and the wheel speed is set. Finally the feedback and stateInfo is prepared.