frequency counting with teensy 3.6, randomly huge frequency values

Status
Not open for further replies.

DanielB

New member
Hi Guys,
I use the teensy 3.6 together with the library freqcounter library ( https://github.com/PaulStoffregen/FreqCount ) in order to measure frequency up to 65 MHz.
The gate length is set to the minimum value of 1 (milli sec).
In general it works quite fine.
However every now and then it happens that the frequency count value reaches very high values.
I've tried to understand the code in the FreqCount-Lib. Maybe it happens in the ISR-function from the FreqCount-Lib:
(line 99-101 in FreqCount.cpp)

count = ((uint32_t)count_msw << 16) + count_lsw;
count_output = count - count_prev;
count_prev = count;

if count is less than count_prev the substraction might result in a huge number. Am I correct?
Any Ideas?

Here is an example:
Input-Frequency: 40 MHz
count_output (most of the time) = 40000
count_output (occasionally) = 4294941760

Interestlingly this number obeys the following equation:
4294941760 = 2^32 - (2^16-40000)
 
Last edited:
forum rule requires you provide a runnable sketch that demonstrates the problem.

Have you declared all the "count" variables uint32_t?
 
Ah, ok. So this is the Program:
Code:
#include <FreqCount.h>

unsigned long count=0;

void setup() {
  Serial.begin(57600);
  FreqCount.begin(1);

}


void loop() {
  if (FreqCount.available()) {
    count = FreqCount.read();
    if (count > 100000) {
      Serial.println(count);
    }
    delay(10);
  } 
}

And this is the output of the Serial Monitor over a few minutes that I get with an Input-Frequency of 40 MHz. The expected value for count would be 40000.
Please note that only count-values above 100000 are beeing printed and most of the time the count-value is at 40000 +- 3.
105535
105538
105538
105538
105536
4294941763
4294941760
105536
105536
4294941760
4294941760
105535
4294941762

It is worth noting that
4294941760 = 2^32 - (2^16-40000)
105536 = 2^16 + 40000

Thank You for Your help.
 
The fastest signal i can generate from another Teensy is 24mhz, and your counting sketch runs just fine (no big numbers). Does your sketch work ok with input at 20 mhz, 24 mhz, 30 mhz?

(How can I get a Teensy 3* to generate a 40 mhz signal?)
 
The fastest signal i can generate from another Teensy is 24mhz, and your counting sketch runs just fine (no big numbers). Does your sketch work ok with input at 20 mhz, 24 mhz, 30 mhz?

(How can I get a Teensy 3* to generate a 40 mhz signal?)

I have a really fancy RF signal generator in my lab. ;-)
However, if I reduce the frequency to 10 MHz I still have the same issue.
Can you tell me how long did you do this measurement? It takes a couple of minutes to measure these outliers.
 
I'm running it here on a Teensy 3.6, with a 40 MHz sine 3Vpp with 1.6V offset on pin 13. I had to comment out "if (count > 100000) {", because it never prints anything if I run it with that line.

Here's what I see in the serial monitor.

sc.png

This is how I connected the hardware:

DSC_0180_web.jpg

This is what's creating the signal:

DSC_0183_web.jpg

For this test I had to use sine with offset, since my function generator's maximum in square wave mode is only 30 MHz. Funny how that seemed like more than I'd ever need only several years ago! At least the sine wave can go up to 80 MHz.
 
I'm running this, with a jumper between pins 13 & 14.

Code:
#include <FreqCount.h>

void setup() {
  FreqCount.begin(1);
  analogWriteFrequency(14, 15000000);
  analogWrite(14, 128);
}

void loop() {
  if (FreqCount.available()) {
    uint32_t count = FreqCount.read();
    if (count < 14000 || count > 16000) {
      Serial.println(count);
    }
  } 
}

The errors are coming in pairs (with the delay removed).

Code:
80536
4294916760
80536
4294916760
80536
4294916760
80536
4294916760
80536
4294916760
80536
4294916760
80536
4294916760
80536
4294916760

Looks like there is indeed a bug. Will work in a fix....
 
Can you tell me how long did you do this measurement? It takes a couple of minutes to measure these outliers.

I guess I didn't wait long enough. FWIW, here is sketch for 30 mhz PWM on pin 16 on T3.2@120mhz (F_BUS 60 mhz)
Code:
void setup() {
  CORE_PIN16_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE; // enable PWM
  //  enabled by init SIM_SCGC6 |= SIM_SCGC6_FTM1;
  // FTM1_CnSC set by init
  FTM1_SC = 0;
  FTM1_CNT = 0;
  FTM1_MOD = 1;   // F_BUS 60, 3  15 mhz, 2  20 mhz, 1 30 mhz
  FTM1_C0V = 1;
  FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0);
}

void loop() {
}

... and i did see a rollover
Code:
29999
30002
30001
4294931762
30000
30001

