Page 1 of 1

PCNT second overflow Handler will not be called

Posted: Wed Jul 05, 2023 5:40 pm
by IF3ST0S
Hello,

the esp32 has a few PCNT Units on Board. With a little bit of searching i managed to put a code together that works. I can count with multiple Units. But i want to Count more than 32.768 with at least two individual Signals.

The first overflow handler for Unit_0 works perfectly but the second one does not. If the overflow is reached the first handler will be always called. The first handler will be executed as long as the flag is not cleared. So if the second/third Unit reaches its limit the esp32 is in an endless loop. Why does the handler do this? Any suggestion how to get by this problem?

Code: Select all

#include "soc/pcnt_struct.h"

#include "driver/pcnt.h"  // ESP32 library for pulse count

// Pin für den Pulszähler
const int pinPCNT_0 = 4;
const int pinPCNT_1 = 5;
const int pinPCNT_2 = 19;

//Counter
int16_t count_PCNT0;
int16_t count_PCNT1;
int16_t count_PCNT2;

//OverflowCounter
int overflowPCNT_0;
int overflowPCNT_1;
int overflowPCNT_2;
int overflowPCNT_3;
int overflowPCNT_4;
int overflowPCNT_5;

//OverflowInterrput
pcnt_isr_handle_t user_isr_handle = NULL; 

//Overflow Handler
void IRAM_ATTR PCNTOverflow_Handler_0(void *arg) {                  // Interrupt for overflow of pulse counter
  Serial.println("Overflow PCNT_0");
  overflowPCNT_0 = overflowPCNT_0 + 1;                     // increase overflow counter
  PCNT.int_clr.val = BIT(PCNT_UNIT_0);                    // clean overflow flag
  pcnt_counter_clear(PCNT_UNIT_0);                        // zero and reset of pulse counter unit
}

void IRAM_ATTR PCNTOverflow_Handler_1(void *arg) {                  // Interrupt for overflow of pulse counter
  Serial.println("Overflow PCNT_1");
  overflowPCNT_1 = overflowPCNT_1 + 1;                     // increase overflow counter
  PCNT.int_clr.val = BIT(PCNT_UNIT_1);                    // clean overflow flag
  pcnt_counter_clear(PCNT_UNIT_1);                        // zero and reset of pulse counter unit
}

void IRAM_ATTR PCNTOverflow_Handler_2(void *arg) {                  // Interrupt for overflow of pulse counter
  Serial.println("Overflow PCNT_2");
 // overflowPCNT_0 = overflowPCNT_0 + 1;                     // increase overflow counter
  PCNT.int_clr.val = BIT(PCNT_UNIT_2);                    // clean overflow flag
  pcnt_counter_clear(PCNT_UNIT_2);                        // zero and reset of pulse counter unit
}

void FC_PCNT_Init_0(){
  // Initialisierung des PCNT
  pcnt_config_t pcntConfig;
  pcntConfig.unit = PCNT_UNIT_0;
  pcntConfig.pulse_gpio_num = pinPCNT_0;
  pcntConfig.ctrl_gpio_num = PCNT_PIN_NOT_USED;
  pcntConfig.channel = PCNT_CHANNEL_0;
  pcntConfig.pos_mode = PCNT_COUNT_INC;
  pcntConfig.neg_mode = PCNT_COUNT_DIS;
  pcntConfig.lctrl_mode = PCNT_MODE_KEEP;
  pcntConfig.hctrl_mode = PCNT_MODE_KEEP;
  pcntConfig.counter_h_lim = 100;
  pcntConfig.counter_l_lim = PCNT_COUNT_DIS;

  // Konfiguration des PCNT
  pcnt_unit_config(&pcntConfig);

  pcnt_counter_pause(PCNT_UNIT_0);                        // pause puls counter unit
  pcnt_counter_clear(PCNT_UNIT_0);                        // zero and reset of pulse counter unit
//Overflow Handler
  pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_H_LIM);         // enable event for interrupt on reaching upper limit of counting
  pcnt_isr_register(PCNTOverflow_Handler_0, NULL, 0, &user_isr_handle);  // configure register overflow interrupt handler
  pcnt_intr_enable(PCNT_UNIT_0);                          // enable overflow interrupt

//Glitch Filter
  pcnt_set_filter_value(PCNT_UNIT_0, 1000);    // set damping, inertia 
  pcnt_filter_enable(PCNT_UNIT_0);
  // Aktivierung des PCNT
 pcnt_counter_resume(PCNT_UNIT_0);
}

