Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 12 of 12

Thread: counting pulses problems

  1. #1

    counting pulses problems

    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?

  2. #2
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    1,643
    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.

  3. #3
    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.

  4. #4
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,691
    Maybe this thread can help?

    https://forum.pjrc.com/threads/48101...ing-Teensy-3-2

    Here's a video demo, comparing the pulse count to a BK Precision counter.


  5. #5
    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.

  6. #6
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,774
    The systick has priority 0, too - have you tried to reduce its priority one step?

  7. #7
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,691
    Quote Originally Posted by Frank B View Post
    The systick has priority 0
    Systick is supposed to have priority 32, due to line 1107 in mk20dx128.c.

    Code:
    	SCB_SHPR3 = 0x20200000; // Systick = priority 32

  8. #8
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,691
    Quote Originally Posted by so999 View Post
    The problem still persist....
    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.

  9. #9
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,774
    Quote Originally Posted by PaulStoffregen View Post
    Systick is supposed to have priority 32, due to line 1107 in mk20dx128.c.

    Code:
        SCB_SHPR3 = 0x20200000; // Systick = priority 32
    Oh, indeed. Since 2015!
    Last edited by Frank B; 11-22-2018 at 12:26 PM.

  10. #10
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,774
    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.

  11. #11
    Quote Originally Posted by Frank B View Post
    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.

  12. #12
    Quote Originally Posted by PaulStoffregen View Post
    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 by so999; 11-22-2018 at 09:43 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •