Clamping a Frequency?


I've ran into a project that I'm unsure as to whether an Arduino is capable of handling. I've been playing around with Arduino's for a few years, but really haven't built anything mind blowing with them... Nothing where timing accuracy was critical. My concern with this project is whether or not an Arduino is fast enough to do what I need, or whether a faster uC would be necessary. Just looking for some advice.

So, basically what I'm looking to do is clamp a signal when it reaches a preset frequency. The input will be a 5v 0-3.5 kHz square wave. The output needs to follow this input signal accurately, until it reaches a predetermined frequency, at which time no matter what the increase of the input frequency is, the output needs to continue to hold at the specified maximum frequency. I.e., if the preset value was defined as 3,300 Hz:

Input: 100 Hz Output: 100 Hz Input: 1,250 Hz Output: 1,250 Hz Input: 3,200 Hz Output: 3,200 Hz Input: 3,475 Hz Output: 3,300 Hz Input: 1,900 Hz Output: 1,900 Hz

I know that I can measure the input frequency, and then produce the same frequency on an output. Given that the signal is 5v, and at such a low frequency, I don't think there would be any problems in that regard.

However, what I am concerned about is whether or not an Arduino can sample the input quickly enough, and continue to output an accurate frequency at the same time as sampling is occurring. The frequency will be changing constantly, and I need to minimize any lag between measuring the input frequency and setting the output frequency, while maintaining accuracy.

I've never done anything related to measuring frequencies with an Arduino, so I'm just not sure whether this is within the capabilities of the platform or not. Is it worth rigging up a test bed and trying this, or is it just flat out too much to ask to do accurately?


If it is only a square wave, no sampling is necessary, just use pulsein().

Yes, use pulseIn to measure, and output a 50% duty cycle using a PWM pin. Then the output can be independent of the input once 3300 is exceeded.

See here as a starting point

Thank you both very much for your advice.

You've given me the feeling that this should be within the capabilities of the hardware. So, I will start trying to put together a solution!

Happy Holidays!

Wow, this page you reference is awesome! Lots of good information that I can use on the measurement half of this idea. Accuracy down to 1 Hz is perfect for what I'm doing. Honestly, accuracy of 2-3 Hz might be good enough.

I was just playing around with the frequency generation side of this. I tried the most obvious; write a 1 to an output, delay X uS, write a 0, loop. Looks like the tightest loop I tried (direct port manipulation, with the only function call being to delayMicroseconds) has a resolution of 10 Hz. I.e., delaying 334 uS between each port change = 3005 Hz. Delaying 335 uS = 3015 Hz.

That's too low of a resolution, so now I'm looking at other methods of generating the frequency.

Was considering using a frequency to voltage IC, digitize the voltage with an SPI ADC, analyze it using the Arduino, then on the opposite side use an SPI DAC, then out to a voltage to frequency converter.

Saw a few DDS modules out there too. Not sure if they go down into the kHz range, but its worth a look.

Maybe I can learn some tricks from the page you referenced that can be applicable to generating the frequency output.

Long story short, thank you! This page has a bunch of good information. I'll continue to read through the info tomorrow and think about the solution more. I'm sure it can be done. Just need to learn a better technique to delay the transitions more accurately. Maybe using assembly code to get delays down to the cycle level instead of delaying for whole uS's using the delayMicroseconds() function. I've never touched AVR assembly, though. Been years since I touched PIC assembly, and even longer since I used x86 assembly. But at least there's still some assembly info floating around in my synapses.

Just another thought.

What if you pass your square wave signal to an op amp in buffer amplifier configuration, so that the input and output are literally perfectly the same in frequency, with maybe a little phase shift. As long as you’re below your max, all the Arduino has to do is measure the frequency using pulsein(). When you hit the max, use an Arduino pin to shut down the amplifier, and instead activate a square wave generator at the desired frequency. Both the pass through amplifier and the oscillator could be built using one little quad opamp, like the LM324. It’s a very docile little critter, and very easy to master.

Good luck

That idea sounds good to me.

You can get faster output by replacing the digital write function calls to direct port manapulation.

The other way of getting a good output is to change the frequency of the PWM timers. The processor's data sheet will tell you what or that site of Nick's has that information in a more palatable form.