LEDC and PCNT on same GPIO
LEDC and PCNT on same GPIO
Hi,
I'm using the LEDC module to sent signals to a stepper control board (A4988). To figure out how many steps the motor has received I'm using the PCNT module on a different GPIO. Currently these two pins are wired together externally.
What I would like to do now is to use only one pin instead of two. I was thinking this could be achieved using an internal signal and routing the LEDC output to the signal, and routing the signal back into the PCNT input.
So far none of my attempts succeeded.
I have seen and unsuccessfully tried this one here: esp32.com/viewtopic.php?f=13&t=4253
Has anyone succeeded to do this and would be willing to share the solution?
Best regards,
Micha
I'm using the LEDC module to sent signals to a stepper control board (A4988). To figure out how many steps the motor has received I'm using the PCNT module on a different GPIO. Currently these two pins are wired together externally.
What I would like to do now is to use only one pin instead of two. I was thinking this could be achieved using an internal signal and routing the LEDC output to the signal, and routing the signal back into the PCNT input.
So far none of my attempts succeeded.
I have seen and unsuccessfully tried this one here: esp32.com/viewtopic.php?f=13&t=4253
Has anyone succeeded to do this and would be willing to share the solution?
Best regards,
Micha
-
- Posts: 290
- Joined: Wed Sep 05, 2018 6:23 am
Re: LEDC and PCNT on same GPIO
yes you can route different peripheral signals to a same GPIO by GPIO matrix. We have many example in our unit test cases. For example: https://github.com/espressif/esp-idf/bl ... _rmt.c#L67
Re: LEDC and PCNT on same GPIO
Hi, thanks for the hint!
I finally got it working. The trick is to set the GPIO, as you suggested, to GPIO_MODE_INPUT_OUTPUT.
But I also had to setup the GPIO matrix again for the LEDC functionality which was probably lost when LEDC was first configured on the GPIO, but then PCNT was configured on the same GPIO.
So the following works for me:
I finally got it working. The trick is to set the GPIO, as you suggested, to GPIO_MODE_INPUT_OUTPUT.
But I also had to setup the GPIO matrix again for the LEDC functionality which was probably lost when LEDC was first configured on the GPIO, but then PCNT was configured on the same GPIO.
So the following works for me:
- configure LEDC on a pin of your choice
- configure PCNT on the same pin as you configured the LEDC on
- set GPIO to GPIO_MODE_INPUT_OUTPUT:
Code: Select all
gpio_set_direction(myPin, GPIO_MODE_INPUT_OUTPUT);
- configure GPIO matrix again for LEDC:
Code: Select all
gpio_matrix_out(myPin, LEDC_HS_SIG_OUT0_IDX + myLedcChannel, 0, 0);
-
- Posts: 1
- Joined: Thu Feb 25, 2021 8:04 pm
Re: LEDC and PCNT on same GPIO
Hi micha5104,micha5104 wrote: ↑Sat Dec 26, 2020 5:18 pmHi, thanks for the hint!
I finally got it working. The trick is to set the GPIO, as you suggested, to GPIO_MODE_INPUT_OUTPUT.
But I also had to setup the GPIO matrix again for the LEDC functionality which was probably lost when LEDC was first configured on the GPIO, but then PCNT was configured on the same GPIO.
So the following works for me:
- configure LEDC on a pin of your choice
- configure PCNT on the same pin as you configured the LEDC on
- set GPIO to GPIO_MODE_INPUT_OUTPUT:
Code: Select all
gpio_set_direction(myPin, GPIO_MODE_INPUT_OUTPUT);
- configure GPIO matrix again for LEDC:
Code: Select all
gpio_matrix_out(myPin, LEDC_HS_SIG_OUT0_IDX + myLedcChannel, 0, 0);
I'm trying to accomplish the same thing , but i think i miss some practice with pcnt. Can you share your code to help me to understand what i should to do? It will be very appreciated.
Code: Select all
ledc_timer_config_t pwm_test = {
.speed_mode = LEDC_HIGH_SPEED_MODE,
.duty_resolution = LEDC_TIMER_1_BIT,
.timer_num = LEDC_TIMER_3,
.freq_hz = 1000,
.clk_cfg = LEDC_AUTO_CLK};
ledc_channel_config_t ch_pwm_test = {
.gpio_num = GPIO_NUM_25,
.speed_mode = LEDC_HIGH_SPEED_MODE,
.channel = LEDC_CHANNEL_5,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = LEDC_TIMER_3,
.duty = 1,
.hpoint = 0 // La valeur à laquel le high s'enclanche ex : hpoint = 10 , l'état changera lorsque le compteur sera à 10. De 10 à duty
};
pcnt_config_t pcnt_test = {
.pulse_gpio_num = GPIO_NUM_25, /*!< Pulse input GPIO number, if you want to use GPIO16, enter pulse_gpio_num = 16, a negative value will be ignored */
.ctrl_gpio_num = PCNT_PIN_NOT_USED, /*!< Control signal input GPIO number, a negative value will be ignored */
.lctrl_mode = PCNT_MODE_REVERSE, // Reverse counting direction if low
.hctrl_mode = PCNT_MODE_KEEP, /*!< PCNT high control mode */
.pos_mode = PCNT_COUNT_INC, // Count up on the positive edge
.neg_mode = PCNT_COUNT_DIS, /*!< PCNT negative edge count mode */
.counter_h_lim = 255,
.counter_l_lim = 0, /*!< Minimum counter value */
.unit = PCNT_UNIT_0,
.channel = PCNT_CHANNEL_0
};
Code: Select all
pcnt_unit_config(&pcnt_test);
ledc_timer_config(&pwm_test);
ledc_channel_config(&ch_pwm_test);
gpio_set_direction(GPIO_NUM_25, GPIO_MODE_INPUT_OUTPUT);
gpio_matrix_out(GPIO_NUM_25, LEDC_HS_SIG_OUT0_IDX + LEDC_CHANNEL_5, 0, 0);
Code: Select all
int16_t compteur;
for (;;)
{
vTaskDelay(1000 / portTICK_PERIOD_MS);
pcnt_get_counter_value(PCNT_UNIT_0,&compteur);
printf("compteur = %d", compteur);
...}
Re: LEDC and PCNT on same GPIO
Hi frankgigeur,
this is the code I am using. Note: I am also using the ISR handler on the PCNT, but it should also work without.
On first glance I don't see a lot of difference between your and my code...
Please let me know if you figured out, what it was.
Initialization:
Start the signal:
Query the counter value:
Good luck!
this is the code I am using. Note: I am also using the ISR handler on the PCNT, but it should also work without.
On first glance I don't see a lot of difference between your and my code...
Please let me know if you figured out, what it was.
Initialization:
Code: Select all
ledc_timer_config_t ledc_timer;
ledc_timer.timer_num = LEDC_TIMER_0; // timer index
ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE; // timer mode
ledc_timer.freq_hz = 4000; // frequency of PWM signal
ledc_timer.duty_resolution = LEDC_TIMER_8_BIT; // resolution of PWM duty
ledc_timer.clk_cfg = LEDC_AUTO_CLK; // Auto select the source clock
// Set configuration of timer for high speed channels
esp_err_t err = ledc_timer_config(&ledc_timer);
if (err != ESP_OK)
{
mLogger->log(Logger::ERROR) << "Error configuring ledc_timer_config: " << esp_err_to_name(err);
}
ledc_channel_config_t ledc_conf;
ledc_conf.channel = LEDC_CHANNEL_0;
ledc_conf.gpio_num = GPIO_NUM_23;
ledc_conf.duty = 0; // don't run off right away :-)
ledc_conf.hpoint = 0; // where in the clock interval the level will be set to high; like a phase shift
ledc_conf.intr_type = LEDC_INTR_DISABLE;
ledc_conf.speed_mode = LEDC_HIGH_SPEED_MODE;
ledc_conf.timer_sel = LEDC_TIMER_0;
err = ledc_channel_config(&ledc_conf);
if (err != ESP_OK)
{
mLogger->log(Logger::ERROR) << "Error configuring ledc_channel_config: " << esp_err_to_name(err);
}
pcnt_config_t pcnt_config =
{
// Set PCNT input signal and control GPIOs
.pulse_gpio_num = GPIO_NUM_23,
.ctrl_gpio_num = -1,
.lctrl_mode = PCNT_MODE_KEEP, // Keep the primary counter mode if high
.hctrl_mode = PCNT_MODE_KEEP, // Keep the primary counter mode if high
.pos_mode = PCNT_COUNT_INC, // Count up on the positive edge
.neg_mode = PCNT_COUNT_DIS, // Ignore
// Set the maximum and minimum limit values to watch
.counter_h_lim = 32760,
.counter_l_lim = -1,
.unit = PCNT_UNIT_0,
.channel = PCNT_CHANNEL_0,
};
/* Initialize PCNT unit */
pcnt_unit_config(&pcnt_config);
/* Configure and enable the input filter */
pcnt_set_filter_value(PCNT_UNIT_0, 100);
pcnt_filter_enable(PCNT_UNIT_0);
pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_H_LIM);
pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_THRES_0);
pcnt_counter_pause(PCNT_UNIT_0);
pcnt_counter_clear(PCNT_UNIT_0);
/* Register ISR handler and enable interrupts for PCNT unit */
pcnt_isr_register(pcnt_intr_handler, &PCNT_UNIT_0, 0, &user_isr_handle);
pcnt_intr_enable(PCNT_UNIT_0);
pcnt_counter_resume(PCNT_UNIT_0);
gpio_set_direction(GPIO_NUM_23, GPIO_MODE_INPUT_OUTPUT);
// NOTE: the following line assumes that we use LEDC_HIGH_SPEED_MODE
gpio_matrix_out(GPIO_NUM_23, LEDC_HS_SIG_OUT0_IDX + LEDC_CHANNEL_0, 0, 0);
Code: Select all
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, (1 << LEDC_TIMER_8_BIT) / 2);
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0);
Code: Select all
int16_t count;
esp_err_t err = pcnt_get_counter_value(PCNT_UNIT_0, &count);
if (err != ESP_OK)
{
mLogger->log(Logger::ERROR) << "Error calling pcnt_get_counter_value";
}
Re: LEDC and PCNT on same GPIO
Hi frankgigeur, have your problem figured out ?
i have a same problem like you,
i can generat pulse from a defined pin, but can't read counter from this pin
i have a same problem like you,
i can generat pulse from a defined pin, but can't read counter from this pin
Who is online
Users browsing this forum: asargent, Gaston1980 and 154 guests