Hello,
I am trying to control a BLDC, gimbal motor using 3 PWM signals, one for each phase, to obtain accurate positioning at low speeds. I use an Arduino Nano ESP32 (previously an Arduino Micro, which worked but is too slow). The 3 PWM signals (MCPWM) need to be synced; otherwise, the motor makes a high-pitched noise.
Here is a part of my code where this is handled:
#ifndef motor_h
#define motor_h
#include "Arduino.h"
#include "driver/mcpwm.h"
#include "config.h"
void motor_init(){
// Initialize MCPWM GPIO
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, MOTOR_PIN_PWM_a);
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM1A, MOTOR_PIN_PWM_b);
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM2A, MOTOR_PIN_PWM_c);
// Configure MCPWM unit 0
mcpwm_config_t pwm_config;
pwm_config.frequency = 10000; // Frequency = 10kHz
pwm_config.cmpr_a = 50.0; // Initial duty cycle of PWMxA = 50%
pwm_config.cmpr_b = 50.0; // Initial duty cycle of PWMxB = 0%
pwm_config.counter_mode = MCPWM_UP_DOWN_COUNTER; // Up-down count mode
pwm_config.duty_mode = MCPWM_DUTY_MODE_0; // Active HIGH
// Initialize PWM0A, PWM1A, and PWM2A with the same configuration
mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config);
mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_1, &pwm_config);
mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_2, &pwm_config);
mcpwm_sync_config_t sync_conf = {
.sync_sig = MCPWM_SELECT_TIMER0_SYNC,
.timer_val = 0,
.count_direction = MCPWM_TIMER_DIRECTION_UP
};
mcpwm_sync_configure(MCPWM_UNIT_0, MCPWM_TIMER_0, &sync_conf);
mcpwm_sync_configure(MCPWM_UNIT_0, MCPWM_TIMER_1, &sync_conf);
mcpwm_sync_configure(MCPWM_UNIT_0, MCPWM_TIMER_2, &sync_conf);
// Enable sync event for all timers to be the TEZ of timer0
mcpwm_set_timer_sync_output(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_SWSYNC_SOURCE_TEZ);
pinMode(MOTOR_PIN_ENABLE , OUTPUT);
}
void motor_write_pwm(float pwm_a, float pwm_b, float pwm_c){
// Update PWM duty cycles
mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A, pwm_a);
mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_A, pwm_b);
mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_2, MCPWM_OPR_A, pwm_c);
}
void motor_enable() {
digitalWrite(MOTOR_PIN_ENABLE, HIGH);
motor_write_pwm(0,0,0);
}
void motor_disable() {
digitalWrite(MOTOR_PIN_ENABLE, LOW);
motor_write_pwm(0,0,0);
}
void motor_turn_to_angle(float motor_angle,uint16_t voltage_peak){
motor_angle = motor_angle * number_of_pole_pairs;
// Calculate duty cycle for each phase
float pwm_a = 100.0* (voltage_peak * sin(motor_angle) + voltage_power_input / 2) / voltage_power_input ;
float pwm_b = 100.0* (voltage_peak * sin(motor_angle + PI*120/180) + voltage_power_input / 2) / voltage_power_input;
float pwm_c = 100.0* (voltage_peak * sin(motor_angle + PI*240/180) + voltage_power_input / 2) / voltage_power_input;
motor_write_pwm(pwm_a,pwm_b,pwm_c);
}
#endif
Has anyone an idea how to correctly sync these pwm signals?
Tanks for your help!
Kind regards,
Maarten