Teensy 4 FreqMeas problem ?

analog&RFmodels

Well-known member
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
 
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\examples\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;
    }
  }
}
 
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() ?
 
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);
}
 
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;
    }
  }
}
 
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
 
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
 
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:
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.
 
analog&RFmodels said:
*** 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?
 
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
 
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:
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);
}
 
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
 
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
 
@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:
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
 
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();
 
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();
[COLOR="#FF0000"][B]    if ( ii == 1 ) {
      FreqMeasure.end();
      FreqMeasure.begin();
    }
[/B][/COLOR]  }

// ...

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
 
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.
 
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);
      }
 
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
 
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();
      {
        [B]uint32_t tmeas = micros();[/B]
        while (!FreqMeasure.available());
        int yy = 0;
        while ( yy < 2 ) { // removed dupe .available() same timing
          if ( FreqMeasure.available()) {
            FreqMeasure.read();
            yy++;
          }
        }
        [B]tmeas = micros() - tmeas;[/B]
        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();
 
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();
      {
        [B]uint32_t tmeas = micros();[/B]
        while (!FreqMeasure.available());
        int yy = 0;
        while ( yy < 2 ) { // removed dupe .available() same timing
          if ( FreqMeasure.available()) {
            FreqMeasure.read();
            yy++;
          }
        }
        [B]tmeas = micros() - tmeas;[/B]
        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:
Back
Top