# Read frequency of input in digital pins

This is a somewhat theoretical question: Let's say I have some sensor that sends digital signals to one of Arduino's digital ports. Now, I don't know the frequency it sends those signals in. For example, the frequency of the sensor output could be 100Hz, so every 1/100 of a second it varies the voltage (or keeps the old voltage if the next signal is the same as the previous one), but it could just as well be 200Hz. Would Arduino be able to faithfully read the digital signal regardless of its frequency? Or is there a conventional frequency that digital devices usually use for output? Wouldn't it be the case that if Arduino expects 100Hz signal, but the signal is 200Hz it would miss half the inputs? For: (1 0 1 0 0 1...) wouldn't it see: (1 1 0) - that is skip every other input because it's sampling rate would be too slow by half? Thanks kindly for your help..

• What do you mean by “digital signal”? Some kind of synchronous serial transmission protocol? SPI maybe? Or I2C? Or maybe an asynchronous one, like logic level UART? Or is it a custom protocol? Your question will start to make sense only once you specify how the data is supposed to be clocked in your protocol. Aug 5, 2018 at 8:20
• so every 1/100 of a second it varies the voltage (or keeps the old voltage if the next signal is the same as the previous one), - are you asking about measuring voltages or frequencies? Aug 5, 2018 at 9:14
• @Nick, let's assume that the 1 voltage is high enough (but not too high) for Arduino to register a 1, and the 0 voltage is also within the threshold for Arduino to register a zero (say 5V for HIGH and 0.5V for LOW). It's the frequency of the signal I'm concerned with. Aug 5, 2018 at 20:42
• @Edgar, I have in mind just a generic digital sensor - let's say one that measures temperature and sends a digital signal to Arduino at some unknown frequency. Aug 5, 2018 at 20:44
• A “generic” digital sensor doesn't mean anything. Digital sensors usually come with either SPI or I2C interfaces. Sometimes asynchronous serial. All those are well defined communication protocols. There are rules stating how the sender should notify the receiver about when precisely the data line is to be sampled. The Arduino has hardware support for these protocols, but other protocols have to be implemented in software (e.g. one wire). So forget about your meaningless “generic” and tell us what serial protocol you intend to use. Aug 6, 2018 at 7:43

100 Hz is pretty trivial. See my page about timers.

This sketch can detect frequencies up to about 5 MHz:

``````// Timer and Counter example
// Author: Nick Gammon
// Date: 17th January 2012

// Input: Pin D5

// these are checked for in the main program
volatile unsigned long timerCounts;

// internal to counting routine
unsigned long overflowCount;
unsigned int timerTicks;
unsigned int timerPeriod;

void startCounting (unsigned int ms)
{
counterReady = false;         // time not up yet
timerPeriod = ms;             // how many 1 ms counts to do
timerTicks = 0;               // reset interrupt counter
overflowCount = 0;            // no overflows yet

// reset Timer 1 and Timer 2
TCCR1A = 0;
TCCR1B = 0;
TCCR2A = 0;
TCCR2B = 0;

// Timer 1 - counts events on pin D5
TIMSK1 = bit (TOIE1);   // interrupt on Timer 1 overflow

// Timer 2 - gives us our 1 ms counting interval
// 16 MHz clock (62.5 ns per tick) - prescaled by 128
//  counter increments every 8 µs.
// So we count 125 of them, giving exactly 1000 µs (1 ms)
TCCR2A = bit (WGM21) ;   // CTC mode
OCR2A  = 124;            // count up to 125  (zero relative!!!!)

// Timer 2 - interrupt on match (ie. every 1 ms)
TIMSK2 = bit (OCIE2A);   // enable Timer2 Interrupt

TCNT1 = 0;      // Both counters to zero
TCNT2 = 0;

// Reset prescalers
GTCCR = bit (PSRASY);        // reset prescaler now
// start Timer 2
TCCR2B =  bit (CS20) | bit (CS22) ;  // prescaler of 128
// start Timer 1
// External clock source on T1 pin (D5). Clock on rising edge.
TCCR1B =  bit (CS10) | bit (CS11) | bit (CS12);
}  // end of startCounting

ISR (TIMER1_OVF_vect)
{
++overflowCount;               // count number of Counter1 overflows
}  // end of TIMER1_OVF_vect

//******************************************************************
//  Timer2 Interrupt Service is invoked by hardware Timer 2 every 1 ms = 1000 Hz
//  16Mhz / 128 / 125 = 1000 Hz

