ESP32 MCPWM Input Capture Problem
Posted: Thu Jul 05, 2018 2:20 am
I am testing the input capture function contained within MCPWM.
I am testing an example source MCPWM(mcpwm_basic_config_example.c).
In order to know the frequency values entered in CAP 0,
the remainder has been disabled and only the pwm0 and Capture0 functions have been enabled.
*Test content
1. I entered a frequency of 2 kHz into the CAP 0 pin.
2. The output results are output alternately between 500us and 9500us, rather than continuously output to 500us as shown below.
3. Also, if I input the input frequency to 20 kHz, the value will be output strangely. I think it's almost impossible to measure.
* Questions
1. Is the example source working normally?
2. Doesn't it work normally with high frequency inputs?
If so, what are the measurable frequency limits?
(I would like to measure up to 200kHz)
* Mainly Function Setting
static void disp_captured_signal(void *arg)
{
uint32_t *current_cap_value = (uint32_t *)malloc(sizeof(CAP_SIG_NUM));
uint32_t *previous_cap_value = (uint32_t *)malloc(sizeof(CAP_SIG_NUM));
capture evt;
while (1) {
xQueueReceive(cap_queue, &evt, portMAX_DELAY);
if (evt.sel_cap_signal == MCPWM_SELECT_CAP0) {
current_cap_value[0] = evt.capture_signal - previous_cap_value[0];
previous_cap_value[0] = evt.capture_signal;
//How was the fomula made?
current_cap_value[0] = (current_cap_value[0] / 10000) * (10000000000 / rtc_clk_apb_freq_get());
printf("%d us \n", current_cap_value[0]);
}
}
}
static void IRAM_ATTR isr_handler()
{
uint32_t mcpwm_intr_status;
capture evt;
mcpwm_intr_status = MCPWM[MCPWM_UNIT_0]->int_st.val; //Read interrupt status
if (mcpwm_intr_status & CAP0_INT_EN) {
evt.capture_signal = mcpwm_capture_signal_get_value(MCPWM_UNIT_0, MCPWM_SELECT_CAP0);
evt.sel_cap_signal = MCPWM_SELECT_CAP0;
xQueueSendFromISR(cap_queue, &evt, NULL);
}
MCPWM[MCPWM_UNIT_0]->int_clr.val = mcpwm_intr_status;
}
static void mcpwm_example_config(void *arg)
{
//1. mcpwm gpio initialization
mcpwm_example_gpio_initialize();
//2. initialize mcpwm configuration
printf("Configuring Initial Parameters of mcpwm...\n");
mcpwm_config_t pwm_config;
pwm_config.frequency = 2000; //frequency = 1000Hz
pwm_config.cmpr_a = 50.0; //duty cycle of PWMxA = 50.0%
pwm_config.cmpr_b = 50.0; //duty cycle of PWMxb = 50.0%
pwm_config.counter_mode = MCPWM_UP_COUNTER;
pwm_config.duty_mode = MCPWM_DUTY_MODE_0;
mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config);
mcpwm_capture_enable(MCPWM_UNIT_0, MCPWM_SELECT_CAP0, MCPWM_POS_EDGE, 0);
MCPWM[MCPWM_UNIT_0]->int_ena.val = CAP0_INT_EN; //Enable interrupt on CAP0, CAP1 and CAP2 signal
mcpwm_isr_register(MCPWM_UNIT_0, isr_handler, NULL, ESP_INTR_FLAG_IRAM, NULL); //Set ISR Handler
vTaskDelete(NULL);
}
Output Result:
500 us
9500 us
500 us
9500 us
500 us
9500 us
500 us
9500 us
500 us
9500 us
500 us
9500 us
500 us
9500 us
500 us
9500 us
500 us
9500 us
500 us
9500 us
.
.
.
I am testing an example source MCPWM(mcpwm_basic_config_example.c).
In order to know the frequency values entered in CAP 0,
the remainder has been disabled and only the pwm0 and Capture0 functions have been enabled.
*Test content
1. I entered a frequency of 2 kHz into the CAP 0 pin.
2. The output results are output alternately between 500us and 9500us, rather than continuously output to 500us as shown below.
3. Also, if I input the input frequency to 20 kHz, the value will be output strangely. I think it's almost impossible to measure.
* Questions
1. Is the example source working normally?
2. Doesn't it work normally with high frequency inputs?
If so, what are the measurable frequency limits?
(I would like to measure up to 200kHz)
* Mainly Function Setting
static void disp_captured_signal(void *arg)
{
uint32_t *current_cap_value = (uint32_t *)malloc(sizeof(CAP_SIG_NUM));
uint32_t *previous_cap_value = (uint32_t *)malloc(sizeof(CAP_SIG_NUM));
capture evt;
while (1) {
xQueueReceive(cap_queue, &evt, portMAX_DELAY);
if (evt.sel_cap_signal == MCPWM_SELECT_CAP0) {
current_cap_value[0] = evt.capture_signal - previous_cap_value[0];
previous_cap_value[0] = evt.capture_signal;
//How was the fomula made?
current_cap_value[0] = (current_cap_value[0] / 10000) * (10000000000 / rtc_clk_apb_freq_get());
printf("%d us \n", current_cap_value[0]);
}
}
}
static void IRAM_ATTR isr_handler()
{
uint32_t mcpwm_intr_status;
capture evt;
mcpwm_intr_status = MCPWM[MCPWM_UNIT_0]->int_st.val; //Read interrupt status
if (mcpwm_intr_status & CAP0_INT_EN) {
evt.capture_signal = mcpwm_capture_signal_get_value(MCPWM_UNIT_0, MCPWM_SELECT_CAP0);
evt.sel_cap_signal = MCPWM_SELECT_CAP0;
xQueueSendFromISR(cap_queue, &evt, NULL);
}
MCPWM[MCPWM_UNIT_0]->int_clr.val = mcpwm_intr_status;
}
static void mcpwm_example_config(void *arg)
{
//1. mcpwm gpio initialization
mcpwm_example_gpio_initialize();
//2. initialize mcpwm configuration
printf("Configuring Initial Parameters of mcpwm...\n");
mcpwm_config_t pwm_config;
pwm_config.frequency = 2000; //frequency = 1000Hz
pwm_config.cmpr_a = 50.0; //duty cycle of PWMxA = 50.0%
pwm_config.cmpr_b = 50.0; //duty cycle of PWMxb = 50.0%
pwm_config.counter_mode = MCPWM_UP_COUNTER;
pwm_config.duty_mode = MCPWM_DUTY_MODE_0;
mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config);
mcpwm_capture_enable(MCPWM_UNIT_0, MCPWM_SELECT_CAP0, MCPWM_POS_EDGE, 0);
MCPWM[MCPWM_UNIT_0]->int_ena.val = CAP0_INT_EN; //Enable interrupt on CAP0, CAP1 and CAP2 signal
mcpwm_isr_register(MCPWM_UNIT_0, isr_handler, NULL, ESP_INTR_FLAG_IRAM, NULL); //Set ISR Handler
vTaskDelete(NULL);
}
Output Result:
500 us
9500 us
500 us
9500 us
500 us
9500 us
500 us
9500 us
500 us
9500 us
500 us
9500 us
500 us
9500 us
500 us
9500 us
500 us
9500 us
500 us
9500 us
.
.
.