mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
example: update bldc example with new driver API
This commit is contained in:
parent
938b3d717f
commit
b77446b5c8
@ -1,51 +1,54 @@
|
||||
| Supported Targets | ESP32 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- |
|
||||
|
||||
# MCPWM BLDC Hall motor control Example
|
||||
# MCPWM BLDC Motor Control with HALL Sensor Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
This example will illustrate how to use MCPWM driver to control BLDC motor with hall sensor feedback. In the example, a timer is running at the background to update the motor speed periodically.
|
||||
|
||||
With the hardware fault detection feature of MCPWM, the example will shut down the MOSFETs when over current happens.
|
||||
The MCPWM peripheral can generate three pairs of complementary PWMs by the internal dead time submodule, which is suitable for a BLDC motor application. This example demonstrates how to use the MCPWM peripheral to control a BLDC motor in a six-step commutation scheme.
|
||||
We will change the on/off state of the six MOSFETs in a predefined order when the Hall sensor detects a change of the motor phase, so that the motor can spin in a predefined direction.
|
||||
|
||||
## How to Use Example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
1. The BLDC motor used in this example has a hall sensor capture sequence of `6-->4-->5-->1-->3-->2-->6-->4-->` and so on.
|
||||
2. A three-phase gate driver, this example uses [IR2136](https://www.infineon.com/cms/en/product/power/gate-driver-ics/ir2136s/).
|
||||
3. Six N-MOSFETs, this example uses [IRF540NS](https://www.infineon.com/cms/en/product/power/mosfet/12v-300v-n-channel-power-mosfet/irf540ns/).
|
||||
4. A development board with any Espressif SoC which features MCPWM peripheral (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.)
|
||||
5. A USB cable for Power supply and programming.
|
||||
1. A ESP board with MCPWM peripheral supported (e.g. ESP32-S3-Motor-DevKit)
|
||||
2. A BLDC motor whose commutation table is `6-->4-->5-->1-->3-->2-->6`
|
||||
3. A three-phase gate driver, for example, the [DRV8302](https://www.ti.com.cn/product/zh-cn/DRV8302)
|
||||
4. Six N-MOSFETs, for example, the [IRF540NS](https://www.infineon.com/cms/en/product/power/mosfet/12v-300v-n-channel-power-mosfet/irf540ns/)
|
||||
5. A USB cable for Power supply and programming
|
||||
|
||||
Connection :
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ ┌───────────────────────────┐ │
|
||||
│ │ │ │
|
||||
┌─────────┴─────────┴───────────┐ ┌────────┴───────┴──────────┐
|
||||
│ GPIO19 GPIO18 │ │ EN FAULT │
|
||||
│ GPIO21├──────┤PWM_UH │ ┌────────────┐
|
||||
│ GPIO22├──────┤PWM_UL U├────────┤ │
|
||||
│ │ │ │ │ │
|
||||
│ GPIO23├──────┤PWM_VH V├────────┤ BLDC │
|
||||
│ ESP Board GPIO25├──────┤PWM_VL 3-Phase Bridge │ │ │
|
||||
│ │ │ + W├────────┤ │
|
||||
│ GPIO26├──────┤PWM_WH MOSFET │ └─┬───┬───┬──┘
|
||||
│ GPIO27├──────┤PWM_WL │ │ │ │
|
||||
│ GPIO5 GPIO4 GPIO2 │ │ │ │ │ │
|
||||
└─────┬──────┬──────┬───────────┘ └───────────────────────────┘ │ │ │
|
||||
│ │ │ Hall U │ │ │
|
||||
│ │ └─────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ Hall V │ │
|
||||
│ └────────────────────────────────────────────────────────────────────┘ │
|
||||
│ Hall W │
|
||||
└───────────────────────────────────────────────────────────────────────────────┘
|
||||
+---------------------------------------------------------------------------------+
|
||||
| |
|
||||
| +---------------------------------------------+ | VM
|
||||
| | | | ^
|
||||
| | +---------------------------+ | | |
|
||||
| | | | | | |
|
||||
+-------------+-----------------------------+---------+-----------+ +--------+-------+-----+---++
|
||||
| GND BLDC_DRV_FAULT_GPIO BLDC_DRV_EN_GPIO | | EN FAULT GND |
|
||||
| BLDC_PWM_UH_GPIO +------+PWM_UH | +------------+
|
||||
| BLDC_PWM_UL_GPIO +------+PWM_UL U+--------+ |
|
||||
| | | | | |
|
||||
| ESP Board BLDC_PWM_VH_GPIO +------+PWM_VH V+--------+ BLDC |
|
||||
| BLDC_PWM_VL_GPIO +------+PWM_VL 3-Phase Bridge | | |
|
||||
| | | + W+--------+ |
|
||||
| BLDC_PWM_WH_GPIO +------+PWM_WH MOSFET | +-+---+---+--+
|
||||
| BLDC_PWM_WL_GPIO +------+PWM_WL | | | |
|
||||
| HALL_CAP_W_GPIO HALL_CAP_V_GPIO HALL_CAP_U_GPIO | | | | | |
|
||||
+-----------+------------------+------------------+---------------+ +---------------------------+ | | |
|
||||
| | | Hall U | | |
|
||||
| | +-------------------------------------------------------------+ | |
|
||||
| | Hall V | |
|
||||
| +------------------------------------------------------------------------------------+ |
|
||||
| Hall W |
|
||||
+-----------------------------------------------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
You can change the GPIO number in the [example code](main/mcpwm_bldc_hall_control_example_main.c) according to your board. You can define the spin direction in the code as well by the `BLDC_SPIN_DIRECTION_CCW` macro.
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Run `idf.py -p PORT flash monitor` to build, flash and monitor the project.
|
||||
@ -62,20 +65,42 @@ Run the example, you will see the following output log:
|
||||
```
|
||||
...
|
||||
I (0) cpu_start: Starting scheduler on APP CPU.
|
||||
I (327) example: Disable gate driver
|
||||
I (327) gpio: GPIO[18]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
|
||||
I (337) example: Setup PWM and Hall GPIO (pull up internally)
|
||||
I (347) example: Initialize PWM (default to turn off all MOSFET)
|
||||
I (357) example: Initialize over current fault action
|
||||
I (357) example: Initialize Hall sensor capture
|
||||
I (367) example: Please turn on the motor power
|
||||
I (5367) example: Enable gate driver
|
||||
I (5367) example: Changing speed at background
|
||||
I (307) example: Disable MOSFET gate
|
||||
I (307) gpio: GPIO[46]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
|
||||
I (317) example: Create MCPWM timer
|
||||
I (317) example: Create MCPWM operator
|
||||
I (327) example: Connect operators to the same timer
|
||||
I (327) example: Create comparators
|
||||
I (337) example: Create over current fault detector
|
||||
I (337) gpio: GPIO[10]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
|
||||
I (347) example: Set brake mode on the fault event
|
||||
I (357) example: Create PWM generators
|
||||
I (357) gpio: GPIO[47]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
|
||||
I (367) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
|
||||
I (377) gpio: GPIO[14]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
|
||||
I (387) gpio: GPIO[13]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
|
||||
I (397) gpio: GPIO[12]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
|
||||
I (407) gpio: GPIO[11]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
|
||||
I (417) example: Set generator actions
|
||||
I (417) example: Setup deadtime
|
||||
I (427) example: Turn off all the gates by default
|
||||
I (427) example: Create Hall sensor capture channels
|
||||
I (437) gpio: GPIO[4]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
|
||||
I (447) gpio: GPIO[5]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
|
||||
I (457) gpio: GPIO[6]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
|
||||
I (457) example: Register event callback for capture channels
|
||||
I (467) example: Start a timer to adjust motor speed periodically
|
||||
I (477) example: Enable MOSFET gate
|
||||
I (477) example: Start the MCPWM timer
|
||||
...
|
||||
```
|
||||
|
||||
## Dive into the example
|
||||
The BLDC motor will update the speed periodically.
|
||||
|
||||
1. How to change the rotation direction?
|
||||
## Troubleshooting
|
||||
|
||||
The rotation direction is controlled by how the hall sensor value is parsed. If you pass `false` to `bldc_get_hall_sensor_value`, the BLDC should rotate in clock wise. Likewise, passing `true` to that function will make tha BLDC rotate in counter clock wise.
|
||||
* Make sure your ESP board and H-bridge module have been connected to the same GND panel.
|
||||
* Check the fault signal polarity, otherwise the motor will not spin if the MCPWM detector treats the normal level as a fault one.
|
||||
* Don't use the PC USB as the power source of the BLDC motor (see the `VM` in the above connection diagram), it might damage your UAB port.
|
||||
|
||||
For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.
|
||||
|
@ -8,47 +8,46 @@
|
||||
#include <stdio.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/mcpwm.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_timer.h"
|
||||
#include "driver/mcpwm_prelude.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#define PWM_DEFAULT_FREQ 14400
|
||||
#define PWM_MIN_DUTY 40.0
|
||||
#define PWM_MAX_DUTY 80.0
|
||||
#define PWM_DUTY_STEP 5.0
|
||||
#define BLDC_MCPWM_GROUP 0
|
||||
#define BLDC_MCPWM_TIMER_U 0
|
||||
#define BLDC_MCPWM_TIMER_V 1
|
||||
#define BLDC_MCPWM_TIMER_W 2
|
||||
#define BLDC_MCPWM_GEN_HIGH MCPWM_GEN_A
|
||||
#define BLDC_MCPWM_GEN_LOW MCPWM_GEN_B
|
||||
#define BLDC_MCPWM_TIMER_RESOLUTION_HZ 10000000 // 10MHz, 1 tick = 0.1us
|
||||
#define BLDC_MCPWM_PERIOD 500 // 50us, 20KHz
|
||||
#define BLDC_SPIN_DIRECTION_CCW false // define the spin direction
|
||||
#define BLDC_SPEED_UPDATE_PERIOD_US 200000 // 200ms
|
||||
|
||||
#define BLDC_DRV_EN_GPIO 46
|
||||
#define BLDC_DRV_FAULT_GPIO 10
|
||||
#define BLDC_PWM_UH_GPIO 47
|
||||
#define BLDC_PWM_UL_GPIO 21
|
||||
#define BLDC_PWM_VH_GPIO 14
|
||||
#define BLDC_PWM_VL_GPIO 13
|
||||
#define BLDC_PWM_WH_GPIO 12
|
||||
#define BLDC_PWM_WL_GPIO 11
|
||||
#define HALL_CAP_U_GPIO 4
|
||||
#define HALL_CAP_V_GPIO 5
|
||||
#define HALL_CAP_W_GPIO 6
|
||||
|
||||
#define BLDC_DRV_EN_GPIO 18
|
||||
#define BLDC_DRV_FAULT_GPIO 19
|
||||
#define BLDC_DRV_OVER_CURRENT_FAULT MCPWM_SELECT_F0
|
||||
|
||||
#define BLDC_PWM_UH_GPIO 21
|
||||
#define BLDC_PWM_UL_GPIO 22
|
||||
#define BLDC_PWM_VH_GPIO 23
|
||||
#define BLDC_PWM_VL_GPIO 25
|
||||
#define BLDC_PWM_WH_GPIO 26
|
||||
#define BLDC_PWM_WL_GPIO 27
|
||||
#define HALL_CAP_U_GPIO 2
|
||||
#define HALL_CAP_V_GPIO 4
|
||||
#define HALL_CAP_W_GPIO 5
|
||||
#define BLDC_MCPWM_OP_INDEX_U 0
|
||||
#define BLDC_MCPWM_OP_INDEX_V 1
|
||||
#define BLDC_MCPWM_OP_INDEX_W 2
|
||||
#define BLDC_MCPWM_GEN_INDEX_HIGH 0
|
||||
#define BLDC_MCPWM_GEN_INDEX_LOW 1
|
||||
|
||||
static const char *TAG = "example";
|
||||
|
||||
typedef void (*bldc_hall_phase_action_t)(mcpwm_gen_handle_t (*gens)[2]);
|
||||
|
||||
static inline uint32_t bldc_get_hall_sensor_value(bool ccw)
|
||||
{
|
||||
uint32_t hall_val = gpio_get_level(HALL_CAP_U_GPIO) * 4 + gpio_get_level(HALL_CAP_V_GPIO) * 2 + gpio_get_level(HALL_CAP_W_GPIO) * 1;
|
||||
return ccw ? hall_val ^ (0x07) : hall_val;
|
||||
}
|
||||
|
||||
static bool IRAM_ATTR bldc_hall_updated(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_channel, const cap_event_data_t *edata, void *user_data)
|
||||
static bool IRAM_ATTR bldc_hall_updated(mcpwm_cap_channel_handle_t cap_channel, const mcpwm_capture_event_data_t *edata, void *user_data)
|
||||
{
|
||||
TaskHandle_t task_to_notify = (TaskHandle_t)user_data;
|
||||
BaseType_t high_task_wakeup = pdFALSE;
|
||||
@ -56,101 +55,99 @@ static bool IRAM_ATTR bldc_hall_updated(mcpwm_unit_t mcpwm, mcpwm_capture_channe
|
||||
return high_task_wakeup == pdTRUE;
|
||||
}
|
||||
|
||||
static void update_bldc_speed(void *arg)
|
||||
// U+V-
|
||||
static void bldc_set_phase_up_vm(mcpwm_gen_handle_t (*gens)[2])
|
||||
{
|
||||
static float duty = PWM_MIN_DUTY;
|
||||
static float duty_step = PWM_DUTY_STEP;
|
||||
duty += duty_step;
|
||||
if (duty > PWM_MAX_DUTY || duty < PWM_MIN_DUTY) {
|
||||
duty_step *= -1;
|
||||
}
|
||||
mcpwm_set_duty(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_HIGH, duty);
|
||||
mcpwm_set_duty(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_LOW, duty);
|
||||
mcpwm_set_duty(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_HIGH, duty);
|
||||
mcpwm_set_duty(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_LOW, duty);
|
||||
mcpwm_set_duty(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_HIGH, duty);
|
||||
mcpwm_set_duty(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_LOW, duty);
|
||||
// U+ = PWM, U- = _PWM_
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_HIGH], -1, true);
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_LOW], -1, true);
|
||||
// V+ = 0, V- = 1
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_LOW], 1, true);
|
||||
// W+ = 0, W- = 0
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_LOW], 0, true);
|
||||
}
|
||||
|
||||
// U+V- / A+B-
|
||||
static void bldc_set_phase_up_vm(void)
|
||||
// W+U-
|
||||
static void bldc_set_phase_wp_um(mcpwm_gen_handle_t (*gens)[2])
|
||||
{
|
||||
mcpwm_set_duty_type(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_HIGH, MCPWM_DUTY_MODE_0); // U+ = PWM
|
||||
mcpwm_deadtime_enable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE, 3, 3); // U- = _PWM_
|
||||
mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V);
|
||||
mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_HIGH); // V+ = 0
|
||||
mcpwm_set_signal_high(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_LOW); // V- = 1
|
||||
mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W);
|
||||
mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_HIGH); // W+ = 0
|
||||
mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_LOW); // W- = 0
|
||||
// U+ = 0, U- = 1
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_LOW], 1, true);
|
||||
|
||||
// V+ = 0, V- = 0
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_LOW], 0, true);
|
||||
|
||||
// W+ = PWM, W- = _PWM_
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_HIGH], -1, true);
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_LOW], -1, true);
|
||||
}
|
||||
|
||||
// W+U- / C+A-
|
||||
static void bldc_set_phase_wp_um(void)
|
||||
// W+V-
|
||||
static void bldc_set_phase_wp_vm(mcpwm_gen_handle_t (*gens)[2])
|
||||
{
|
||||
mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U);
|
||||
mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_HIGH); // U+ = 0
|
||||
mcpwm_set_signal_high(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_LOW); // U- = 1
|
||||
mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V);
|
||||
mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_HIGH); // V+ = 0
|
||||
mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_LOW); // V- = 0
|
||||
mcpwm_set_duty_type(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_HIGH, MCPWM_DUTY_MODE_0); // W+ = PWM
|
||||
mcpwm_deadtime_enable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE, 3, 3); // W- = _PWM_
|
||||
// U+ = 0, U- = 0
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_LOW], 0, true);
|
||||
|
||||
// V+ = 0, V- = 1
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_LOW], 1, true);
|
||||
|
||||
// W+ = PWM, W- = _PWM_
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_HIGH], -1, true);
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_LOW], -1, true);
|
||||
}
|
||||
|
||||
// W+V- / C+B-
|
||||
static void bldc_set_phase_wp_vm(void)
|
||||
// V+U-
|
||||
static void bldc_set_phase_vp_um(mcpwm_gen_handle_t (*gens)[2])
|
||||
{
|
||||
mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U);
|
||||
mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_HIGH); // U+ = 0
|
||||
mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_LOW); // U- = 0
|
||||
mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V);
|
||||
mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_HIGH); // V+ = 0
|
||||
mcpwm_set_signal_high(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_LOW); // V- = 1
|
||||
mcpwm_set_duty_type(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_HIGH, MCPWM_DUTY_MODE_0); // W+ = PWM
|
||||
mcpwm_deadtime_enable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE, 3, 3); // W- = _PWM_
|
||||
// U+ = 0, U- = 1
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_LOW], 1, true);
|
||||
|
||||
// V+ = PWM, V- = _PWM_
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_HIGH], -1, true);
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_LOW], -1, true);
|
||||
|
||||
// W+ = 0, W- = 0
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_LOW], 0, true);
|
||||
}
|
||||
|
||||
// V+U- / B+A-
|
||||
static void bldc_set_phase_vp_um(void)
|
||||
// V+W-
|
||||
static void bldc_set_phase_vp_wm(mcpwm_gen_handle_t (*gens)[2])
|
||||
{
|
||||
mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U);
|
||||
mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_HIGH); // U+ = 0
|
||||
mcpwm_set_signal_high(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_LOW); // U- = 1
|
||||
mcpwm_set_duty_type(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_HIGH, MCPWM_DUTY_MODE_0); // V+ = PWM
|
||||
mcpwm_deadtime_enable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE, 3, 3); // V- = _PWM_
|
||||
mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W);
|
||||
mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_HIGH); // W+ = 0
|
||||
mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_LOW); // W- = 0
|
||||
}
|
||||
// U+ = 0, U- = 0
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_LOW], 0, true);
|
||||
|
||||
// V+W- / B+C-
|
||||
static void bldc_set_phase_vp_wm(void)
|
||||
{
|
||||
mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U);
|
||||
mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_HIGH); // U+ = 0
|
||||
mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_LOW); // U- = 0
|
||||
mcpwm_set_duty_type(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_HIGH, MCPWM_DUTY_MODE_0); // V+ = PWM
|
||||
mcpwm_deadtime_enable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE, 3, 3); // V- = _PWM_
|
||||
mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W);
|
||||
mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_HIGH); // W+ = 0
|
||||
mcpwm_set_signal_high(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_LOW); // W- = 1
|
||||
// V+ = PWM, V- = _PWM_
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_HIGH], -1, true);
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_LOW], -1, true);
|
||||
|
||||
// W+ = 0, W- = 1
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_LOW], 1, true);
|
||||
}
|
||||
|
||||
// U+W- / A+C-
|
||||
static void bldc_set_phase_up_wm(void)
|
||||
static void bldc_set_phase_up_wm(mcpwm_gen_handle_t (*gens)[2])
|
||||
{
|
||||
mcpwm_set_duty_type(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_MCPWM_GEN_HIGH, MCPWM_DUTY_MODE_0); // U+ = PWM
|
||||
mcpwm_deadtime_enable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE, 3, 3); // U- = _PWM_
|
||||
mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V);
|
||||
mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_HIGH); // V+ = 0
|
||||
mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_MCPWM_GEN_LOW); // V- = 0
|
||||
mcpwm_deadtime_disable(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W);
|
||||
mcpwm_set_signal_low(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_HIGH); // W+ = 0
|
||||
mcpwm_set_signal_high(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_MCPWM_GEN_LOW); // W- = 1
|
||||
}
|
||||
// U+ = PWM, U- = _PWM_
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_HIGH], -1, true);
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_LOW], -1, true);
|
||||
|
||||
typedef void (*bldc_hall_phase_action_t)(void);
|
||||
// V+ = 0, V- = 0
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_LOW], 0, true);
|
||||
|
||||
// W+ = 0, W- = 1
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
|
||||
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_LOW], 1, true);
|
||||
}
|
||||
|
||||
static const bldc_hall_phase_action_t s_hall_actions[] = {
|
||||
[2] = bldc_set_phase_up_vm,
|
||||
@ -161,90 +158,191 @@ static const bldc_hall_phase_action_t s_hall_actions[] = {
|
||||
[3] = bldc_set_phase_up_wm,
|
||||
};
|
||||
|
||||
static void update_motor_speed_callback(void *arg)
|
||||
{
|
||||
static int step = 20;
|
||||
static int cur_speed = 0;
|
||||
if ((cur_speed + step) > 300 || (cur_speed + step) < 0) {
|
||||
step *= -1;
|
||||
}
|
||||
cur_speed += step;
|
||||
|
||||
mcpwm_cmpr_handle_t *cmprs = (mcpwm_cmpr_handle_t *)arg;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ESP_ERROR_CHECK(mcpwm_comparator_set_compare_value(cmprs[i], cur_speed));
|
||||
}
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
uint32_t hall_sensor_value = 0;
|
||||
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
|
||||
|
||||
ESP_LOGI(TAG, "Disable gate driver");
|
||||
ESP_LOGI(TAG, "Disable MOSFET gate");
|
||||
gpio_config_t drv_en_config = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = 1 << BLDC_DRV_EN_GPIO,
|
||||
.pin_bit_mask = 1ULL << BLDC_DRV_EN_GPIO,
|
||||
};
|
||||
ESP_ERROR_CHECK(gpio_config(&drv_en_config));
|
||||
gpio_set_level(BLDC_DRV_EN_GPIO, 0);
|
||||
|
||||
ESP_LOGI(TAG, "Setup PWM and Hall GPIO (pull up internally)");
|
||||
mcpwm_pin_config_t mcpwm_gpio_config = {
|
||||
.mcpwm0a_out_num = BLDC_PWM_UH_GPIO,
|
||||
.mcpwm0b_out_num = BLDC_PWM_UL_GPIO,
|
||||
.mcpwm1a_out_num = BLDC_PWM_VH_GPIO,
|
||||
.mcpwm1b_out_num = BLDC_PWM_VL_GPIO,
|
||||
.mcpwm2a_out_num = BLDC_PWM_WH_GPIO,
|
||||
.mcpwm2b_out_num = BLDC_PWM_WL_GPIO,
|
||||
.mcpwm_cap0_in_num = HALL_CAP_U_GPIO,
|
||||
.mcpwm_cap1_in_num = HALL_CAP_V_GPIO,
|
||||
.mcpwm_cap2_in_num = HALL_CAP_W_GPIO,
|
||||
.mcpwm_sync0_in_num = -1, //Not used
|
||||
.mcpwm_sync1_in_num = -1, //Not used
|
||||
.mcpwm_sync2_in_num = -1, //Not used
|
||||
.mcpwm_fault0_in_num = BLDC_DRV_FAULT_GPIO,
|
||||
.mcpwm_fault1_in_num = -1, //Not used
|
||||
.mcpwm_fault2_in_num = -1 //Not used
|
||||
ESP_LOGI(TAG, "Create MCPWM timer");
|
||||
mcpwm_timer_handle_t timer = NULL;
|
||||
mcpwm_timer_config_t timer_config = {
|
||||
.group_id = 0,
|
||||
.clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,
|
||||
.resolution_hz = BLDC_MCPWM_TIMER_RESOLUTION_HZ,
|
||||
.count_mode = MCPWM_TIMER_COUNT_MODE_UP,
|
||||
.period_ticks = BLDC_MCPWM_PERIOD,
|
||||
};
|
||||
ESP_ERROR_CHECK(mcpwm_set_pin(BLDC_MCPWM_GROUP, &mcpwm_gpio_config));
|
||||
// In case there's no pull-up resister for hall sensor on board
|
||||
gpio_pullup_en(HALL_CAP_U_GPIO);
|
||||
gpio_pullup_en(HALL_CAP_V_GPIO);
|
||||
gpio_pullup_en(HALL_CAP_W_GPIO);
|
||||
gpio_pullup_en(BLDC_DRV_FAULT_GPIO);
|
||||
ESP_ERROR_CHECK(mcpwm_new_timer(&timer_config, &timer));
|
||||
|
||||
ESP_LOGI(TAG, "Initialize PWM (default to turn off all MOSFET)");
|
||||
mcpwm_config_t pwm_config = {
|
||||
.frequency = PWM_DEFAULT_FREQ,
|
||||
.cmpr_a = PWM_MIN_DUTY,
|
||||
.cmpr_b = PWM_MIN_DUTY,
|
||||
.counter_mode = MCPWM_UP_COUNTER,
|
||||
.duty_mode = MCPWM_HAL_GENERATOR_MODE_FORCE_LOW,
|
||||
ESP_LOGI(TAG, "Create MCPWM operator");
|
||||
mcpwm_oper_handle_t operators[3];
|
||||
mcpwm_operator_config_t operator_config = {
|
||||
.group_id = 0,
|
||||
};
|
||||
ESP_ERROR_CHECK(mcpwm_init(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, &pwm_config));
|
||||
ESP_ERROR_CHECK(mcpwm_init(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, &pwm_config));
|
||||
ESP_ERROR_CHECK(mcpwm_init(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, &pwm_config));
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ESP_ERROR_CHECK(mcpwm_new_operator(&operator_config, &operators[i]));
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Initialize over current fault action");
|
||||
ESP_ERROR_CHECK(mcpwm_fault_init(BLDC_MCPWM_GROUP, MCPWM_LOW_LEVEL_TGR, BLDC_DRV_OVER_CURRENT_FAULT));
|
||||
ESP_ERROR_CHECK(mcpwm_fault_set_cyc_mode(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_U, BLDC_DRV_OVER_CURRENT_FAULT, MCPWM_ACTION_FORCE_LOW, MCPWM_ACTION_FORCE_LOW));
|
||||
ESP_ERROR_CHECK(mcpwm_fault_set_cyc_mode(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_V, BLDC_DRV_OVER_CURRENT_FAULT, MCPWM_ACTION_FORCE_LOW, MCPWM_ACTION_FORCE_LOW));
|
||||
ESP_ERROR_CHECK(mcpwm_fault_set_cyc_mode(BLDC_MCPWM_GROUP, BLDC_MCPWM_TIMER_W, BLDC_DRV_OVER_CURRENT_FAULT, MCPWM_ACTION_FORCE_LOW, MCPWM_ACTION_FORCE_LOW));
|
||||
ESP_LOGI(TAG, "Connect operators to the same timer");
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ESP_ERROR_CHECK(mcpwm_operator_connect_timer(operators[i], timer));
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Initialize Hall sensor capture");
|
||||
mcpwm_capture_config_t cap_config = {
|
||||
.cap_edge = MCPWM_BOTH_EDGE,
|
||||
.cap_prescale = 1,
|
||||
.capture_cb = bldc_hall_updated,
|
||||
.user_data = cur_task,
|
||||
ESP_LOGI(TAG, "Create comparators");
|
||||
mcpwm_cmpr_handle_t comparators[3];
|
||||
mcpwm_comparator_config_t compare_config = {
|
||||
.flags.update_cmp_on_tez = true,
|
||||
};
|
||||
ESP_ERROR_CHECK(mcpwm_capture_enable_channel(BLDC_MCPWM_GROUP, 0, &cap_config));
|
||||
ESP_ERROR_CHECK(mcpwm_capture_enable_channel(BLDC_MCPWM_GROUP, 1, &cap_config));
|
||||
ESP_ERROR_CHECK(mcpwm_capture_enable_channel(BLDC_MCPWM_GROUP, 2, &cap_config));
|
||||
ESP_LOGI(TAG, "Please turn on the motor power");
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
ESP_LOGI(TAG, "Enable gate driver");
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ESP_ERROR_CHECK(mcpwm_new_comparator(operators[i], &compare_config, &comparators[i]));
|
||||
// set compare value to 0, we will adjust the speed in a period timer callback
|
||||
ESP_ERROR_CHECK(mcpwm_comparator_set_compare_value(comparators[i], 0));
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Create over current fault detector");
|
||||
mcpwm_fault_handle_t over_cur_fault = NULL;
|
||||
mcpwm_gpio_fault_config_t gpio_fault_config = {
|
||||
.gpio_num = BLDC_DRV_FAULT_GPIO,
|
||||
.group_id = 0,
|
||||
.flags.active_level = 0, // low level means fault, refer to DRV8302 datasheet
|
||||
.flags.pull_up = true, // internally pull up
|
||||
};
|
||||
ESP_ERROR_CHECK(mcpwm_new_gpio_fault(&gpio_fault_config, &over_cur_fault));
|
||||
|
||||
ESP_LOGI(TAG, "Set brake mode on the fault event");
|
||||
mcpwm_brake_config_t brake_config = {
|
||||
.brake_mode = MCPWM_OPER_BRAKE_MODE_CBC,
|
||||
.fault = over_cur_fault,
|
||||
.flags.cbc_recover_on_tez = true,
|
||||
};
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ESP_ERROR_CHECK(mcpwm_operator_set_brake_on_fault(operators[i], &brake_config));
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Create PWM generators");
|
||||
mcpwm_gen_handle_t generators[3][2] = {};
|
||||
mcpwm_generator_config_t gen_config = {};
|
||||
const int gen_gpios[3][2] = {
|
||||
{BLDC_PWM_UH_GPIO, BLDC_PWM_UL_GPIO},
|
||||
{BLDC_PWM_VH_GPIO, BLDC_PWM_VL_GPIO},
|
||||
{BLDC_PWM_WH_GPIO, BLDC_PWM_WL_GPIO},
|
||||
};
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
gen_config.gen_gpio_num = gen_gpios[i][j];
|
||||
ESP_ERROR_CHECK(mcpwm_new_generator(operators[i], &gen_config, &generators[i][j]));
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Set generator actions");
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ESP_ERROR_CHECK(mcpwm_generator_set_actions_on_timer_event(generators[i][BLDC_MCPWM_GEN_INDEX_HIGH],
|
||||
MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH),
|
||||
MCPWM_GEN_TIMER_EVENT_ACTION_END()));
|
||||
ESP_ERROR_CHECK(mcpwm_generator_set_actions_on_compare_event(generators[i][BLDC_MCPWM_GEN_INDEX_HIGH],
|
||||
MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, comparators[i], MCPWM_GEN_ACTION_LOW),
|
||||
MCPWM_GEN_COMPARE_EVENT_ACTION_END()));
|
||||
ESP_ERROR_CHECK(mcpwm_generator_set_actions_on_brake_event(generators[i][BLDC_MCPWM_GEN_INDEX_HIGH],
|
||||
MCPWM_GEN_BRAKE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_CBC, MCPWM_GEN_ACTION_LOW),
|
||||
MCPWM_GEN_BRAKE_EVENT_ACTION_END()));
|
||||
ESP_ERROR_CHECK(mcpwm_generator_set_actions_on_brake_event(generators[i][BLDC_MCPWM_GEN_INDEX_HIGH],
|
||||
MCPWM_GEN_BRAKE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_CBC, MCPWM_GEN_ACTION_LOW),
|
||||
MCPWM_GEN_BRAKE_EVENT_ACTION_END()));
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Setup deadtime");
|
||||
mcpwm_dead_time_config_t dt_config = {
|
||||
.posedge_delay_ticks = 5,
|
||||
};
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(generators[i][BLDC_MCPWM_GEN_INDEX_HIGH], generators[i][BLDC_MCPWM_GEN_INDEX_HIGH], &dt_config));
|
||||
}
|
||||
dt_config = (mcpwm_dead_time_config_t) {
|
||||
.negedge_delay_ticks = 5,
|
||||
.flags.invert_output = true,
|
||||
};
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(generators[i][BLDC_MCPWM_GEN_INDEX_HIGH], generators[i][BLDC_MCPWM_GEN_INDEX_LOW], &dt_config));
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Turn off all the gates");
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
ESP_ERROR_CHECK(mcpwm_generator_set_force_level(generators[i][j], 0, true));
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Create Hall sensor capture channels");
|
||||
mcpwm_cap_timer_handle_t cap_timer = NULL;
|
||||
mcpwm_capture_timer_config_t cap_timer_config = {
|
||||
.group_id = 0,
|
||||
.clk_src = MCPWM_CAPTURE_CLK_SRC_DEFAULT,
|
||||
};
|
||||
ESP_ERROR_CHECK(mcpwm_new_capture_timer(&cap_timer_config, &cap_timer));
|
||||
mcpwm_cap_channel_handle_t cap_channels[3];
|
||||
mcpwm_capture_channel_config_t cap_channel_config = {
|
||||
.prescale = 1,
|
||||
.flags.pull_up = true,
|
||||
.flags.neg_edge = true,
|
||||
.flags.pos_edge = true,
|
||||
};
|
||||
const int cap_chan_gpios[3] = {HALL_CAP_U_GPIO, HALL_CAP_V_GPIO, HALL_CAP_W_GPIO};
|
||||
for (int i = 0; i < 3; i++) {
|
||||
cap_channel_config.gpio_num = cap_chan_gpios[i];
|
||||
ESP_ERROR_CHECK(mcpwm_new_capture_channel(cap_timer, &cap_channel_config, &cap_channels[i]));
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Register event callback for capture channels");
|
||||
TaskHandle_t task_to_notify = xTaskGetCurrentTaskHandle();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
mcpwm_capture_event_callbacks_t cbs = {
|
||||
.on_cap = bldc_hall_updated,
|
||||
};
|
||||
ESP_ERROR_CHECK(mcpwm_capture_channel_register_event_callbacks(cap_channels[i], &cbs, task_to_notify));
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Start a timer to adjust motor speed periodically");
|
||||
esp_timer_handle_t periodic_timer = NULL;
|
||||
const esp_timer_create_args_t periodic_timer_args = {
|
||||
.callback = update_motor_speed_callback,
|
||||
.arg = comparators,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer));
|
||||
ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, BLDC_SPEED_UPDATE_PERIOD_US));
|
||||
|
||||
ESP_LOGI(TAG, "Enable MOSFET gate");
|
||||
gpio_set_level(BLDC_DRV_EN_GPIO, 1);
|
||||
ESP_LOGI(TAG, "Changing speed at background");
|
||||
const esp_timer_create_args_t bldc_timer_args = {
|
||||
.callback = update_bldc_speed,
|
||||
.name = "bldc_speed"
|
||||
};
|
||||
esp_timer_handle_t bldc_speed_timer;
|
||||
ESP_ERROR_CHECK(esp_timer_create(&bldc_timer_args, &bldc_speed_timer));
|
||||
ESP_ERROR_CHECK(esp_timer_start_periodic(bldc_speed_timer, 2000000));
|
||||
|
||||
ESP_LOGI(TAG, "Start the MCPWM timer");
|
||||
ESP_ERROR_CHECK(mcpwm_timer_enable(timer));
|
||||
ESP_ERROR_CHECK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_START_NO_STOP));
|
||||
|
||||
uint32_t hall_sensor_value = 0;
|
||||
while (1) {
|
||||
// The rotation direction is controlled by inverting the hall sensor value
|
||||
hall_sensor_value = bldc_get_hall_sensor_value(false);
|
||||
if (hall_sensor_value >= 1 && hall_sensor_value < sizeof(s_hall_actions) / sizeof(s_hall_actions[0])) {
|
||||
s_hall_actions[hall_sensor_value]();
|
||||
hall_sensor_value = bldc_get_hall_sensor_value(BLDC_SPIN_DIRECTION_CCW);
|
||||
if (hall_sensor_value >= 1 && hall_sensor_value <= 6) {
|
||||
s_hall_actions[hall_sensor_value](generators);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "invalid bldc phase, wrong hall sensor value:%d", hall_sensor_value);
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.esp32s3
|
||||
@pytest.mark.generic
|
||||
def test_bldc_hall_control_example(dut: Dut) -> None:
|
||||
dut.expect_exact('example: Disable MOSFET gate')
|
||||
dut.expect_exact('example: Create MCPWM timer')
|
||||
dut.expect_exact('example: Create MCPWM operator')
|
||||
dut.expect_exact('example: Connect operators to the same timer')
|
||||
dut.expect_exact('example: Create comparators')
|
||||
dut.expect_exact('example: Create over current fault detector')
|
||||
dut.expect_exact('example: Set brake mode on the fault event')
|
||||
dut.expect_exact('example: Create PWM generators')
|
||||
dut.expect_exact('example: Set generator actions')
|
||||
dut.expect_exact('example: Setup deadtime')
|
||||
dut.expect_exact('example: Turn off all the gates')
|
||||
dut.expect_exact('example: Create Hall sensor capture channels')
|
||||
dut.expect_exact('example: Start a timer to adjust motor speed periodically')
|
||||
dut.expect_exact('example: Enable MOSFET gate')
|
||||
dut.expect_exact('example: Start the MCPWM timer')
|
Loading…
x
Reference in New Issue
Block a user