Skip to content

Commit df435c4

Browse files
committed
Merge branch 'feat/esp_simplefoc_support_6pwm_driver' into 'master'
feat: esp_simplefoc support 6pwm driver Closes AEGHB-889 See merge request ae_group/esp-iot-solution!1153
2 parents b7c99f5 + b4f0387 commit df435c4

File tree

7 files changed

+351
-2
lines changed

7 files changed

+351
-2
lines changed

components/motor/esp_simplefoc/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# ChangeLog
22

3+
## v1.1.0 - 2024-11-26
4+
### Enhancements:
5+
* FOC:
6+
* Support 6PWM driver. Note that only chips that support ``MCPWM`` can use 6PWM driver.
7+
38
## v1.0.0 - 2024-9-20
49
### Enhancements:
510
* FOC:

components/motor/esp_simplefoc/CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@ set(SRC_FILES
99
"port/angle_sensor/mt6701.cpp"
1010
"port/angle_sensor/as5048a.cpp")
1111

12+
if(CONFIG_SOC_MCPWM_SUPPORTED)
13+
list(APPEND SRC_FILES "port/esp/esp_hal_bldc_6pwm.cpp")
14+
endif()
15+
1216
set(INC_FILES "port/esp/include/" "port/angle_sensor")
13-
set(IGNORE_FILES "port/esp/esp_hal_adc.cpp" "port/esp/esp_hal_mcpwm.cpp"
17+
set(IGNORE_FILES "port/esp/esp_hal_adc.cpp" "port/esp/esp_hal_bldc_6pwm.cpp"
1418
"port/esp/esp_hal_bldc_3pwm.cpp" "port/angle_sensor/mt6701.cpp" "port/angle_sensor/as5048a.cpp")
1519

1620
idf_component_register(

components/motor/esp_simplefoc/idf_component.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: 1.0.0
1+
version: 1.1.0
22
targets:
33
- esp32
44
- esp32s2
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include "esp_hal_bldc_6pwm.h"
8+
#include "esp_log.h"
9+
#include "esp_check.h"
10+
11+
#define _PWM_FREQUENCY 20000 /*!< default frequency of MCPWM */
12+
#define _PWM_FREQUENCY_MAX 50000 /*!< Max frequency of MCPWM */
13+
#define _PWM_TIMEBASE_RESOLUTION_HZ (10 * 1000 * 1000) /*!< Resolution of MCPWM */
14+
15+
static const char* TAG = "esp_hal_bldc_6pwm";
16+
17+
BLDCDriver6PWM::BLDCDriver6PWM(int phA_h, int phA_l, int phB_h, int phB_l, int phC_h, int phC_l, int en, int mcpwm_group_id)
18+
{
19+
pwmA_h = phA_h;
20+
pwmB_h = phB_h;
21+
pwmC_h = phC_h;
22+
pwmA_l = phA_l;
23+
pwmB_l = phB_l;
24+
pwmC_l = phC_l;
25+
26+
// enable_pin pin
27+
enable_pin = en;
28+
29+
// default power-supply value
30+
voltage_power_supply = DEF_POWER_SUPPLY;
31+
voltage_limit = NOT_SET;
32+
pwm_frequency = NOT_SET;
33+
34+
// dead zone initial - 2%
35+
dead_zone = 0.02f;
36+
37+
this->mcpwm_group_id = mcpwm_group_id;
38+
}
39+
40+
void BLDCDriver6PWM::enable()
41+
{
42+
// enable_pin the driver - if enable_pin pin available
43+
if (_isset(enable_pin)) {
44+
digitalWrite(enable_pin, enable_active_high);
45+
}
46+
// set phase state enabled
47+
setPhaseState(PhaseState::PHASE_ON, PhaseState::PHASE_ON, PhaseState::PHASE_ON);
48+
// set zero to PWM
49+
setPwm(0, 0, 0);
50+
}
51+
52+
void BLDCDriver6PWM::disable()
53+
{
54+
// set phase state to disabled
55+
setPhaseState(PhaseState::PHASE_OFF, PhaseState::PHASE_OFF, PhaseState::PHASE_OFF);
56+
// set zero to PWM
57+
setPwm(0, 0, 0);
58+
// disable the driver - if enable_pin pin available
59+
if (_isset(enable_pin)) {
60+
digitalWrite(enable_pin, !enable_active_high);
61+
}
62+
}
63+
64+
int BLDCDriver6PWM::init()
65+
{
66+
// PWM pins
67+
pinMode(pwmA_h, OUTPUT);
68+
pinMode(pwmB_h, OUTPUT);
69+
pinMode(pwmC_h, OUTPUT);
70+
pinMode(pwmA_l, OUTPUT);
71+
pinMode(pwmB_l, OUTPUT);
72+
pinMode(pwmC_l, OUTPUT);
73+
if (_isset(enable_pin)) {
74+
pinMode(enable_pin, OUTPUT);
75+
}
76+
77+
// sanity check for the voltage limit configuration
78+
if (!_isset(voltage_limit) || voltage_limit > voltage_power_supply) {
79+
voltage_limit = voltage_power_supply;
80+
}
81+
82+
// set phase state to disabled
83+
phase_state[0] = PhaseState::PHASE_OFF;
84+
phase_state[1] = PhaseState::PHASE_OFF;
85+
phase_state[2] = PhaseState::PHASE_OFF;
86+
87+
// set zero to PWM
88+
dc_a = dc_b = dc_c = 0;
89+
90+
// configure 6pwm
91+
// hardware specific function - depending on driver and mcu
92+
if (mcpwm_group_id < 0 || mcpwm_group_id >= SOC_MCPWM_GROUPS) {
93+
ESP_LOGE(TAG, "MCPWM group id: %d is not available\n", mcpwm_group_id);
94+
return 0;
95+
}
96+
97+
// Init mcpwm driver
98+
mcpwm_timer_config_t timer_config = {
99+
.group_id = mcpwm_group_id,
100+
.clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,
101+
.resolution_hz = _PWM_TIMEBASE_RESOLUTION_HZ,
102+
.count_mode = MCPWM_TIMER_COUNT_MODE_UP_DOWN,
103+
.period_ticks = (uint32_t)(1 * _PWM_TIMEBASE_RESOLUTION_HZ / _PWM_FREQUENCY),
104+
};
105+
ESP_ERROR_CHECK(mcpwm_new_timer(&timer_config, &timer));
106+
107+
mcpwm_operator_config_t operator_config = {
108+
.group_id = mcpwm_group_id,
109+
};
110+
111+
for (int i = 0; i < 3; i++) {
112+
ESP_ERROR_CHECK(mcpwm_new_operator(&operator_config, &oper[i]));
113+
ESP_ERROR_CHECK(mcpwm_operator_connect_timer(oper[i], timer));
114+
}
115+
116+
mcpwm_comparator_config_t comparator_config = {0};
117+
comparator_config.flags.update_cmp_on_tez = true;
118+
comparator_config.flags.update_cmp_on_tep = false;
119+
comparator_config.flags.update_cmp_on_sync = false;
120+
121+
for (int i = 0; i < 3; i++) {
122+
ESP_ERROR_CHECK(mcpwm_new_comparator(oper[i], &comparator_config, &comparator[i]));
123+
ESP_ERROR_CHECK(mcpwm_comparator_set_compare_value(comparator[i], (0)));
124+
}
125+
126+
mcpwm_generator_config_t generator_config = {};
127+
int gen_gpios[3][2] = {
128+
{pwmA_h, pwmA_l},
129+
{pwmB_h, pwmB_l},
130+
{pwmC_h, pwmC_l},
131+
};
132+
133+
for (int i = 0; i < 3; i++) {
134+
for (int j = 0; j < 2; j++) {
135+
generator_config.gen_gpio_num = gen_gpios[i][j];
136+
ESP_ERROR_CHECK(mcpwm_new_generator(oper[i], &generator_config, &generator[i][j]));
137+
}
138+
}
139+
140+
for (int i = 0; i < 3; i++) {
141+
ESP_ERROR_CHECK(mcpwm_generator_set_actions_on_compare_event(generator[i][0],
142+
MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, comparator[i], MCPWM_GEN_ACTION_LOW),
143+
MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_DOWN, comparator[i], MCPWM_GEN_ACTION_HIGH),
144+
MCPWM_GEN_COMPARE_EVENT_ACTION_END()));
145+
}
146+
147+
mcpwm_dead_time_config_t dt_config = {
148+
.posedge_delay_ticks = (uint32_t)(dead_zone * timer_config.period_ticks),
149+
};
150+
151+
mcpwm_dead_time_config_t inv_dt_config = {
152+
.negedge_delay_ticks = (uint32_t)(dead_zone * timer_config.period_ticks),
153+
};
154+
inv_dt_config.flags.invert_output = true;
155+
156+
for (int i = 0; i < 3; i++) {
157+
ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(generator[i][0], generator[i][0], &dt_config));
158+
ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(generator[i][0], generator[i][1], &inv_dt_config));
159+
}
160+
161+
// enable mcpwm
162+
ESP_ERROR_CHECK(mcpwm_timer_enable(timer));
163+
ESP_ERROR_CHECK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_START_NO_STOP));
164+
165+
// save timer period
166+
mcpwm_period = timer_config.period_ticks / 2;
167+
initialized = 1;
168+
169+
return 1;
170+
}
171+
172+
int BLDCDriver6PWM::deinit()
173+
{
174+
if (initialized) {
175+
ESP_ERROR_CHECK(mcpwm_timer_disable(timer));
176+
177+
for (int i = 0; i < 3; i++) {
178+
ESP_ERROR_CHECK(mcpwm_del_generator(generator[i][0]));
179+
ESP_ERROR_CHECK(mcpwm_del_generator(generator[i][1]));
180+
ESP_ERROR_CHECK(mcpwm_del_comparator(comparator[i]));
181+
ESP_ERROR_CHECK(mcpwm_del_operator(oper[i]));
182+
}
183+
ESP_ERROR_CHECK(mcpwm_del_timer(timer));
184+
initialized = 0;
185+
return 1;
186+
}
187+
188+
return 0;
189+
}
190+
191+
void BLDCDriver6PWM::setPwm(float Ua, float Ub, float Uc)
192+
{
193+
// limit the voltage in driver
194+
Ua = _constrain(Ua, 0, voltage_limit);
195+
Ub = _constrain(Ub, 0, voltage_limit);
196+
Uc = _constrain(Uc, 0, voltage_limit);
197+
// calculate duty cycle
198+
// limited in [0,1]
199+
dc_a = _constrain(Ua / voltage_power_supply, 0.0f, 1.0f);
200+
dc_b = _constrain(Ub / voltage_power_supply, 0.0f, 1.0f);
201+
dc_c = _constrain(Uc / voltage_power_supply, 0.0f, 1.0f);
202+
// hardware specific writing
203+
// hardware specific function - depending on driver and mcu
204+
halPwmWrite();
205+
}
206+
207+
void BLDCDriver6PWM::setPhaseState(PhaseState sa, PhaseState sb, PhaseState sc)
208+
{
209+
phase_state[0] = sa;
210+
phase_state[1] = sb;
211+
phase_state[2] = sc;
212+
}
213+
214+
void BLDCDriver6PWM::halPwmWrite()
215+
{
216+
if (!initialized) {
217+
return;
218+
}
219+
220+
ESP_ERROR_CHECK(mcpwm_comparator_set_compare_value(comparator[0], (uint32_t)((mcpwm_period * dc_a))));
221+
ESP_ERROR_CHECK(mcpwm_comparator_set_compare_value(comparator[1], (uint32_t)((mcpwm_period * dc_b))));
222+
ESP_ERROR_CHECK(mcpwm_comparator_set_compare_value(comparator[2], (uint32_t)((mcpwm_period * dc_c))));
223+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
#pragma once
7+
8+
#include "BLDCDriver.h"
9+
#include "foc_utils.h"
10+
#include "time_utils.h"
11+
#include "defaults.h"
12+
#include "drivers/hardware_api.h"
13+
#include "driver/mcpwm_prelude.h"
14+
15+
class BLDCDriver6PWM : public BLDCDriver {
16+
public:
17+
/**
18+
* @brief Construct a new BLDCDriver6PWM object
19+
*
20+
* @param phA_h High-side PWM pin for phase A
21+
* @param phA_l Low-side PWM pin for phase A
22+
* @param phB_h High-side PWM pin for phase B
23+
* @param phB_l Low-side PWM pin for phase B
24+
* @param phC_h High-side PWM pin for phase C
25+
* @param phC_l Low-side PWM pin for phase C
26+
* @param en Optional enable pin (default: NOT_SET)
27+
* @param mcpwm_group_id The MCPWM group ID to be used (default: 0)
28+
*/
29+
BLDCDriver6PWM(int phA_h, int phA_l, int phB_h, int phB_l, int phC_h, int phC_l, int en = NOT_SET, int mcpwm_group_id = 0);
30+
31+
/**
32+
* @brief Motor hardware init function
33+
*
34+
* @return
35+
* - 0 Failed
36+
* - 1 Success
37+
*/
38+
int init() override;
39+
40+
/**
41+
* @brief Motor hardware deinit function
42+
*
43+
* @return
44+
* - 0 Failed
45+
* - 1 Success
46+
*/
47+
int deinit();
48+
49+
/**
50+
* @brief Motor disable function
51+
*
52+
*/
53+
void disable() override;
54+
55+
/**
56+
* @brief Motor enable function
57+
*
58+
*/
59+
void enable() override;
60+
61+
// hardware variables
62+
int pwmA_h, pwmA_l; /*!< phase A pwm pin number */
63+
int pwmB_h, pwmB_l; /*!< phase B pwm pin number */
64+
int pwmC_h, pwmC_l; /*!< phase C pwm pin number */
65+
int enable_pin; /*!< enable pin number */
66+
int mcpwm_group_id; /*!< mcpwm group id */
67+
bool enable_active_high = true;
68+
float dead_zone; /*!< a percentage of dead-time(zone) (both high and low side in low) for each pwm cycle [0,1] */
69+
PhaseState phase_state[3]; /*!< phase state (active / disabled) */
70+
71+
/**
72+
* @brief Set voltage to the pwm pin
73+
*
74+
* @param Ua phase A voltage
75+
* @param Ub phase B voltage
76+
* @param Uc phase C voltage
77+
*/
78+
void setPwm(float Ua, float Ub, float Uc) override;
79+
80+
/**
81+
* @brief Set the phase state
82+
*
83+
* @param sa phase A state
84+
* @param sb phase B state
85+
* @param sc phase C state
86+
*/
87+
virtual void setPhaseState(PhaseState sa, PhaseState sb, PhaseState sc) override;
88+
89+
/**
90+
* @brief PWM generating function
91+
*
92+
*/
93+
void halPwmWrite();
94+
95+
private:
96+
uint32_t mcpwm_period;
97+
mcpwm_timer_handle_t timer = NULL;
98+
mcpwm_oper_handle_t oper[3];
99+
mcpwm_cmpr_handle_t comparator[3];
100+
mcpwm_gen_handle_t generator[3][2];
101+
};

components/motor/esp_simplefoc/port/esp/include/esp_simplefoc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "esp_platform.h"
99
#include "BLDCMotor.h"
1010
#include "esp_hal_bldc_3pwm.h"
11+
#include "esp_hal_bldc_6pwm.h"
1112
#include "communication/SimpleFOCDebug.h"
1213
#include "communication/Commander.h"
1314
#include "sensors/GenericSensor.h"

components/motor/esp_simplefoc/test_apps/main/test_esp_simplefoc.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,21 @@ TEST_CASE("test as5048a", "[sensor][as5048a][spi]")
7878
as5048a.deinit();
7979
}
8080

81+
#if CONFIG_SOC_MCPWM_SUPPORTED
82+
TEST_CASE("test 6pwm driver", "[driver][6pwm]")
83+
{
84+
BLDCDriver6PWM driver = BLDCDriver6PWM(1, 2, 3, 4, 5, 6);
85+
TEST_ASSERT_EQUAL(driver.init(), 1);
86+
driver.dc_a = 0.2;
87+
driver.dc_b = 0.4;
88+
driver.dc_c = 0.8;
89+
90+
driver.halPwmWrite();
91+
vTaskDelay(2000 / portTICK_PERIOD_MS);
92+
driver.deinit();
93+
}
94+
#endif
95+
8196
TEST_CASE("test esp_simplefoc openloop control", "[single motor][openloop][14pp][ledc][drv8313][c3]")
8297
{
8398
BLDCMotor motor = BLDCMotor(14);

0 commit comments

Comments
 (0)