ISR (TIMER2_COMPA_vect)
{
// grab counter value before it changes any more
unsigned int timer1CounterValue;
timer1CounterValue = TCNT1;  // see datasheet, page 117 (accessing 16-bit registers)
unsigned long overflowCopy = overflowCount;

// see if we have reached timing period
if (++timerTicks < timerPeriod)
return;  // not yet

// if just missed an overflow
if ((TIFR1 & bit (TOV1)) && timer1CounterValue < 256)
overflowCopy++;

// end of gate time, measurement ready

TCCR1A = 0;    // stop timer 1
TCCR1B = 0;

TCCR2A = 0;    // stop timer 2
TCCR2B = 0;

TIMSK1 = 0;    // disable Timer1 Interrupt
TIMSK2 = 0;    // disable Timer2 Interrupt

// calculate total count
timerCounts = (overflowCopy << 16) + timer1CounterValue;  // each overflow is 65536 more
counterReady = true;              // set global flag for end count period
}  // end of TIMER2_COMPA_vect

void setup ()
{
Serial.begin(115200);
Serial.println("Frequency Counter");
} // end of setup

void loop ()
{
// stop Timer 0 interrupts from throwing the count out
byte oldTCCR0A = TCCR0A;
byte oldTCCR0B = TCCR0B;
TCCR0A = 0;    // stop timer 0
TCCR0B = 0;

startCounting (500);  // how many ms to count for

{ }  // loop until count over

// adjust counts by counting interval to give frequency in Hz
float frq = (timerCounts *  1000.0) / timerPeriod;

Serial.print ("Frequency: ");
Serial.print ((unsigned long) frq);
Serial.println (" Hz.");

// restart timer 0
TCCR0A = oldTCCR0A;
TCCR0B = oldTCCR0B;

// let serial stuff finish
delay(200);
}   // end of loop
``````

Or is there a conventional frequency that digital devices usually use for output?

No.

Wouldn't it be the case that if Arduino expects 100Hz signal, but the signal is 200Hz it would miss half the inputs? For: (1 0 1 0 0 1...)

No.

Why would it "expect" a frequency? It isn't a person expecting a chocolate cake on its birthday.

So whatever frequency the sensor sends its data in - be it 100Hz or 5Mhz - Arduino is smart enough to read all the voltage signals faithfully?

I'm not quite sure what you mean by "read all the voltage signals" which seems to imply you want to measure the voltage.

so every 1/100 of a second it varies the voltage (or keeps the old voltage if the next signal is the same as the previous one)

But then you say:

let's assume that the 1 voltage is high enough (but not too high) for Arduino to register a 1, and the 0 voltage is also within the threshold for Arduino to register a zero (say 5V for HIGH and 0.5V for LOW). It's the frequency of the signal I'm concerned with.

The voltage levels for 0 and 1 are documented in the datasheet. For the Atmega328P for most pins they are as follows: You can see that if Vcc is 2.4V or above then LOW is -0.5V to 0.3 * Vcc, which if Vcc is 5V then a LOW is -0.5 to 1.5V.

Similarly a HIGH is 0.6V * Vcc to Vcc + 0.5, so if Vcc is 5V then a HIGH is 3V to 5.5V.

In between 1.5V and 3V then the digital status would be undefined.

So, if your LOW and HIGH are in those voltage ranges, yes you can detect the frequency of the signal.

I'm not sure about the bit where you said "keeps the old voltage if the next signal is the same as the previous one". That seems to imply that if the signals stay the same (eg. for a second) then the voltage won't change at all, and thus the frequency will be zero.

• Thanks @Nick. So whatever frequency the sensor sends its data in - be it 100Hz or 5Mhz - Arduino is smart enough to read all the voltage signals faithfully? If that's the case, that's encouraging news.. One additional question pls: can you determine the frequency of the sensor from the code - i,e. determine if the sensor is 100Hz, 200Hz etc. Aug 5, 2018 at 20:32
• See amended answer. Aug 5, 2018 at 23:38
• thanks @nick for all the info. About the last paragraph: wouldn't it be the case that if there's a stream of 1s and not 0s for a whole second, then the voltage graph would look like a horizontal line of 5V (basically like DC of 5V) for that 1 sec.)? Aug 6, 2018 at 19:22
• Yes, absolutely. Aug 7, 2018 at 6:14