Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESP_SimpleFOC 6PWM driver (AEGHB-889) #432

Closed
3 tasks done
HirenDayro017 opened this issue Nov 22, 2024 · 12 comments
Closed
3 tasks done

ESP_SimpleFOC 6PWM driver (AEGHB-889) #432

HirenDayro017 opened this issue Nov 22, 2024 · 12 comments
Labels

Comments

@HirenDayro017
Copy link

Answers checklist.

  • I have read the documentation ESP-IDF Programming Guide and the issue is not addressed there.
  • I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there.
  • I have searched the issue tracker for a similar issue and not found a similar issue.

General issue report

How soon can we get esp_hal_bldc_6pwm driver for a bldc driver that needs 6pwm?

@github-actions github-actions bot changed the title ESP_SimpleFOC 6PWM driver ESP_SimpleFOC 6PWM driver (AEGHB-889) Nov 22, 2024
@YanKE01
Copy link
Contributor

YanKE01 commented Nov 24, 2024

Support for the 6PWM driver will begin soon. The 6PWM driver can only run on chips that support MCPWM, and it will take some time to test it.

@HirenDayro017
Copy link
Author

ok, thanks. That's great to hear.

@dayro-ram
Copy link

@YanKE01 , I have tried to make a library for 6PWM but not sure why it doesn't work. If you could debug the code, that would be great, as we are running late on key milestones. Kindly note this is based on esp_hal_bldc_3pwm library files.
Here is my esp_hal_bldc_6pwm.h
/*

  • SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
  • SPDX-License-Identifier: Apache-2.0
    */

#pragma once

#include
#include "BLDCDriver.h"
#include "foc_utils.h"
#include "time_utils.h"
#include "defaults.h"
#include "drivers/hardware_api.h"
#include "driver/ledc.h"

#ifdef CONFIG_SOC_MCPWM_SUPPORTED
#include "driver/mcpwm_prelude.h"
#endif

#define _PWM_FREQUENCY 20000 /*!< default frequency of MCPWM /
#define _PWM_FREQUENCY_MAX 50000 /
!< Max frequency of MCPWM /
#define _PWM_TIMEBASE_RESOLUTION_HZ (10 * 1000 * 1000) /
!< Resolution of MCPWM /
#define _LEDC_TIMER LEDC_TIMER_0 /
!< Timer od LEDC /
#define _LEDC_MODE LEDC_LOW_SPEED_MODE /
!< Speed Mode of LEDC /
#define _LEDC_DUTY_RES LEDC_TIMER_9_BIT /
!< Resolution of LEDC /
#define _LEDC_DUTY (511) /
!< Max duty of LEDC /
#define _LEDC_FREQUENCY (20 * 1000) /
!< Frequency of LEDC */

enum class DriverMode {
mcpwm = 0, /*!< Foc hardware drive mode:MCPWM /
ledc = 1, /
!< Foc hardware drive mode:LEDC */
};

class BLDCDriver6PWM : public BLDCDriver {
public:
/**
* @brief Construct a new BLDCDriver6PWM object
* @param phA_h A phase pwm pin
* @param phA_l A phase pwm pin
* @param phB_h B phase pwm pin
* @param phB_l A phase pwm pin
* @param phC_h C phase pwm pin
* @param phC_l A phase pwm pin
* @param en1 enable pin (optional input)
* @param en2 enable pin (optional input)
* @param en3 enable pin (optional input)
*/
BLDCDriver6PWM(int phA_h,int phA_l, int phB_h,int phB_l, int phC_h, int phC_l, int en1 = NOT_SET);

/**
 * @brief Motor hardware init function.
 *
 * @return
 *     - 0 Failed
 *     - 1 Success
 */
int init() override;

#ifdef CONFIG_SOC_MCPWM_SUPPORTED
/**
* @brief Motor hardware init function, using MCPWM.
*
* @param _mcpwm_group mcpwm group, such as 0
* @return
* - 0 Failed
* - 1 Success
*/
int init(int _mcpwm_group);
#endif

/**
 * @brief Motor hardware init function, using LEDC.
 *
 * @param _ledc_channels ledc channel, such as {1,2,3}
 * @return
 *     - 0 Failed
 *     - 1 Success
 */
// int init(std::vector<int> _ledc_channels);

/**
 * @brief Motor hardware deinit function.
 *
 * @return
 *     - 0 Failed
 *     - 1 Success
 */
int deinit();

/**
 * @brief Motor disable function.
 *
 */
void disable() override;

/**
 * @brief Motor enable function.
 *
 */
void enable() override;

// hardware variables
int pwmA_h;                       /*!< phase A high side pwm pin number */
int pwmA_l;                       /*!< phase A low side pwm pin number */
int pwmB_h;                       /*!< phase B high side pwm pin number */
int pwmB_l;                       /*!< phase B low side pwm pin number */
int pwmC_h;                       /*!< phase C high side pwm pin number */
int pwmC_l;                       /*!< phase C low side pwm pin number */
int enableA_pin;                /*!< enable pin number */
bool enable_active_high = true; /*!< enable driver level */

/**
 * Set phase voltages to the hardware.
 *
 * @param Ua - phase A voltage
 * @param Ub - phase B voltage
 * @param Uc - phase C voltage
 */
void setPwm(float Ua, float Ub, float Uc) override;

/**
 * @brief Set phase voltages to the hardware.
 *
 * @param sa phase A state : active / disabled ( high impedance )
 * @param sb phase B state : active / disabled ( high impedance )
 * @param sc phase C state : active / disabled ( high impedance )
 */
virtual void setPhaseState(PhaseState sa, PhaseState sb, PhaseState sc) override;

/**
 * @brief PWM generating function.
 *
 */
void halPwmWrite();

private:
DriverMode driverMode;
std::vector ledc_channels;
uint32_t mcpwm_period;
#ifdef CONFIG_SOC_MCPWM_SUPPORTED
int mcpwm_group;
mcpwm_timer_handle_t timer = NULL;
mcpwm_gen_handle_t generator[3][2] = {};
mcpwm_cmpr_handle_t comparator[3];
mcpwm_oper_handle_t oper[3];
#endif
};

Here is my esp_hal_bldc_6pwm.cpp
/*

  • SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
  • SPDX-License-Identifier: Apache-2.0
    */

#include
#include "esp_hal_bldc_6pwm.h"

#ifdef CONFIG_SOC_MCPWM_SUPPORTED
#define MCPWM_TIMER_CLK_SRC MCPWM_TIMER_CLK_SRC_DEFAULT
#endif

std::vector<std::pair<DriverMode, std::tuple<int, int>>> HardwareResource = {
{DriverMode::mcpwm, {0, 0}},
{DriverMode::mcpwm, {1, 0}},
{DriverMode::ledc, {0, 0}},
{DriverMode::ledc, {1, 0}},
{DriverMode::ledc, {2, 0}},
{DriverMode::ledc, {3, 0}},
{DriverMode::ledc, {4, 0}},
{DriverMode::ledc, {5, 0}},
{DriverMode::ledc, {6, 0}},
{DriverMode::ledc, {7, 0}},
{DriverMode::ledc, {8, 0}},
};

int auto_mcpwm_group = -1;
std::vector auto_ledc_channels(3, -1);
int auto_ledc_count = 0;

