0

I am doing a project with a color sensor, where the output of the color sensor is a PWM square wave.

To measure its frequency using an Arduino Uno I am using the pulseIn() function, but I can't get the correct result.

Can an Arduino Uno measure a frequency of up to 600 kHz using the pulseIn() function?

ocrdu
  • 1,775
  • 3
  • 11
  • 24

1 Answers1

3

The documentation for pulseIn states that it can be used for intervals of 10 microseconds to 3 minutes.

600 kHz frequency will have an interval of 1.6 microseconds and thus is not suitable for this application. (1 / 600000 = 0.000001666).

I have code on my web page about timers for a sketch that can measure up to 8 MHz with only 0.5% error.

This code is reproduced below:

// 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; volatile boolean counterReady;

// 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

while (!counterReady) { } // 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


Whether Arduino UNO can measure the frequency upto 600 KHz if we use the pulseIn() function?

No. Not using pulseIn. However see the code above for a way of measuring such a frequency.

Nick Gammon
  • 38,184
  • 13
  • 65
  • 124