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

ESP32 S3 Pulse Counter Skipping Steps (IDFGH-14317) #15108

Open
3 tasks done
anagnostouJohn opened this issue Dec 29, 2024 · 5 comments
Open
3 tasks done

ESP32 S3 Pulse Counter Skipping Steps (IDFGH-14317) #15108

anagnostouJohn opened this issue Dec 29, 2024 · 5 comments
Assignees
Labels
Awaiting Response awaiting a response from the author Status: Opened Issue is new

Comments

@anagnostouJohn
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

I am running the simple example of rottary encoder and as i can see when rottary spins fast some steps are skipped. I dont know if it is due to ESP_LOGI or i am missing something. I am using ESP-32 S3 and the rottary encoder has 600 steps per rotation.


 #include <stdio.h>
#include <driver/pulse_cnt.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "esp_task_wdt.h"
#include "esp_rom_sys.h"
#include "esp_system.h"
#include "esp_err.h"
#include "sdkconfig.h"
#include "freertos/queue.h"
#include "esp_sleep.h"

static const char *TAG = "example";

#define EXAMPLE_PCNT_HIGH_LIMIT 2400
#define EXAMPLE_PCNT_LOW_LIMIT  -2400

#define EXAMPLE_EC11_GPIO_A 35
#define EXAMPLE_EC11_GPIO_B 2


#define DirPin GPIO_NUM_4
#define PulcePin GPIO_NUM_5


int direction = 0;
int PrevValue = 0;
int current_value;
SemaphoreHandle_t xBinarySemaphoreClock;

void Task1(void *pvParameters) {


    esp_rom_gpio_pad_select_gpio(DirPin);
    gpio_set_direction(DirPin, GPIO_MODE_OUTPUT);

    esp_rom_gpio_pad_select_gpio(PulcePin);
    gpio_set_direction(PulcePin, GPIO_MODE_OUTPUT);

    while (1) {
        
        if(xSemaphoreTake(xBinarySemaphoreClock, portMAX_DELAY)==pdTRUE){
            
            ESP_LOGI("SEM TAKEN", "AAAAAAAAAAAAAAAA >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> %d", direction);
            gpio_set_level(DirPin,direction);
            gpio_set_level(PulcePin, 1);
            esp_rom_delay_us(1000);

            gpio_set_level(PulcePin, 0);
        }
    }
   
}

void TaskRottary(void *pvParameters)
{
    ESP_LOGI(TAG, "install pcnt unit");
    pcnt_unit_handle_t pcnt_unit = NULL;// INFO  I TOOK IT FROM BELO
    pcnt_unit_config_t unit_config = {
        .high_limit = EXAMPLE_PCNT_HIGH_LIMIT,
        .low_limit = EXAMPLE_PCNT_LOW_LIMIT,
    };
   
    ESP_ERROR_CHECK(pcnt_new_unit(&unit_config, &pcnt_unit));

    ESP_LOGI(TAG, "set glitch filter");
    pcnt_glitch_filter_config_t filter_config = {
        .max_glitch_ns = 50,
    };
    ESP_ERROR_CHECK(pcnt_unit_set_glitch_filter(pcnt_unit, &filter_config));

    ESP_LOGI(TAG, "install pcnt channels");
    pcnt_chan_config_t chan_a_config = {
        .edge_gpio_num = EXAMPLE_EC11_GPIO_A,
        .level_gpio_num = EXAMPLE_EC11_GPIO_B,
    };
    pcnt_channel_handle_t pcnt_chan_a = NULL;
    ESP_ERROR_CHECK(pcnt_new_channel(pcnt_unit, &chan_a_config, &pcnt_chan_a));
    pcnt_chan_config_t chan_b_config = {
        .edge_gpio_num = EXAMPLE_EC11_GPIO_B,
        .level_gpio_num = EXAMPLE_EC11_GPIO_A,
    };
    pcnt_channel_handle_t pcnt_chan_b = NULL;
    ESP_ERROR_CHECK(pcnt_new_channel(pcnt_unit, &chan_b_config, &pcnt_chan_b));

    ESP_LOGI(TAG, "set edge and level actions for pcnt channels");
    ESP_ERROR_CHECK(pcnt_channel_set_edge_action(pcnt_chan_a, PCNT_CHANNEL_EDGE_ACTION_DECREASE, PCNT_CHANNEL_EDGE_ACTION_INCREASE));
    ESP_ERROR_CHECK(pcnt_channel_set_level_action(pcnt_chan_a, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_INVERSE));
    ESP_ERROR_CHECK(pcnt_channel_set_edge_action(pcnt_chan_b, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_DECREASE));
    ESP_ERROR_CHECK(pcnt_channel_set_level_action(pcnt_chan_b, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_INVERSE));


    ESP_LOGI(TAG, "enable pcnt unit");
    ESP_ERROR_CHECK(pcnt_unit_enable(pcnt_unit));
    ESP_LOGI(TAG, "clear pcnt unit");
    ESP_ERROR_CHECK(pcnt_unit_clear_count(pcnt_unit));
    ESP_LOGI(TAG, "start pcnt unit");
    ESP_ERROR_CHECK(pcnt_unit_start(pcnt_unit));

#if CONFIG_EXAMPLE_WAKE_UP_LIGHT_SLEEP
    // EC11 channel output high level in normal state, so we set "low level" to wake up the chip
    ESP_ERROR_CHECK(gpio_wakeup_enable(EXAMPLE_EC11_GPIO_A, GPIO_INTR_LOW_LEVEL));
    ESP_ERROR_CHECK(esp_sleep_enable_gpio_wakeup());
    ESP_ERROR_CHECK(esp_light_sleep_start());
#endif

    // Report counter value
    int pulse_count = 0;

    while (1) {
            ESP_ERROR_CHECK(pcnt_unit_get_count(pcnt_unit, &pulse_count));
            if (PrevValue != pulse_count ) {
                    ESP_LOGI(TAG, "Pulse count: %d", pulse_count);
                    PrevValue=pulse_count;
            }
    }
}