BLDCDriver6PWM::BLDCDriver6PWM(int phA_h,int phA_l, int phB_h,int phB_l, int phC_h, int phC_l, int en1)
{
// Pin initialization
pwmA_h = phA_h;
pwmA_l = phA_l;
pwmB_h = phB_h;
pwmB_l = phB_l;
pwmC_h = phC_h;
pwmC_l = phC_l;

// enable_pin pin
enableA_pin = en1;

// default power-supply value
voltage_power_supply = DEF_POWER_SUPPLY;
voltage_limit = NOT_SET;
pwm_frequency = NOT_SET;

}

void BLDCDriver6PWM::enable()
{
// enable_pin the driver - if enable_pin pin available
if (_isset(enableA_pin)) {
digitalWrite(enableA_pin, enable_active_high);
}

// set zero to PWM
setPwm(0, 0, 0);

}

void BLDCDriver6PWM::disable()
{
// set zero to PWM
setPwm(0, 0, 0);
// disable the driver - if enable_pin pin available
if (_isset(enableA_pin)) {
digitalWrite(enableA_pin, !enable_active_high);
}
}

void BLDCDriver6PWM::setPhaseState(PhaseState sa, PhaseState sb, PhaseState sc)
{
// disable if needed
if (_isset(enableA_pin) && _isset(enableB_pin) && _isset(enableC_pin)) {
digitalWrite(enableA_pin, sa == PhaseState::PHASE_ON ? enable_active_high : !enable_active_high);
}
}

// Set voltage to the pwm pin
void BLDCDriver6PWM::setPwm(float Ua, float Ub, float Uc)
{
// limit the voltage in driver
Ua = _constrain(Ua, 0.0f, voltage_limit);
Ub = _constrain(Ub, 0.0f, voltage_limit);
Uc = _constrain(Uc, 0.0f, voltage_limit);
// calculate duty cycle
// limited in [0,1]
dc_a = _constrain(Ua / voltage_power_supply, 0.0f, 0.25f);
dc_b = _constrain(Ub / voltage_power_supply, 0.0f, 0.25f);
dc_c = _constrain(Uc / voltage_power_supply, 0.0f, 0.25f);

halPwmWrite();

}

bool checkMcpwmGroupAvailable(int group_id)
{
for (const auto &kvp : HardwareResource) {
if (kvp.first == DriverMode::mcpwm) {
int mcpwm_group = std::get<0>(kvp.second);
int mcpwm_used = std::get<1>(kvp.second);

        if (mcpwm_group == group_id) {
            return !mcpwm_used;
        }
    }
}
return false;

}

bool checkLedcAvailable(std::vector ledc_channels)
{
int channeld_available_num = 0;
if (ledc_channels.size() != 3) {
printf("The number of channels is incorrect and should be set to 3");
return false;
}

for (auto channel : ledc_channels) {
    for (const auto &kvp : HardwareResource) {
        if (kvp.first == DriverMode::ledc) {
            int ledc_channel = std::get<0>(kvp.second);
            int ledc_channel_used = std::get<1>(kvp.second);
            if (channel == ledc_channel) {
                if (!ledc_channel_used) {
                    channeld_available_num++;
                }
            }
        }
    }
}

return channeld_available_num == 3;

}

int checkAvailableDriver()
{
auto_mcpwm_group = -1; // restore to default
// find mcpwm
for (auto &kvp : HardwareResource) {
if (kvp.first == DriverMode::mcpwm) {
if (std::get<1>(kvp.second) == 0) {
auto_mcpwm_group = std::get<0>(kvp.second);
break;
}
}
}

if (auto_mcpwm_group != -1) {
    printf("MCPWM Group: %d is idle\n", auto_mcpwm_group);
    return 1;
}

printf("no available mcpwm driver\n");

// find ledc
for (auto &kvp : HardwareResource) {
    if (kvp.first == DriverMode::ledc) {
        if (std::get<1>(kvp.second) == 0 && auto_ledc_count < 3) {
            auto_ledc_channels[auto_ledc_count++] = std::get<0>(kvp.second);
            continue;
        }
    }
}

if (auto_ledc_count == 3) {
    printf("Ledc channel: %d %d %d is idle\n", auto_ledc_channels[0], auto_ledc_channels[1], auto_ledc_channels[2]);
    auto_ledc_count = 0;
    return 2;
}

printf("no available ledc driver\n");

return 0;

}

void setMcpwmGroupUsed(int group_id)
{
for (auto &kvp : HardwareResource) {
if (kvp.first == DriverMode::mcpwm) {
int mcpwm_group = std::get<0>(kvp.second);
if (mcpwm_group == group_id) {
kvp.second = {mcpwm_group, 1};
}
}
}
}

void setMcpwmGroupUnUsed(int group_id)
{
for (auto &kvp : HardwareResource) {
if (kvp.first == DriverMode::mcpwm) {
int mcpwm_group = std::get<0>(kvp.second);
if (mcpwm_group == group_id) {
kvp.second = {mcpwm_group, 0};
}
}
}
}

void setLedcChannelUsed(std::vector ledc_channels)
{
for (auto channel : ledc_channels) {
for (auto &kvp : HardwareResource) {
if (kvp.first == DriverMode::ledc) {
int ledc_channel = std::get<0>(kvp.second);
if (channel == ledc_channel) {
kvp.second = {channel, 1};
}
}
}
}
}

void setLedcChannelUnUsed(std::vector ledc_channels)
{
for (auto channel : ledc_channels) {
for (auto &kvp : HardwareResource) {
if (kvp.first == DriverMode::ledc) {
int ledc_channel = std::get<0>(kvp.second);
if (channel == ledc_channel) {
kvp.second = {channel, 0};
}
}
}
}
}

