Select one of the symbols to view example projects that use it.
 
Outline
#include <stdio.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "driver/gpio.h"
#include "foc/esp_foc.h"
#include "svpwm/esp_svpwm.h"
TAG
#define EXAMPLE_FOC_DRV_EN_GPIO
#define EXAMPLE_FOC_DRV_FAULT_GPIO
#define EXAMPLE_FOC_PWM_UH_GPIO
#define EXAMPLE_FOC_PWM_UL_GPIO
#define EXAMPLE_FOC_PWM_VH_GPIO
#define EXAMPLE_FOC_PWM_VL_GPIO
#define EXAMPLE_FOC_PWM_WH_GPIO
#define EXAMPLE_FOC_PWM_WL_GPIO
#define EXAMPLE_FOC_MCPWM_TIMER_RESOLUTION_HZ
#define EXAMPLE_FOC_MCPWM_PERIOD
#define EXAMPLE_FOC_WAVE_FREQ
#define EXAMPLE_FOC_WAVE_AMPL
bsp_bridge_driver_init()
bsp_bridge_driver_enable(bool)
inverter_update_cb(mcpwm_timer_handle_t, const mcpwm_timer_event_data_t *, void *)
app_main()
Files
loading...
SourceVuESP-IDF Framework and Examplesmcpwm_foc_svpwm_open_loop samplemain/app_main.c
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/* * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 *//* ... */ #include <stdio.h> #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" #include "driver/gpio.h" #include "foc/esp_foc.h" #include "svpwm/esp_svpwm.h"8 includes static const char *TAG = "example_foc"; ////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////// Please update the following configuration according to your HardWare spec ///////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////// #define EXAMPLE_FOC_DRV_EN_GPIO 46 #define EXAMPLE_FOC_DRV_FAULT_GPIO 10 #define EXAMPLE_FOC_PWM_UH_GPIO 47 #define EXAMPLE_FOC_PWM_UL_GPIO 21 #define EXAMPLE_FOC_PWM_VH_GPIO 14 #define EXAMPLE_FOC_PWM_VL_GPIO 13 #define EXAMPLE_FOC_PWM_WH_GPIO 12 #define EXAMPLE_FOC_PWM_WL_GPIO 11 #define EXAMPLE_FOC_MCPWM_TIMER_RESOLUTION_HZ 10000000 // 10MHz, 1 tick = 0.1us #define EXAMPLE_FOC_MCPWM_PERIOD 1000 // 1000 * 0.1us = 100us, 10KHz #define EXAMPLE_FOC_WAVE_FREQ 10 // 50Hz 3 phase AC wave #define EXAMPLE_FOC_WAVE_AMPL 100 // Wave amplitude, Use up-down timer mode, max value should be (EXAMPLE_FOC_MCPWM_PERIOD/2)12 defines void bsp_bridge_driver_init(void) { gpio_config_t drv_en_config = { .mode = GPIO_MODE_OUTPUT, .pin_bit_mask = 1ULL << EXAMPLE_FOC_DRV_EN_GPIO, }{...}; ESP_ERROR_CHECK(gpio_config(&drv_en_config)); }{ ... } void bsp_bridge_driver_enable(bool enable) { ESP_LOGI(TAG, "%s MOSFET gate", enable ? "Enable" : "Disable"); gpio_set_level(EXAMPLE_FOC_DRV_EN_GPIO, enable); }{ ... } bool inverter_update_cb(mcpwm_timer_handle_t timer, const mcpwm_timer_event_data_t *edata, void *user_ctx) { BaseType_t task_yield = pdFALSE; xSemaphoreGiveFromISR(*((SemaphoreHandle_t *)user_ctx), &task_yield); return task_yield; }{ ... } void app_main(void) { ESP_LOGI(TAG, "Hello FOC"); // counting semaphore used to sync update foc calculation when mcpwm timer updated SemaphoreHandle_t update_semaphore = xSemaphoreCreateCounting(1, 0); foc_dq_coord_t dq_out = {_IQ(0), _IQ(0)}; foc_ab_coord_t ab_out; foc_uvw_coord_t uvw_out; int uvw_duty[3]; float elec_theta_deg = 0; _iq elec_theta_rad; inverter_config_t cfg = { .timer_config = { .group_id = 0, .clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT, .resolution_hz = EXAMPLE_FOC_MCPWM_TIMER_RESOLUTION_HZ, .count_mode = MCPWM_TIMER_COUNT_MODE_UP_DOWN, //UP_DOWN mode will generate center align pwm wave, which can reduce MOSFET switch times on same effect, extend life .period_ticks = EXAMPLE_FOC_MCPWM_PERIOD, }{...}, .operator_config = { .group_id = 0, }{...}, .compare_config = { .flags.update_cmp_on_tez = true, }{...}, .gen_gpios = { {EXAMPLE_FOC_PWM_UH_GPIO, EXAMPLE_FOC_PWM_UL_GPIO}, {EXAMPLE_FOC_PWM_VH_GPIO, EXAMPLE_FOC_PWM_VL_GPIO}, {EXAMPLE_FOC_PWM_WH_GPIO, EXAMPLE_FOC_PWM_WL_GPIO}, }{...}, .dt_config = { .posedge_delay_ticks = 5, }{...}, .inv_dt_config = { .negedge_delay_ticks = 5, .flags.invert_output = true, }{...}, }{...}; inverter_handle_t inverter1; ESP_ERROR_CHECK(svpwm_new_inverter(&cfg, &inverter1)); ESP_LOGI(TAG, "Inverter init OK"); mcpwm_timer_event_callbacks_t cbs = { .on_full = inverter_update_cb, }{...}; ESP_ERROR_CHECK(svpwm_inverter_register_cbs(inverter1, &cbs, &update_semaphore)); ESP_ERROR_CHECK(svpwm_inverter_start(inverter1, MCPWM_TIMER_START_NO_STOP)); ESP_LOGI(TAG, "Inverter start OK"); // Enable gate driver chip bsp_bridge_driver_init(); bsp_bridge_driver_enable(true); ESP_LOGI(TAG, "Start FOC"); while (true) { xSemaphoreTake(update_semaphore, portMAX_DELAY); // Calculate elec_theta_deg increase step of 50Hz output on 10000Hz call elec_theta_deg += (EXAMPLE_FOC_WAVE_AMPL * 360.f) / (EXAMPLE_FOC_MCPWM_TIMER_RESOLUTION_HZ / EXAMPLE_FOC_WAVE_FREQ); if (elec_theta_deg > 360) { elec_theta_deg -= 360; }{...} elec_theta_rad = _IQmpy(_IQ(elec_theta_deg), _IQ(M_PI / 180.f)); // In FOC motor control, we usually set Vd for alignment or weak-meg control, and set Vq for torque control. // As here is open loop output, use Vd is enough, and coord aligned dq_out.d = _IQ(EXAMPLE_FOC_WAVE_AMPL); foc_inverse_park_transform(elec_theta_rad, &dq_out, &ab_out); #if CONFIG_ESP_FOC_USE_SVPWM foc_svpwm_duty_calculate(&ab_out, &uvw_out); #else // Use spwm (sin pwm) instead. (see menuconfig help to know difference between SVPWM and SPWM) foc_inverse_clarke_transform(&ab_out, &uvw_out); #endif // Regular uvw data to (0 ~ (EXAMPLE_FOC_MCPWM_PERIOD/2)) uvw_duty[0] = _IQtoF(_IQdiv2(uvw_out.u)) + (EXAMPLE_FOC_MCPWM_PERIOD / 4); uvw_duty[1] = _IQtoF(_IQdiv2(uvw_out.v)) + (EXAMPLE_FOC_MCPWM_PERIOD / 4); uvw_duty[2] = _IQtoF(_IQdiv2(uvw_out.w)) + (EXAMPLE_FOC_MCPWM_PERIOD / 4); // output pwm duty ESP_ERROR_CHECK(svpwm_inverter_set_duty(inverter1, uvw_duty[0], uvw_duty[1], uvw_duty[2])); }{...} bsp_bridge_driver_enable(false); ESP_ERROR_CHECK(svpwm_inverter_start(inverter1, MCPWM_TIMER_STOP_EMPTY)); ESP_ERROR_CHECK(svpwm_del_inverter(inverter1)); }{ ... }
Details
Show:
from
Types: Columns:
This file uses the notable symbols shown below. Click anywhere in the file to view more details.