Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 2 1 2 LastLast
Results 1 to 25 of 32

Thread: Teensy 4 FreqMeas problem ?

  1. #1
    Member
    Join Date
    Aug 2019
    Location
    southwest USA
    Posts
    48

    Teensy 4 FreqMeas problem ?

    in the code below which is mostly stolen from and old Teensy LC program that works fine,
    the output seems to wander around (see output below). this happens with and w/o waiting
    for an edge, with or w/o declaring the input pin as input (that is why all the commented out lines.
    i have run a homemade freq meas that is pure software looking at that same pin w same vin,
    fin, and protection resistor and numbers quite repeatable.

    sq wave input goes 0.1 v to 3.1 v with 10k series protection resistor, tried 500 hz, 1khz, 1.5 khz

    i found a reference in the forum that freqmeas uses pin 22 as input - could that have changed?
    that same post showed good output from testing and signed off on freqmeas for T4
    am i overlooking something?
    is this really a bug?

    here is the code:

    Code:
    #include <FreqMeasure.h>
    
    volatile unsigned int fm,nm;
    volatile unsigned short int rp1,rp2;
    volatile unsigned short int wc;
    volatile unsigned short int vc=2;
    
    int main() {
    //  pinMode(22, INPUT);
      Serial.begin(9600);
      delay(2000);
    mloop:
    // wait for pin 22 to change
    //  goto skp;
    //  wc=0;
    //wtchg:
    //  rp1=digitalReadFast(22);
    //  delayMicroseconds(2);
    //  rp2=digitalReadFast(22);
    //  delayMicroseconds(2);
    //  if (rp1==rp2) goto wtchg;
    //  ++wc;
    //  if (wc<vc) goto wtchg;
    //skp:
    //  pinMode(22, INPUT);
      FreqMeasure.begin();
    fmeas:
      nm = FreqMeasure.available();
      if (!nm) goto fmeas;
      fm = FreqMeasure.read();
      FreqMeasure.end();
      Serial.println(fm);
      delay(5000);
      goto mloop;
    }
    here is the output:

    Code:
    65950
    85325
    29860
    122921
    119221
    87416
    31073
    118509
    112515
    81163
    28398
    115655
    112744
    77425
    46578
    66131
    102791
    124760
    131521
    52774
    82790
    27665
    121714
    127578
    47403
    76589
    18656
    107765
    105009
    74826
    18979
    107823
    109641
    91503
    49450
    148374
    95197
    86666
    58260
    70732
    91769
    91935
    71547
    31934
    129091
    73530
    69537

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,939
    Typical for forum sketches to be in IDE format to allow actually running the code unchanged.

    Why the repeated :: { .begin, .end, .begin , … }

    This examples shows intended usage to some degree :: ...\hardware\teensy\avr\libraries\FreqMeasure\exam ples\Serial_Output

    Code:
    /* FreqMeasure - Example with serial output
     * http://www.pjrc.com/teensy/td_libs_FreqMeasure.html
     *
     * This example code is in the public domain.
     */
    #include <FreqMeasure.h>
    
    void setup() {
      Serial.begin(57600);
      FreqMeasure.begin();
    }
    
    double sum=0;
    int count=0;
    
    void loop() {
      if (FreqMeasure.available()) {
        // average several reading together
        sum = sum + FreqMeasure.read();
        count = count + 1;
        if (count > 30) {
          float frequency = FreqMeasure.countToFrequency(sum / count);
          Serial.println(frequency);
          sum = 0;
          count = 0;
        }
      }
    }

  3. #3
    Member
    Join Date
    Aug 2019
    Location
    southwest USA
    Posts
    48
    what is IDE format ? that was select all then copy in arduino ide, paste to notepad, flash drive, web computer, paste into
    the post - that was what i ran to get the output you see. or are you speaking of the fact that it uses main() instead of
    setup() and loop() ?

  4. #4
    Member
    Join Date
    Aug 2019
    Location
    southwest USA
    Posts
    48
    it just dawned on me that not everyones arduino will use main (tls and t3.6 do it and one of the senior members showed me what
    to edit so t4 will do it too) so i can pull up old pgms and compile t4 to double check all will work.

    so i need to always send sample code that uses setup() and loop() so others can just drop it in and compile.

    so i modified to use setup() and loop() and the symptoms did not change - just like output shown in my first bug report on this.

    but here is the setup() and loop() version that should drop in and compile/run. i am using win7x64, arduino 1.8.5, and
    teensyduino 1.48 release

    the reason for all of the start and begin is that the big pgm (fsk receiver) has the freqcount pin and the freqmeas pins tied
    together and does watch for change input - freqmeasure.begin - wait for synch tones - freqmeasure.end - freqcount.begin(x) -
    get 32-64 sequential msmnts into array - freqcount.end - decoding - loop for new message.
    i was afraid not to turn each off so would not get in each others hair - it all woked fine


    Code:
    #include <FreqMeasure.h>
    
    volatile unsigned int nm,fm;
    volatile unsigned short int rp1,rp2;
    volatile unsigned short int wc;
    volatile unsigned short int vc=2;
    
    void setup() {
    //  pinMode(22, INPUT);
      Serial.begin(9600);
      delay(2000);
    //  FreqMeasure.begin();
    }
    
    
    void loop() {
    // wait for pin 22 to change
    //  goto skp;
    //  wc=0;
    //wtchg:
    //  rp1=digitalReadFast(22);
    //  delayMicroseconds(2);
    //  rp2=digitalReadFast(22);
    //  delayMicroseconds(2);
    //  if (rp1==rp2) goto wtchg;
    //  ++wc;
    //  if (wc<vc) goto wtchg;
    //skp:
    //  pinMode(22, INPUT);
      FreqMeasure.begin();
    fmeas:
      nm = FreqMeasure.available();
      if (!nm) goto fmeas;
      fm = FreqMeasure.read();
      delay(100);
      Serial.println(fm);
      FreqMeasure.end();
    //  Serial.println(fm);
      delay(5000);
    }

  5. #5
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,939
    Quote Originally Posted by analog&RFmodels View Post
    what is IDE format ? that was select all then copy in arduino ide, paste to notepad, flash drive, web computer, paste into
    the post - that was what i ran to get the output you see. or are you speaking of the fact that it uses main() instead of
    setup() and loop() ?
    Yes, as in the post #2 example from the IDE install - setup() begin() is normal IDE format.

    Code could to do this and then just rename main when sharing and use the setup() and loop() funcs - where loop wouldn't have to exit:
    Code:
    void main(){
      setup();
      while(1) loop();
    }
    That is all Arduino norm does with main - except it adds a yield() call in the while(1) loop for serialEvent_X() processing.

    Pin #22 is used by 'FreqMeasure': - that should be documented on the web page … but not yet:
    Code:
    #elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
      #define CAPTURE_USE_FLEXPWM4_CH0A 22 // FlexPWM CH0-A is pin 22
    It isn't noted what freq is being tested against? PJRC web page notes:: FreqMeasure: best for 0.1 Hz to 1 kHz

    For a forum user to re-create with a known freq a PWM pin could be set up and tied to the measure pin.

    Indicate what freq is at hand - modify this sketch and give it a try?

    Code:
    /* FreqMeasure - Example with serial output
     * http://www.pjrc.com/teensy/td_libs_FreqMeasure.html
     *
     * This example code is in the public domain.
     */
    #include <FreqMeasure.h>
    
    void main(){
      setup();
      while(1) loop();
    }
    
    void setup() {
      Serial.begin(57600);
      FreqMeasure.begin();
      analogWriteFrequency(23, 800);  // test jumper 22 to 23 
      analogWrite(23, 128);
    }
    
    double sum=0;
    int count=0;
    
    void loop() {
      if (FreqMeasure.available()) {
        // average several reading together
        sum = sum + FreqMeasure.read();
        count = count + 1;
        if (count > 30) {
          float frequency = FreqMeasure.countToFrequency(sum / count);
          Serial.println(frequency);
          sum = 0;
          count = 0;
        }
      }
    }

  6. #6
    Member
    Join Date
    Aug 2019
    Location
    southwest USA
    Posts
    48
    ok pin 22 is still correct - makes sense, when i turn the generator off dead standstill for awhile
    i tried 500 hz 1000 hz and 1500 hz - all wander terribly as if the internal timer is not getting reset before measurement
    i will try your code but would like to know what is wrong with my code because in the finished large pgm (fsk rcvr) there
    is absolutely no time for averaging - in the big pgm (which runs fine on the teensylc and from which this was stolen)
    FreqMeas works very well without averaging and works well 300 hz - 1000 hz

    if your code runs here maybe i can just take the averaging out

    by the way - do you know which pin FreqCount library uses for T4 input ?
    looking in the code i saw a pin 47 ? but which board pin would that be ?
    in teensylc and 3.6 FreqMeas and FreqCount use different pins

  7. #7
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,231
    Quote Originally Posted by analog&RFmodels View Post

    by the way - do you know which pin FreqCount library uses for T4 input ?
    looking in the code i saw a pin 47 ? but which board pin would that be ?
    in teensylc and 3.6 FreqMeas and FreqCount use different pins
    T4 FreqCount uses pin 9 -- see lib example Serial_Output_T4.ino

  8. #8
    Member
    Join Date
    Aug 2019
    Location
    southwest USA
    Posts
    48
    manitou,

    thank you for the feedback

    defragster,

    thank you for the feedback

    i ran the code you were nice enuf to post w 22 and 23 tied together - ran fine very near 800.0 every time

    switched back to my generator - very near 1000 every time

    took out the averaging - 1000.0 to 1000.3 every time

    added 5 sec delay at bottom of loop - still good

    commented out your FreqMeasure.begin() and put one at the top inside of the loop with a FreqMeasure.end()
    after the 5 sec delay followed by 100 ms delay for good measure - started bad wandering like my code had

    *** with FreqMeas library, for whatever reason the TLC will withstand the repetitive ..begins ...measure and ...ends all day long but T4 no dice. ***

    but that probably is not a show stopper - i will try to work around knowing this.

    thanks again for all of the feedback
    Last edited by analog&RFmodels; 10-17-2019 at 02:05 AM. Reason: additions

  9. #9
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,939
    Glad you saw it work - not sure of the mechanics of the counting timing involved - and how .begin .end would mess with that - but is seemed possible or likely. Not surprising the M0 T_LC is a bit diff than the M7 T_4.

  10. #10
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,206
    Quote Originally Posted by analog&RFmodels
    *** with FreqMeas library, for whatever reason the TLC will withstand the repetitive ..begins ...measure and ...ends all day long but T4 no dice. ***
    Have it running here now with .begins and .ends and it doesn't seem to have any problems. When you say no dice what exactly is occurring?

  11. #11
    Member
    Join Date
    Aug 2019
    Location
    southwest USA
    Posts
    48
    Quote Originally Posted by mjs513 View Post
    Have it running here now with .begins and .ends and it doesn't seem to have any problems. When you say no dice what exactly is occurring?
    the number returned has terrible wander - ie not repeatable - as if the timer is not getting reset each time or is not synchronized

    that output is listed in the orig report

    a couple of posts later is the same code in setup() loop() format w same symptoms

    ..begin .. available .. meas ..end then delay 5 sec inside a loop gives wandering

    ..begin before the loop then ..available ..meas then delay 5 sec inside the loop is repeatable

    maybe i am overlooking something or have a misunderstanding of how it really should function
    i used start: wait for pins change .. beginfreqmeas .. avail ..freqmeas ..avail freqmeas ..end .. begin freqcount (..avail
    ..meas) 30 times ..end freqcount loop to start and wait foe next message (saw 5 sec to 5 minutes during that wait)
    work just fine teensy lc

    if you need i can send a minimum code for wander and the other for not

  12. #12
    Member
    Join Date
    Aug 2019
    Location
    southwest USA
    Posts
    48
    here is a piece of t4 code that shows the fmeas problem i am seeing,
    and seems to at least isolate the nature of the problem. and turns out
    tlc does it too - in my old application it was "invisible" but with this
    diag code tlc shows it.

    it is an offshoot of something defragster sent me and at first i thought
    it just plain worked and did what i needed - two fmeas cycles right in a
    row and the a big delay and repeat. but by the time i looked at the display
    all looked ok but when i captured the entire window including what had
    scrolled off the top it was obvious that the first two readings were in
    error but all of the pairs after that ok.

    so bottom line is - first two fmeas cycles after freqmeasure.begin may
    be in error, so you do not have to do two dummies every time you do a
    pair of measurements (which was my bandaid) - you only have to do two
    dummy cycles after the last ...begin.

    i have no idea if this is a problem or a bug or just inherent in the way
    the library code works, but in most applications it could be worked around
    unless time is very of the essence.

    in the future i think i will always use an external generator because after all
    this it seemed like some problems showed up more often that way than with
    an on board pwm gen - maybe because the on board is time or phase
    locked to an internal bus along w the timer in question ?? could be my
    imagination.


    here is the code:

    Code:
    // for t4 works ok - first two meas pair bogus then all ok
    /* FreqMeasure - Example with serial output
     * http://www.pjrc.com/teensy/td_libs_FreqMeasure.html
     *
     * This example code is in the public domain.
     */
    #include <FreqMeasure.h>
    
    void setup() {
      Serial.begin(9600);
      FreqMeasure.begin();
    //  analogWriteFrequency(23, 800);  // test jumper 22 to 23 
    //  analogWrite(23, 128);
    }
    
    double sum1=0,sum2=0;
    int count=0;
    
    void loop() {
      delay(1);
    loop:
      if (!FreqMeasure.available()) goto loop;
      sum1 = FreqMeasure.read();
    loop2:
      if (!FreqMeasure.available()) goto loop2;
      sum2 = FreqMeasure.read();
          float frequency1 = 150000000/sum1;
          float frequency2 = 150000000/sum2;
          Serial.println(frequency1);
          Serial.println(frequency2);
          Serial.println(" ");
          delay(5000);
    }
    here is the output:

    Code:
    6578.66
    3179.79
     
    9933.12
    9932.46
     
    9932.46
    9932.46
     
    9931.80
    9932.46
     
    9932.46
    9932.46
     
    9933.12
    9933.12
    Last edited by analog&RFmodels; 10-17-2019 at 11:44 PM. Reason: clarity

  13. #13
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,939
    Interesting - as noted : "not sure of the mechanics of the counting timing involved"

    If those two first parts {6578+3179 = = 9757 } are added they almost account for a full count over a cycle time of 9932 ~= 9757.

    Might be a way to clean it up - but somehow partial periods on start seem to be involved with the .begin. It is common with PWM's for instance that pushing a new freq value doesn't start until the current period ends and the new value is reloaded.

    Maybe the way self test jumpering running on the same clocks and at same bus rate syncs faster properly.

    When sketch starts and issues .begin a (partial?) period starts - not sure when the external count starts and seems to get buffered as done and put in the queue. Maybe the first one triggers an early end to the second based on buffer counting /queing?
    Code:
    uint8_t FreqMeasureClass::available(void)
    {
    	uint8_t head, tail;
    
    	head = buffer_head;
    	tail = buffer_tail;
    	if (head >= tail) return head - tail;
    	return FREQMEASURE_BUFFER_LEN + head - tail;
    }
    So printing the return of .available() will show how many are ready. What does this show?:
    Code:
    #include <FreqMeasure.h>
    
    void setup() {
      Serial.begin(9600);
      FreqMeasure.begin();
    //  analogWriteFrequency(23, 800);  // test jumper 22 to 23 
    //  analogWrite(23, 128);
    }
    
    double sum1=0,sum2=0;
    int count=0;
    int countA=0;
    
    void loop() {
      delay(1);
    loop:
      if (!FreqMeasure.available()) goto loop;
      count = FreqMeasure.available();
      sum1 = FreqMeasure.read();
    //      float frequency1 = 150000000/sum1;
          Serial.printf(" S1: Cnt = %u\t us=%u\t", count, micros() );
    loop2:
      if (!FreqMeasure.available()) goto loop2;
      countA = FreqMeasure.available();
          Serial.println(FreqMeasure.countToFrequency(sum1));
      sum2 = FreqMeasure.read();
    //      float frequency2 = 150000000/sum2;
          Serial.printf(" S2: Cnt = %u\t us=%u\t", countA, micros() );
    //      Serial.println(frequency2);
          Serial.println(FreqMeasure.countToFrequency(sum2));
          Serial.println(" ");
          delay(5000);
    }

  14. #14
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,939
    it only takes 6 to 8 microseconds to determine the count it seems using this code:
    Code:
    #include <FreqMeasure.h>
    
    void setup() {
      Serial.begin(9600);
      analogWriteFrequency(23, 18000);  // test jumper 22 to 23
      analogWrite(23, 128);
      FreqMeasure.begin();
    }
    
    void loop() {
      for ( int ii = 0; ii < 4; ii++ ) {
    loop:
        if (!FreqMeasure.available()) goto loop;
        int count = FreqMeasure.available();
        uint32_t sum = FreqMeasure.read();
        Serial.printf(" S1: Cnt = %u\t us=%u\thz=%f\n", count, micros(), FreqMeasure.countToFrequency(sum) );
      }
      Serial.println(" ");
      delay(5000);
    }
    And for 18 KHZ it shows:
    Code:
     S1: Cnt = 11	 us=5300396	hz=18000.720703
     S1: Cnt = 10	 us=5300403	hz=18000.720703
     S1: Cnt = 9	 us=5300410	hz=18000.720703
     S1: Cnt = 9	 us=5300417	hz=18000.720703
     
     S1: Cnt = 11	 us=10300423	hz=18000.720703
     S1: Cnt = 10	 us=10300430	hz=18000.720703
     S1: Cnt = 10	 us=10300438	hz=18000.720703
     S1: Cnt = 9	 us=10300445	hz=18000.720703
     
     S1: Cnt = 11	 us=15300452	hz=18000.720703
     S1: Cnt = 11	 us=15300460	hz=18000.720703
     S1: Cnt = 10	 us=15300467	hz=18000.720703
     S1: Cnt = 9	 us=15300474	hz=18000.720703
    And when running at 800 Mhz:
    Code:
     S1: Cnt = 11	 us=5303979	hz=800.000000
     S1: Cnt = 10	 us=5303986	hz=800.000000
     S1: Cnt = 9	 us=5303993	hz=800.000000
     S1: Cnt = 8	 us=5304000	hz=800.000000
     
     S1: Cnt = 11	 us=10304006	hz=800.000000
     S1: Cnt = 10	 us=10304013	hz=800.000000
     S1: Cnt = 9	 us=10304021	hz=800.000000
     S1: Cnt = 8	 us=10304027	hz=800.000000

  15. #15
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,939
    Numbers above are right - but only reading from non-empty queue.

    This code catches queue empty and then after delay empties it as ordered:
    Code:
    #include <FreqMeasure.h>
    
    void setup() {
      Serial.begin(9600);
      while ( !Serial ) ;
      analogWriteFrequency(23, 800);  // test jumper 22 to 23
      analogWrite(23, 128);
      FreqMeasure.begin();
      while (FreqMeasure.available())
        FreqMeasure.read();
    }
    
    #define ASET 5
    uint32_t Nums[ASET][2];
    void loop() {
      for ( int ii = 0; ii < ASET; ii++ ) {
        while (!FreqMeasure.available());
        Nums[ii][0] = FreqMeasure.available();
        Nums[ii][1] = FreqMeasure.read();
      }
    
      for ( int ii = 0; ii < ASET; ii++ ) {
        Serial.printf(" Cnt = %u\t us=%u\thz=%f\n", Nums[ii][0], micros(), FreqMeasure.countToFrequency( Nums[ii][1] ) );
      }
    
      delay(5000);
      int kk = 0;
      uint32_t xcnt = 0;
      while (FreqMeasure.available()) {
        xcnt += FreqMeasure.read();
        kk++;
      }
      Serial.printf(" Avg wait Cnt = %u\thz=%f\n", kk, FreqMeasure.countToFrequency( xcnt / kk ) );
      Serial.println(" ");
    
    }

    Here is first run of this code:
    Code:
     Cnt = 1	 us=419004	hz=2288.504150
     Cnt = 1	 us=419011	hz=800.000000
     Cnt = 1	 us=419017	hz=800.000000
     Cnt = 1	 us=419023	hz=800.000000
     Cnt = 1	 us=419029	hz=800.000000
     Avg wait Cnt = 11	hz=800.000000
     
     Cnt = 1	 us=5425254	hz=800.000000
     Cnt = 1	 us=5425260	hz=800.000000
     Cnt = 1	 us=5425267	hz=800.000000
     Cnt = 1	 us=5425273	hz=800.000000
     Cnt = 1	 us=5425280	hz=800.000000
     Avg wait Cnt = 11	hz=800.000000

  16. #16
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,939
    @analog&RFmodels and @mjs513 … Paul?

    First note is that the initial prints were being LOST without the while(!Serial); in setup().

    Getting that resolved and putting .begin() at Setup() end that basically falls into loop() on first entry the first count is recorded with no time to queue or lose any counts.

    It can be seen that on first counting the count is way high for some reason?

    It looks like this :: period = capture - capture_previous;

    Uses capture_previous=0 to start, and then going forward just uses the DIFF of current and prior count.

    So the first calculation returned will be count plus random offset of the counter at start from zero.

    Either the counter needs a true zero from the start of .begin() - or the running value at that time needs to be used for capture_previous ?

    Here is start with self test PWM freq == 8000 - that first number is always the same:
    Code:
     Cnt = 1	 us=419635	hz=2288.608887
     Cnt = 1	 us=419642	hz=8000.000000
     Cnt = 1	 us=419649	hz=8000.000000
     Cnt = 1	 us=419655	hz=8000.000000
     Cnt = 1	 us=419661	hz=8000.000000
    Last edited by defragster; 10-18-2019 at 02:55 AM.

  17. #17
    Member
    Join Date
    Aug 2019
    Location
    southwest USA
    Posts
    48
    it took me so long to get back to the bench that you had already run and improved the code you had posted in post #13.
    but my results with it were first one or two samples in error then all ok and like you i got avg of 6us per read cycle whether
    fin was 1 khz or 10 kz so even if you did run 2 dummy cycles after each ..begin it would only cost 12 us at 600 mhz
    i am glad you thought to have it report elapsed time. the microseconds timing numbers show that some clever variable
    prescaling or something like that is being done given how similar the elapsed times are when the input frequency
    changes 10:1

    you really got to the bottom of this - thank you

    here are my results with your simple version (w 500ms loop delay):

    Code:
    gen = 9949 hz
    
     S1: Cnt = 10	 us=301001	10708.17
     S2: Cnt = 9	 us=301007	2694.98
     
     S1: Cnt = 11	 us=5302011	9946.29
     S2: Cnt = 10	 us=5302017	9946.95
     
     S1: Cnt = 11	 us=10303022	9945.63
     S2: Cnt = 10	 us=10303028	9946.95
     
     S1: Cnt = 11	 us=15304034	9946.95
     S2: Cnt = 10	 us=15304040	9946.95
     
     S1: Cnt = 11	 us=20305046	9946.95
     S2: Cnt = 10	 us=20305052	9946.95
    
    gen = 989 hz
    
     S1: Cnt = 1	 us=301001	1402.05
     S2: Cnt = 1	 us=301419	988.90
     
     S1: Cnt = 11	 us=5302424	988.88
     S2: Cnt = 10	 us=5302429	988.87
     
     S1: Cnt = 11	 us=10303435	988.87
     S2: Cnt = 10	 us=10303441	988.85
     
     S1: Cnt = 11	 us=15304447	988.94
     S2: Cnt = 10	 us=15304453	988.96

  18. #18
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,939
    This does show the first reading is wrong with the initial value set :: capture_previous=0 :: With that then factoring into first reading.

    The code handles various timer types - not sure if the 1062 usage is unique and different? And which set of #ifdef code paths need edits to resolve this?

    For workaround >> This with .begin() should make it go well as it will discard the first reading or 3 and end up with capture_previous being in sync with the clocks::
    Code:
    FreqMeasure.begin();
    delayMicroseconds(15);
    while (FreqMeasure.available()) FreqMeasure.read();

  19. #19
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,939
    Making this edit to post #15 loop() code shows the trouble with .end() then .begin():
    Code:
    void loop() {
      for ( int ii = 0; ii < ASET; ii++ ) {
        while (!FreqMeasure.available());
        Nums[ii][0] = FreqMeasure.available();
        Nums[ii][1] = FreqMeasure.read();
        if ( ii == 1 ) {
          FreqMeasure.end();
          FreqMeasure.begin();
        }
      }
    
    // ...
    Here is Sermon output with that change - clean read for first two in group - then after .end/.begin the next two are random offset to prior capture_previous:
    Code:
     Cnt = 1	 us=160438520	hz=8000.000000
     Cnt = 1	 us=160438527	hz=8000.000000
     Cnt = 1	 us=160438534	hz=980392.187500
     Cnt = 1	 us=160438541	hz=4015.956787
     Cnt = 1	 us=160438548	hz=8000.000000
     Avg wait Cnt = 11	hz=8000.000000
     
     Cnt = 1	 us=165439145	hz=8000.000000
     Cnt = 1	 us=165439152	hz=8000.000000
     Cnt = 1	 us=165439159	hz=4363.636230
     Cnt = 1	 us=165439166	hz=4015.096680
     Cnt = 1	 us=165439173	hz=8000.000000
     Avg wait Cnt = 11	hz=8000.000000
     
     Cnt = 1	 us=170439770	hz=8000.000000
     Cnt = 1	 us=170439777	hz=8000.000000
     Cnt = 1	 us=170439784	hz=48812.234375
     Cnt = 1	 us=170439791	hz=4015.526611
     Cnt = 1	 us=170439798	hz=8000.000000
     Avg wait Cnt = 11	hz=8000.000000
    Somehow capture_previous needs to be Sync'd with counter value at .begin(). Either setting directly, or waiting for first interval to pass and pulling value from the queue before return in ~7 us

  20. #20
    Member
    Join Date
    Aug 2019
    Location
    southwest USA
    Posts
    48
    after running several hundred cold starts the 100% safe thing to do is on FreqMeas, delay for 40 microsec just after ...begin AND do two dummy cycles before real measurements,
    this only costs about 52 microseconds

    similarly on FreqCount, do one dummy meas cycle before real measurements (i knew the TLC usually needed this) in my typical application this really has no cost because i just start
    my FreqCount loop one time interval early, loop one more time than required, and when pulling results out of the array later just start w index one higher than i would have

    in my typical applications these work-arounds are simple and do not stop the show

    these cautions are applicable to the TeensyLC and Teensy4, and i have not tested Teensy 3.6, and cannot test any others
    i am not sure how to link threads so i will start a new one w this same content titled FreqCount caution.

  21. #21
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,939
    I find code like this actually resolves the issue:
    Code:
          FreqMeasure.end();
          FreqMeasure.begin();
          {
            while (!FreqMeasure.available());
            int yy = 0;
            while (FreqMeasure.available() || yy < 2 ) {
              if ( FreqMeasure.available()) {
                FreqMeasure.read();
                yy++;
              }
            }
            Serial.print("\t\t DISCARD INITIAL READS #=");
            Serial.println(yy);
          }

  22. #22
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,939
    Here is complete code that exhibits the issue and shows HACK to hide the break after .begin()

    SIMILAR thread: pjrc.com/threads/58062-FreqCount-caution

    The FreqCount exhibits similar startup behavior on .begin()
    Last edited by defragster; 10-19-2019 at 02:18 AM.

  23. #23
    Member
    Join Date
    Aug 2019
    Location
    southwest USA
    Posts
    48
    here is an update to post #20 this thread:

    caught TLC w first two FreqMeas measurements that did not match once in a blue moon so:

    TLC 48 mhz smallest 40 microsec delay after last ..begin AND 3 dummy reads before actual reads overhead time typ 56 us
    T4 600 mhz faster 40 microsec delay after last ..begin AND 2 dummy reads before actual reads overhead time typ 42 us

  24. #24
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,939
    Quote Originally Posted by analog&RFmodels View Post
    here is an update to post #20 this thread:

    caught TLC w first two FreqMeas measurements that did not match once in a blue moon so:

    TLC 48 mhz smallest 40 microsec delay after last ..begin AND 3 dummy reads before actual reads overhead time typ 56 us
    T4 600 mhz faster 40 microsec delay after last ..begin AND 2 dummy reads before actual reads overhead time typ 42 us
    Ideally there is a CORES LIB fix in the waiting here … but … can you show code that does that?

    When I was coding before the p#21 code it was tried with delayMicroseconds() as high as 105 and it was somehow not triggering the expected clearing reads … so the above was done.

    And timing that discard code takes :: DISCARD INITIAL READS #=2 takes us #=249
    Code:
          FreqMeasure.begin();
          {
            uint32_t tmeas = micros();
            while (!FreqMeasure.available());
            int yy = 0;
            while ( yy < 2 ) { // removed dupe .available() same timing
              if ( FreqMeasure.available()) {
                FreqMeasure.read();
                yy++;
              }
            }
            tmeas = micros() - tmeas;
            Serial.print("\t\t DISCARD INITIAL READS #=");
            Serial.print(yy);
            Serial.print("\t takes us #=");
            Serial.println(tmeas);
          }
    >> PERHAPS it is longer because this follows - not just on the first begin()?:
    Code:
          FreqMeasure.end();
          FreqMeasure.begin();

  25. #25
    Member
    Join Date
    Aug 2019
    Location
    southwest USA
    Posts
    48
    Quote Originally Posted by defragster View Post
    Ideally there is a CORES LIB fix in the waiting here … but … can you show code that does that?

    When I was coding before the p#21 code it was tried with delayMicroseconds() as high as 105 and it was somehow not triggering the expected clearing reads … so the above was done.

    And timing that discard code takes :: DISCARD INITIAL READS #=2 takes us #=249
    Code:
          FreqMeasure.begin();
          {
            uint32_t tmeas = micros();
            while (!FreqMeasure.available());
            int yy = 0;
            while ( yy < 2 ) { // removed dupe .available() same timing
              if ( FreqMeasure.available()) {
                FreqMeasure.read();
                yy++;
              }
            }
            tmeas = micros() - tmeas;
            Serial.print("\t\t DISCARD INITIAL READS #=");
            Serial.print(yy);
            Serial.print("\t takes us #=");
            Serial.println(tmeas);
          }
    >> PERHAPS it is longer because this follows - not just on the first begin()?:
    Code:
          FreqMeasure.end();
          FreqMeasure.begin();
    these are the codes i am testing with lately

    after you tie the two input pins together per the comments near top of code, apply sq wave 0-3.3 or 0.1-2.8 v fin there
    t4 10k series each pin then tie together to gen
    tlc direct to pin 13 and 2k to pin 16 from gen
    these resistances allow you to safely unplug from usb while gen still running (another reason i like external gen) then re-plug
    usb and see if numbers ok power on (cold) start, and i have also been doing sketch-upload to see if numbers ok warm start

    these codes exercise both fmeas and fcount but if you have not made the posted edits to
    two of the FreqCount lib files the t4 compile will crash - just comment everything related
    to FreqCount and you will be ok. i am testing both the same way and in the same order
    that my finished app does things

    both these pgms have a define at the top where you choose tlc or t4 and it sets up several things according to that
    including 3 dummy Fmeas for tls and 2 for t4. one dummy cycle for Fcount no matter which cpu
    40 microsec delay after begin fmeas no matter which cpu

    all of my testing so far has been tlc 48mhz smallest t4 600mhz faster

    does two FreqMeas in a row and then FreqCount once - i have been doing most testing with 990 hz and 9950 hz
    the first pgm does that and prints
    the second pgm is similar but computes and prints the "overhead"time for FreqMeas and then for FreqCount fixes
    maybe i am miscalculating from the elapsed microseconds

    code is not clean or elegant - a) i am a duffer programmer and b) when i am chasing a funny i never clean anything
    up til the funny is quashed. please excuse all of the unused variables

    here is the first pgm:
    Code:
    // diag for fmeas and fcount
    // set cpu for either tlc or t4
    // t4  tie pin 22 to pin  9
    // tlc tie pin 13 to pin 16
    
    // ************************************
    // note that both tlc and t4 only meas
    // freq same both times if a) you delay
    // 40 microsec after .. begin and b)
    // there are two dummy ..avail ..read
    // blobs before the two real ones
    // note that freq count has a similar
    // issue and one dummy read should be
    // done before measurements
    // ************************************
    
    // this diag code does part of what the big
    // pgm does which is freqmeas, freqmeas,
    // many times freqcount all on the same
    // signal
    // data serial print order is fmeas1,fmeas2,fcount
    // fcount is the 5th of 16 count measurements to
    // keep the output small
    
    // there are many unused left over variables
    // from the pgm this was extracted from
    
    #define cpu 1  // 0 for tlc  1 for t4
    
    #include <FreqCount.h>
    #include <FreqMeasure.h>
    
      unsigned int data1,data2,data3;
    
      unsigned short int tbit,sdelay,i,fe;
      unsigned short int lim1,lim2,lim3;
      unsigned short int lim4,lim5;
    
    volatile unsigned short int cnt;
    volatile unsigned int ary[45];
    volatile unsigned short int lc;
    volatile unsigned short int pdta;
    volatile unsigned short int rp1,rp2;
    volatile unsigned short int wrd0r,wrd1r,wrd2r;
    volatile unsigned short int shft;
    volatile unsigned short int wc;
    volatile unsigned short int adr;
    volatile unsigned short int fc;
    volatile unsigned short int flag;
    volatile unsigned short int mc;
    volatile unsigned short int vc;
    volatile unsigned int fm;
    volatile unsigned int pe2;
    volatile unsigned short int nm,fmd,fmpin,cpin;
    volatile unsigned short int c8;
    
    
    void setup(){
    
    // tbit may be 20 or 40 or 80 or 140 or 200
       tbit=80;
       if(tbit== 80) sdelay=80;
       if(tbit== 80) lim1=29;
       if(tbit== 80) lim2=51;
       if(tbit== 80) lim3=81;
       if(tbit== 80) lim4=128;
       if(tbit== 80) lim5=193;
    // next two lines allow different intermeasurement
    // delay on the fmeas blobs - sometimes 10 (ms)
    // gives slightly less jumping betweem x 2x on the
    // t4 but that is a lot of wasted time
       if(cpu==0) fmd=1;
       if(cpu==1) fmd=1;
       if(cpu==0) fmpin=13;
       if(cpu==1) fmpin=22;
       if(cpu==0)  cpin=16;
       if(cpu==1)  cpin= 9;
    
    
      vc=1;
      adr=1;
    // in pin for fmeas
      pinMode(fmpin, INPUT);
    // in pin for fcount
      pinMode(cpin, INPUT);
     
      pinMode( 5, OUTPUT);
      Serial.begin(9600);
      digitalWrite(5, LOW);
      delay(2000);
      digitalWrite(5,HIGH);
    }
    
    void loop(){
      mc=0;
    lmc:
      ary[mc]=0;
      ++mc;
      if(mc<44)goto lmc;
      Serial.println("begin");
    // wait for pin 22 (fmeas) to change
      wc=0;
    wtchg:
      rp1=digitalReadFast(fmpin);
      delayMicroseconds(5);
      rp2=digitalReadFast(fmpin);
      delayMicroseconds(5);
      if (rp1==rp2) goto wtchg;
      Serial.println("change@in - start fmeas");
      nm=0;
      fm=0;
      if (tbit== 80) delay(20);
      FreqMeasure.begin();
      delayMicroseconds(40);
    // dummy meas 1
      delay(fmd);
    fmea:
      nm = FreqMeasure.available();
      if (!nm) goto fmea;
      fm = FreqMeasure.read();
    // dummy meas 2
      delay(fmd);
    fmeas:
      nm = FreqMeasure.available();
      if (!nm) goto fmeas;
      fm = FreqMeasure.read();
      if(cpu==1) goto skp3;
    // dummy meas 3
      delay(fmd);
    fmeas7:
      nm = FreqMeasure.available();
      if (!nm) goto fmeas7;
      fm = FreqMeasure.read();
    skp3:
      et1=etime;
    // real meas 1
      delay(fmd);
    fmeasa:
      nm = FreqMeasure.available();
      if (!nm) goto fmeasa;
      fm = FreqMeasure.read();
      data1=fm;
    // real meas 2
      delay(fmd);
    fmeas2:
      nm = FreqMeasure.available();
      if (!nm) goto fmeas2;
      fm = FreqMeasure.read();
      delay(fmd);
      data2=fm;
      FreqMeasure.end();
      Serial.println("now start count 16 times");
      delay(sdelay);
      if (cpu == 1)FreqCount.begin(sdelay*1000);
      if (cpu == 0)FreqCount.begin(sdelay*   1);
      lc=0;
    
    // meas cts per x ms 16 times
    // and store msmnts in ary[]
    
       lc=0;
    loop:
        if (!FreqCount.available()) goto loop;
        Serial.print("*");
        cnt = FreqCount.read();
        ++lc;
        ary[lc]=cnt;
      if (lc < 16) goto loop;
      FreqCount.end();
      Serial.println(" ");  
    //  data3=ary[5];
    
    // diag prints
      Serial.println(data1); //f meas 1 should be aprox same each time
      Serial.println(data2); //f meas 2 should be same as 1
    // these 3 should be the same each time
      fe=2;
      data3=ary[fe];
      Serial.println(data3);
      data3=ary[fe+1];
      Serial.println(data3);
      data3=ary[fe+2];
      Serial.println(data3);
      Serial.println(" ");
      
      delay(5000);
    }
    here is the second pgm that adds overhead timing

    Code:
    // diag for fmeas and fcount
    // set cpu for either tlc or t4
    // t4  tie pin 22 to pin  9
    // tlc tie pin 13 to pin 16
    
    // ************************************
    // note that both tlc and t4 only meas
    // freq same both times if a) you delay
    // 40 microsec after .. begin and b)
    // there are two dummy ..avail ..read
    // blobs before the two real ones
    // note that freq count has a similar
    // issue and one dummy read should be
    // done before measurements
    // ************************************
    
    // this diag code does part of what the big
    // pgm does which is freqmeas, freqmeas,
    // many times freqcount all on the same
    // signal
    // data serial print order is fmeas1,fmeas2,fcount
    // fcount is the 5th of 16 count measurements to
    // keep the output small
    
    // there are many unused left over variables
    // from the pgm this was extracted from
    
    #define cpu 1  // 0 for tlc  1 for t4
    
    #include <FreqCount.h>
    #include <FreqMeasure.h>
    
      elapsedMicros etime;
      int et1,et2;
    
      unsigned int data1,data2,data3;
    
      unsigned short int tbit,sdelay,i,fe;
      unsigned short int lim1,lim2,lim3;
      unsigned short int lim4,lim5;
    
    volatile unsigned short int cnt;
    volatile unsigned int ary[45];
    volatile unsigned short int lc;
    volatile unsigned short int pdta;
    volatile unsigned short int rp1,rp2;
    volatile unsigned short int wrd0r,wrd1r,wrd2r;
    volatile unsigned short int shft;
    volatile unsigned short int wc;
    volatile unsigned short int adr;
    volatile unsigned short int fc;
    volatile unsigned short int flag;
    volatile unsigned short int mc;
    volatile unsigned short int vc;
    volatile unsigned int fm;
    volatile unsigned int pe2;
    volatile unsigned short int nm,fmd,fmpin,cpin;
    volatile unsigned short int c8;
    
    
    void setup(){
    
    // tbit may be 20 or 40 or 80 or 140 or 200
       tbit=80;
       if(tbit== 80) sdelay=80;
       if(tbit== 80) lim1=29;
       if(tbit== 80) lim2=51;
       if(tbit== 80) lim3=81;
       if(tbit== 80) lim4=128;
       if(tbit== 80) lim5=193;
    // next two lines allow different intermeasurement
    // delay on the fmeas blobs - sometimes 10 (ms)
    // gives slightly less jumping betweem x 2x on the
    // t4 but that is a lot of wasted time
       if(cpu==0) fmd=1;
       if(cpu==1) fmd=1;
       if(cpu==0) fmpin=13;
       if(cpu==1) fmpin=22;
       if(cpu==0)  cpin=16;
       if(cpu==1)  cpin= 9;
    
    
      vc=1;
      adr=1;
    // in pin for fmeas
      pinMode(fmpin, INPUT);
    // in pin for fcount
      pinMode(cpin, INPUT);
     
      pinMode( 5, OUTPUT);
      Serial.begin(9600);
      digitalWrite(5, LOW);
      delay(2000);
      digitalWrite(5,HIGH);
    }
    
    void loop(){
      mc=0;
    lmc:
      ary[mc]=0;
      ++mc;
      if(mc<44)goto lmc;
      Serial.println("begin");
    // wait for pin 22 (fmeas) to change
      wc=0;
    wtchg:
      rp1=digitalReadFast(fmpin);
      delayMicroseconds(5);
      rp2=digitalReadFast(fmpin);
      delayMicroseconds(5);
      if (rp1==rp2) goto wtchg;
      Serial.println("change@in - start fmeas");
      nm=0;
      fm=0;
      if (tbit== 80) delay(20);
      FreqMeasure.begin();
      etime=0;
      delayMicroseconds(40);
    // dummy meas 1
      delay(fmd);
    fmea:
      nm = FreqMeasure.available();
      if (!nm) goto fmea;
      fm = FreqMeasure.read();
    // dummy meas 2
      delay(fmd);
    fmeas:
      nm = FreqMeasure.available();
      if (!nm) goto fmeas;
      fm = FreqMeasure.read();
      if(cpu==1) goto skp3;
    // dummy meas 3
      delay(fmd);
    fmeas7:
      nm = FreqMeasure.available();
      if (!nm) goto fmeas7;
      fm = FreqMeasure.read();
    skp3:
      et1=etime;
    // real meas 1
      delay(fmd);
    fmeasa:
      nm = FreqMeasure.available();
      if (!nm) goto fmeasa;
      fm = FreqMeasure.read();
      data1=fm;
    // real meas 2
      delay(fmd);
    fmeas2:
      nm = FreqMeasure.available();
      if (!nm) goto fmeas2;
      fm = FreqMeasure.read();
      delay(fmd);
      data2=fm;
      FreqMeasure.end();
      Serial.println("now start count 16 times");
      delay(sdelay);
      if (cpu == 1)FreqCount.begin(sdelay*1000);
      if (cpu == 0)FreqCount.begin(sdelay*   1);
      lc=0;
    
    // meas cts per x ms 16 times
    // and store msmnts in ary[]
    
       lc=0;
       etime=0;
    loop:
        if (!FreqCount.available()) goto loop;
    //    Serial.print("*");
        cnt = FreqCount.read();
        ++lc;
        ary[lc]=cnt;
      if (lc < 16) goto loop;
      et2=etime;
      FreqCount.end();
      Serial.println(" ");  
    //  data3=ary[5];
    
    // diag prints
      Serial.println(data1); //f meas 1 should be aprox same each time
      Serial.println(data2); //f meas 2 should be same as 1
    // these 3 should be the same each time
      fe=2;
      data3=ary[fe];
      Serial.println(data3);
      data3=ary[fe+1];
      Serial.println(data3);
      data3=ary[fe+2];
      Serial.println(data3);
      Serial.println(" ");
      if (cpu==1) et1=et1-2*fmd*1000;
      if (cpu==0) et1=et1-3*fmd*1000;
      Serial.println(et1);
      et2=et2/16-80000;
      Serial.println(et2);
      Serial.println(" ");
      delay(5000);
    }
    Last edited by analog&RFmodels; 10-19-2019 at 01:16 AM.

Posting Permissions

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