int BLDCDriver6PWM::init()
{
int ret = -1;
// PWM pins
pinMode(pwmA_h, OUTPUT);
pinMode(pwmA_l, OUTPUT);
pinMode(pwmB_h, OUTPUT);
pinMode(pwmB_l, OUTPUT);
pinMode(pwmC_h, OUTPUT);
pinMode(pwmC_l, OUTPUT);
if (_isset(enableA_pin)) {
pinMode(enableA_pin, OUTPUT);
}

// sanity check for the voltage limit configuration
if (!_isset(voltage_limit) || voltage_limit > voltage_power_supply) {
    voltage_limit = voltage_power_supply;
}

// ESP32 Platform specific function. Auto select driver.
ret = checkAvailableDriver();
if (ret == 0) {
    initialized = 0;
    printf("No available Driver.\n");
    return 0;
}

#ifdef CONFIG_SOC_MCPWM_SUPPORTED
if (ret == 1) {
// mcpwm
driverMode = DriverMode::mcpwm;
setMcpwmGroupUsed(auto_mcpwm_group); // mark this group is used.
printf("Auto. Current Driver uses Mcpwm GroupId:%d\n", auto_mcpwm_group);

    // Init mcpwm driver.
    mcpwm_timer_config_t timer_config = {
        .group_id = auto_mcpwm_group,
        .clk_src = MCPWM_TIMER_CLK_SRC,
        .resolution_hz = _PWM_TIMEBASE_RESOLUTION_HZ,
        .count_mode = MCPWM_TIMER_COUNT_MODE_UP,                                      // centeral mode
        .period_ticks = (uint32_t)(1 * _PWM_TIMEBASE_RESOLUTION_HZ / _PWM_FREQUENCY), // real frequency is pwm_frequency/2
    };

    ESP_ERROR_CHECK(mcpwm_new_timer(&timer_config, &timer));

    mcpwm_operator_config_t operator_config = {
        .group_id = auto_mcpwm_group, // operator must be in the same group to the timer
    };

    for (int i = 0; i < 3; i++) {
        ESP_ERROR_CHECK(mcpwm_new_operator(&operator_config, &oper[i]));
    }

    for (int i = 0; i < 3; i++) {            
        ESP_ERROR_CHECK(mcpwm_operator_connect_timer(oper[i], timer));
    }

    mcpwm_comparator_config_t comparator_config = {0};
    comparator_config.intr_priority = 0;
    comparator_config.flags.update_cmp_on_tez = true;
    comparator_config.flags.update_cmp_on_tep = false;
    comparator_config.flags.update_cmp_on_sync = false;

    for (int i = 0; i < 3; i++) {
        ESP_ERROR_CHECK(mcpwm_new_comparator(oper[i], &comparator_config, &comparator[i]));
        ESP_ERROR_CHECK(mcpwm_comparator_set_compare_value(comparator[i], (0)));
    }

    mcpwm_generator_config_t generator_config = {};
    int gen_gpios[3][2] = {
                            {pwmA_h,pwmA_l},
                            {pwmB_h,pwmB_l}, 
                            {pwmC_h,pwmC_l}
    }; // six gpio port;

    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 2; j++){
            generator_config.gen_gpio_num = gen_gpios[i][j];
            ESP_ERROR_CHECK(mcpwm_new_generator(oper[i], &generator_config, &generator[i][j]));

        }
    }

    for (int i = 0; i < 3; i++) {
        ESP_ERROR_CHECK(mcpwm_generator_set_actions_on_timer_event(generator[i][0],
                                                                   MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH),
                                                                   MCPWM_GEN_TIMER_EVENT_ACTION_END()));
        // go low on compare threshold
        ESP_ERROR_CHECK(mcpwm_generator_set_actions_on_compare_event(generator[i][0],
                                                                   MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, comparator[i], MCPWM_GEN_ACTION_LOW),
                                                                   MCPWM_GEN_COMPARE_EVENT_ACTION_END()));
    }
    // mcpwm_dead_time_config_t dead_time_config; 
    mcpwm_dead_time_config_t dt_config;         // dead time config for positive pwm output
    mcpwm_dead_time_config_t inv_dt_config;
    dt_config.posedge_delay_ticks = 5;
    inv_dt_config.negedge_delay_ticks = 5;
    inv_dt_config.flags.invert_output = true;
    
    for (int i = 0; i < 3; i++) {
        mcpwm_generator_set_dead_time(generator[i][0], generator[i][0], &dt_config);
        mcpwm_generator_set_dead_time(generator[i][0], generator[i][1], &inv_dt_config);
    }

    // // enable mcpwm
    ESP_ERROR_CHECK(mcpwm_timer_enable(timer));
    ESP_ERROR_CHECK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_START_NO_STOP));

    mcpwm_period = timer_config.period_ticks;
    initialized = 1;
} else

#endif
if (ret == 2) {
// ledc
driverMode = DriverMode::ledc;
printf("Current Driver uses LEDC Channel:%d %d %d\n", auto_ledc_channels[0], auto_ledc_channels[1], auto_ledc_channels[2]);
ledc_channels = auto_ledc_channels;
setLedcChannelUsed(ledc_channels); // mark this ledc channel is used.

        ledc_timer_config_t ledc_timer = {
            .speed_mode = _LEDC_MODE,
            .duty_resolution = _LEDC_DUTY_RES,
            .timer_num = LEDC_TIMER_0,
            .freq_hz = _LEDC_FREQUENCY, // Set output frequency at 20 kHz

#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
.clk_cfg = LEDC_AUTO_CLK
#else
.clk_cfg = LEDC_USE_APB_CLK
#endif
};
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));

        int pins[3] = {pwmA_h, pwmB_h, pwmC_h}; // save pins

        ledc_channel_config_t ledc_channel;
        for (int i = 0; i < 3; i++) {
            ledc_channel.speed_mode = _LEDC_MODE;
            ledc_channel.timer_sel = LEDC_TIMER_0;
            ledc_channel.duty = 0;
            ledc_channel.hpoint = 0;
            ledc_channel.intr_type = LEDC_INTR_DISABLE;
            ledc_channel.channel = static_cast<ledc_channel_t>(ledc_channels[i]);
            ledc_channel.gpio_num = pins[i];
            ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
        }

        initialized = 1;
        mcpwm_period = _LEDC_DUTY;
    }

return 1;

}

#ifdef CONFIG_SOC_MCPWM_SUPPORTED
int BLDCDriver6PWM::init(int _mcpwm_group)
{
// PWM pins
pinMode(pwmA_h, OUTPUT);
pinMode(pwmA_l, OUTPUT);
pinMode(pwmB_h, OUTPUT);
pinMode(pwmB_l, OUTPUT);
pinMode(pwmC_h, OUTPUT);
pinMode(pwmC_l, OUTPUT);
if (_isset(enableA_pin)) {
pinMode(enableA_pin, OUTPUT);
}

// sanity check for the voltage limit configuration
if (!_isset(voltage_limit) || voltage_limit > voltage_power_supply) {
    voltage_limit = voltage_power_supply;
}

// ESP32 Platform specific function. Using mcpwm driver
driverMode = DriverMode::mcpwm;
if (checkMcpwmGroupAvailable(_mcpwm_group) == false) {
    printf("MCPWM GroupId:%d is not available\n", _mcpwm_group);
    initialized = 0;
    return 0;
}
setMcpwmGroupUsed(_mcpwm_group); // mark this group is used.
printf("Current Driver uses Mcpwm GroupId:%d\n", _mcpwm_group);

// Init mcpwm driver.
mcpwm_timer_config_t timer_config = {
    .group_id = _mcpwm_group,
    .clk_src = MCPWM_TIMER_CLK_SRC,
    .resolution_hz = _PWM_TIMEBASE_RESOLUTION_HZ,
    .count_mode = MCPWM_TIMER_COUNT_MODE_UP,                                      // centeral mode
    .period_ticks = (uint32_t)(1 * _PWM_TIMEBASE_RESOLUTION_HZ / _PWM_FREQUENCY), // real frequency is pwm_frequency/2
};
ESP_ERROR_CHECK(mcpwm_new_timer(&timer_config, &timer));

mcpwm_operator_config_t operator_config = {
    .group_id = _mcpwm_group, // operator must be in the same group to the timer
};

for (int i = 0; i < 6; i++) {
    ESP_ERROR_CHECK(mcpwm_new_operator(&operator_config, &oper[i]));
}

for (int i = 0; i < 6; i++) {
    ESP_ERROR_CHECK(mcpwm_operator_connect_timer(oper[i], timer));
}

mcpwm_comparator_config_t comparator_config = {0};
comparator_config.intr_priority = 0;
comparator_config.flags.update_cmp_on_tez = true;
comparator_config.flags.update_cmp_on_tep = false;
comparator_config.flags.update_cmp_on_sync = false;

for (int i = 0; i < 6; i++) {
    ESP_ERROR_CHECK(mcpwm_new_comparator(oper[i], &comparator_config, &comparator[i]));
    ESP_ERROR_CHECK(mcpwm_comparator_set_compare_value(comparator[i], (0)));
}

mcpwm_generator_config_t generator_config = {};
int gen_gpios[3][2] = {
                        {pwmA_h,pwmA_l},
                        {pwmB_h,pwmB_l}, 
                        {pwmC_h,pwmC_l}
}; // six gpio port;

for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 2; j++){
        generator_config.gen_gpio_num = gen_gpios[i][j];
        ESP_ERROR_CHECK(mcpwm_new_generator(oper[i], &generator_config, &generator[i][j]));

    }
}

