Gas station without pumps

2015 September 2

Calibrating PteroDAQ frequency measurements

Filed under: Circuits course,Data acquisition — gasstationwithoutpumps @ 22:35
Tags: , , , ,

In PteroDAQ frequency channels, I wrote

One of the clocks is out of spec.  When the FG085 was putting out a nominal 500kHz signal, the PteroDAQ system measured it at 499958.5 Hz, which is –83ppm.  The two crystals should each be about ±20ppm, so an 83ppm discrepancy is larger than expected. With a nominal 5kHZ signal, the PteroDAQ system measured it at 4999.524 Hz (–95ppm).  I’ll have to take the function generator and PteroDAQ board into the circuits lab and use the frequency counters and function generators there to see what the actual accuracies are.  For anything that we do in the applied electronics class, 100ppm is good enough, but it would be nice to know how far off my instruments really are.

Today I took all three of my PteroDAQ boards (Teensy 3.1, Teensy LC, and FRDM-KL25Z) and my JYEtech FG085 function generator into the circuits lab, to compare the measurements made with the PteroDAQ to measurements made with the bench equipment in the lab.  I also used the function generator in the lab to get higher frequencies with less jitter, to see if that made a difference in the measurement.

The bench instruments I was using were

  • Agilent 34401A multimeter
  • Leader LDC822 frequency counter
  • Tektronix MSO 2024 digital storage oscilloscope
  • Agilent 33120A arbitrary function generator

Some  general observations:

  • The Agilent 33120A multimeter provided the highest precision on the measurements, but failed at 1MHz.
  • The multimeter also had some trouble with pulse trains with a lot of jitter, such as those produced by the FG085.
  • The oscilloscope routine reports the frequency for the inputs, but also has a “frequency” option on the measurement menu. The routine report seems to be stable and precise, while the “measurement” option fluctuated a lot—perhaps tracking the jitter in the signal.

The Leader frequency counter and the Agilent function generator agreed pretty well on frequencies, with the Leader counter reporting that the function generator was about 0.3–0.5ppm lower than it claimed to be.   The oscilloscope had less precision, and reported the Agilent function generator as 3–5ppm high.  The multimeter reported the function generator as 1.4–1.6ppm high.

I’m interested in the PteroDAQ measurements relative to any of the bench instruments.  Here is a table of the ppm error for several frequencies (f_s is the sampling frequency for PteroDAQ looking at the frequency channel):

33120A setting Teensy 3.1 FRDM-KL25Z Teensy LC
MHz /33120A /Leader f_s /33120A /Leader f_s /33120A /Leader f_s
0.5 11.2 11.6 20 Hz  27.4 27.8 1 Hz  -24  -21.6 1 Hz
0.9 11.556 11.889 30 Hz  27.444  27.778 1 Hz  -23.889  -23.556 1 Hz
1.0 9. 9.3 31 Hz  27  27.5 1 Hz  -23.7  -23.5 1 Hz
2.0 -23. -22.5 62 Hz  26.5  27 2 Hz  -25  -25 2 Hz
3.0 -59.667 -59 100 Hz  25.333  26 3 Hz  -25.333  -25 3 Hz
3.9  24.359  24.872 4 Hz  -27.179  -26.923 4 Hz
4.0 -87.75 -87.25 125 Hz  -1660.8  -1660.3 4 Hz  -2059.5  -2059.3 4 Hz
4.5 -1777.555 -1774.667 140 Hz
avg -23.11 -22.66  26.339  26.825  -24.85  -23.263

The entries in red show the frequency counter failing by not counting all the edges—when the DMA channel can’t keep up, it silently ignores edges (not a great failure mode, since the numbers may look plausible while being several percent off). I did not include the red numbers in the average.

The KL25 and KL26 processors (FRDM-KL25Z and Teensy LC) both have fairly sharp transitions between counting every edge (at 3.9MHz) and missing many (at 4MHz). The K20 (Teensy 3.1) has stranger behavior, where it overestimates low frequencies and underestimates high frequencies.  There error a 3MHz is already fairly large.  I suspect that the problem may result from the shorter counter in the K20, which necessitated counting for shorter periods at high frequencies to avoid overflow.  There is a brief dead time at each period while the DMA counter is reset.

If there is a dead time of duration \tau, during which the first pulse is counted (captured by the port circuitry), but subsequent pulses in the dead time are missed, then the relative errors should be f_{s} \min(0, 1- \tau f) /f where f_{s} is the sampling frequency and f is the frequency being measured. Note that \tau f is an estimate of how many pulses arrive during one dead time.  If this is 1 or less, then no pulses are missed, otherwise only one of the arriving pulses is counted.

If the dead time for the Teensy 3.1 is about 900ns, then the errors should be about 0,0,0, -25, -57, and -81 for 0.5MHz, 0.9MHz, 1MHz, 2MHz, 3MHz, and 4MHz, consistent with the observed pattern.  With the longer counters  and so lower sampling frequencies on the other two boards, I expect errors of about 0,0,0,-1,-2,-3 ppm for a 1µs dead time, which is also consistent with the pattern of errors observed.