EDIT: I changed sketch to print only if count > 40000 and i keep a sample cnt, so i print cnt and count to see frequency of big count.
Code:
4039 95536
9090 95535
10038 95537
10986 95535
11999 95535
16623 4294931759
17701 95536
27093 95535
28808 4294931761
33511 95536
35291 95536
41709 95537
44567 95536
46282 4294931759
49140 95535
59299 4294931758
 
Last edited:
OK updated FreqCount.cpp and ran original sketch with 30 mhz PWM signal and confirmed sketch is still properly counting (e.g. 30000 ...).
Now running my sketch that prints outliers ... so far so good ...

"Absence of proof is not proof of absence"

EDIT: ... 15 minutes and no outliers ...
 
Last edited:
My sketch doesn't last 15 minutes - OLD (edit ... not new) code or with changed cpp. Behavior doesn't seem changed based on sketch below.

I was thinking you might find something in the setup of the timer/counter - or in some bit carrying across the SREG = status; It seemed like plugging it in fresh might have been more stable than after some Reset or Reprogram.

Code:
#include <FreqCount.h>
// https://forum.pjrc.com/threads/53292-frequency-counting-with-teensy-3-6-randomly-huge-frequency-values?p=184543&viewfull=1#post184543
void setup() {
  FreqCount.begin(1);
  analogWriteFrequency(14, 15000000);
  analogWrite(14, 128);
  while (!Serial && millis() < 5000 );
  Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
  delay(100);
}
int32_t icnt = 9999;
int32_t jcnt = 0;
void loop() {
  if (FreqCount.available()) {
    uint32_t count = FreqCount.read();
    if (count < 14000 || count > 16000) { // use for:: FreqCount.begin(1);
      if ( icnt ) {
        Serial.print("\n-----[");
        Serial.print(icnt);
        Serial.println(']');
        icnt = 0;
      }
      Serial.println(count);
    }
    else {
      icnt++;
      if ( icnt > 8190 ) {
        Serial.println(); // leaving this line here causes it to fail more regularly - often with icnt 8190 above
        Serial.print("[");
        Serial.print(icnt);
        Serial.println(']');
        icnt = 0;
      }
    }
  }
}


Except the first primed print [10000] those [counts] are to show a count of proper freq. - with a print on occasion - it was synching on 8190 valid reads before a bad one for the longest time.

When you see "-----" that is how many proper counts since the last print were good when the following out of range values appeared. Then the paired out of range vals print and back to counting good ones.

I could change the looping code and get longer GOOD runs like 4 million samples? 8+ pages of SerMon printing.

For a while I was seeing the error recur on [8190] … as shown below after plugging the Teensy in after unplug a few secs - this just repeated TWICE on re-plugging::
T:\tCode\FORUM\FreqSpaz_aug03a\FreqSpaz_aug03a.ino Aug 3 2018 20:57:41

[10000]

-----[1834]
80535
4294916760

-----[8190]
80537
4294916759

-----[8190]
80536
4294916761

-----[8190]
80536
4294916759

[8191]

[8191]
80535
4294916760

-----[8190]
80536
4294916760

-----[8190]
80535
4294916760

-----[8190]
80537
4294916759

-----[8190]
80536
4294916761

-----[8190]
80536
4294916759
 
Last edited:
... as noted in this line >> // Serial.println(); // leaving this line here causes it to fail more regularly - often with icnt 8190 above

If I comment and recompile it works better - and with replug.

I didn't post this code and notes before because it seems really nebulous - I couldn't adjust it to get anything clearer than now posted. But the updated code did not change anything it shows.:

T:\tCode\FORUM\FreqSpaz_aug03a\FreqSpaz_aug03a.ino Aug 3 2018 21:12:29
[10000]
[8191]
[8191]
[8191]
[8191]
[8191]

T:\tCode\FORUM\FreqSpaz_aug03a\FreqSpaz_aug03a.ino Aug 3 2018 21:12:29
[10000]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]

-----[1896]
80537
4294916759
[8191]
[8191]
[8191]
[8191]
[8191]
[8191]
 
Paul - after this local var msw is not used again before _isr ends. It looks like the same thing is happening in this IF and ELSE? Doesn't matter the value of lsw, msw goes into count_msw with a +1.

Is this what was intended?