for (int i = 0; i < 3; i++) {
    ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(generator[i][j],
                                                              MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH)));
    // go low on compare threshold
    ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(generator[i][j],
                                                                MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, comparator[i], MCPWM_GEN_ACTION_LOW)));
}

// mcpwm_dead_time_config_t dead_time_config; 
mcpwm_dead_time_config_t dt_config;         // dead time config for positive pwm output
mcpwm_dead_time_config_t inv_dt_config;
dt_config.posedge_delay_ticks = 5;
inv_dt_config.negedge_delay_ticks = 5;
inv_dt_config.flags.invert_output = true;

for (int i = 0; i < 3; i++) {
    ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(generator[i][0], generator[i][0], &dt_config));
    ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(generator[i][0], generator[i][1], &inv_dt_config));
}

// enable mcpwm
ESP_ERROR_CHECK(mcpwm_timer_enable(timer));
ESP_ERROR_CHECK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_START_NO_STOP));

mcpwm_period = timer_config.period_ticks;
initialized = 1;

return 1;

}
#endif

int BLDCDriver6PWM::init(std::vector _ledc_channels)
{
// PWM pins
pinMode(pwmA_h, OUTPUT);
pinMode(pwmA_l, OUTPUT);
pinMode(pwmB_h, OUTPUT);
pinMode(pwmB_l, OUTPUT);
pinMode(pwmC_h, OUTPUT);
pinMode(pwmC_l, OUTPUT);
if (_isset(enableA_pin)) {
pinMode(enableA_pin, OUTPUT);
}

// sanity check for the voltage limit configuration
if (!_isset(voltage_limit) || voltage_limit > voltage_power_supply) {
    voltage_limit = voltage_power_supply;
}

// ESP32 Platform specific function. Using ledc driver
driverMode = DriverMode::ledc;
if (checkLedcAvailable(_ledc_channels) == false) {
    printf("LEDC Channels is not available\n");
    initialized = 0;
    return 0;
}

printf("Current Driver uses LEDC Channel:%d %d %d\n", _ledc_channels[0], _ledc_channels[1], _ledc_channels[2]);
ledc_channels = _ledc_channels;
setLedcChannelUsed(ledc_channels); //  mark this ledc channel is used.

ledc_timer_config_t ledc_timer = {
    .speed_mode = _LEDC_MODE,
    .duty_resolution = _LEDC_DUTY_RES,
    .timer_num = LEDC_TIMER_0,
    .freq_hz = _LEDC_FREQUENCY, // Set output frequency at 20 kHz

#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
.clk_cfg = LEDC_AUTO_CLK
#else
.clk_cfg = LEDC_USE_APB_CLK
#endif
};
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));

int pins[3] = {pwmA_h, pwmB_h, pwmC_h}; // save pins

ledc_channel_config_t ledc_channel;
for (int i = 0; i < 6; i++) {
    ledc_channel.speed_mode = _LEDC_MODE;
    ledc_channel.timer_sel = LEDC_TIMER_0;
    ledc_channel.duty = 0;
    ledc_channel.hpoint = 0;
    ledc_channel.intr_type = LEDC_INTR_DISABLE;
    ledc_channel.channel = static_cast<ledc_channel_t>(ledc_channels[i]);
    ledc_channel.gpio_num = pins[i];
    ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
}

initialized = 1;
mcpwm_period = _LEDC_DUTY;

return 1;

}

int BLDCDriver6PWM::deinit()
{
switch (driverMode) {
case DriverMode::ledc:
for (int i = 0; i < 3; i++) {
if (ledc_stop(_LEDC_MODE, static_cast<ledc_channel_t>(ledc_channels[i]), 0) != ESP_OK) {
return 0;
}
}
setLedcChannelUnUsed(ledc_channels);
break;
#ifdef CONFIG_SOC_MCPWM_SUPPORTED
case DriverMode::mcpwm:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; i++) {
if (mcpwm_del_generator(generator[i])[j] != ESP_OK) {
return 0;
}
}

        if (mcpwm_del_comparator(comparator[i]) != ESP_OK) {
            return 0;
        }

        if (mcpwm_del_operator(oper[i]) != ESP_OK) {
            return 0;
        }
    }
    if (mcpwm_timer_disable(timer) != ESP_OK) {
        return 0;
    }

    if (mcpwm_del_timer(timer) != ESP_OK) {
        return 0;
    }

    setMcpwmGroupUnUsed(mcpwm_group);
    break;

#endif
default:
break;
}

initialized = 0;
return 1;

}

void BLDCDriver6PWM::halPwmWrite()
{
if (!initialized) {
return;
}

switch (driverMode) {
case DriverMode::ledc:
    ESP_ERROR_CHECK(ledc_set_duty(_LEDC_MODE, static_cast<ledc_channel_t>(ledc_channels[0]), (uint32_t)((mcpwm_period * dc_a))));
    ESP_ERROR_CHECK(ledc_update_duty(_LEDC_MODE, static_cast<ledc_channel_t>(ledc_channels[0])));
    ESP_ERROR_CHECK(ledc_set_duty(_LEDC_MODE, static_cast<ledc_channel_t>(ledc_channels[1]), (uint32_t)((mcpwm_period * dc_b))));
    ESP_ERROR_CHECK(ledc_update_duty(_LEDC_MODE, static_cast<ledc_channel_t>(ledc_channels[1])));
    ESP_ERROR_CHECK(ledc_set_duty(_LEDC_MODE, static_cast<ledc_channel_t>(ledc_channels[2]), (uint32_t)((mcpwm_period * dc_c))));
    ESP_ERROR_CHECK(ledc_update_duty(_LEDC_MODE, static_cast<ledc_channel_t>(ledc_channels[2])));
    break;

case DriverMode::mcpwm:
    // printf("\n Duty Cycle Ua : %ld Ub : %ld Uc : %ld", (uint32_t)((mcpwm_period * dc_a)), (uint32_t)((mcpwm_period * dc_b)), (uint32_t)((mcpwm_period * dc_c)));
    ESP_ERROR_CHECK(mcpwm_comparator_set_compare_value(comparator[0], (uint32_t)((mcpwm_period * dc_a))));
    ESP_ERROR_CHECK(mcpwm_comparator_set_compare_value(comparator[1], (uint32_t)((mcpwm_period * dc_b))));
    ESP_ERROR_CHECK(mcpwm_comparator_set_compare_value(comparator[2], (uint32_t)((mcpwm_period * dc_c))));
    break;
    
default:
    break;
}

}