void FC_PCNT_Init_1(){
  // Initialisierung des PCNT
  pcnt_config_t pcntConfig;
  pcntConfig.unit = PCNT_UNIT_1;
  pcntConfig.pulse_gpio_num = pinPCNT_1;
  pcntConfig.ctrl_gpio_num = PCNT_PIN_NOT_USED;
  pcntConfig.channel = PCNT_CHANNEL_0;
  pcntConfig.pos_mode = PCNT_COUNT_INC;
  pcntConfig.neg_mode = PCNT_COUNT_DIS;
  pcntConfig.lctrl_mode = PCNT_MODE_KEEP;
  pcntConfig.hctrl_mode = PCNT_MODE_KEEP;
  pcntConfig.counter_h_lim = 100;
  pcntConfig.counter_l_lim = PCNT_COUNT_DIS;

  // Konfiguration des PCNT
  pcnt_unit_config(&pcntConfig);
   if ( pcnt_unit_config(&pcntConfig) == ESP_OK ) {
    Serial.println("Init_PCNT_1 OK!");
    pcnt_counter_pause(PCNT_UNIT_1);                        // pause puls counter unit
    pcnt_counter_clear(PCNT_UNIT_1);                        // zero and reset of pulse counter unit
    //Overflow Handler
    pcnt_event_enable(PCNT_UNIT_1, PCNT_EVT_H_LIM);         // enable event for interrupt on reaching upper limit of counting
    pcnt_isr_register(PCNTOverflow_Handler_1, NULL, 0, &user_isr_handle);  // configure register overflow interrupt handler
    pcnt_intr_enable(PCNT_UNIT_1);                          // enable overflow interrupt

    //Glitch Filter
      pcnt_set_filter_value(PCNT_UNIT_1, 1000);    // set damping, inertia 
      pcnt_filter_enable(PCNT_UNIT_1);
      // Aktivierung des PCNT
    pcnt_counter_resume(PCNT_UNIT_1);
  }
  else {
    Serial.println("Init_PCNT_1 FAILED!!!!!!!!!!!!");
  }

  pcnt_counter_pause(PCNT_UNIT_1);                        // pause puls counter unit
  pcnt_counter_clear(PCNT_UNIT_1);                        // zero and reset of pulse counter unit
//Overflow Handler
  pcnt_event_enable(PCNT_UNIT_1, PCNT_EVT_H_LIM);         // enable event for interrupt on reaching upper limit of counting
  pcnt_isr_register(PCNTOverflow_Handler_1, NULL, 0, &user_isr_handle);  // configure register overflow interrupt handler
  pcnt_intr_enable(PCNT_UNIT_1);                          // enable overflow interrupt

//Glitch Filter
  pcnt_set_filter_value(PCNT_UNIT_1, 1000);    // set damping, inertia 
  pcnt_filter_enable(PCNT_UNIT_1);
  // Aktivierung des PCNT
 pcnt_counter_resume(PCNT_UNIT_1);
}

void FC_PCNT_Init_2(){
  // Initialisierung des PCNT
  pcnt_config_t pcntConfig;
  pcntConfig.unit = PCNT_UNIT_2;
  pcntConfig.pulse_gpio_num = pinPCNT_2;
  pcntConfig.ctrl_gpio_num = PCNT_PIN_NOT_USED;
  pcntConfig.channel = PCNT_CHANNEL_0;
  pcntConfig.pos_mode = PCNT_COUNT_INC;
  pcntConfig.neg_mode = PCNT_COUNT_DIS;
  pcntConfig.lctrl_mode = PCNT_MODE_KEEP;
  pcntConfig.hctrl_mode = PCNT_MODE_KEEP;
  pcntConfig.counter_h_lim = 100;
  pcntConfig.counter_l_lim = PCNT_COUNT_DIS;

  // Konfiguration des PCNT
 // pcnt_unit_config(&pcntConfig);
  if ( pcnt_unit_config(&pcntConfig) == ESP_OK ) {
    Serial.println("Init_PCNT_2 OK!");
    pcnt_counter_pause(PCNT_UNIT_2);                        // pause puls counter unit
    pcnt_counter_clear(PCNT_UNIT_2);                        // zero and reset of pulse counter unit
    //Overflow Handler
    pcnt_event_enable(PCNT_UNIT_2, PCNT_EVT_H_LIM);         // enable event for interrupt on reaching upper limit of counting
    pcnt_isr_register(PCNTOverflow_Handler_2, NULL, 0, &user_isr_handle);  // configure register overflow interrupt handler
    pcnt_intr_enable(PCNT_UNIT_2);                          // enable overflow interrupt

    //Glitch Filter
      pcnt_set_filter_value(PCNT_UNIT_2, 1000);    // set damping, inertia 
      pcnt_filter_enable(PCNT_UNIT_2);
      // Aktivierung des PCNT
    pcnt_counter_resume(PCNT_UNIT_2);
  }
  else {
    Serial.println("Init_PCNT_2 FAILED!!!!!!!!!!!!");
  }

  
}

void setup() {
  // Initialisierung der seriellen Kommunikation
  Serial.begin(115200);
  FC_PCNT_Init_0();
  FC_PCNT_Init_1();
  FC_PCNT_Init_2();

}