I could compensate for the error in PteroDAQ (on the host), by adding f_{s}\min(0, \tau f -1) to f.  The small initial error in f makes an insignificant change to \tau f. I will have to get a better estimate of the dead time than 900ns and 1µs, though, perhaps by counting instruction cycles for the compiled code between disabling and re-enabling the DMAMUX.  (Incidentally, do you have any idea how hard it is for a bioinformatician to type “DMA” instead of “DNA”?)

The ±27ppm error for the FRDM-KL25Z and Teensy LC boards seems fairly typical for a cheap crystal oscillator (which is usually ±30ppm).  Those errors are much larger than the <2ppm differences between the bench instruments, so it really doesn’t matter which of the bench instruments we treat as the “standard”.

What about the FG085 function generator? What is the ppm error on it?

FG085 setting 34401A
Leader LDC822
30Hz  -23.667 to -121  0
3kHz  -88.333  -100
30kHz  -58.667  -63.333
327kHz  -55.352  -58.716
600kHz  -103.33  -58.500
999kHz  -58.158
avg  -76.4  -56.45

The multimeter had some difficult producing consistent reading when there was a lot of jitter in the signal. The frequency counter was more consistent, indicating that the JYEtech FG085 function generator was running about 57ppm slow, which is well outside the normal crystal frequency range. The cheapest crystals are ±30ppm, and ±20ppm often doesn’t cost any more. (There are ±50ppm crystals, but you have to go out of your way to find them, and they aren’t any cheaper.)

There are several possibilities:

  •  an error in the way the firmware for the FG085 sets up the frequencies,
  • I picked particularly bad frequencies to test at, or
  • the crystals are unusually bad.

The FG085 uses a 24-bit phase oscillator with a 2.5MHz clock (except for frequencies below 40Hz, where it uses a 10kHz clock), so the worst case rounding should be for 3kHz, with a phase increment of 20133 instead of 20132.659, making the frequency 17ppm too high.  If they truncated instead of rounding, then the frequency would be 32.7ppm low.  At 30kHz, truncation error would be only 3ppm, though, so this does not explain the consistently high errors.  I think that bad crystals are the simplest explanation—it is certainly consistent with the super-cheap (and bad) design of their DAC (see FG085 function generator bugs).