@YanKE01
Copy link
Contributor

YanKE01 commented Nov 25, 2024

Hi, @dayro-ram .We're glad to see your interest in esp_simplefoc. For the 6PWM driver, we recommend keeping it in a separate file, similar to arduino-foc, as this makes it easier to troubleshoot issues. You can also provide your runtime logs to help us locate the problem more efficiently. Additionally, I have already implemented an initial version of the 6PWM driver and created a TEST_CASE. We will review and release it as soon as possible. Lastly, the current 3PWM driver has become overly complex, as it considers too many factors, such as automatically selecting available LEDC channels. We will simplify the entire process soon.

TEST_CASE("test 6pwm driver", "[driver][6pwm]")
{
    BLDCDriver6PWM driver = BLDCDriver6PWM(1, 2, 3, 4, 5, 6);
    driver.init();
    driver.dc_a = 0.2;
    driver.dc_b = 0.4;
    driver.dc_c = 0.8;

    while (1) {
        driver.halPwmWrite();
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

image

@leeebo leeebo added the motor label Nov 26, 2024
@dayro-ram
Copy link

@YanKE01 Thanks for your quick response. We will try following your suggestion to keep the 6PWM library in a separate component folder. For now we got 6PWM working by using Arduino as component. We look forward to get 6PWM working library soon. I have shared the code with a hope that the code help expedite the development. Thanks again.

@YanKE01
Copy link
Contributor

YanKE01 commented Nov 28, 2024

Hi @dayro-ram @HirenDayro017 . Thank you for your attention to esp_simplefoc. Support for the 6PWM mode has been added in version 1.1.0. Our next step will be to synchronize esp_simplefoc with the upstream version 2.3.4. We welcome your feedback on usage.

@dayro-ram
Copy link

HI @YanKE01 Thanks for quick support. We have tested foc_velocity_control example by changing necessary object instantiations & tested. The code is working. We will explore more and provide update if we encounter any issues.

@HirenDayro017
Copy link
Author

Hi @YanKE01 ,I tried the foc_knob_example with my "SparkFun IoT Brushless Motor Driver" board. Here is the code snippet:
Can you help me with what is the issue with this? The same motor with similar configuration works fine with Arduino Simple FOC Library.

/**********************************************************************************************************************/

/update motor parameters based on hardware design/
BLDCDriver6PWM driver = BLDCDriver6PWM(16, 17, 18, 23, 19,33,32,0);
BLDCMotor motor = BLDCMotor(7);
TMAG5273 tmag = TMAG5273(I2C_NUM_0, GPIO_NUM_22, GPIO_NUM_21);
uint8_t conversionAverage = TMAG5273_X32_CONVERSION;
uint8_t magneticChannel = TMAG5273_XYX_ENABLE;
uint8_t angleCalculation = TMAG5273_XY_ANGLE_CALCULATION;

void tmag_init(void)
{
esp_err_t ret;
tmag.init();

ret = tmag.setConvAvg(conversionAverage);
if(ret != ESP_OK){
    ESP_LOGE(TAG, "Conversion Average not set");
}else{
    ESP_LOGI(TAG, "Conversion Average set");
}

ret = tmag.setMagneticChannel(magneticChannel);
if(ret != ESP_OK){
    ESP_LOGE(TAG,"Magnetic Channel not set");
}else{
    ESP_LOGI(TAG, "Magnetic Channel set");
}

ret = tmag.setAngleEn(angleCalculation);
if(ret != ESP_OK){
    ESP_LOGE(TAG,"Angle reading not enabled");
}else{
    ESP_LOGI(TAG, "Angle reading enabled");
}    

}

/Motor initialization/
void motor_init(void)
{
SimpleFOCDebug::enable();
Serial.begin(115200);

tmag_init();
motor.LPF_angle = LowPassFilter(0.02);
motor.linkSensor(&tmag);
driver.voltage_power_supply = 5;
driver.voltage_limit = 4;

#if USING_MCPWM
driver.init();
#else
driver.init({LEDC_CHAN_0, LEDC_CHAN_1, LEDC_CHAN_2});
#endif

motor.linkDriver(&driver);

motor.foc_modulation = SpaceVectorPWM;
motor.controller = MotionControlType::torque;

motor.PID_velocity.P = 4.0;
motor.PID_velocity.I = 0.0;
motor.PID_velocity.D = 0.04;
motor.PID_velocity.output_ramp = 10000;
motor.PID_velocity.limit = 10;

motor.useMonitoring(Serial);
motor.enable();
motor.init();                                        // initialize motor
// motor.pole_pairs = MOTOR_PP;
motor.initFOC();                                     // align sensor and start FOC
ESP_LOGI(TAG, "Motor Initialize Successfully");

}

/**********************************************************************************************************************/

Here is the log:

PS D:\Other\foc_knob_example> & set IDF_PATH='C:/Espressif/frameworks/esp-idf-v5.1.5/'
PS D:\Other\foc_knob_example> & 'C:/Espressif/python_env/idf5.1_py3.11_env/Scripts/python.exe' 'C:\Espressif\frameworks\esp-idf-v5.1.5\tools\idf_monitor.py' -p COM11 -b 115200 --toolchain-prefix xtensa-esp32-elf- --target esp32 'd:\Other\foc_knob_example\build\foc_knob_example.elf'
--- Warning: GDB cannot open serial ports accessed as COMx
--- Using \.\COM11 instead...
--- esp-idf-monitor 1.5.0 on \.\COM11 115200
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H
ets Jul 29 2019 12:21:46

rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:7116
ho 0 tail 12 room 4
load:0x40078000,len:15624
ho 0 tail 12 room 4
load:0x40080400,len:4
--- 0x40080400: _init at ??:?

load:0x40080404,len:3876
entry 0x4008064c
I (33) boot: ESP-IDF v5.1.5-dirty 2nd stage bootloader
I (33) boot: compile time Dec 6 2024 11:36:25
I (33) boot: Multicore bootloader
I (38) boot: chip revision: v3.1
I (42) boot.esp32: SPI Speed : 40MHz
I (46) boot.esp32: SPI Mode : DIO
I (51) boot.esp32: SPI Flash Size : 16MB
I (55) boot: Enabling RNG early entropy source...
I (61) boot: Partition Table:
I (64) boot: ## Label Usage Type ST Offset Length
I (72) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (79) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (87) boot: 2 factory factory app 00 00 00010000 00100000
I (94) boot: End of partition table
I (98) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=21944h (137540) map
I (156) esp_image: segment 1: paddr=0003196c vaddr=3ff80000 size=00004h ( 4) load
I (157) esp_image: segment 2: paddr=00031978 vaddr=3ffb0000 size=023a0h ( 9120) load
I (166) esp_image: segment 3: paddr=00033d20 vaddr=40080000 size=0c2f8h ( 49912) load
I (191) esp_image: segment 4: paddr=00040020 vaddr=400d0020 size=53508h (341256) map
I (315) esp_image: segment 5: paddr=00093530 vaddr=4008c2f8 size=01628h ( 5672) load
I (324) boot: Loaded app from partition at offset 0x10000
I (324) boot: Disabling RNG early entropy source...
I (337) cpu_start: Multicore app
I (338) cpu_start: Pro cpu up.
I (338) cpu_start: Starting app cpu, entry point is 0x400813b0
--- 0x400813b0: call_start_cpu1 at C:/Espressif/frameworks/esp-idf-v5.1.5/components/esp_system/port/cpu_start.c:159

I (0) cpu_start: App cpu up.
I (355) cpu_start: Pro cpu start user code
I (356) cpu_start: cpu freq: 240000000 Hz
I (356) cpu_start: Application information:
I (360) cpu_start: Project name: foc_knob_example
I (366) cpu_start: App version: 1
I (370) cpu_start: Compile time: Dec 6 2024 11:36:09
I (377) cpu_start: ELF file SHA256: 225c88a1d5407ff5...
I (383) cpu_start: ESP-IDF: v5.1.5-dirty
I (388) cpu_start: Min chip rev: v0.0
I (393) cpu_start: Max chip rev: v3.99
I (397) cpu_start: Chip rev: v3.1
I (402) heap_init: Initializing. RAM available for dynamic allocation:
I (410) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (415) heap_init: At 3FFB4B38 len 0002B4C8 (173 KiB): DRAM
I (422) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (428) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (434) heap_init: At 4008D920 len 000126E0 (73 KiB): IRAM
I (442) spi_flash: detected chip: generic
I (445) spi_flash: flash io: dio
I (453) app_start: Starting scheduler on CPU0
I (454) app_start: Starting scheduler on CPU1
I (454) main_task: Started on CPU0
I (464) main_task: Calling app_main()
I (467) button: IoT Button Version: 3.1E (495) TMAG5273: angle enable read failure
I (497) FOC_Knob_Example: Conversion Average set
I (499) FOC_Knob_Example: Magnetic Channel set
I (502) FOC_Knob_Example: Angle reading enabled
I (505) gpio: GPIO[16]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (514) gpio: GPIO[18]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (524) gpio: GPIO[19]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (533) gpio: GPIO[17]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (542) gpio: GPIO[23]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (552) gpio: GPIO[33]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (561) gpio: GPIO[32]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (571) gpio: GPIO[16]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (580) gpio: GPIO[17]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (589) gpio: GPIO[18]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (598) gpio: GPIO[23]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (607) gpio: GPIO[19]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (617) gpio: GPIO[33]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
MOT: Monitor enabled!
MOT: Init
MOT: Enable driver.
MOT: Align sensor.
MOT: sensor_direction==CW
MOT: PP check: fail - estimated pp: 0.0207517
MOT: Zero elec. angle: 2.46681
MOT: No current sense.
MOT: Ready.
I (6770) FOC_Knob_Example: Motor Initialize Successfully
I (6771) main_task: Returned from app_main()
--- Error: GetOverlappedResult failed (PermissionError(13, 'Access is denied.', None, 5))
--- Waiting for the device to reconnect....
}-���}ᅵ���� Conversion Average set
I (498) FOC_Knob_Example: Magnetic Channel set
I (500) FOC_Knob_Example: Angle reading enabled
I (501) gpio: GPIO[16]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (511) gpio: GPIO[18]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (520) gpio: GPIO[19]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (529) gpio: GPIO[17]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (538) gpio: GPIO[23]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (548) gpio: GPIO[33]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (557) gpio: GPIO[32]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (567) gpio: GPIO[16]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (576) gpio: GPIO[17]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (585) gpio: GPIO[18]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (594) gpio: GPIO[23]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (603) gpio: GPIO[19]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (613) gpio: GPIO[33]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
MOT: Monitor enabled!
MOT: Init
MOT: Enable driver.
MOT: Align sensor.
MOT: sensor_direction==CW
MOT: PP check: fail - estimated pp: 0.0212228
MOT: Zero elec. angle: 1.15431
MOT: No current sense.
MOT: Ready.
I (6765) FOC_Knob_Example: Motor Initialize Successfully
I (6766) main_task: Returned from app_main()
I (320486) FOC_Knob_Example: mode: 1
I (324596) FOC_Knob_Example: mode: 2
I (325566) FOC_Knob_Example: mode: 3
I (326249) FOC_Knob_Example: foc_knob_l_lim_cb
I (326621) FOC_Knob_Example: foc_knob_l_lim_cb
I (326823) FOC_Knob_Example: foc_knob_l_lim_cb
I (328245) FOC_Knob_Example: foc_knob_l_lim_cb
I (329011) FOC_Knob_Example: foc_knob_l_lim_cb
I (329761) FOC_Knob_Example: mode: 4
I (329843) FOC_Knob_Example: foc_knob_h_lim_cb
I (330019) FOC_Knob_Example: foc_knob_l_lim_cb
I (332097) FOC_Knob_Example: foc_knob_h_lim_cb
I (332215) FOC_Knob_Example: foc_knob_l_lim_cb
I (332423) FOC_Knob_Example: foc_knob_h_lim_cb
I (332537) FOC_Knob_Example: foc_knob_l_lim_cb
I (332641) FOC_Knob_Example: foc_knob_h_lim_cb
I (332723) FOC_Knob_Example: foc_knob_l_lim_cb
I (333521) FOC_Knob_Example: mode: 5
I (334179) FOC_Knob_Example: foc_knob_h_lim_cb
I (335549) FOC_Knob_Example: foc_knob_h_lim_cb
I (335559) FOC_Knob_Example: foc_knob_h_lim_cb
I (335605) FOC_Knob_Example: foc_knob_l_lim_cb
I (335729) FOC_Knob_Example: foc_knob_h_lim_cb
I (336826) FOC_Knob_Example: mode: 6
I (336851) FOC_Knob_Example: foc_knob_h_lim_cb
I (336857) FOC_Knob_Example: foc_knob_l_lim_cb
I (337379) FOC_Knob_Example: foc_knob_h_lim_cb
I (337485) FOC_Knob_Example: foc_knob_l_lim_cb
I (337899) FOC_Knob_Example: foc_knob_h_lim_cb
I (337949) FOC_Knob_Example: foc_knob_l_lim_cb
I (339166) FOC_Knob_Example: mode: 0

