In this post I describe the Bot Application Framework that I have prepared for the Digilent Arty S7 based bot and provides an overview of the Arty S7 Bot Application Framework, its architecture, components, and usage model.
This post is part 7 of my contribution to the "7 Ways to Leave Your Spartan-6" program, learning about the Xilinx Spartan-7 FPGA on the Digilent Arty S7 50 board.
Short video demonstrating the main driving functions using the Arty S7 Bot Framework
Hardware and Development Environment
For this Bot Application Framework you'll need, Windows 10, AMD Xilinx Vivado ML 2021.1 and the following hardware:
Product Name | Manufacturer | Datasheet |
Arty S7 50 | Digilent | Buy Now |
TI-RSLK | element14 | Buy Now |
PmodOLED | Digilent | Buy Now |
Components and Architecture of the Bot Application Framework
The Bot Application Framework is a Hardware Abstraction Layer (HAL) that provides a function API-based service to higher-level layers that allows them to perform hardware-oriented operations independent of the actual details of the hardware.
The figure shows a representative block diagram of the Bot Application Framework in relation with a possible custom application for the bot
The Driving Driver depends on:
- Motor Position Driver;
- Speed PID Controller;
- Distance PID Controller;
- Motor PWM Speed Controller;
- and the H-Bridge Drive
Framework configuration
The Bot Application Framework is highly customizable.
You can configure the bot parameters with the bot_parameters.h header file depending on your FPGA configuration.
- AXI GPIO Address and Channel for the 2 board RGB LEDS
- AXI GPIO Address and Channel for the 4 board red LEDS
- AXI GPIO Address and Channel for the 4 board switches
- AXI GPIO Address and Channel for the 4 board push buttons
- AXI GPIO Address and Channel for the 4 dual hbridge control signals
- Right Motor Timer /Counter Device ID
- Left Motor Timer /Counter Device ID
- Motor Speed PWM Control signal period in nanoseconds
- Motor position feedback AXI Base Address
- Gear box motor ratio
- Motor Position Module Clock Frequency
- OLED AXI LITE GPIO Base Address
- OLED AXI LITE SPI Base Address
- OLED white background or black background
- Proportional Constant for the Rotational Motor Speed PID control
- Integral factor for the Rotational Motor Speed PID control
- Derivative factor for the Rotational Motor Speed PID control
- Proportional factor for the Traveled Distance PID control
- Integral factor for the Traveled Distance PID control
- Derivative factor for the Traveled Distance PID control
- Base duty cycle, base speed for the PID controllers
- Distance correction factor when rotating
- Distance correction factors when driving straight
Framework Drivers
The Bot Application Framework provides several drivers that allows to perform hardware-oriented operations independent of the actual details of the hardware.
- Bot Driver: Initializes the whole framework or specific parts of the framework.
- Driving Driver : Functions to drive the bot: forward, backward, turn left. turn right and swinging on both wheels
- Motor Position: Keep track of motor rotation counters.
- Speed PID Controller: PID control with goal of maintaining the same target speed for both wheels
- Distance PID Controller: PID control with goal of maintaining the same traveled distance for both wheels
- Motor PWM Speed Controller: Motor Speed controller Controls with Pulse Width Modulated signals
- H-Bridge Driver: Control motor direction and sleep mode
- Buttons Driver: Driver to poll to the four board buttons state
- Switches Driver: Driver to poll to the four board switches state
- Leds Driver: Driver to control the four board red leds state
- RGB Leds Driver: Driver to control the four board RGB leds state
- OLED Extensions: Functions to extend OLED Driver as displaying integers and floats
- OLED Driver: Functions to control the OLED display
Bot Driver
Initializes the whole framework or specific parts of the framework.
- BOT_init()
- BOT_init_driving_driver()
- BOT_init_gpio_inputs()
- BOT_init_gpio_outputs()
- BOT_init_oled_display()
Driving Driver
Functions to drive the bot: forward, backward, turn left. turn right and swinging on both wheels
- DRIVING_DRIVER_end()
- DRIVING_DRIVER_init()
- DRIVING_DRIVER_drive_backward_cm()
- DRIVING_DRIVER_drive_backward_continuous_cm()
- DRIVING_DRIVER_drive_forward_cm()
- DRIVING_DRIVER_drive_forward_continuous_cm()
- DRIVING_DRIVER_set_speed()
- DRIVING_DRIVER_swing_turn_left_degrees()
- DRIVING_DRIVER_swing_turn_right_degrees()
- DRIVING_DRIVER_turn_left_continuous_degrees()
- DRIVING_DRIVER_turn_left_degrees()
- DRIVING_DRIVER_turn_right_continuous_degrees()
- DRIVING_DRIVER_turn_right_degrees()
Motor Position Driver
Keep track of motor rotation counters.
- MOTOR_POSITION_clear_pos_counter()
- MOTOR_POSITION_clear_speed_counters()
- MOTOR_POSITION_get_distance_traveled()
- MOTOR_POSITION_get_edge_counts()
- MOTOR_POSITION_get_position_difference()
- MOTOR_POSITION_get_positions()
- MOTOR_POSITION_get_speeds()
- MOTOR_POSITION_init()
Speed PID Controller
PID control with goal of maintaining the same target speed for both wheels
- SPEED_PID_CONTROLLER_init()
- SPEED_PID_CONTROLLER_reset_errors()
- SPEED_PID_CONTROLLER_get_new_outputs()
- SPEED_PID_CONTROLLER_set_duty_cycle()
Distance PID Controller
PID control with goal of maintaining the same traveled distance for both wheels
- DISTANCE_PID_CONTROLLER_get_new_outputs()
- DISTANCE_PID_CONTROLLER_init()
- DISTANCE_PID_CONTROLLER_reset_errors()
- DISTANCE_PID_CONTROLLER_set_duty_cycle()
Motor PWM Speed Controller
Motor Speed controller Controls with Pulse Width Modulated signals
- PWM_DRIVER_disable()
- PWM_DRIVER_enable()
- PWM_DRIVER_get_duty_pct()
- PWM_DRIVER_get_period_ns()
- PWM_DRIVER_init()
- PWM_DRIVER_set_duty_pct()
- PWM_DRIVER_set_period_ns()
H-Bridge Driver
Control motor direction and sleep mode
- HBRIDGE_DRIVER_get_hbridge_state()
- HBRIDGE_DRIVER_init()
- HBRIDGE_DRIVER_left_motor_backward()
- HBRIDGE_DRIVER_left_motor_direction_toggle()
- HBRIDGE_DRIVER_left_motor_forward()
- HBRIDGE_DRIVER_right_motor_backward()
- HBRIDGE_DRIVER_right_motor_direction_toggle()
- HBRIDGE_DRIVER_right_motor_forward()
- HBRIDGE_DRIVER_set_direction()
- HBRIDGE_DRIVER_set_hbridge_state()
Board Buttons Driver
Driver to poll to the four board buttons state with unbouncing function
- BUTTONS_DRIVER_button1_pressed()
- BUTTONS_DRIVER_button2_pressed()
- BUTTONS_DRIVER_button3_pressed()
- BUTTONS_DRIVER_button4_pressed()
- BUTTONS_DRIVER_get_state()
- BUTTONS_DRIVER_init()
- BUTTONS_DRIVER_poll()
- BUTTONS_DRIVER_reset()
Board Switches Driver
Driver to poll to the four board switches state with unbouncing function
- SWITCHES_DRIVER_get_state()
- SWITCHES_DRIVER_init()
- SWITCHES_DRIVER_poll()
- SWITCHES_DRIVER_poll_switch1()
- SWITCHES_DRIVER_poll_switch2()
- SWITCHES_DRIVER_poll_switch3()
- SWITCHES_DRIVER_poll_switch4()
Board Red Leds Driver
Driver to control the four board red leds state
- LEDS_DRIVER_get_leds_state()
- LEDS_DRIVER_init()
- LEDS_DRIVER_set_led1_off()
- LEDS_DRIVER_set_led1_on()
- LEDS_DRIVER_set_led1_toggle()
- LEDS_DRIVER_set_led2_off()
- LEDS_DRIVER_set_led2_on()
- LEDS_DRIVER_set_led2_toggle()
- LEDS_DRIVER_set_led3_off()
- LEDS_DRIVER_set_led3_on()
- LEDS_DRIVER_set_led3_toggle()
- LEDS_DRIVER_set_led4_off()
- LEDS_DRIVER_set_led4_on()
- LEDS_DRIVER_set_led4_toggle()
- LEDS_DRIVER_set_leds_state()
Board RGB Leds Driver
Driver to control the four board RGB leds state
- RGB_LEDS_DRIVER_get_rgb_leds_state()
- RGB_LEDS_DRIVER_init()
- RGB_LEDS_DRIVER_set_rgb_led1_blue_off()
- RGB_LEDS_DRIVER_set_rgb_led1_blue_on()
- RGB_LEDS_DRIVER_set_rgb_led1_blue_toggle()
- RGB_LEDS_DRIVER_set_rgb_led1_green_off()
- RGB_LEDS_DRIVER_set_rgb_led1_green_on()
- RGB_LEDS_DRIVER_set_rgb_led1_green_on()
- RGB_LEDS_DRIVER_set_rgb_led1_green_toggle()
- RGB_LEDS_DRIVER_set_rgb_led1_red_off()
- RGB_LEDS_DRIVER_set_rgb_led1_red_on()
- RGB_LEDS_DRIVER_set_rgb_led1_red_toggle()
- RGB_LEDS_DRIVER_set_rgb_led1_set_color()
- RGB_LEDS_DRIVER_set_rgb_led2_blue_off()
- RGB_LEDS_DRIVER_set_rgb_led2_blue_on()
- RGB_LEDS_DRIVER_set_rgb_led2_blue_toggle()
- RGB_LEDS_DRIVER_set_rgb_led2_green_off()
- RGB_LEDS_DRIVER_set_rgb_led2_green_on()
- RGB_LEDS_DRIVER_set_rgb_led2_green_toggle()
- RGB_LEDS_DRIVER_set_rgb_led2_red_off()
- RGB_LEDS_DRIVER_set_rgb_led2_red_on()
- RGB_LEDS_DRIVER_set_rgb_led2_red_toggle()
- RGB_LEDS_DRIVER_set_rgb_led2_set_color()
- RGB_LEDS_DRIVER_set_rgb_leds_state()
OLED Extensions
Functions to extend OLED Driver as displaying integers and floats
- OLED_putFloatVariable()
- OLED_putIntVariable()
Usage Model
Initialization using Driving Drivers, Led Driver and Buttons Driver
void test_bot() { BotDrivers botDrivers; xil_printf("BOT TEST Started\n\r"); BOT_init(&botDrivers); while (1) { LEDS_DRIVER_set_led1_toggle(&botDrivers.ledsDriver); oled_show_home(&botDrivers.oled, " PRESS BUTTON"); if (BUTTONS_DRIVER_button1_pressed(&botDrivers.buttonsDriver)) { play_button_1_show(&botDrivers.drivingDriver, &botDrivers.oled); BUTTONS_DRIVER_reset(&botDrivers.buttonsDriver); } if (BUTTONS_DRIVER_button2_pressed(&botDrivers.buttonsDriver)) { play_button_2_show(&botDrivers.drivingDriver, &botDrivers.oled); BUTTONS_DRIVER_reset(&botDrivers.buttonsDriver); } if (BUTTONS_DRIVER_button3_pressed(&botDrivers.buttonsDriver)) { play_button_3_show(&botDrivers.drivingDriver, &botDrivers.oled); BUTTONS_DRIVER_reset(&botDrivers.buttonsDriver); } usleep(5000); } DRIVING_DRIVER_end(&botDrivers.drivingDriver); OLED_End(&botDrivers.oled); xil_printf("BOT TEST Finished\n\r"); OLED_End(&botDrivers.oled); }
Driving the bot
void play_button_3_show(DrivingDriver* botDriver, PmodOLED* oled) { xil_printf("BTN2 pressed\n\r"); sleep(1); oled_show_action(oled, " SWING LEFT 90"); DRIVING_DRIVER_swing_turn_left_degrees(botDriver, 90); usleep(50000); oled_show_action(oled, " FORWARD 7 cm"); DRIVING_DRIVER_drive_forward_cm(botDriver, 7); usleep(50000); oled_show_action(oled, " TURN RIGHT 90"); DRIVING_DRIVER_turn_right_degrees(botDriver, 90); usleep(50000); oled_show_action(oled, " FORWARD 7 cm"); DRIVING_DRIVER_drive_forward_cm(botDriver, 7); usleep(50000); sleep(1); oled_show_action(oled, " TURN RIGHT 90"); DRIVING_DRIVER_swing_turn_right_degrees(botDriver, 90); usleep(50000); oled_show_action(oled, " FORWARD 7 cm"); DRIVING_DRIVER_drive_forward_cm(botDriver, 7); usleep(50000); oled_show_action(oled, "TURN LEFT 90"); DRIVING_DRIVER_turn_left_degrees(botDriver, 90); usleep(50000); oled_show_action(oled, " FORWARD 7 cm"); DRIVING_DRIVER_drive_forward_cm(botDriver, 7); usleep(50000); sleep(1); }
Using only LEDs and push buttons
void test_leds_and_buttons() { LedsDriver ledsDriver; RgbLedsDriver rgbLedsDriver; ButtonsDriver buttonsDriver; SwitchesDriver switchesDriver; XGpio GpioLedsAndRgbLeds; /* Dual GPIO Driver for LEDs and RGB LEDS*/ XGpio GpioSwitchsAndButtons; /* Dual GPIO Driver for Switchs and Push Buttons */ LEDS_DRIVER_init(&ledsDriver, &GpioLedsAndRgbLeds, BOT_LEDS_RGBLEDS_DEVICE_ID, BOT_LED_CHANNEL, 0b0000); RGB_LEDS_DRIVER_init(&rgbLedsDriver, &GpioLedsAndRgbLeds, BOT_LEDS_RGBLEDS_DEVICE_ID, BOT_RGB_LED_CHANNEL, 0b000000); BUTTONS_DRIVER_init(&buttonsDriver, &GpioSwitchsAndButtons, BOT_BUTTONS_SWITCHES_DEVICE_ID, BOT_BUTTONS_CHANNEL); SWITCHES_DRIVER_init(&switchesDriver, &GpioSwitchsAndButtons, BOT_BUTTONS_SWITCHES_DEVICE_ID, BOT_SWITCHES_CHANNEL); unsigned long semiperiod = 250000; xil_printf("LED TEST Started\n\r"); LEDS_DRIVER_set_led1_toggle(&ledsDriver); usleep(semiperiod); LEDS_DRIVER_set_led1_toggle(&ledsDriver); usleep(semiperiod); LEDS_DRIVER_set_led2_toggle(&ledsDriver); usleep(semiperiod); LEDS_DRIVER_set_led2_toggle(&ledsDriver); usleep(semiperiod); LEDS_DRIVER_set_led3_toggle(&ledsDriver); usleep(semiperiod); LEDS_DRIVER_set_led3_toggle(&ledsDriver); usleep(semiperiod); LEDS_DRIVER_set_led4_toggle(&ledsDriver); usleep(semiperiod); LEDS_DRIVER_set_led4_toggle(&ledsDriver); usleep(semiperiod); RGB_LEDS_DRIVER_set_rgb_led1_set_color(&rgbLedsDriver, COLOR_RED); usleep(semiperiod); RGB_LEDS_DRIVER_set_rgb_led1_set_color(&rgbLedsDriver, COLOR_GREEN); usleep(semiperiod); RGB_LEDS_DRIVER_set_rgb_led1_set_color(&rgbLedsDriver, COLOR_BLUE); usleep(semiperiod); RGB_LEDS_DRIVER_set_rgb_led1_set_color(&rgbLedsDriver, COLOR_CYAN); usleep(semiperiod); RGB_LEDS_DRIVER_set_rgb_led1_set_color(&rgbLedsDriver, COLOR_MAGENTA); usleep(semiperiod); RGB_LEDS_DRIVER_set_rgb_led1_set_color(&rgbLedsDriver, COLOR_MAGENTA); usleep(semiperiod); RGB_LEDS_DRIVER_set_rgb_led1_set_color(&rgbLedsDriver, COLOR_YELLOW); usleep(semiperiod); RGB_LEDS_DRIVER_set_rgb_led1_set_color(&rgbLedsDriver, COLOR_WHITE); usleep(semiperiod); RGB_LEDS_DRIVER_set_rgb_led1_set_color(&rgbLedsDriver, COLOR_BLACK); usleep(semiperiod); RGB_LEDS_DRIVER_set_rgb_led2_set_color(&rgbLedsDriver, COLOR_RED); usleep(semiperiod); RGB_LEDS_DRIVER_set_rgb_led2_set_color(&rgbLedsDriver, COLOR_GREEN); usleep(semiperiod); RGB_LEDS_DRIVER_set_rgb_led2_set_color(&rgbLedsDriver, COLOR_BLUE); usleep(semiperiod); RGB_LEDS_DRIVER_set_rgb_led2_set_color(&rgbLedsDriver, COLOR_CYAN); usleep(semiperiod); RGB_LEDS_DRIVER_set_rgb_led2_set_color(&rgbLedsDriver, COLOR_MAGENTA); usleep(semiperiod); RGB_LEDS_DRIVER_set_rgb_led2_set_color(&rgbLedsDriver, COLOR_MAGENTA); usleep(semiperiod); RGB_LEDS_DRIVER_set_rgb_led2_set_color(&rgbLedsDriver, COLOR_YELLOW); usleep(semiperiod); RGB_LEDS_DRIVER_set_rgb_led2_set_color(&rgbLedsDriver, COLOR_WHITE); usleep(semiperiod); RGB_LEDS_DRIVER_set_rgb_led2_set_color(&rgbLedsDriver, COLOR_BLACK); usleep(semiperiod); while (!BUTTONS_DRIVER_button3_pressed(&buttonsDriver)) { LEDS_DRIVER_set_leds_state(&ledsDriver, BUTTONS_DRIVER_poll(&buttonsDriver)); RGB_LEDS_DRIVER_set_rgb_leds_state(&rgbLedsDriver, SWITCHES_DRIVER_poll(&switchesDriver) << 2 | SWITCHES_DRIVER_poll(&switchesDriver)); } xil_printf("LED TEST Finished\n\r"); }
Github repository
Bot Application Framework Github Repository
Bot Framework documentation
See the complete framework library documentation:
Credits
Parts of the driving library are inspired on Arvin Tang's ArtyBot Library
References
Summary
It has been a long development. The libraries are quite extensive and cover all the hardware configured so far in the FPGA for our Bot.
This framework will allow us to carry out new experiments with our robot with less effort.