diff --git a/examples/peripherals/mcpwm/mcpwm_brushed_dc_control/README.md b/examples/peripherals/mcpwm/mcpwm_brushed_dc_control/README.md index 8b11c6b434..41ba39935d 100644 --- a/examples/peripherals/mcpwm/mcpwm_brushed_dc_control/README.md +++ b/examples/peripherals/mcpwm/mcpwm_brushed_dc_control/README.md @@ -1,25 +1,68 @@ -| Supported Targets | ESP32 | -| ----------------- | ----- | +| Supported Targets | ESP32 | ESP32-S3 | +| ----------------- | ----- | -------- | +# MCPWM Brushed DC Motor Example -# MCPWM brushed dc motor control Example +(See the README.md file in the upper level 'examples' directory for more information about examples.) -This example will show you how to use MCPWM module to control brushed dc motor, you need to make connection between ESP32 and motor driver - -This code is tested with L298 motor driver, user needs to make changes according to the driver they use - -Motor first moves forward, then backward and then stops for 2 Secs each countinuously +This example mainly illustrates how to drive a brushed DC motor by generating two specific PWM signals. We used [L298N](https://www.st.com/content/st_com/en/products/motor-drivers/brushed-dc-motor-drivers/l298.html) as the H-bridge driver to provide the needed voltage and current for brushed DC motor. + +## How to Use Example + +### Hardware Required + +* A development board with any Espressif SoC which features MCPWM peripheral (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.) +* A USB cable for Power supply and programming +* A separate 12V power for brushed DC (the voltage depends on the motor model used in the example) +* A brushed DC motor, e.g. [25GA370](http://www.tronsunmotor.com/data/upload/file/201807/e03b98802b5c5390d6570939def525ba.pdf) + +Connection : +``` + Power (12V) + ^ + | ++----------------+ +------------+--------------+ +-------------+ +| | | | | | +| GPIO15+------ PWM0A +-+ IN_A +------+ +-------+ OUT_A +------+ Brushed | +| ESP | | H-Bridge | | DC | +| GPIO16+------ PWM0B +-+ IN_B +------+ +-------+ OUT_B +------+ Motor | +| | | | | | ++--------+-------+ +------------+--------------+ +-------------+ + | | + +------------------------------------------------->+ + | + v + GND +``` + +### Build and Flash + +Run `idf.py -p PORT flash monitor` to build, flash and monitor the project. + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. -## Step 1: Pin assignment -* GPIO15 is assigned as the enable/input 1 for motor driver -* GPIO16 is assigned as the enable/input 2 for motor driver +## Example Output +Run the example, you will see the following output log: -## Step 2: Connection -* connect GPIO15 with input 1 of motor driver -* connect GPIO16 with input 2 of motor driver +``` +... +I (0) cpu_start: Starting scheduler on APP CPU. +I (350) example: running forward +I (2350) example: running backward +I (4350) example: stop +I (6350) example: running forward +I (8350) example: running backward +I (10350) example: stop +... +``` +Motor first moves forward, then backward and then stops for 2 seconds each, continuously. -## Step 3: Initialize MCPWM -* You need to set the frequency and duty cycle of MCPWM timer -* You need to set the MCPWM unit you want to use, and bind the unit with one of the timers +## Troubleshooting + +* Make sure your ESP board and H-bridge module have been connected to the same GND panel. + +For any technical queries, please open an [issue] (https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. diff --git a/examples/peripherals/mcpwm/mcpwm_brushed_dc_control/main/CMakeLists.txt b/examples/peripherals/mcpwm/mcpwm_brushed_dc_control/main/CMakeLists.txt index 855c8bd51e..d0ee6ea1b6 100644 --- a/examples/peripherals/mcpwm/mcpwm_brushed_dc_control/main/CMakeLists.txt +++ b/examples/peripherals/mcpwm/mcpwm_brushed_dc_control/main/CMakeLists.txt @@ -1,2 +1,2 @@ -idf_component_register(SRCS "mcpwm_brushed_dc_control_example.c" +idf_component_register(SRCS "mcpwm_brushed_dc_example_main.c" INCLUDE_DIRS ".") diff --git a/examples/peripherals/mcpwm/mcpwm_brushed_dc_control/main/mcpwm_brushed_dc_control_example.c b/examples/peripherals/mcpwm/mcpwm_brushed_dc_control/main/mcpwm_brushed_dc_control_example.c deleted file mode 100644 index ee35fcc60a..0000000000 --- a/examples/peripherals/mcpwm/mcpwm_brushed_dc_control/main/mcpwm_brushed_dc_control_example.c +++ /dev/null @@ -1,95 +0,0 @@ -/* brushed dc motor control example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -/* - * This example will show you how to use MCPWM module to control brushed dc motor. - * This code is tested with L298 motor driver. - * User may need to make changes according to the motor driver they use. -*/ - -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_attr.h" - -#include "driver/mcpwm.h" -#include "soc/mcpwm_periph.h" - -#define GPIO_PWM0A_OUT 15 //Set GPIO 15 as PWM0A -#define GPIO_PWM0B_OUT 16 //Set GPIO 16 as PWM0B - -static void mcpwm_example_gpio_initialize(void) -{ - printf("initializing mcpwm gpio...\n"); - mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, GPIO_PWM0A_OUT); - mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0B, GPIO_PWM0B_OUT); -} - -/** - * @brief motor moves in forward direction, with duty cycle = duty % - */ -static void brushed_motor_forward(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num , float duty_cycle) -{ - mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_B); - mcpwm_set_duty(mcpwm_num, timer_num, MCPWM_OPR_A, duty_cycle); - mcpwm_set_duty_type(mcpwm_num, timer_num, MCPWM_OPR_A, MCPWM_DUTY_MODE_0); //call this each time, if operator was previously in low/high state -} - -/** - * @brief motor moves in backward direction, with duty cycle = duty % - */ -static void brushed_motor_backward(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num , float duty_cycle) -{ - mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_A); - mcpwm_set_duty(mcpwm_num, timer_num, MCPWM_OPR_B, duty_cycle); - mcpwm_set_duty_type(mcpwm_num, timer_num, MCPWM_OPR_B, MCPWM_DUTY_MODE_0); //call this each time, if operator was previously in low/high state -} - -/** - * @brief motor stop - */ -static void brushed_motor_stop(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num) -{ - mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_A); - mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_B); -} - -/** - * @brief Configure MCPWM module for brushed dc motor - */ -static void mcpwm_example_brushed_motor_control(void *arg) -{ - //1. mcpwm gpio initialization - mcpwm_example_gpio_initialize(); - - //2. initial mcpwm configuration - printf("Configuring Initial Parameters of mcpwm...\n"); - mcpwm_config_t pwm_config; - pwm_config.frequency = 1000; //frequency = 500Hz, - pwm_config.cmpr_a = 0; //duty cycle of PWMxA = 0 - pwm_config.cmpr_b = 0; //duty cycle of PWMxb = 0 - pwm_config.counter_mode = MCPWM_UP_COUNTER; - pwm_config.duty_mode = MCPWM_DUTY_MODE_0; - mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config); //Configure PWM0A & PWM0B with above settings - while (1) { - brushed_motor_forward(MCPWM_UNIT_0, MCPWM_TIMER_0, 50.0); - vTaskDelay(2000 / portTICK_RATE_MS); - brushed_motor_backward(MCPWM_UNIT_0, MCPWM_TIMER_0, 30.0); - vTaskDelay(2000 / portTICK_RATE_MS); - brushed_motor_stop(MCPWM_UNIT_0, MCPWM_TIMER_0); - vTaskDelay(2000 / portTICK_RATE_MS); - } -} - -void app_main(void) -{ - printf("Testing brushed motor...\n"); - xTaskCreate(mcpwm_example_brushed_motor_control, "mcpwm_examlpe_brushed_motor_control", 4096, NULL, 5, NULL); -} diff --git a/examples/peripherals/mcpwm/mcpwm_brushed_dc_control/main/mcpwm_brushed_dc_example_main.c b/examples/peripherals/mcpwm/mcpwm_brushed_dc_control/main/mcpwm_brushed_dc_example_main.c new file mode 100644 index 0000000000..40c4fb0c12 --- /dev/null +++ b/examples/peripherals/mcpwm/mcpwm_brushed_dc_control/main/mcpwm_brushed_dc_example_main.c @@ -0,0 +1,73 @@ +/* Brushed DC motor control example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "driver/mcpwm.h" + +static const char *TAG = "example"; + +#define GPIO_PWM0A_OUT (15) //Set GPIO 15 as PWM0A +#define GPIO_PWM0B_OUT (16) //Set GPIO 16 as PWM0B + +/** + * @brief motor moves in forward direction, with duty cycle = duty % + */ +static void brushed_motor_forward(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, float duty_cycle) +{ + ESP_LOGI(TAG, "running forward"); + mcpwm_set_duty_type(mcpwm_num, timer_num, MCPWM_OPR_B, MCPWM_HAL_GENERATOR_MODE_FORCE_LOW); + mcpwm_set_duty(mcpwm_num, timer_num, MCPWM_OPR_A, duty_cycle); + mcpwm_set_duty_type(mcpwm_num, timer_num, MCPWM_OPR_A, MCPWM_DUTY_MODE_0); +} + +/** + * @brief motor moves in backward direction, with duty cycle = duty % + */ +static void brushed_motor_backward(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, float duty_cycle) +{ + ESP_LOGI(TAG, "running backward"); + mcpwm_set_duty_type(mcpwm_num, timer_num, MCPWM_OPR_A, MCPWM_HAL_GENERATOR_MODE_FORCE_LOW); + mcpwm_set_duty(mcpwm_num, timer_num, MCPWM_OPR_B, duty_cycle); + mcpwm_set_duty_type(mcpwm_num, timer_num, MCPWM_OPR_B, MCPWM_DUTY_MODE_0); +} + +static void brushed_motor_stop(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num) +{ + ESP_LOGI(TAG, "stop"); + mcpwm_set_duty_type(mcpwm_num, timer_num, MCPWM_OPR_A, MCPWM_HAL_GENERATOR_MODE_FORCE_LOW); + mcpwm_set_duty_type(mcpwm_num, timer_num, MCPWM_OPR_B, MCPWM_HAL_GENERATOR_MODE_FORCE_LOW); +} + +void app_main(void) +{ + // Initialize GPIO + mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, GPIO_PWM0A_OUT); + mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0B, GPIO_PWM0B_OUT); + + // MCPWM configuration + mcpwm_config_t pwm_config = { + .frequency = 1000, + .cmpr_a = 0, + .cmpr_b = 0, + .counter_mode = MCPWM_UP_COUNTER, + .duty_mode = MCPWM_DUTY_MODE_0, + }; + mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config); + + while (1) { + brushed_motor_forward(MCPWM_UNIT_0, MCPWM_TIMER_0, 50.0); + vTaskDelay(pdMS_TO_TICKS(2000)); + brushed_motor_backward(MCPWM_UNIT_0, MCPWM_TIMER_0, 30.0); + vTaskDelay(pdMS_TO_TICKS(2000)); + brushed_motor_stop(MCPWM_UNIT_0, MCPWM_TIMER_0); + vTaskDelay(pdMS_TO_TICKS(2000)); + } +}