/**********************************************************************************************************************/

Here is how it behaves, the motor keeps hunting.

PXL_20241206_062958033.mp4

@YanKE01
Copy link
Contributor

YanKE01 commented Dec 6, 2024

Hi, @HirenDayro017 .From the log, it seems to be an error in the pole number estimation. Please fill in the correct pole number based on the specific motor parameters. I have encountered a situation before where the distance between the magnetic encoder and the magnetic ring was too far, which led to an incorrect pole number estimation. In any case, you can check whether the magnetic encoder is functioning properly. Additionally, You can also troubleshoot the problem by comparing the hardware output of arduino-foc. I don't have any 6PWM drivers around, so if you can, send me the PCB and I'll prototype and test it.

@HirenDayro017
Copy link
Author

Hi @YanKE01 , have a look at the log from the code in which I have added SimpleFOC as Arduino Component. The code works pretty fine in this case.

Simple FOC as Arduino Component:

"components/arduino/libraries/Simple_FOC/src/"

Here is the same configuration:

#define DRIVER_FAULT_GPIO 12
#define DRIVER_UH_GPIO 16
#define DRIVER_UL_GPIO 17
#define DRIVER_VH_GPIO 18
#define DRIVER_VL_GPIO 23
#define DRIVER_WH_GPIO 19
#define DRIVER_WL_GPIO 33

