The system I'm developing includes two pressure transducers that have three frequency outputs: reference, pressure and temperature. That's six frequencies I need to measure. The reference frequency is approximately 7.2 MHz, whilst the two signal frequencies are in the range 10 to 100 kHz.

I've got a Microchip dsPIC33E device on my main board, which I know can be configured (using the Input Capture peripheral modules) to do the job. However, reading the pressure sensors is neither the main function of the micro nor the most time-critical, so I'm reluctant to burden it with this job as well. For the same reason, I don't want to use an off-chip device with an interface, as the separation between layers 1, 2 and 3 is not clean and the protocol overhead high in comparison with + or an .

Are there any relatively simple electronic solutions to the problem?

  • There are several IC devices available that have LCD driver outputs, but I've been unable to find anything (that's still in production) with a SPI interface.
  • I'd rather not use a second micro-controller, but might consider it if there really is no practical alternative.
  • An analogue solution could be acceptable, providing it is sufficiently accurate.
  • FPGA or CPLD solutions may have potential.

Further Information

The devices are Quartzdyne Frequency Output Pressure Transducers, which are to be deployed in an environment where the pressure and temperature can vary significantly over time. Changes in either pressure or temperature can cause variation in the signal on both the pressure and temperature inputs. The reference signal is provided as a control, as it is affected equally by both pressure and temperature variations. Consequently, for best accuracy, all three frequencies have to be measured. The device manufacturer provides mathematical functions for calculating the pressure and temperature from the three frequency measurements.

Resolution: A frequency error of +/- 0.01 Hz of the 7.2 MHz signal (or better) is desirable to achieve the best accuracy of the sensor.

Bandwidth: The pressure and temperature frequencies should be updated at 10 Hz. If I use a period counting solution on a micro-controller, a gate time of 1 second (or longer) may be required. But this could be achieved by accumulating consecutive counts over shorter periods in a circular buffer to create a longer 'virtual' gate time.

  • \$\begingroup\$ Do you need to know the absolute frequency of all three outputs of each sensor? Or do you just need to know maybe the ratio between the pressure/temperature outputs and the reference output frequency? \$\endgroup\$
    – The Photon
    Commented Jan 14, 2016 at 17:04
  • \$\begingroup\$ Maybe the LM2907-N frequency to voltage IC might work? \$\endgroup\$
    – Kvegaoro
    Commented Jan 14, 2016 at 17:25
  • 2
    \$\begingroup\$ A second uC would be easier/cheaper than a separate CPLD or FPGA. But the final answer depends on the performance specs you actually need. \$\endgroup\$
    – Dave Tweed
    Commented Jan 14, 2016 at 17:49
  • \$\begingroup\$ What bandwidth are you trying to achieve? What resolution? An additional one or two micros might be used in a ratiometric measurement (clocked by the reference) or a small FPGA. Using a micro per sensor, one could encapsulate the linearization and calibration of the sensor and provide processed data. \$\endgroup\$ Commented Jan 14, 2016 at 18:02
  • \$\begingroup\$ If your PIC has two IOs that can act as clock inputs to timers, you should be able to use that to count the number of cycles in the reference and on the measured signal on the other hand, and use the period counting from the manual you link to. It won't tax your microcontroller, as you simply need to take the current readings of both counters periodically, the counting itself is done by the timer. \$\endgroup\$
    – Timo
    Commented Jan 15, 2016 at 11:15

2 Answers 2


As I understand that from your question that your hesitation in using the PIC to do the frequency measurement is that you don't want the MCU to have to serve interrupts and such due to other, more time critical tasks. I'd like to suggest that this is a misplaced worry.

Using the reference oscillator as an external clock (the TCS bit in the control register) for 32-bit timer/counter, you can count the number of cycles of the reference oscillator. At the same time, with the other timer/counters, again using the oscillator as an external clock, you count the cycles for the frequencies to be measured, for this 16-bit will do fine.