I’m a little disappointed with FG085 function generator, since for about 50¢ more, they could have made a much better instrument (using a resistor-ladder chip instead of discrete, unmatched resistors; using a ±20ppm crystal; drilling large enough holes in the top so that the buttons didn’t stick).


  1. I just wanted to say thank you for your draft book which I bought a few days ago, and thanks for the PteroDaq software. I’m going to try and test it out this weekend. I’m hoping to use it with some ultrasonic sensors for velocity measurement. I went to price out some dynamics carts, tracks and sensors from Vernier and Pasco and realized that the only thing I’ll ever be able to afford for my classroom is maybe one usb hub. Do you have a gut feeling on how well a Teensy with an ultrasonic sensor would work for velocity measurement?

    The other thing I might try is to use an optical sensor as a cart moves past it. I could make my own picket fence on the side of a cart to trigger hi/low on the sensor. I don’t know if this would interface nicely with PteroDAQ though, I’d have to correlate timing of the hi/low with a distance for speed. In theory, would a Teensy and an optical sensor be fast enough to catch a transition from low to hi every 2 ms?


    Comment by bcphysics — 2015 September 6 @ 09:37 | Reply

    • I didn’t have much luck with ultrasonic sensors in my physics experiments (see ), but maybe my experience can help—most of the hobbyist sensors need a pretty big target.

      PteroDAQ should work quite well for timing. That is what we started from (see and )

      With PteroDAQ, I’d use an LED and phototransistor (perhaps the Sparkfun photointerrupter breakout board) and PteroDAQ’s trigger on either edge option. This provides timing to about 50ns resolution. The only problems will be mechanical ones (lining up your picket fence to have consistent angle, not running into the photointerrupter, …). The Sparkfun breakout board is for an LED and phototransistor with only a 1cm separation. If you want a big photogate (like Vernier and Pasco use), you’ll have to build your own and use a brighter infrared LED. If you want to be able to use a photogate in bright ambient light, a more complicated circuit is needed—you’d want to modulate the LED and look for interruption in the modulated signal, rather than a simple DC threshold. That’s usually not necessary indoors, but might be if you want to work in sunlight.

      Take a look through the “Homeschooling Calculus-based Physics” posts that I link to in the right-hand sidebar—there are a few examples of using a photointerrupter. The most successful was probably timing a long pendulum.

      Comment by gasstationwithoutpumps — 2015 September 6 @ 10:22 | Reply

      • Thanks.
        I used to use Omron photo interrupts like the Sparkfun, they’re useful if the motion is constrained. Thanks for the reminder. I can stick flags on the side of the cart, one at the front and one at the back. Provided that I build an inexpensive track for a cart, I can put the sensor on the track and get one “instantaneous” speed. I could also do as you suggest and make my own housing. I might try this, as we have a 3d printer at school which I can probably get access to.

        I agree about the ultrasonic sensor. I tried one a couple of years ago and the results weren’t great. I’m not sure how much I’d have to spend to get decent accuracy.

        Comment by bcphysics — 2015 September 6 @ 10:54 | Reply

        • One of these days (when I’m not working on my book or teaching classes) I’ll have to get out the ultrasonic rangefinders again and experiment with them to find out what the problem really is. I think that the problem is that they are just sending a pulse and listening for the echo, and that the echoes are weak from small targets. It would take some sophisticated signal processing to detect and deconvolve the echoes when they are weak, and the cheap sensors just don’t have the capability to do that.

          The MaxBotix MB1020 that I have only claims a 1″ resolution, which is probably not good enough for physics labs (they also make sensors for which they claim 1mm resolution). It sends out a 42kHz square-wave burst and provides 3 different ways of interfacing the return value. It has a free-running mode that could interface well with PteroDAQ.

          The Ping))) sensor that I have uses a 40kHz square wave (8-cycle burst), but does not report a resolution—I suspect that resolution is limited by the noise in the filter that detects the return pulse, and varies a lot depending on the strength of the return signal. It requires sending a pulse to the sensor to initiate each measurement—something that PteroDAQ doesn’t currently offer (though we’ve thought a bit about how to add that sort of capability to PteroDAQ).

          Comment by gasstationwithoutpumps — 2015 September 6 @ 12:47 | Reply

          • I’m having some trouble with PteroDAQ, not too sure what is happening. I’m using windows with Python2 and an Arduino Uno. I’m starting simple: using a reed switch. gnd-1kOhm-D7-reed switch – 5V. Trigger sample is set to 10Hz, Ch1 is set to D7. Bringing magnet close to switch doesn’t do anything on PteroDAQ, the GUI doesn’t seem to respond or do anything. As far as I can tell, no data is collected. I saved the run and get a text file that tells me the settings I’ve used with 0 samples. Any ideas what I’m doing wrong?

            Comment by bcphysics — 2015 September 7 @ 11:24 | Reply

            • If you have triggering set to 10Hz (not to edge triggering), then when you press the record button, the counts should go up by 10 every second. Sometimes briefly shorting out the power on the board will cause the host computer to shut down the USB port, which usually requires quitting the program, unplugging the USB cable, and plugging it back in.

              Are you running on Windows, Mac OS X, or Linux? Most of the debugging has been done on Mac OS X, some on Linux. I only recently bought a cheap Windows 8 laptop for testing with, and haven’t set up PteroDAQ on it yet. But if you get to the point of having the PteroDAQ window and being able to choose triggering options, then the host-dependent communications problems have usually been addressed.

              Comment by gasstationwithoutpumps — 2015 September 7 @ 11:35 | Reply

  2. […] Earlier today I made a comment: […]

    Pingback by Ultrasonic rangefinder pings | Gas station without pumps — 2015 September 6 @ 23:00 | Reply

  3. I must be doing something wrong, as I don’t see the counts going up. I started this on Windows 10 using python2.7.
    Here is a short video clip of what I did:

    I then downloaded PteroDAQ to my ubuntu notebook and i get the same thing. Looking at a quick sketch I made on the Arduino IDE has the serial monitor reading 0’s and 1’s.

    Comment by bcphysics — 2015 September 7 @ 14:12 | Reply

    • You’re right—there is a bug. You did everything correctly, so far as I can see.

      I’ll look for the bug right away (it may be only on Arduinos, as we’ve done most of the changes and testing lately on Teensy boards). I’ll get back to you soon.

      Comment by gasstationwithoutpumps — 2015 September 7 @ 14:32 | Reply

      • Found and fixed. Download the newest version. The bugs were in the Python code for sending the configuration string. The new way that the averaging byte was being determined was fragile (didn’t work with Arduino boards, which don’t have hardware averaging).

        There are not changes to the firmware, just to the Python code.

        Comment by gasstationwithoutpumps — 2015 September 7 @ 14:44 | Reply

        • Thanks a lot, you nailed it. Works on Windows 10 FWIW.

          Comment by bcphysics — 2015 September 7 @ 14:56 | Reply

          • Thanks for the bug report! We try to test everything, but with so many different platforms, we often don’t get everything tested after each minor update. The combinations (FRDM-KL25Z, Teensy 3.1, Teensy LC, Uno, Leonardo, Duemilanove, …) × (Python 2.6, Python 2.7, Python 3.2, Python 3.3, Python 3.4) × (Mac OS 10.6.8, Mac OS 10.8.1, …, Ubuntu Linux, Windows 7, Windows 8, Windows 10) results in too many things to test. So we just test the stuff we think has been affected on the easy-to-access systems (mainly a Teensy 3.1 board, Python 2.7 and 3.4, and my Mac OS 10.6.8 laptop), and hope that we haven’t broken anything else. A professional development team would have a large suite of regression tests and test on all the machines, but for a spare-time project, we can’t afford to do that and still make any progress on new development.

            Comment by gasstationwithoutpumps — 2015 September 7 @ 15:20 | Reply

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: