Programming The ESP32 In C - MCPWM First Example
Written by Harry Fairhead   
Tuesday, 03 December 2024
Article Index
Programming The ESP32 In C - MCPWM First Example
Setting up the MCPWM
Setting Action
A Simple example

Setting up the MCPWM

To build a basic MCPWM system we need a timer and an operator.

First, to create a timer we use:

mcpwm_new_timer(pconfig, ptimerhandle)

where pconfig points to mcpwm_timer_config_t, a struct containing:

  • group_id MCPWM group number, 0 or 1

  • clk_src Clock source usually MCPWM_TIMER_CLK_SRC_DEFAULT running at 80MHz

  • resolution_hz Counter resolution in Hz

  • count_mode One of:

MCPWM_TIMER_COUNT_MODE_PAUSE 
MCPWM_TIMER_COUNT_MODE_UP
MCPWM_TIMER_COUNT_MODE_DOWN
MCPWM_TIMER_COUNT_MODE_UP_DOWN
  • period_ticks Number of ticks in a period

  • intr_priority 0 = low priority

  • update_period_on_empty When timer counts to zero

  • uint32_t update_period_on_sync On sync event

The key facts are that resolution_hz sets the time for a single counter increment as 1/resolution_hz in seconds and period_ticks sets the time to count from 0 to rollover. For example, setting resolution_hz to 1000000 makes one tick take 1μs and hence setting period_ticks to 20000 makes the time to rollover 20000μs or 20ms, i.e. the PWM frequency is 50Hz. The counter starts at 0 and rolls over at 200000. Given that the default clock is 80MHz, the divider will be automatically set to 4000.

So, to set up a timer for a 50Hz PWM signal:

  mcpwm_timer_config_t timer_config = {
      .group_id = 0,
      .clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,
      .resolution_hz = 1000000,
      .period_ticks = 20000,
      .count_mode = MCPWM_TIMER_COUNT_MODE_UP,
  };
  mcpwm_timer_handle_t timer = NULL;
  mcpwm_new_timer(&timer_config, &timer); 

After the timer we need to create an operator:

mcpwm_new_operator(pconfig, poper)

where pconfig points to mcpwm_operator_config_t ,a struct with fields:

  • group_id MCPWM group number, 0 or 1.

  • intr_priority 0 = low priority

  • update_gen_action_on_tez Update generator action on timer zero

  • update_gen_action_on_tep: Update generator action on timer peak

  • update_gen_action_on_sync Update generator action on sync event

  • update_dead_time_on_tez Update deadtime on timer zero

  • update_dead_time_on_tep Update deadtime on timer peak

  • update_dead_time_on_sync Update deadtime on sync event

You can ignore the update fields for the moment as they only control when software-applied updates are acted on.

A simple operator that can be used with the timer is:

  mcpwm_operator_config_t operator_config = {
      .group_id = 0, 
  }; 
 
  mcpwm_oper_handle_t oper = NULL;
  mcpwm_new_operator(&operator_config, &oper);

Now that we have an operator and a timer we can connect them together using:

mcpwm_operator_connect_timer(oper, timer)

The operator contains other modules to generate a PWM signal, but all we need for a simple single PWM signal is a generator that connects the PWM signal to a GPIO line.

A new generator can be created using:

mcpwm_new_generator(handle_t oper, pconfig, pret_gen)

where pconfig points to mcpwm_generator_config_t, a struct with fields:

  • gen_gpio_num GPIO line used to output the PWM signal

  • invert_pwm Invert the PWM signal

  • io_loop_back For debug/test

  • io_od_mode GPIO in open-drain mode

  • pull_up Use pull up

  • pull_down Use pull down

A simple generator to connect to GPIO line 2 is:

  mcpwm_generator_config_t generator_config = {
      .gen_gpio_num = 2,
  };
  mcpwm_gen_handle_t generator = NULL;
  mcpwm_new_generator(oper, &generator_config,
&generator);

Now we have a minimal MCPWM system configured and ready to be used.

 



Last Updated ( Tuesday, 03 December 2024 )