Setting up the counters and having them run will not cost you anything in terms of MCU cycles. Using the fixed \$N_s\$ counting according to section 3.2 in the manual, you set up an interrupt on 16-bit compare match, or overflow if you want \$N_s = 65536\$. You'd probably change the gate time dynamically if you want a 10Hz update time, or by storing a list of counts of the 32-bit counter with \$N_s\$ such that the compare matches more than 10 times a second, as you suggest, for a longer "virtual gate time".

The interrupt will cost you a little, but only for reading the reference count of the reference oscillator, so it's essentially one register read, which you store. You can do the divide in the formula whenever convenient, for an example a main loop. If you have more time critical tasks, make sure to set the interrupt priorities accordingly.

Basically the only fixed burden here is the interrupt at around 20 times a second (for the two signals), and I'm not sure how much better you can do. Reading an ADC, if you were to somehow convert the frequency to voltage, would get rid of the interrupt, but there I don't think you can get enough accuracy in the ratio of the frequencies. Consider, for example, that if there's a voltage divider conditioning your ADC inputs, 0.1% resistors are already a bit of a special part, and even that may not be enough accuracy here.

So, I would seriously suggest at least giving a try to using the PIC directly, unless you have very time critical tasks I would expect this straightforward solution will work.

  • \$\begingroup\$ This does look like a good idea, however I'm not sure I have enough Timer/Counter peripherals on my device to do this. It looks like 8 would be required: four for each transducer. I'm already using one as a milliseond timer and another for a Quadrature Encoder velocity counter. I'll have to have a think about it. \$\endgroup\$ Commented Jan 15, 2016 at 14:42
  • \$\begingroup\$ @MikeofSST isn't that three per device, the reference, pressure, and temperature? Admittedly the reference really needs a 32-bit timer, so you'll tie up both of those on your dsPIC. \$\endgroup\$
    – Timo
    Commented Jan 15, 2016 at 14:49
  • \$\begingroup\$ Yes, three (or four) per device and two devices. \$\endgroup\$ Commented Jan 18, 2016 at 9:05
  • \$\begingroup\$ @MikeofSST ah, right, you were counting in terms of 16-bit timers, i.e. one 32-bit counts as two. So we agree on the count. \$\endgroup\$
    – Timo
    Commented Jan 18, 2016 at 10:06
  • \$\begingroup\$ This is working great. With the addition of the DMA and the micro clocked at 80 MHz (40MIPS), the CPU load is under 5% for the DMA ISRs and all of the processing of the frequency data from both signals of both devices captured by the driver. It took a while to get all the peripheral configuration right, but worth the effort. Thanks. \$\endgroup\$ Commented Jan 28, 2016 at 11:07

The answer marked as correct works, with a few tweaks as follows.

  • Allocate a timer/counter module to each of the reference frequencies. Just one, 16 bit counter per reference frequency is sufficient.
  • Allocate an input capture (IC) module to each of the signal frequecies, configured to use the reference frequency counter as the time-base.
  • Allocate a DMA module to each of the IC modules. Each DMA buffer is a 32 word array, with the module configured to interrupt after 16 words in flip-flop mode.
  • Start the IC module in simple capture mode with pre-scaling of 16.

The IC modules are now capturing the value in the reference frequency counter on every 16th rising edge of the signal. The DMA transfers the reference count to the buffer with an interrupt generated on every 16th IC event.

The user code in the DMA ISR is called at a frequency 256 times lower than the signal frequency. All it has to do is accumulate the counts in the DMA buffer and increment the signal count by 256 to obtain counts for both the reference and signal frequencies. (The reference frequency count can roll over between IC events, which has to be accounted for: it's not enough just to subtract the earliest count from the latest. Accounting is done by taking the difference between consecutive counts in the DMA buffer, as per this answer on SO, with the last count saved in a static variable to retain the value between calls to the ISR.)

Finally, the background loop periodically checks when the DMA ISRs have updated the frequency counts and adds them to a rolling gate-time accumulator. This has been implemented so that it can provide updates at 10 Hz (as required), but maintains the counts for over 1 second to achieve the gate time necessary for the required accuracy.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.