bdc_motor: component moved to registry

pull/9565/head
morris 2022-08-11 13:34:26 +08:00
rodzic 1d4c08cef4
commit 6261eae50c
8 zmienionych plików z 3 dodań i 526 usunięć

Wyświetl plik

@ -4,11 +4,11 @@
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example mainly illustrates how to drive a brushed DC motor by generating two specific PWM signals. However the PWM signals from ESP chip can't drive motors directly as the motor usually consumes high current. So an H-bridge like [DRV8848](https://www.ti.com/product/DRV8848) should be used to provide the needed voltage and current for brushed DC motor. To simplify the DC motor control of MCPWM peripheral driver, there's a component called [bdc_motor](components/bdc_motor/README.md) which abstracts the common operations into a generic interface. The most useful operations are: `forward`, `reverse`, `coast` and `brake`.
This example mainly illustrates how to drive a brushed DC motor by generating two specific PWM signals. However the PWM signals from ESP chip can't drive motors directly as the motor usually consumes high current. So an H-bridge like [DRV8848](https://www.ti.com/product/DRV8848) should be used to provide the needed voltage and current for brushed DC motor. To simplify the DC motor control of MCPWM peripheral driver, there's a component called [bdc_motor](https://components.espressif.com/component/espressif/bdc_motor) which abstracts the common operations into a generic interface. The most useful operations are: `forward`, `reverse`, `coast` and `brake`.
To measure the speed of motor, a photoelectric encoder is used to generate the "speed feedback" signals (e.g. a pair of quadrature signal). In the example, we use the PCNT peripheral to decode that quadrature signals. For more information, please refer to [rotary encoder example](../../pcnt/rotary_encoder/README.md) as well.
The example uses a simple PID algorithm to keep the motor spin in a stable speed. The PID component is fetched from the [IDF Component Registry](https://components.espressif.com/component/espressif/pid_ctrl).
The example uses a simple PID algorithm to keep the motor spin in a stable speed. Like the [bdc_motor](https://components.espressif.com/component/espressif/bdc_motor), the [PID component](https://components.espressif.com/component/espressif/pid_ctrl) is also managed by the component manager. These components' dependencies are listed in the [manifest file](main/idf_component.yml).
## How to Use Example

Wyświetl plik

@ -1,9 +0,0 @@
set(srcs "src/bdc_motor.c")
if(CONFIG_SOC_MCPWM_SUPPORTED)
list(APPEND srcs "src/bdc_motor_mcpwm_impl.c")
endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS "include" "interface"
PRIV_REQUIRES "driver")

Wyświetl plik

@ -1,7 +0,0 @@
# Brushed DC Motor Component
This directory contains an implementation for Brushed DC Motor by different peripherals. Currently only MCPWM is supported as the BDC motor backend.
To learn more about how to use this component, please check API Documentation from header file [bdc_motor.h](./include/bdc_motor.h).
Please note that this component is not considered to be a part of ESP-IDF stable API. It may change and it may be removed in the future releases.

Wyświetl plik

@ -1,145 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Brushed DC Motor handle
*/
typedef struct bdc_motor_t *bdc_motor_handle_t;
/**
* @brief Enable BDC motor
*
* @param motor: BDC Motor handle
*
* @return
* - ESP_OK: Enable motor successfully
* - ESP_ERR_INVALID_ARG: Enable motor failed because of invalid parameters
* - ESP_FAIL: Enable motor failed because other error occurred
*/
esp_err_t bdc_motor_enable(bdc_motor_handle_t motor);
/**
* @brief Disable BDC motor
*
* @param motor: BDC Motor handle
*
* @return
* - ESP_OK: Disable motor successfully
* - ESP_ERR_INVALID_ARG: Disable motor failed because of invalid parameters
* - ESP_FAIL: Disable motor failed because other error occurred
*/
esp_err_t bdc_motor_disable(bdc_motor_handle_t motor);
/**
* @brief Set speed for bdc motor
*
* @param motor: BDC Motor handle
* @param speed: BDC speed
*
* @return
* - ESP_OK: Set motor speed successfully
* - ESP_ERR_INVALID_ARG: Set motor speed failed because of invalid parameters
* - ESP_FAIL: Set motor speed failed because other error occurred
*/
esp_err_t bdc_motor_set_speed(bdc_motor_handle_t motor, uint32_t speed);
/**
* @brief Forward BDC motor
*
* @param motor: BDC Motor handle
*
* @return
* - ESP_OK: Forward motor successfully
* - ESP_FAIL: Forward motor failed because some other error occurred
*/
esp_err_t bdc_motor_forward(bdc_motor_handle_t motor);
/**
* @brief Reverse BDC Motor
*
* @param strip: BDC Motor handle
*
* @return
* - ESP_OK: Reverse motor successfully
* - ESP_FAIL: Reverse motor failed because some other error occurred
*/
esp_err_t bdc_motor_reverse(bdc_motor_handle_t motor);
/**
* @brief Stop motor in a coast way (a.k.a Fast Decay)
*
* @param motor: BDC Motor handle
*
* @return
* - ESP_OK: Stop motor successfully
* - ESP_FAIL: Stop motor failed because some other error occurred
*/
esp_err_t bdc_motor_coast(bdc_motor_handle_t motor);
/**
* @brief Stop motor in a brake way (a.k.a Slow Decay)
*
* @param motor: BDC Motor handle
*
* @return
* - ESP_OK: Stop motor successfully
* - ESP_FAIL: Stop motor failed because some other error occurred
*/
esp_err_t bdc_motor_brake(bdc_motor_handle_t motor);
/**
* @brief Free BDC Motor resources
*
* @param strip: BDC Motor handle
*
* @return
* - ESP_OK: Free resources successfully
* - ESP_FAIL: Free resources failed because error occurred
*/
esp_err_t bdc_motor_del(bdc_motor_handle_t motor);
/**
* @brief BDC Motor Configuration
*/
typedef struct {
uint32_t pwma_gpio_num; /*!< BDC Motor PWM A gpio number */
uint32_t pwmb_gpio_num; /*!< BDC Motor PWM B gpio number */
uint32_t pwm_freq_hz; /*!< PWM frequency, in Hz */
} bdc_motor_config_t;
/**
* @brief BDC Motor MCPWM specific configuration
*/
typedef struct {
int group_id; /*!< MCPWM group number */
uint32_t resolution_hz; /*!< MCPWM timer resolution */
} bdc_motor_mcpwm_config_t;
/**
* @brief Create BDC Motor based on MCPWM peripheral
*
* @param motor_config: BDC Motor configuration
* @param mcpwm_config: MCPWM specific configuration
* @param ret_motor Returned BDC Motor handle
* @return
* - ESP_OK: Create BDC Motor handle successfully
* - ESP_ERR_INVALID_ARG: Create BDC Motor handle failed because of invalid argument
* - ESP_ERR_NO_MEM: Create BDC Motor handle failed because of out of memory
* - ESP_FAIL: Create BDC Motor handle failed because some other error
*/
esp_err_t bdc_motor_new_mcpwm_device(const bdc_motor_config_t *motor_config, const bdc_motor_mcpwm_config_t *mcpwm_config, bdc_motor_handle_t *ret_motor);
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -1,116 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct bdc_motor_t bdc_motor_t; /*!< Type of BDC motor */
/**
* @brief BDC motor interface definition
*/
struct bdc_motor_t {
/**
* @brief Enable BDC motor
*
* @param motor: BDC Motor handle
*
* @return
* - ESP_OK: Enable motor successfully
* - ESP_ERR_INVALID_ARG: Enable motor failed because of invalid parameters
* - ESP_FAIL: Enable motor failed because other error occurred
*/
esp_err_t (*enable)(bdc_motor_t *motor);
/**
* @brief Disable BDC motor
*
* @param motor: BDC Motor handle
*
* @return
* - ESP_OK: Disable motor successfully
* - ESP_ERR_INVALID_ARG: Disable motor failed because of invalid parameters
* - ESP_FAIL: Disable motor failed because other error occurred
*/
esp_err_t (*disable)(bdc_motor_t *motor);
/**
* @brief Set speed for bdc motor
*
* @param motor: BDC Motor handle
* @param speed: BDC speed
*
* @return
* - ESP_OK: Set motor speed successfully
* - ESP_ERR_INVALID_ARG: Set motor speed failed because of invalid parameters
* - ESP_FAIL: Set motor speed failed because other error occurred
*/
esp_err_t (*set_speed)(bdc_motor_t *motor, uint32_t speed);
/**
* @brief Forward BDC motor
*
* @param motor: BDC Motor handle
*
* @return
* - ESP_OK: Forward motor successfully
* - ESP_FAIL: Forward motor failed because some other error occurred
*/
esp_err_t (*forward)(bdc_motor_t *motor);
/**
* @brief Reverse BDC Motor
*
* @param motor: BDC Motor handle
*
* @return
* - ESP_OK: Reverse motor successfully
* - ESP_FAIL: Reverse motor failed because some other error occurred
*/
esp_err_t (*reverse)(bdc_motor_t *motor);
/**
* @brief Stop motor in a coast way (a.k.a Fast Decay)
*
* @param motor: BDC Motor handle
*
* @return
* - ESP_OK: Stop motor successfully
* - ESP_FAIL: Stop motor failed because some other error occurred
*/
esp_err_t (*coast)(bdc_motor_t *motor);
/**
* @brief Stop motor in a brake way (a.k.a Slow Decay)
*
* @param motor: BDC Motor handle
*
* @return
* - ESP_OK: Stop motor successfully
* - ESP_FAIL: Stop motor failed because some other error occurred
*/
esp_err_t (*brake)(bdc_motor_t *motor);
/**
* @brief Free BDC Motor handle resources
*
* @param motor: BDC Motor handle
*
* @return
* - ESP_OK: Free resources successfully
* - ESP_FAIL: Free resources failed because error occurred
*/
esp_err_t (*del)(bdc_motor_t *motor);
};
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -1,62 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdlib.h>
#include <string.h>
#include <sys/cdefs.h>
#include "esp_log.h"
#include "esp_check.h"
#include "bdc_motor.h"
#include "bdc_motor_interface.h"
static const char *TAG = "bdc_motor";
esp_err_t bdc_motor_enable(bdc_motor_handle_t motor)
{
ESP_RETURN_ON_FALSE(motor, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
return motor->enable(motor);
}
esp_err_t bdc_motor_disable(bdc_motor_handle_t motor)
{
ESP_RETURN_ON_FALSE(motor, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
return motor->disable(motor);
}
esp_err_t bdc_motor_set_speed(bdc_motor_handle_t motor, uint32_t speed)
{
ESP_RETURN_ON_FALSE(motor, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
return motor->set_speed(motor, speed);
}
esp_err_t bdc_motor_forward(bdc_motor_handle_t motor)
{
ESP_RETURN_ON_FALSE(motor, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
return motor->forward(motor);
}
esp_err_t bdc_motor_reverse(bdc_motor_handle_t motor)
{
ESP_RETURN_ON_FALSE(motor, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
return motor->reverse(motor);
}
esp_err_t bdc_motor_coast(bdc_motor_handle_t motor)
{
ESP_RETURN_ON_FALSE(motor, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
return motor->coast(motor);
}
esp_err_t bdc_motor_brake(bdc_motor_handle_t motor)
{
ESP_RETURN_ON_FALSE(motor, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
return motor->brake(motor);
}
esp_err_t bdc_motor_del(bdc_motor_handle_t motor)
{
ESP_RETURN_ON_FALSE(motor, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
return motor->del(motor);
}

Wyświetl plik

@ -1,185 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdlib.h>
#include <string.h>
#include <sys/cdefs.h>
#include "esp_log.h"
#include "esp_check.h"
#include "driver/mcpwm_prelude.h"
#include "bdc_motor.h"
#include "bdc_motor_interface.h"
static const char *TAG = "bdc_motor_mcpwm";
typedef struct {
bdc_motor_t base;
mcpwm_timer_handle_t timer;
mcpwm_oper_handle_t operator;
mcpwm_cmpr_handle_t cmpa;
mcpwm_cmpr_handle_t cmpb;
mcpwm_gen_handle_t gena;
mcpwm_gen_handle_t genb;
} bdc_motor_mcpwm_obj;
static esp_err_t bdc_motor_mcpwm_set_speed(bdc_motor_t *motor, uint32_t speed)
{
bdc_motor_mcpwm_obj *mcpwm_motor = __containerof(motor, bdc_motor_mcpwm_obj, base);
ESP_RETURN_ON_ERROR(mcpwm_comparator_set_compare_value(mcpwm_motor->cmpa, speed), TAG, "set compare value failed");
ESP_RETURN_ON_ERROR(mcpwm_comparator_set_compare_value(mcpwm_motor->cmpb, speed), TAG, "set compare value failed");
return ESP_OK;
}
static esp_err_t bdc_motor_mcpwm_enable(bdc_motor_t *motor)
{
bdc_motor_mcpwm_obj *mcpwm_motor = __containerof(motor, bdc_motor_mcpwm_obj, base);
ESP_RETURN_ON_ERROR(mcpwm_timer_enable(mcpwm_motor->timer), TAG, "enable timer failed");
ESP_RETURN_ON_ERROR(mcpwm_timer_start_stop(mcpwm_motor->timer, MCPWM_TIMER_START_NO_STOP), TAG, "start timer failed");
return ESP_OK;
}
static esp_err_t bdc_motor_mcpwm_disable(bdc_motor_t *motor)
{
bdc_motor_mcpwm_obj *mcpwm_motor = __containerof(motor, bdc_motor_mcpwm_obj, base);
ESP_RETURN_ON_ERROR(mcpwm_timer_start_stop(mcpwm_motor->timer, MCPWM_TIMER_STOP_EMPTY), TAG, "stop timer failed");
ESP_RETURN_ON_ERROR(mcpwm_timer_disable(mcpwm_motor->timer), TAG, "disable timer failed");
return ESP_OK;
}
static esp_err_t bdc_motor_mcpwm_forward(bdc_motor_t *motor)
{
bdc_motor_mcpwm_obj *mcpwm_motor = __containerof(motor, bdc_motor_mcpwm_obj, base);
ESP_RETURN_ON_ERROR(mcpwm_generator_set_force_level(mcpwm_motor->gena, -1, true), TAG, "disable force level for gena failed");
ESP_RETURN_ON_ERROR(mcpwm_generator_set_force_level(mcpwm_motor->genb, 0, true), TAG, "set force level for genb failed");
return ESP_OK;
}
static esp_err_t bdc_motor_mcpwm_reverse(bdc_motor_t *motor)
{
bdc_motor_mcpwm_obj *mcpwm_motor = __containerof(motor, bdc_motor_mcpwm_obj, base);
ESP_RETURN_ON_ERROR(mcpwm_generator_set_force_level(mcpwm_motor->genb, -1, true), TAG, "disable force level for genb failed");
ESP_RETURN_ON_ERROR(mcpwm_generator_set_force_level(mcpwm_motor->gena, 0, true), TAG, "set force level for gena failed");
return ESP_OK;
}
static esp_err_t bdc_motor_mcpwm_coast(bdc_motor_t *motor)
{
bdc_motor_mcpwm_obj *mcpwm_motor = __containerof(motor, bdc_motor_mcpwm_obj, base);
ESP_RETURN_ON_ERROR(mcpwm_generator_set_force_level(mcpwm_motor->gena, 0, true), TAG, "set force level for gena failed");
ESP_RETURN_ON_ERROR(mcpwm_generator_set_force_level(mcpwm_motor->genb, 0, true), TAG, "set force level for genb failed");
return ESP_OK;
}
static esp_err_t bdc_motor_mcpwm_brake(bdc_motor_t *motor)
{
bdc_motor_mcpwm_obj *mcpwm_motor = __containerof(motor, bdc_motor_mcpwm_obj, base);
ESP_RETURN_ON_ERROR(mcpwm_generator_set_force_level(mcpwm_motor->gena, 1, true), TAG, "set force level for gena failed");
ESP_RETURN_ON_ERROR(mcpwm_generator_set_force_level(mcpwm_motor->genb, 1, true), TAG, "set force level for genb failed");
return ESP_OK;
}
static esp_err_t bdc_motor_mcpwm_del(bdc_motor_t *motor)
{
bdc_motor_mcpwm_obj *mcpwm_motor = __containerof(motor, bdc_motor_mcpwm_obj, base);
mcpwm_del_generator(mcpwm_motor->gena);
mcpwm_del_generator(mcpwm_motor->genb);
mcpwm_del_comparator(mcpwm_motor->cmpa);
mcpwm_del_comparator(mcpwm_motor->cmpb);
mcpwm_del_operator(mcpwm_motor->operator);
mcpwm_del_timer(mcpwm_motor->timer);
free(mcpwm_motor);
return ESP_OK;
}
esp_err_t bdc_motor_new_mcpwm_device(const bdc_motor_config_t *motor_config, const bdc_motor_mcpwm_config_t *mcpwm_config, bdc_motor_handle_t *ret_motor)
{
bdc_motor_mcpwm_obj *mcpwm_motor = NULL;
esp_err_t ret = ESP_OK;
ESP_GOTO_ON_FALSE(motor_config && mcpwm_config && ret_motor, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
mcpwm_motor = calloc(1, sizeof(bdc_motor_mcpwm_obj));
ESP_GOTO_ON_FALSE(mcpwm_motor, ESP_ERR_NO_MEM, err, TAG, "no mem for rmt motor");
// mcpwm timer
mcpwm_timer_config_t timer_config = {
.group_id = mcpwm_config->group_id,
.clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,
.resolution_hz = mcpwm_config->resolution_hz,
.period_ticks = mcpwm_config->resolution_hz / motor_config->pwm_freq_hz,
.count_mode = MCPWM_TIMER_COUNT_MODE_UP,
};
ESP_GOTO_ON_ERROR(mcpwm_new_timer(&timer_config, &mcpwm_motor->timer), err, TAG, "create MCPWM timer failed");
mcpwm_operator_config_t operator_config = {
.group_id = mcpwm_config->group_id,
};
ESP_GOTO_ON_ERROR(mcpwm_new_operator(&operator_config, &mcpwm_motor->operator), err, TAG, "create MCPWM operator failed");
ESP_GOTO_ON_ERROR(mcpwm_operator_connect_timer(mcpwm_motor->operator, mcpwm_motor->timer), err, TAG, "connect timer and operator failed");
mcpwm_comparator_config_t comparator_config = {
.flags.update_cmp_on_tez = true,
};
ESP_GOTO_ON_ERROR(mcpwm_new_comparator(mcpwm_motor->operator, &comparator_config, &mcpwm_motor->cmpa), err, TAG, "create comparator failed");
ESP_GOTO_ON_ERROR(mcpwm_new_comparator(mcpwm_motor->operator, &comparator_config, &mcpwm_motor->cmpb), err, TAG, "create comparator failed");
// set the initial compare value for both comparators
mcpwm_comparator_set_compare_value(mcpwm_motor->cmpa, 0);
mcpwm_comparator_set_compare_value(mcpwm_motor->cmpb, 0);
mcpwm_generator_config_t generator_config = {
.gen_gpio_num = motor_config->pwma_gpio_num,
};
ESP_GOTO_ON_ERROR(mcpwm_new_generator(mcpwm_motor->operator, &generator_config, &mcpwm_motor->gena), err, TAG, "create generator failed");
generator_config.gen_gpio_num = motor_config->pwmb_gpio_num;
ESP_GOTO_ON_ERROR(mcpwm_new_generator(mcpwm_motor->operator, &generator_config, &mcpwm_motor->genb), err, TAG, "create generator failed");
mcpwm_generator_set_actions_on_timer_event(mcpwm_motor->gena,
MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH),
MCPWM_GEN_TIMER_EVENT_ACTION_END());
mcpwm_generator_set_actions_on_compare_event(mcpwm_motor->gena,
MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, mcpwm_motor->cmpa, MCPWM_GEN_ACTION_LOW),
MCPWM_GEN_COMPARE_EVENT_ACTION_END());
mcpwm_generator_set_actions_on_timer_event(mcpwm_motor->genb,
MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH),
MCPWM_GEN_TIMER_EVENT_ACTION_END());
mcpwm_generator_set_actions_on_compare_event(mcpwm_motor->genb,
MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, mcpwm_motor->cmpb, MCPWM_GEN_ACTION_LOW),
MCPWM_GEN_COMPARE_EVENT_ACTION_END());
mcpwm_motor->base.enable = bdc_motor_mcpwm_enable;
mcpwm_motor->base.disable = bdc_motor_mcpwm_disable;
mcpwm_motor->base.forward = bdc_motor_mcpwm_forward;
mcpwm_motor->base.reverse = bdc_motor_mcpwm_reverse;
mcpwm_motor->base.coast = bdc_motor_mcpwm_coast;
mcpwm_motor->base.brake = bdc_motor_mcpwm_brake;
mcpwm_motor->base.set_speed = bdc_motor_mcpwm_set_speed;
mcpwm_motor->base.del = bdc_motor_mcpwm_del;
*ret_motor = &mcpwm_motor->base;
return ESP_OK;
err:
if (mcpwm_motor) {
if (mcpwm_motor->gena) {
mcpwm_del_generator(mcpwm_motor->gena);
}
if (mcpwm_motor->genb) {
mcpwm_del_generator(mcpwm_motor->genb);
}
if (mcpwm_motor->cmpa) {
mcpwm_del_comparator(mcpwm_motor->cmpa);
}
if (mcpwm_motor->cmpb) {
mcpwm_del_comparator(mcpwm_motor->cmpb);
}
if (mcpwm_motor->operator) {
mcpwm_del_operator(mcpwm_motor->operator);
}
if (mcpwm_motor->timer) {
mcpwm_del_timer(mcpwm_motor->timer);
}
free(mcpwm_motor);
}
return ret;
}

Wyświetl plik

@ -1,2 +1,3 @@
dependencies:
pid_ctrl: "^0.1.1"
bdc_motor: "^0.1.0"