using namespace std;
static const char *TAG = "Knob_demo";

BLDCMotor motor = BLDCMotor(7);
BLDCDriver6PWM driver = BLDCDriver6PWM(DRIVER_UH_GPIO, DRIVER_UL_GPIO, DRIVER_VH_GPIO, DRIVER_VL_GPIO, DRIVER_WH_GPIO, DRIVER_WL_GPIO);

/**********************************************************************************************************************/

PS D:\Dayro\Knob> & set IDF_PATH='C:/Espressif/frameworks/esp-idf-v5.1.5/'
PS D:\Dayro\Knob> & 'C:/Espressif/python_env/idf5.1_py3.11_env/Scripts/python.exe' 'C:\Espressif\frameworks\esp-idf-v5.1.5\tools\idf_monitor.py' -p COM11 -b 115200 --toolchain-prefix xtensa-esp32-elf- --target esp32 'd:\Dayro\Knob\build\dayro_knob.elf'
--- Warning: GDB cannot open serial ports accessed as COMx
--- Using \.\COM11 instead...
--- esp-idf-monitor 1.5.0 on \.\COM11 115200
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H
ets Jul 29 2019 12:21:46

rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:7116
ho 0 tail 12 room 4
load:0x40078000,len:15624
ho 0 tail 12 room 4
load:0x40080400,len:4
--- 0x40080400: _init at ??:?

load:0x40080404,len:3876
entry 0x4008064c
I (33) boot: ESP-IDF v5.1.5-dirty 2nd stage bootloader
I (33) boot: compile time Dec 6 2024 12:38:16
I (33) boot: Multicore bootloader
I (38) boot: chip revision: v3.1
I (42) boot.esp32: SPI Speed : 40MHz
I (46) boot.esp32: SPI Mode : DIO
I (51) boot.esp32: SPI Flash Size : 16MB
I (55) boot: Enabling RNG early entropy source...
I (61) boot: Partition Table:
I (64) boot: ## Label Usage Type ST Offset Length
I (72) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (79) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (87) boot: 2 factory factory app 00 00 00010000 00177000
I (94) boot: End of partition table
I (98) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=3c19ch (246172) map
I (196) esp_image: segment 1: paddr=0004c1c4 vaddr=3ffb0000 size=03e54h ( 15956) load
I (202) esp_image: segment 2: paddr=00050020 vaddr=400d0020 size=dc130h (901424) map
I (528) esp_image: segment 3: paddr=0012c158 vaddr=3ffb3e54 size=00104h ( 260) load
I (528) esp_image: segment 4: paddr=0012c264 vaddr=40080000 size=17c5ch ( 97372) load
I (586) boot: Loaded app from partition at offset 0x10000
I (586) boot: Disabling RNG early entropy source...
I (598) cpu_start: Multicore app
I (599) cpu_start: Pro cpu up.
I (599) cpu_start: Starting app cpu, entry point is 0x400814cc
--- 0x400814cc: call_start_cpu1 at C:/Espressif/frameworks/esp-idf-v5.1.5/components/esp_system/port/cpu_start.c:159

I (0) cpu_start: App cpu up.
I (616) cpu_start: Pro cpu start user code
I (616) cpu_start: cpu freq: 160000000 Hz
I (616) cpu_start: Application information:
I (621) cpu_start: Project name: dayro_knob
I (626) cpu_start: App version: c13da90
I (631) cpu_start: Compile time: Dec 6 2024 12:37:33
I (637) cpu_start: ELF file SHA256: edc889d7cf080fa7...
I (643) cpu_start: ESP-IDF: v5.1.5-dirty
I (648) cpu_start: Min chip rev: v0.0
I (653) cpu_start: Max chip rev: v3.99
I (658) cpu_start: Chip rev: v3.1
I (663) heap_init: Initializing. RAM available for dynamic allocation:
I (670) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (676) heap_init: At 3FFBA428 len 00025BD8 (150 KiB): DRAM
I (682) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (688) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (695) heap_init: At 40097C5C len 000083A4 (32 KiB): IRAM
I (703) spi_flash: detected chip: generic
I (706) spi_flash: flash io: dio
I (714) app_start: Starting scheduler on CPU0
I (715) app_start: Starting scheduler on CPU1
I (715) main_taskI (733) Knob_demo: [APP] Startup..
I (734) Knob_demo: [APP] Free memory: 262336 bytes
I (734) Knob_demo: [APP] IDF version: v5.1.5-dirty
I (759) example_connect: Start example_connect.
I (762) wifi:wifi driver task: 3ffc3eb0, prio:23, stack:6656, core=0
I (776) wifi:wifi firmware version: bbd58fc31
I (776) wifi:wifi certification version: v7.0
I (776) wifi:config NVS flash: enabled
I (777) wifi:config nano formating: disabled
I (781) wifi:Init data frame dynamic rx buffer num: 32
I (786) wifi:Init static rx mgmt buffer num: 5
I (790) wifi:Init management short buffer num: 32
I (794) wifi:Init dynamic tx buffer num: 32
I (798) wifi:Init static rx buffer size: 1600
I (802) wifi:Init static rx buffer num: 10
I (806) wifi:Init dynamic rx buffer num: 32
I (811) wifi_init: rx ba win: 6
I (813) wifi_init: tcpip mbox: 32
I (817) wifi_init: udp mbox: 6
I (821) wifi_init: tcp mbox: 6
I (825) wifi_init: tcp tx win: 5760
I (829) wifi_init: tcp rx win: 5760
I (833) wifi_init: tcp mss: 1440
I (837) wifi_init: WiFi IRAM OP enabled
I (841) wifi_init: WiFi RX IRAM OP enabled
I (848) phy_init: phy_version 4840,02e0d70,Sep 2 2024,19:39:07
I (932) wifi:mode : sta (48:e7:29:96:43:10)
I (933) wifi:enable tsf
I (937) example_connect: Connecting to Airtel_dayro...
W (938) wifi:Password length matches WPA2 standards, authmode threshold changes from OPEN to WPA2
I (946) example_connect: Waiting for IP(s)
--- Error: GetOverlappedResult failed (PermissionError(13, 'Access is denied.', None, 5))
--- Waiting for the device to reconnect...
I (528) esp_image: segment 3: paddr=0012c158 vaddr=3ffb3e54 size=00104h ( 260) load
I (528) esp_image: segment 4: paddr=0012c264 vaddr=40080000 size=17c5ch ( 97372) load
I (586) boot: Loaded app from partition at offset 0x10000
I (586) boot: Disabling RNG early entropy source...
I (598) cpu_start: Multicore app
I (599) cpu_start: Pro cpu up.
I (599) cpu_start: Starting app cpu, entry point is 0x400814cc
--- 0x400814cc: call_start_cpu1 at C:/Espressif/frameworks/esp-idf-v5.1.5/components/esp_system/port/cpu_start.c:159

