Welcome to MicroROS V2 Robot Car repository
9. Drive Motors
Driving Motors
Experiment Objective
This section will guide you through driving DC geared motors with the MicroROS-V2 control board. Through this tutorial, you will learn how to use the ESP32-S3's MCPWM peripheral together with the bdc_motor component to control the forward/reverse direction and speed of the motors, implementing basic control such as acceleration, braking, and coasting stop.
Experiment Principle
1. Keywords
| Keyword | Description |
|---|---|
| DC Geared Motor | A DC motor with a built-in reduction gearbox that provides high torque; speed is controlled by regulating the voltage through PWM |
| MCPWM | The ESP32-S3's motor control PWM peripheral, which can configure multiple groups of timers and generators to drive DC motors together with the bdc_motor component |
| bdc_motor | Espressif's official DC motor driver component, which encapsulates MCPWM configuration and forward/reverse, brake, and coast control logic |
| Brake stop (STOP_BRAKE) | The motor coil is short-circuited, producing electromagnetic damping that stops the motor immediately |
| Coast stop (STOP_COAST) | The motor coil is disconnected, and the motor decelerates to a stop by inertia |
| Dead Zone | The region where the motor cannot rotate when the PWM duty cycle is too low; the code automatically adds a bias value (200) to cross the dead zone |
2. Technical Architecture
The program uses the ESP32-S3's MCPWM peripheral together with Espressif's official bdc_motor component to drive two DC geared motors (M1 and M2). M1 uses GPIO13 (PWM A) and GPIO14 (PWM B); M2 uses GPIO11 (PWM A) and GPIO12 (PWM B). The PWM frequency is 25KHz and the timebase resolution is 10MHz. The code implements logic direction mapping (M2 is inverted due to mirrored mounting), dead zone filtering, and limit protection, providing basic control functions such as forward, reverse, brake stop, and coast stop.
Main component files:
main/main.c— main program entry, demonstrates the forward / brake / reverse / coast cyclecomponents/pwm_motor/pwm_motor.c/pwm_motor.h— motor driver implementation and interface declarations
Experiment Steps
1. Hardware Preparation
| Hardware | Requirement |
|---|---|
| MicroROS-V2 control board | ✅ Required |
| USB data cable | ✅ Required (for power supply and serial monitor) |
| Battery (12V) | ✅ Required (to power the motor driver) |
| MicroROS-V2 chassis motors | ✅ Required (connected to motor interfaces M1 / M2) |
2. Prerequisites
ESP32-IDF development environment set up
MicroROS-V2 control board connected to the PC via USB
Battery connected to the control board power interface
Motor wiring description
The motor driver interfaces on the MicroROS-V2 control board are defined as follows:
| Motor interface | Pin A | Pin B |
|---|---|---|
| M1 | GPIO14 (PWMA) | GPIO13 (PWMB) |
| M2 | GPIO12 (PWMA) | GPIO11 (PWMB) |
Note: The physical wiring directions of M1 and M2 are opposite, which is already handled in the code through logic direction constants.
3. Compile and Flash
x
cd ~/esp/base_samples/pwm_motorsource ~/esp/esp-idf/export.shidf.py build flash monitor
After the program starts, the motors execute the following action cycle in sequence:
Motors rotate forward (forward direction) at maximum speed
Brake stop (STOP_BRAKE)
Motors rotate reverse (backward direction) at maximum speed
Coast stop (STOP_COAST)
Each state lasts 1 second and the cycle repeats.
4. How to Stop
Press Ctrl+] in the terminal to exit the serial monitor.
Experiment Result
After correctly flashing and running the program, the serial monitor outputs the following logs:
xxxxxxxxxxhello yahboomI (xxx) MAIN: Nice to meet you!I (xxx) PWM_MOTOR: Init PwmMotor DeviceI (xxx) MAIN: Motor ForwardI (xxx) MAIN: Motor Stop BrakeI (xxx) MAIN: Motor backwardI (xxx) MAIN: Motor Stop CoastI (xxx) MAIN: Motor Forward...
The DC motors connected to the M1 and M2 interfaces execute forward, brake stop, reverse, and coast stop in sequence according to the log order, with each state lasting 1 second.
Forward/Reverse: the motors rotate at maximum speed
Brake stop: the motors stop rotating immediately
Coast stop: the motors gradually decelerate to a stop by inertia
Code Explanation
Source code paths:
Firmware source code:
~/esp/base_samples/pwm_motor/main/main.cMotor driver:
~/esp/base_samples/pwm_motor/components/pwm_motor/pwm_motor.h,pwm_motor.c
1. Project Structure
xxxxxxxxxxpwm_motor/├── CMakeLists.txt # Top-level CMake project file├── main/│ ├── CMakeLists.txt # main component build configuration│ └── main.c # Main program entry├── components/│ └── pwm_motor/│ ├── CMakeLists.txt # Component configuration (depends on driver, bdc_motor)│ ├── idf_component.yml # Component dependency declarations (bdc_motor: ^0.1.0)│ ├── pwm_motor.c # Motor driver implementation│ └── pwm_motor.h # Motor driver interface declarations└── managed_components/└── espressif__bdc_motor/ # bdc_motor component (automatically pulled in)├── include/bdc_motor.h└── src/bdc_motor.c
The
bdc_motorcomponent is the official DC motor driver library provided by Espressif. During compilation, it is automatically pulled from the component registry according toidf_component.yml.
2. Main Program Logic
The execution flow of app_main in main.c:
Print the startup information
After a 1-second delay, call
PwmMotor_Init()to initialize the motor driverEnter the main loop, executing in sequence:
PwmMotor_Set_Speed_All(speed, speed)— both wheels rotate forward at maximum speedPwmMotor_Stop(MOTOR_ID_ALL, STOP_BRAKE)— both wheels brake stopPwmMotor_Set_Speed_All(-speed, -speed)— both wheels rotate reverse at maximum speedPwmMotor_Stop(MOTOR_ID_ALL, STOP_COAST)— both wheels coast stop
3. Key Components
Motor Driver (pwm_motor.h / pwm_motor.c)
Pin and PWM parameter definitions:
Parameter definition file:
~/esp/base_samples/pwm_motor/components/pwm_motor/pwm_motor.h
xxxxxxxxxx// Motor driver GPIO// M1 motor phase A// M1 motor phase B// M2 motor phase A// M2 motor phase B
// Logic direction (the forward direction of the car is the positive direction)// M1 positive direction// M2 reverse direction (mirrored mounting)
// PWM clock and frequency// 10MHz, 1 tick = 0.1us// PWM frequency 25KHz// Theoretical maximum duty cycle ticks (10MHz / 25KHz)// Dead zone filtering value// Maximum effective speed value (400 - 200)The logic direction of M2 is inverted (
-1) because the two motors are mounted in a mirror configuration on the car chassis; reverse direction control is needed for them to drive in the same direction.
Enumeration definitions:
xxxxxxxxxxtypedef enum _motor_id { MOTOR_ID_ALL = 0, // All motors MOTOR_ID_M1 = 1, // Motor M1 MOTOR_ID_M2 = 2, // Motor M2} motor_id_t;
typedef enum _stop_mode { STOP_COAST = 0, // Coast stop (motor coil disconnected, free rotation) STOP_BRAKE = 1 // Brake stop (motor coil short-circuited, immediate stop)} stop_mode_t;Motor initialization (PwmMotor_Init_M1 / PwmMotor_Init_M2):
Initialize the motor using the bdc_motor component:
xxxxxxxxxxbdc_motor_config_t motor_config = { .pwm_freq_hz = PWM_MOTOR_FREQ_HZ, // 25KHz .pwma_gpio_num = PWM_GPIO_M1B, // M1's PWMA is connected to GPIO14 .pwmb_gpio_num = PWM_GPIO_M1A, // M1's PWMB is connected to GPIO13};
bdc_motor_mcpwm_config_t mcpwm_config = { .group_id = PWM_MOTOR_TIMER_GROUP_ID_M1, // Timer group ID (M1 and M2 are both group 0) .resolution_hz = PWM_MOTOR_TIMER_RESOLUTION_HZ, // 10MHz};
bdc_motor_new_mcpwm_device(&motor_config, &mcpwm_config, &motor);bdc_motor_enable(motor);M2's pin configuration is PWMA=GPIO12, PWMB=GPIO11, consistent with the A/B phase order of M1.
Speed control function (PwmMotor_Apply_To_Device):
The low-level speed setting function, with parameters bdc_motor_handle_t and the speed value:
xxxxxxxxxxstatic void PwmMotor_Apply_To_Device(bdc_motor_handle_t motor, int speed)Processing flow:
PwmMotor_Limit_Speed— limits to[-PWM_MOTOR_DUTY_TICK_MAX, PWM_MOTOR_DUTY_TICK_MAX]speed > 0: callbdc_motor_forwardfor forward rotation +bdc_motor_set_speedto set the speedspeed < 0: callbdc_motor_reversefor reverse rotation +bdc_motor_set_speedto set the speed (absolute value)speed == 0: choosebdc_motor_brake(brake) orbdc_motor_coast(coast) according to thestop_brakeflag
Dead zone filtering (PwmMotor_Ignore_Dead_Zone):
There is a dead zone near a speed value of 0; the motor cannot rotate when the PWM duty cycle is too low. The code automatically adds PWM_MOTOR_DEAD_ZONE (200) to the speed value to ensure the speed command can effectively drive the motor:
xxxxxxxxxxstatic int PwmMotor_Ignore_Dead_Zone(int speed){ if (speed > 0) return speed + PWM_MOTOR_DEAD_ZONE; if (speed < 0) return speed - PWM_MOTOR_DEAD_ZONE; return 0;}Logic direction mapping (PwmMotor_Apply_Logic_Direction):
Apply the logic direction sign according to the motor ID; M1 is positive (+1) and M2 is negative (-1):
xxxxxxxxxxstatic int PwmMotor_Apply_Logic_Direction(motor_id_t motor_id, int speed){ int logic_sign = 1; if (motor_id == MOTOR_ID_M1) logic_sign = PWM_MOTOR_LOGIC_SIGN_M1; else if (motor_id == MOTOR_ID_M2) logic_sign = PWM_MOTOR_LOGIC_SIGN_M2; return speed * logic_sign;}API functions:
| Function | Description |
|---|---|
void PwmMotor_Init(void) | Initialize the two-channel motor driver |
void PwmMotor_Set_Speed_All(int speed_1, int speed_2) | Set the speeds of M1 and M2 simultaneously |
void PwmMotor_Set_Speed(motor_id_t motor_id, int speed) | Set the speed of the specified motor |
void PwmMotor_Stop(motor_id_t motor_id, bool brake) | Stop the specified motor; true for brake, false for coast |
A positive speed value indicates forward rotation (forward), and a negative value indicates reverse rotation (backward). The speed range is [-200, 200] (after dead zone filtering, the actual PWM duty cycle is 0~400).
Common Problems
| Problem | Cause | Solution |
|---|---|---|
| Motors do not rotate | Battery not connected or poor motor wiring | Confirm the battery is connected to the control board power interface and check whether the motor wiring is plugged in firmly |
| Motors only rotate in one direction | Wrong logic direction configuration or M1/M2 wiring reversed | Check the value of PWM_MOTOR_LOGIC_SIGN_M2 and whether the motor wires are inserted in reverse |
| Motors jitter or make sound without rotating | Dead zone filtering value too small or insufficient battery voltage | Check the PWM_MOTOR_DEAD_ZONE value, or use a freshly charged battery |
| Motor forward direction is opposite to expected | Logic direction constants need adjustment | Modify the signs of PWM_MOTOR_LOGIC_SIGN_M1 and PWM_MOTOR_LOGIC_SIGN_M2 |