Code:
		if (lsw < 0x8000) {
			msw = msw + 1;
			count_msw = msw;
		} else {
			count_msw = msw + 1;

Not sure if it stuck out to you and helps - but with my sketch the value split is on these two freq counts with 80536 +/- 1:
-----[1]
80536
4294916760

Same value with or without that Serial.println(); line commented - just more frequent failure with that active.

BTW: you'll see my sketch has unused jcnt = 0. I was using that to selectively remove the println() - and I noticed that even without the println() going to USB just adding this line that NEVER RUNS the FreqCount error becomes more prominent.
Code:
    else {
      icnt++;
      if ( icnt > 8190 ) {
        [B][U]if ( jcnt > 2 ) jcnt++;[/U][/B]
        // Serial.println(); // leaving this line here causes it to fail more regularly - often with icnt 8190 above

So it isn't the added USB newline that causes the issue - but just adding a couple bytes of code that never executes that makes it recur more often. It was worse after reprogram - but here is has returned after a replug with the [8190] on the count and the 80536 on the wrong freqCnt:
T:\tCode\FORUM\FreqSpaz_aug03a\FreqSpaz_aug03a.ino Aug 3 2018 23:08:12
[10000]

-----[1842]
80535
4294916760

-----[8190]
80537
4294916759

-----[8190]
80536
4294916761

-----[8190]
80536
4294916759


BTW: This T_3.6 is compiling default FASTER at 180 MHz. I just bumped to 240 MHz and the same code took 20 iterations of [8191] with added println() - but it did show, just not as quickly, and not as often - another 28 [8191] groups before another single error.
 
Last edited:
At 120 Mhz it failed repeatedly on [8190]

I went to 168 MHz and the failure is RADICALY different - with or without the commentable lines::

Code:
T:\tCode\FORUM\FreqSpaz_aug03a\FreqSpaz_aug03a.ino Aug  3 2018 23:29:32

[10000]

-----[108]
13999

-----[299]
13999

-----[13]
13999

-----[102]
13999

-----[13]
13999

-----[8]
13999

-----[21]
13999

-----[15]
13999

-----[6]
13999
 
Paul - after this local var msw is not used again before _isr ends.

It most certainly is used, on line 105:

count = ((uint32_t)msw << 16) + lsw;


It looks like the same thing is happening in this IF and ELSE? Doesn't matter the value of lsw, msw goes into count_msw with a +1.

Is this what was intended?

Code:
		if (lsw < 0x8000) {
			msw = msw + 1;
			count_msw = msw;
		} else {
			count_msw = msw + 1;

Indeed this would be pointless if msw were not used on line 105. The value actually used on line 105 is the critical part.

The bug occurs when counter overflow happens within a very short timing window after counter_read(). Just a few cycles later, counter_overflow() returns true, so we increment count_msw. But if the overflow happened within that very short period between these two, then using the incremented count_msw later on 105 is wrong. We need the msw value from *before* the overflow happened.


Not sure if it stuck out to you and helps - but with my sketch the value split is on these two freq counts with 80536 +/- 1:

Please double check that you really have all the new file with all the lines changed. If that change is missing on line 105, then you'll still experience the bug. Also, use 0xFA00. My first commit with 0x8000 was really unnecessary. Even if Teensy runs at 24 MHz and the measured frequency is 64 MHz, using 0xFA00 is plenty.
 
opps ... I do have that line - just - just missed seeing it properly. I even knew what I was looking for ... subsequent use of that local ... there it is only 7 lines away.

opps and DOUBLE opps ... I have the code ... but not in the path of the IDE I had open ....

Opened that IDE 1.8.5 TD_1.42 and 23 and counting sets of [8191] coming through just fine at 180 MHz. <edit> 67+ sets and no errors

Still odd at 168 MHz - that must be a Freq conflict on write<>read pin?
 
Last edited:
Still odd at 168 MHz - that must be a Freq conflict on write<>read pin?

I tested with the CPU at 168 MHz, both with the 13-14 jumper and a 64 MHz sine wave from my function gen. Didn't see any issues.

Of course, with 168 MHz and the 13-14 jumper, I see readings of 14000, not 15000, but that's because of lower F_BUS limiting the PWM frequency.

Maybe I should try running the exact same program you're using? Can you post it? And tell me clearly what hardware connection you're using?
 
Tested latest FreqCount.cpp (0xFA00) with 30mhz PWM input, after 20 minutes no outliers ...

just for the record, with analogWriteFrequency(14, 30000000), i was using analogWrite(14, 127) and getting nothing, you have to use analogWrite(14,128);. 30 mhz PWM on T3.6 works on pins 2-10,14,20-23,29,30.

For some reason, on my T3.6, analogWriteFrequency(16,30000000) gets 0 from count, count ok at 8mhz. As noted the handcoded FTM code snippet works for pin 16 at 30mhz. pins_teensy.c uses TPM1 clocked at 16mhz for pins 16 and 17. Handcoding is also required on pin 17 to get 30 mhz PWM. From https://www.pjrc.com/teensy/td_pulse.html,
"On Teensy 3.6, pins 16 & 17 operate from a fixed 16 MHz clock"
 
Last edited:
Mine ran overnight with the 168 MHz sketch. Two out of bounds on the 14000 - came in at 13989 and 13986.

Otherwise 3,734 sets of [8191] without issue.

Just recompiled at 180 MHz and no trouble on initial 50+ sets

<edit>: Has completed many more sets since creating this post only one anomaly where I tightened the test range to +/- 10 it shows this reasonable miscount where one interval is accounted for in the other interval:
[8191]

-----[4]
15013
14986

[8191]
 
Last edited:
Hey Guys,
thank you very much for your help. I have set up a frequency offset lock between two lasers with the teensy microcontroller and it works pretty fine now.

Bye,

Daniel.
 
Status
Not open for further replies.
Back
Top