void loop() {
  // Abrufen Zählerstand
  pcnt_get_counter_value(PCNT_UNIT_0, &count_PCNT0);
  pcnt_get_counter_value(PCNT_UNIT_1, &count_PCNT1);
  pcnt_get_counter_value(PCNT_UNIT_2, &count_PCNT2);

  // Anzeige des Zählerstandes
  Serial.print("Unit_0 Count: ");
  Serial.println(count_PCNT0);
  Serial.print("Unit_0 Overflow: ");
  Serial.println(overflowPCNT_0);
  Serial.print("Unit_1 Count: ");
  Serial.println(count_PCNT1);
  Serial.print("Unit_1 Overflow: ");
  Serial.println(overflowPCNT_1);
  Serial.print("Unit_2 Count: ");
  Serial.println(count_PCNT2);
  Serial.print("Unit_2 Overflow: ");
  Serial.println(overflowPCNT_2);

  delay(100);

}

Booting

Code: Select all

Init_PCNT_1 OK!
Init_PCNT_2 OK!
Unit_0 Count: 0
Unit_0 Overflow: 0
Unit_1 Count: 0
Unit_1 Overflow: 0
Unit_2 Count: 0
Unit_2 Overflow: 0
Unit_0 Count: 0
Unit_0 Overflow: 0
Unit_1 Count: 0
Unit_1 Overflow: 0
Unit_2 Count: 0
Unit_2 Overflow: 0
Unit_0 Overflow

Code: Select all

Unit_2 Overflow: 0
Overflow PCNT_0
Unit_0 Count: 1
Unit_0 Overflow: 1
Unit_1 Count: 0
Unit_1 Overflow: 0
Unit_2 Count: 0
Unit_2 Overflow: 0
Unit_1 Overflow see Comment

Code: Select all

Unit_0 Count: 0
Unit_0 Overflow: 0
Unit_1 Count: 96
Unit_1 Overflow: 0
Unit_2 Count: 0
Unit_2 Overflow: 0
Overflow PCNT_0
Overflow PCNT_0
Overflow PCNT_0
Overflow PCNT_0
Overflow PCNT_0
Overflow PCNT_0
Overflow PCNT_0
Overflow PCNTGuru Meditation Error: Core  1 panic'ed (Interrupt wdt timeout on CPU1). 

Core  1 register dump:
PC      : 0x4008aae6  PS      : 0x00060135  A0      : 0x80089a5a  A1      : 0x3ffbf13c  
A2      : 0x3ffb897c  A3      : 0x3ffbce0c  A4      : 0x00000004  A5      : 0x00060123  
A6      : 0x00060123  A7      : 0x00000001  A8      : 0x3ffbce0c  A9      : 0x00000019  
A10     : 0x3ffbce0c  A11     : 0x00000019  A12     : 0x3ffc298c  A13     : 0x00060123  
A14     : 0x007bf2f8  A15     : 0x003fffff  SAR     : 0x00000020  EXCCAUSE: 0x00000006  
EXCVADDR: 0x00000000  LBEG    : 0x40086355  LEND    : 0x40086365  LCOUNT  : 0xfffffffb  
Core  1 was running in ISR context:
EPC1    : 0x400dabdb  EPC2    : 0x00000000  EPC3    : 0x00000000  EPC4    : 0x00000000


Backtrace: 0x4008aae3:0x3ffbf13c |<-CORRUPTED


Core  0 register dump:
PC      : 0x4008ac7f  PS      : 0x00060035  A0      : 0x80089683  A1      : 0x3ffbea1c  
A2      : 0x3ffbf2f8  A3      : 0xb33fffff  A4      : 0x0000abab  A5      : 0x00060023  
A6      : 0x00060021  A7      : 0x0000cdcd  A8      : 0x0000abab  A9      : 0xffffffff  
A10     : 0x3ffc27a4  A11     : 0x00000000  A12     : 0x3ffc27a0  A13     : 0x00000007  
A14     : 0x007bf2f8  A15     : 0x003fffff  SAR     : 0x0000001d  EXCCAUSE: 0x00000006  
EXCVADDR: 0x00000000  LBEG    : 0x00000000  LEND    : 0x00000000  LCOUNT  : 0x00000000  


Backtrace: 0x4008ac7c:0x3ffbea1c |<-CORRUPTED




ELF file SHA256: 50bb7d4c025eaee8

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1344
load:0x40078000,len:13924
ho 0 tail 12 room 4
load:0x40080400,len:3600
entry 0x400805f0
Init_PCNT_1 OK!
Init_PCNT_2 OK!
Unit_0 Count: 0
Unit_0 Overflow: 0
Unit_1 Count: 0
Unit_1 Overflow: 0
Unit_2 Count: 0
Unit_2 Overflow: 0