Closed anvgfr closed 1 year ago
Made an error : read library v1.0.6 instead of 1.6.0 I have tried down to 2.0.0, still the same issue, seems that something is broken starting with 2.0.0 CPU is ESP32-D0WDQ6-V3
Arduino Core 2.0.x is based on IDF 4.4. Arduino Core 1.0.6 is based on IDF 3.3. I suggest using Arduino Core 2.0.9 and PCNT IDF API from IDF 4.4.4. It is possible and valid to use IDF 4.4.4 PCNT calls inside an Arduino Sketch.
Documentation: https://docs.espressif.com/projects/esp-idf/en/v4.4.4/esp32/api-reference/peripherals/pcnt.html
Examples can be found at: https://github.com/espressif/esp-idf/tree/v4.4.4/examples/peripherals/pcnt/pulse_count_event https://github.com/espressif/esp-idf/tree/v4.4.4/examples/peripherals/pcnt/rotary_encoder
If i look at the pulse_count_event sample, the call for pcnt_isr_service_install seems to take a 0 for parameter (isr_flags), but when i search for it in the api reference, there is no change, It doesn't seems to work, if i use 0 i got the same error (driver not initialized).
To make it work, i had to move the pcnt_isr_service_install call after the first call to pcnt_unit_config... Strange...
About the parameter:
It says that intr_alloc_flags
is none (0) or more flags found in esp_intr_alloc.h
(ESP_INTR_FLAG_*
using OR |
)
https://docs.espressif.com/projects/esp-idf/en/v4.4.4/esp32/api-reference/peripherals/pcnt.html#_CPPv424pcnt_isr_service_installi
Your code must do the configuration as desribed in the example:
#define PCNT_H_LIM_VAL 10
#define PCNT_L_LIM_VAL -10
#define PCNT_THRESH1_VAL 5
#define PCNT_THRESH0_VAL -5
#define PCNT_INPUT_SIG_IO 4 // Pulse Input GPIO
#define PCNT_INPUT_CTRL_IO 5 // Control GPIO HIGH=count up, LOW=count down
xQueueHandle pcnt_evt_queue; // A queue to handle pulse counter events
/* A sample structure to pass events from the PCNT
* interrupt handler to the main program.
*/
typedef struct {
int unit; // the PCNT unit that originated an interrupt
uint32_t status; // information on the event type that caused the interrupt
} pcnt_evt_t;
/* Decode what PCNT's unit originated an interrupt
* and pass this information together with the event type
* the main program using a queue.
*/
static void IRAM_ATTR pcnt_example_intr_handler(void *arg)
{
int pcnt_unit = (int)arg;
pcnt_evt_t evt;
evt.unit = pcnt_unit;
/* Save the PCNT event type that caused an interrupt
to pass it to the main program */
pcnt_get_event_status(pcnt_unit, &evt.status);
xQueueSendFromISR(pcnt_evt_queue, &evt, NULL);
}
/* Initialize PCNT functions:
* - configure and initialize PCNT
* - set up the input filter
* - set up the counter events to watch
*/
static void pcnt_example_init(int unit)
{
/* Prepare configuration for the PCNT unit */
pcnt_config_t pcnt_config = {
// Set PCNT input signal and control GPIOs
.pulse_gpio_num = PCNT_INPUT_SIG_IO,
.ctrl_gpio_num = PCNT_INPUT_CTRL_IO,
.channel = PCNT_CHANNEL_0,
.unit = unit,
// What to do on the positive / negative edge of pulse input?
.pos_mode = PCNT_COUNT_INC, // Count up on the positive edge
.neg_mode = PCNT_COUNT_DIS, // Keep the counter value on the negative edge
// What to do when control input is low or high?
.lctrl_mode = PCNT_MODE_REVERSE, // Reverse counting direction if low
.hctrl_mode = PCNT_MODE_KEEP, // Keep the primary counter mode if high
// Set the maximum and minimum limit values to watch
.counter_h_lim = PCNT_H_LIM_VAL,
.counter_l_lim = PCNT_L_LIM_VAL,
};
/* Initialize PCNT unit */
pcnt_unit_config(&pcnt_config);
/* Configure and enable the input filter */
pcnt_set_filter_value(unit, 100);
pcnt_filter_enable(unit);
/* Set threshold 0 and 1 values and enable events to watch */
pcnt_set_event_value(unit, PCNT_EVT_THRES_1, PCNT_THRESH1_VAL);
pcnt_event_enable(unit, PCNT_EVT_THRES_1);
pcnt_set_event_value(unit, PCNT_EVT_THRES_0, PCNT_THRESH0_VAL);
pcnt_event_enable(unit, PCNT_EVT_THRES_0);
/* Enable events on zero, maximum and minimum limit values */
pcnt_event_enable(unit, PCNT_EVT_ZERO);
pcnt_event_enable(unit, PCNT_EVT_H_LIM);
pcnt_event_enable(unit, PCNT_EVT_L_LIM);
/* Initialize PCNT's counter */
pcnt_counter_pause(unit);
pcnt_counter_clear(unit);
/* Install interrupt service and add isr callback handler */
pcnt_isr_service_install(0);
pcnt_isr_handler_add(unit, pcnt_example_intr_handler, (void *)unit);
/* Everything is set up, now go to counting */
pcnt_counter_resume(unit);
}
The pulse_count_event sample converted to Arduino Sketch looks like this: I have tested it. It seems to work fine. It is necessary to connect GPIO18 to GPIO5 and GPIO4 to GND or 3.3V. GPIO 18 generates a signal of 1KHz with 10% duty. GPIO5 counts Pulses GPIO4 tells the sketch to count UP (when connected to GND) or DOWN (when connected to 3.3V)
#include "driver/pcnt.h"
#define PCNT_H_LIM_VAL 10
#define PCNT_L_LIM_VAL -10
#define PCNT_THRESH1_VAL 5
#define PCNT_THRESH0_VAL -5
#define PCNT_INPUT_SIG_IO 4 // Pulse Input GPIO
#define PCNT_INPUT_CTRL_IO 5 // Control GPIO HIGH=count up, LOW=count down
#define LEDC_OUTPUT_IO 18 // Output GPIO of a sample 1 Hz pulse generator
#define LEDC_CHANNEL_1 1
xQueueHandle pcnt_evt_queue; // A queue to handle pulse counter events
/* A sample structure to pass events from the PCNT
interrupt handler to the main program.
*/
typedef struct {
int unit; // the PCNT unit that originated an interrupt
uint32_t status; // information on the event type that caused the interrupt
} pcnt_evt_t;
/* Decode what PCNT's unit originated an interrupt
and pass this information together with the event type
the main program using a queue.
*/
static void IRAM_ATTR pcnt_example_intr_handler(void *arg)
{
uint32_t pcnt_unit = (uint32_t)arg;
pcnt_evt_t evt;
evt.unit = (pcnt_unit_t)pcnt_unit;
/* Save the PCNT event type that caused an interrupt
to pass it to the main program */
pcnt_get_event_status((pcnt_unit_t) pcnt_unit, &evt.status);
xQueueSendFromISR(pcnt_evt_queue, &evt, NULL);
}
/* Initialize PCNT functions:
- configure and initialize PCNT
- set up the input filter
- set up the counter events to watch
*/
static void pcnt_example_init(pcnt_unit_t unit)
{
/* Prepare configuration for the PCNT unit */
pcnt_config_t pcnt_config = {
// Set PCNT input signal and control GPIOs
.pulse_gpio_num = PCNT_INPUT_SIG_IO,
.ctrl_gpio_num = PCNT_INPUT_CTRL_IO,
// What to do when control input is low or high?
.lctrl_mode = PCNT_MODE_REVERSE, // Reverse counting direction if low
.hctrl_mode = PCNT_MODE_KEEP, // Keep the primary counter mode if high
// What to do on the positive / negative edge of pulse input?
.pos_mode = PCNT_COUNT_INC, // Count up on the positive edge
.neg_mode = PCNT_COUNT_DIS, // Keep the counter value on the negative edge
// Set the maximum and minimum limit values to watch
.counter_h_lim = PCNT_H_LIM_VAL,
.counter_l_lim = PCNT_L_LIM_VAL,
.unit = unit,
.channel = PCNT_CHANNEL_0,
};
/* Initialize PCNT unit */
pcnt_unit_config(&pcnt_config);
/* Configure and enable the input filter */
pcnt_set_filter_value(unit, 100);
pcnt_filter_enable(unit);
/* Set threshold 0 and 1 values and enable events to watch */
pcnt_set_event_value(unit, PCNT_EVT_THRES_1, PCNT_THRESH1_VAL);
pcnt_event_enable(unit, PCNT_EVT_THRES_1);
pcnt_set_event_value(unit, PCNT_EVT_THRES_0, PCNT_THRESH0_VAL);
pcnt_event_enable(unit, PCNT_EVT_THRES_0);
/* Enable events on zero, maximum and minimum limit values */
pcnt_event_enable(unit, PCNT_EVT_ZERO);
pcnt_event_enable(unit, PCNT_EVT_H_LIM);
pcnt_event_enable(unit, PCNT_EVT_L_LIM);
/* Initialize PCNT's counter */
pcnt_counter_pause(unit);
pcnt_counter_clear(unit);
/* Install interrupt service and add isr callback handler */
pcnt_isr_service_install(0);
pcnt_isr_handler_add(unit, pcnt_example_intr_handler, (void *)unit);
/* Everything is set up, now go to counting */
pcnt_counter_resume(unit);
}
pcnt_unit_t pcnt_unit = PCNT_UNIT_0;
void pcnt_task(void *param) {
int16_t count = 0;
pcnt_evt_t evt;
portBASE_TYPE res;
while (1) {
/* Wait for the event information passed from PCNT's interrupt handler.
Once received, decode the event type and print it on the serial monitor.
*/
res = xQueueReceive(pcnt_evt_queue, &evt, 1000 / portTICK_PERIOD_MS);
if (res == pdTRUE) {
pcnt_get_counter_value(pcnt_unit, &count);
log_i("Event PCNT unit[%d]; cnt: %d", evt.unit, count);
if (evt.status & PCNT_EVT_THRES_1) {
log_i("THRES1 EVT");
}
if (evt.status & PCNT_EVT_THRES_0) {
log_i("THRES0 EVT");
}
if (evt.status & PCNT_EVT_L_LIM) {
log_i("L_LIM EVT");
}
if (evt.status & PCNT_EVT_H_LIM) {
log_i("H_LIM EVT");
}
if (evt.status & PCNT_EVT_ZERO) {
log_i("ZERO EVT");
}
} else {
pcnt_get_counter_value(pcnt_unit, &count);
log_i("Current counter value :%d", count);
}
}
}
void setup() {
ledcSetup(LEDC_CHANNEL_1, 1000, 10); // 1KHz with 10 bit resoution
ledcAttachPin(LEDC_OUTPUT_IO, LEDC_CHANNEL_1);
ledcWrite(LEDC_CHANNEL_1, 102); // about 10% Duty (1024 / 10)
/* Initialize PCNT event queue and PCNT functions */
pcnt_evt_queue = xQueueCreate(10, sizeof(pcnt_evt_t));
xTaskCreateUniversal(pcnt_task, "pcnt_task", 4096, NULL, 1, NULL, ARDUINO_RUNNING_CORE);
pcnt_example_init(pcnt_unit);
}
void loop() {
}
Closing as expired due to no asnwer.
Board
ESP32 WRoom 32
Device Description
Lilygo T8 v1.7.1
Hardware Configuration
GPIO 25,26,27,12,14,35 for PCNT usage GPIO 23,18,4,5 for SPI display
Version
v2.0.9
IDE Name
Arduino IDE 2.1.0
Operating System
Windows 10
Flash frequency
80 Mhz
PSRAM enabled
yes
Upload speed
912500
Description
When trying to compile with lastest ESP32 library, pcnt_isr_install_service call failed with a driver error. Building & Running same project with ESP32 Arduino library 1.6.0 run successfully...
Sketch
Debug Message
Other Steps to Reproduce
No response
I have checked existing issues, online documentation and the Troubleshooting Guide