I (0) cpu_start: App cpu up.
I (616) cpu_start: Pro cpu start user code
I (616) cpu_start: cpu freq: 160000000 Hz
I (616) cpu_start: Application information:
I (621) cpu_start: Project name: dayro_knob
I (626) cpu_start: App version: c13da90
I (631) cpu_start: Compile time: Dec 6 2024 12:37:33
I (637) cpu_start: ELF file SHA256: edc889d7cf080fa7...
I (643) cpu_start: ESP-IDF: v5.1.5-dirty
I (648) cpu_start: Min chip rev: v0.0
I (653) cpu_start: Max chip rev: v3.99
I (658) cpu_start: Chip rev: v3.1
I (663) heap_init: Initializing. RAM available for dynamic allocation:
I (670) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (676) heap_init: At 3FFBA428 len 00025BD8 (150 KiB): DRAM
I (682) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (688) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (695) heap_init: At 40097C5C len 000083A4 (32 KiB): IRAM
I (703) spi_flash: detected chip: generic
I (706) spi_flash: flash io: dio
I (714) app_start: Starting scheduler on CPU0
I (715) app_start: Starting scheduler on CPU1
I (715) main_taskI (733) Knob_demo: [APP] Startup..
I (734) Knob_demo: [APP] Free memory: 262336 bytes
I (734) Knob_demo: [APP] IDF version: v5.1.5-dirty
I (759) example_connect: Start example_connect.
I (762) wifi:wifi driver task: 3ffc3eb0, prio:23, stack:6656, core=0
I (776) wifi:wifi firmware version: bbd58fc31
I (776) wifi:wifi certification version: v7.0
I (776) wifi:config NVS flash: enabled
I (777) wifi:config nano formating: disabled
I (781) wifi:Init data frame dynamic rx buffer num: 32
I (786) wifi:Init static rx mgmt buffer num: 5
I (790) wifi:Init management short buffer num: 32
I (794) wifi:Init dynamic tx buffer num: 32
I (798) wifi:Init static rx buffer size: 1600
I (802) wifi:Init static rx buffer num: 10
I (806) wifi:Init dynamic rx buffer num: 32
I (811) wifi_init: rx ba win: 6
I (813) wifi_init: tcpip mbox: 32
I (817) wifi_init: udp mbox: 6
I (821) wifi_init: tcp mbox: 6
I (825) wifi_init: tcp tx win: 5760
I (829) wifi_init: tcp rx win: 5760
I (833) wifi_init: tcp mss: 1440
I (837) wifi_init: WiFi IRAM OP enabled
I (841) wifi_init: WiFi RX IRAM OP enabled
I (848) phy_init: phy_version 4840,02e0d70,Sep 2 2024,19:39:07
I (932) wifi:mode : sta (48:e7:29:96:43:10)
I (934) wifi:enable tsf
I (937) example_connect: Connecting to Airtel_dayro...
W (938) wifi:Password length matches WPA2 standards, authmode threshold changes from OPEN to WPA2
I (946) example_connect: Waiting for IP(s)
I (3604) wifi:new:<6,1>, old:<1,0>, ap:<255,255>, sta:<6,1>, prof:1
I (3606) wifi:state: init -> auth (b0)
I (3613) wifi:state: auth -> assoc (0)
I (3620) wifi:state: assoc -> run (10)
I (3722) wifi:connected with Airtel_dayro, aid = 2, channel 6, 40U, bssid = f0:ed:b8:15:e7:91
I (3723) wifi:security: WPA2-PSK, phy: bgn, rssi: -48
I (3725) wifi:pm start, type: 1

I (3728) wifi:dp: 1, bi: 102400, li: 3, scale listen interval from 307200 us to 307200 us
I (3781) wifi:AP's beacon interval = 102400 us, DTIM period = 1
I (3854) wifi:idx:0 (ifx:0, f0:ed:b8:15:e7:91), tid:0, ssn:2, winSize:64
I (4741) esp_netif_handlers: example_netif_sta ip: 192.168.1.11, mask: 255.255.255.0, gw: 192.168.1.1
I (4742) example_connect: Got IPv4 event: Interface "example_netif_sta" address: 192.168.1.11
I (4760) example_connect: Got IPv6 event: Interface "example_netif_sta" address: fe80:0000:0000:0000:4ae7:29ff:fe96:4310, type: ESP_IP6_ADDR_IS_LINK_LOCAL
I (4764) example_common: Connected to example_netif_sta
I (4770) example_common: - IPv4 address: 192.168.1.11,
I (4776) example_common: - IPv6 address: fe80:0000:0000:0000:4ae7:29ff:fe96:4310, type: ESP_IP6_ADDR_IS_LINK_LOCAL
I (4788) Knob_demo: Other event id:7

MAIN: Sensor Init Success!!
.......Intiailizing motor....
I (4819) gpio: GPIO[16]| InputEn: 1| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (4822) gpio: GPIO[18]| InputEn: 1| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (4831) gpio: GPIO[19]| InputEn: 1| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (4840) gpio: GPIO[17]| InputEn: 1| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (4849) gpio: GPIO[23]| InputEn: 1| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (4859) gpio: GPIO[33]| InputEn: 1| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
ESP32-DRV: ESP32_MCPWM_MCU: Configuring 6PWM for ESP32
ESP32-DRV: Configuring 6PWM in group: 0 on timer: 0
ESP32-DRV: ESP32_DRIVER_MCPWM: Configuring 6PWM for ESP32
ESP32-DRV: Configuring 3 operators.
ESP32-DRV: Configuring 6PWM with hardware dead-time
ESP32-DRV: Configuring 3 comparators.
ESP32-DRV: Configuring 6 generators.
I (4904) gpio: GPIO[16]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (4906) gpio: GPIO[17]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (4916) gpio: GPIO[18]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (4925) gpio: GPIO[23]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (4934) gpio: GPIO[19]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (4944) gpio: GPIO[33]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
ESP32-DRV: Configuring Center-Aligned 6 pwm.
ESP32-DRV: Configuring dead-time.
ESP32-DRV: Enabling timer: 0
ESP32-DRV: MCPWM configured!
DRIVER: params::1
DRIVER: Init Status::1
MOT: Init
MOT: Enable driver.
I (5946) Knob_demo: MQTT_EVENT_CONNECTED
I (5949) Knob_demo: sent publish successful, msg_id=0
I (5951) Knob_demo: sent subscribe successful, msg_id=2615
MOT: Align sensor.
I (6015) Knob_demo: MQTT_EVENT_SUBSCRIBED, msg_id=2615
I (6019) Knob_demo: sent publish successful, msg_id=0
MOT: sensor_direction==CCW
MOT: PP check: OK!
MOT: No current sense.
MOT: Ready.
intiailized....
Command Received, moving the knob
New Position=0
Target position reached,motor stopped
Current Angle: 0.00°
MOT: Init
MOT: Enable driver.
MOT: Align sensor.
MOT: Skip dir calib.
MOT: Skip offset calib.
MOT: No current sense.
MOT: Ready.

/**********************************************************************************************************************/

Here is the behaviour:

sparkfun_board.mp4

@YanKE01
Copy link
Contributor

YanKE01 commented Dec 6, 2024

It looks quite fascinating. Perhaps we could add print statements individually in the angle sensor or driver to investigate further. I usually use the 3PWM driver, so the 6PWM driver was only tested for feasibility with the waveform. I will try prototyping a board to test it out. You could also try investigating and submit a PR.

@HirenDayro017
Copy link
Author

sure @YanKE01 , I will let you know if I find anything useful. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants