Control duty-cycle of a PWM signal using mcpwm

shaiknisar_frill
Posts: 1
Joined: Wed Aug 23, 2023 2:39 pm

Control duty-cycle of a PWM signal using mcpwm

Postby shaiknisar_frill » Wed Aug 23, 2023 2:49 pm

  1. I'm using ESP32 to control the speed of a brushed DC motor. It requires a PWM signal to control the speed of the motor. I'm using the latest ESP-IDF (v5.1). The ESP-IDF has example code uses "bdc_motor" component, which I do not want to use. I want to create a PWM signal on a single GPIO pin, which will be fed to the DC motor. For this I have followed the below code sequence. Now I want to control the duty cycle of the PWM signal to control the speed, I'm not able to find the API required to control the duty cycle. The deprecated mcpwm driver was easy to use, but the latest mcpwm driver is confusing. Can anyone please suggest how to control the duty-cycle using mcpwm?  Is there any code sequence for controlling the duty-cycle?

Code: Select all

#include <stdio.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "gpio.h"
#include "mcpwm_timer.h"
#include "mcpwm_oper.h"
#include "mcpwm_gen.h"

#include "driver/mcpwm.h"
#include "soc/mcpwm_periph.h"

/*****************************************************************************************************************************/
/*************************************                 MACRO DEFINITIONS                 *************************************/
/*****************************************************************************************************************************/

/* GPIO Pin on which the PWM signal is generated.*/
#define PWM_GPIO_PIN    (GPIO_NUM_25)

/* 1MHz, 1us per tick. This value ranges from around 300KHz to 80MHz. The step size of
each count tick equals to (1 / resolution_hz) seconds.*/
#define DC_MOTOR_TIMEBASE_RESOLUTION_HZ (1000000)

/* This value is to configure number of count ticks within a period (i.e., configuring the PWM frequency). */
#define DC_MOTOR_TIMEBASE_PERIOD        (15000)

/*****************************************************************************************************************************/
/*************************************                GLOBAL ARRAYS                *******************************************/
/*****************************************************************************************************************************/


/*****************************************************************************************************************************/
/*************************************                GLOBAL VARIABLES                ****************************************/
/*****************************************************************************************************************************/

/* MCPWM timer handle.*/
mcpwm_timer_handle_t DC_Motor_mcpwmTimerHandle = NULL;

/* MCPWM Operator handle.*/
mcpwm_oper_handle_t DC_Motor_mcpwmOperatorHandle = NULL;

/* MCPWM Generator handle.*/
mcpwm_gen_handle_t DC_Motor_mcpwmGeneratorHandle = NULL;

/*****************************************************************************************************************************/
/* Function Name : MY1016_DCMotorInit                                                                                        */
/* Description   : Function performs the required initializations to generate the PWM signal to be fed to the DC motor.      */
/*****************************************************************************************************************************/

void MY1016_DCMotor_PWMInit(void)
{
    /* Configuring the timer (sub-module of mcpwm). 
    Note: 'group-id' refers to MCPWM unit (i.e., MCPWM unit-0 or MCPWM unit-1).*/
    mcpwm_timer_config_t DC_Motor_mcpwmTimerCfg =
    {
        .group_id       = 0,
        .clk_src        = MCPWM_TIMER_CLK_SRC_DEFAULT,
        .resolution_hz  = DC_MOTOR_TIMEBASE_RESOLUTION_HZ,
        .period_ticks   = DC_MOTOR_TIMEBASE_PERIOD,
        .count_mode     = MCPWM_TIMER_COUNT_MODE_UP,
    };
    ESP_ERROR_CHECK(mcpwm_new_timer(&DC_Motor_mcpwmTimerCfg, &DC_Motor_mcpwmTimerHandle));

    /* Configuring the Operator (sub-module of mcpwm). */
    mcpwm_operator_config_t DC_Motor_mcpwmOperatorCfg = 
    {
        .group_id = 0,
    };
    ESP_ERROR_CHECK(mcpwm_new_operator(&DC_Motor_mcpwmOperatorCfg, &DC_Motor_mcpwmOperatorHandle));

    /* Connecting the timer and the operator.
    Note: Both Operator and the timer should belong to the same MCPWM unit.*/
    ESP_ERROR_CHECK(mcpwm_operator_connect_timer(DC_Motor_mcpwmOperatorHandle, DC_Motor_mcpwmTimerHandle));

    mcpwm_generator_config_t DC_Motor_mcpwmGeneratorCfg = 
    {
        .gen_gpio_num = PWM_GPIO_PIN,
    };
    ESP_ERROR_CHECK(mcpwm_new_generator(DC_Motor_mcpwmOperatorHandle, &DC_Motor_mcpwmGeneratorCfg, &DC_Motor_mcpwmGeneratorHandle));

    /* Setting generator action on timer event.*/
    ESP_ERROR_CHECK(mcpwm_generator_set_actions_on_timer_event(DC_Motor_mcpwmGeneratorHandle,
                    MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH),
                    MCPWM_GEN_TIMER_EVENT_ACTION_END()));

    /* Enable and start the timer.*/
    ESP_ERROR_CHECK(mcpwm_timer_enable(DC_Motor_mcpwmTimerHandle));
    ESP_ERROR_CHECK(mcpwm_timer_start_stop(DC_Motor_mcpwmTimerHandle, MCPWM_TIMER_START_NO_STOP));
}

void app_main(void)
{
	MY1016_DCMotor_PWMInit();
	
	// What mcpwm driver API to call to control the duty cycle??
}

abellofiore
Posts: 10
Joined: Tue May 16, 2023 7:02 pm

Re: Control duty-cycle of a PWM signal using mcpwm

Postby abellofiore » Thu Aug 24, 2023 3:31 pm

I do exactly this control of a DC motor. Here's what I used (adapted from my code for yours):

Code: Select all

esp_err_t set_mcpwm_generator_dc(int dc)
{
	esp_err_t rc;
        rc = mcpwm_comparator_set_compare_value(comparator, dc_to_count(dc));
    return rc;
}

int dc_to_count(int dc)
{
	return (dc * DC_MOTOR_TIMEBASE_PERIOD) / 100;
}
Example:

Code: Select all

      set_mcpwm_generator_dc(0); // OFF
      set_mcpwm_generator_dc(50); // 50% DC
      set_mcpwm_generator_dc(100); // 100% DC

Who is online

Users browsing this forum: No registered users and 216 guests