void app_main() {

   
    xBinarySemaphoreClock = xSemaphoreCreateBinary();
    if (xBinarySemaphoreClock == NULL) {
        ESP_LOGE("app_main", "Failed to create semaphore");
        return; // Abort if semaphore creation fails
    }
    

    // Create the task and pin it to core 1
    xTaskCreatePinnedToCore(
        Task1,            // Function that implements the task
        "BlinkTask",      // Name of the task
        4096,             // Stack size
        NULL,             // Task input parameter
        1,                // Priority of the task
        NULL,             // Task handle
        1                 // Core where the task should run (1 for core 1, 0 for core 0)
    );





    xTaskCreatePinnedToCore(  
        TaskRottary,
        "RotaryEncoder",
        4096,
        NULL,
        1,
        NULL,
        0
    );
}

Further more why i cannot use more than 5 watch_points and why they have to have the High_Limit Zero and the Low_Limit

@espressif-bot espressif-bot added the Status: Opened Issue is new label Dec 29, 2024
@github-actions github-actions bot changed the title ESP32 S3 Pulse Counter Skipping Steps ESP32 S3 Pulse Counter Skipping Steps (IDFGH-14317) Dec 29, 2024
@Kainarx
Copy link
Collaborator

Kainarx commented Dec 30, 2024

Hi @anagnostouJohn
What is your pulse width? You can try without setting glitch filter. There is a real possibility of loss if the pulse width is less than the APB_CLK period. For more information on watch_points, you can refer to our TRM

@anagnostouJohn
Copy link
Author

imagine the max rpm of the rottary encoder will be 2000rpms. I have set

CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240

Also i remove from my code the glitch filter. Theoretically PCNT doesent have a problem when a rottary encoder runs at 2000rpms.

@Kainarx
Copy link
Collaborator

Kainarx commented Dec 31, 2024

If the max RPM of the rotary encoder is 2000, I believe this frequency is not an issue. Instead, you could try increasing the max_glitch_ns. I suspect that the rotary encoder might have mechanical jitter. While you are printing the logs, the quadrature decoding increments the count in the background, but it is immediately followed by a decrement. As a result, the count does not change by the time of the next loop check, making it appear as if steps are lost. Anyway, you could also try printing the logs at different points to see the results. 😄

@anagnostouJohn
Copy link
Author

There should be a possibility that the problem is at ESP_LOGI(TAG, "Pulse count: %d", pulse_count); Or the ESP_LOGI delays the pulse_count to increase its number or it is increased but it skips some prints

@Kainarx
Copy link
Collaborator

Kainarx commented Jan 3, 2025

This is possible.You can try turning the baud rate up, and if that still doesn't work, you can store pulse_count in an array and print it out at once when you stop counting.

@espressif-bot espressif-bot added the Awaiting Response awaiting a response from the author label Jan 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting Response awaiting a response from the author Status: Opened Issue is new
Projects
None yet
Development

No branches or pull requests

3 participants