counting pulses problems

Status
Not open for further replies.

so999

Member
Hello,
I need to generate a specified number of pulses with a Teensy3.2
First time I configured timer1 with analogwritefrequency and analogwrite to generate the pulses on pin 3 and I attached an interrupt on the pin 3. The interrupt routine only counts the pulses and stops when the limit is reached. I counted the real pulses with another board : ESP32. I was surprised to find that ESP32 counted more pulses than the interrupt routine. For lower frequencies (50kHz) and a total number of about 1,800,000 pulses there is only one extra pulse counted by ESP32. For 500kHz : 12 pulses. For many pulses (18millions) and 700kHz, there are more than 10,000 extra pulses counted by ESP32. This is the code used for generating the pulses.

Code:
uint8_t pulse_pin = 3;
unsigned long NoOfPulses=0;
unsigned long pulseCount=0;
void setup() {
    pinMode(pulse_pin, OUTPUT);
    pulseCount=0;

    delay(15000);

    NoOfPulses=18502051; 
    analogWriteResolution(16);
    analogWriteFrequency(pulse_pin, 700000.0L); 
    analogWrite(pulse_pin, 32000);
    attachInterrupt (pulse_pin, pulseCounting, RISING); 
}

void pulseCounting()
{
  pulseCount++;
  if (pulseCount >= NoOfPulses)
   {
    detachInterrupt (pulse_pin);
    analogWriteFrequency(pulse_pin, 0.0); //in the same case (ramping still working and the end freq not restored), it will be restored now
    analogWrite(pulse_pin, 32000);
    Serial.println("Count ended!");
    Serial.print("Counts: ");Serial.println(pulseCount);
   }
}

void loop() {}

The second approach was to manually configure the Timer1 and to count the pulses when a compare match occurs. This is the code.

Code:
uint8_t pulsePin = 3;

volatile unsigned long pulseCount = 0;
unsigned long Npulses = 0;

#define FTM1_CH0_PIN 3
#define FTM_PINCFG(pin) FTM_PINCFG2(pin)
#define FTM_PINCFG2(pin) CORE_PIN ## pin ## _CONFIG

void setup() {
  pinMode(pulsePin, OUTPUT);

  FTM_PINCFG(FTM1_CH0_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;

  Npulses = 1920000;
  double freq=200000.0L;
  pulseCount=0;

  delay(17000);

  FTM1_COMBINE=0;
  FTM1_SC=B1001000;
  FTM1_C0SC=B1101000;
  double fff=0.0L;
  fff=48000000.0L/freq;
  FTM1_MOD = (int) fff;
  FTM1_C0V = (int) fff/2.0L;
  NVIC_ENABLE_IRQ(IRQ_FTM1);
}



extern "C" void ftm1_isr(void) {
pulseCount++;
if(pulseCount>=Npulses)
{
  FTM1_C0V = 0;
  FTM1_MOD = 0;
  Serial.println("end");
  Serial.print("Pulses:");Serial.println(pulseCount);
}
}

void loop(void)
{}

The result is very wrong: for a 200kHz signal and a limit of 1,920,000 pulses, ESP32 counts only 131,646 pulses. Obviously in the interrupt routine occur other events, but I don’t know how to filter them to count only for one compare match event.

Could you please help me to properly configure the interrupt routine?
 
in your first sketch you are abusing pin 3. Use pin 2 for the attachInterrupt/detachInterrupt and jumper pin 2 to pin 3. Since pin 3 is used by analogWrite, you don't need pinMode(pulse_pin, OUTPUT); attachInterrupt on T3.2 is probably workable as long as frequency is less than 1 mhz.
 
Thank you for answering!
I connected pin 2 with pin 3 and I attached the interrupt on pin 2. The modified code is below.

Code:
uint8_t pulse_pin = 3;
uint8_t interrupt_pin=2;

unsigned long NoOfPulses=0;
unsigned long pulseCount=0;

void setup() {
    pulseCount=0;
    NoOfPulses=18502051; 

    pinMode(interrupt_pin, INPUT); 
    attachInterrupt (interrupt_pin, pulseCounting, FALLING); 

    delay(15000);
     
    analogWriteResolution(16);
    analogWriteFrequency(pulse_pin, 700000.0L); 
    analogWrite(pulse_pin, 32000);

}






void pulseCounting()
{
  pulseCount++;
  if (pulseCount >= NoOfPulses)
   {
    analogWriteFrequency(pulse_pin, 0.0); //in the same case (ramping still working and the end freq not restored), it will be restored now
    analogWrite(pulse_pin, 32000);
    detachInterrupt (interrupt_pin);

    Serial.println("Count ended!");
    Serial.print("Counts: ");Serial.println(pulseCount);
   }
}


void loop() {

}

For low frequency (100kHz) and a small number of pulses (about 1,8 million pulses) it works. Unfortunately, for higher frequencies and many pulses the problem still remain.
The results for 18,502,051 pulses and:
-100kHz : ESP32 counts 1 extra pulse;
-200kHz : ESP32 counts 2 extra pulses;
-300kHz : ESP32 counts 6 extra pulses;
-700kHz : ESP32 counts more than 10,000 extra pulses!
These numbers are not the same. For the same frequency and the same limit they vary a bit around the mentioned count.
I tried to configure the interrupt to work on falling or rising edge and also I configured the interrupt_pin to input and input_pullup without noticeable differences.

I know that ESP32 is working well because I did the same test but with the pulses generated by Teensy with the PIT timer. There in the interrupt I put a digitalwrite to generate the pulses. In that test the results were the same for any number of pulses and for any frequency under 1MHz.
 
Thank you Paul.
It is a lot to digest in that thread, but for the moment I tried to set the priority of the interrupt to 0. The result improved somehow. For 700kHz ESP32 still counts more pulses - but only 10 (before were over 10,000 extra pulses). The problem still persist as there are extra pulses even for 100kHz.
 
Dumb question: If you need a specified number of pulses-so the first solution that comes to mind is to use a simple for (... ) loop and bitbang..write 1 and 0. You might want to insert a small delay if it's too fast.
 
Dumb question: If you need a specified number of pulses-so the first solution that comes to mind is to use a simple for (... ) loop and bitbang..write 1 and 0. You might want to insert a small delay if it's too fast.

No, I can’t use a loop. I need teensy to be responsive to other actions and eventually to some serial events. Actually I solved the problem in a similar way with the PIT timer. In the interrupt routine was the code for counting and also for generating the pulses, so every pulse is correctly counted. But I would like to let the hardware to produce the pulses and to put the minimum load on the mcu.
 
Maybe try using the FreqCount library (or copy & edit its code). FreqCount uses the asynchronous LPTMR to count the pulses, so pretty much no software overhead at all.
I took a brief look at the FreqCount library and as I understand it is oriented to count pulses in an interval of time so I can’t use it as it is. But I saw that LPTMR has a pulse counting mode. It is an interesting option. I will test it soon.
 
Last edited:
Maybe try using the FreqCount library (or copy & edit its code). FreqCount uses the asynchronous LPTMR to count the pulses, so pretty much no software overhead at all.

Hi Paul - i watched your interesting video using a Teensy to count pulses

Do you think a teensy could be used to count 4 high speed counters and still run a main loop that would not be interrupted

my target frequency is 60 khz

should extra hardware be used on the board to do the counting ? what would be suitable to do this, I have read about the 74LS112D flip flop
 
Status
Not open for further replies.
Back
Top