Hi,
thanks to everybody, and in particular to Nick Gammon, for their work.
I've tryed Nick Gammon's sketch on Mega 2560: Timer1 works on Uno, but not Mega 2560 - #12 by nickgammon - Programming Questions - Arduino Forum, and feeding pin 47 with another Mega (blinking at some given frequencies), I can see only frequencies (and counts) in 2^n order (1,2,4,8,16,32,...), or similar: with this code on "feeder Mega"
void loop() {
digitalWrite(5,HIGH); // PORTD = B00100000; // sets digital pin 5 HIGH
delay(DELAY_MS);
digitalWrite(5,LOW); // PORTD = B00000000; // sets digital pin 5 LOW
delay(DELAY_MS);
}
on "feeded Mega" with your above sketch I get this freqs:
DELAY_MS freq
64000 0
32000 1
16000 2
8000 4
4000 8
2000 16
1000 31
500 61
250 122
122 244
100 244
50 488
20 488
10 488
5 488
2 488
1 800
0 46002
so, for example, I get same counts (and freq) for 2ms or 50ms delay()... any suggestion?
thanx in advance.. and sorry for bad english
Alì
as stated by GoForSmoke, code is the linked one; anyway now I post both codes:
Freq. generator:
#define DELAY_MS 20
/*
DELAY_MS freq
64000 0
32000 1
16000 2
8000 4
4000 8
2000 16
1000 31
500 61
250 122
122 244
100 244
50 488
20 488
10 488
5 488
2 488
1 800
0 46002
-- 73430
*/
void setup()
{
pinMode(5, OUTPUT); //we use this pin for pulse output
noInterrupts(); // Disable all INT (speeds up things a little)
}
void loop()
{
digitalWrite(5,HIGH); // PORTD = B00100000; // sets digital pin 5 HIGH
delay(DELAY_MS);
digitalWrite(5,LOW); // PORTD = B00000000; // sets digital pin 5 LOW
delay(DELAY_MS);
}
Freq. calcolator:
/*
DELAY_MS PERIODO counts
20 500 244
20 1000 488
*/
// Timer and Counter example for Mega2560
// Author: Nick Gammon
// Date: 24th April 2012
// input on pin D47 (T5)
#define PERIODO 1000
// 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 2 and Timer 5
TCCR2A = 0;
TCCR2B = 0;
TCCR5A = 0;
TCCR5B = 0;
// Timer 5 - counts events on pin D47
TIMSK5 = _BV (TOIE1); // interrupt on Timer 5 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 uS.
// So we count 125 of them, giving exactly 1000 uS (1 mS)
TCCR2A = _BV (WGM21) ; // CTC mode
OCR2A = 124; // count up to 125 (zero relative!!!!)
// Timer 2 - interrupt on match (ie. every 1 mS)
TIMSK2 = _BV (OCIE2A); // enable Timer2 Interrupt
TCNT2 = 0;
TCNT5 = 0; // Both counters to zero
// Reset prescalers
GTCCR = _BV (PSRASY); // reset prescaler now
// start Timer 2
TCCR2B = _BV (CS20) | _BV (CS22) ; // prescaler of 128
// start Timer 5
// External clock source on T4 pin (D47). Clock on rising edge.
TCCR5B = _BV (CS50) | _BV (CS51) | _BV (CS52);
} // end of startCounting
ISR (TIMER5_OVF_vect)
{
++overflowCount; // count number of Counter1 overflows
} // end of TIMER5_OVF_vect
//******************************************************************
// Timer2 Interrupt Service is invoked by hardware Timer 2 every 1ms = 1000 Hz
// 16Mhz / 128 / 125 = 1000 Hz
ISR (TIMER2_COMPA_vect)
{
// grab counter value before it changes any more
unsigned int timer5CounterValue;
timer5CounterValue = TCNT5; // see datasheet, (accessing 16-bit registers)
// see if we have reached timing period
if (++timerTicks < timerPeriod)
return; // not yet
// end of gate time, measurement ready
TCCR5A = 0; // stop timer 5
TCCR5B = 0;
TCCR2A = 0; // stop timer 2
TCCR2B = 0;
TIMSK2 = 0; // disable Timer2 Interrupt
TIMSK5 = 0; // disable Timer5 Interrupt
// calculate total count
timerCounts = (overflowCount << 16) + timer5CounterValue; // 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 () {
startCounting (PERIODO); // 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 ("Counts: ");
Serial.println ((unsigned long) timerCounts);
// Serial.print ("Frequency: ");
// Serial.println ((unsigned long) frq);
// let serial stuff finish
delay(200);
} // end of loop
#define CJ_ID "Wavelength2560 version:C"
/* Frequency counter using Timer 3 to work out the interval (i.e wavelength)
by counting between two consecutive rising interrupts (leading edge) on pin D18 (int3).
Based on Nick Gammon's similar program for Atmel 328P processor, here:
http://www.gammon.com.au/forum/?id=11504
Adapted for MEGA2560 by Chris Jennings, 8 May 2014.
Timer 3 is a high-precision 16-bit timer. By using no prescaler the timer counts
every clock cycle (62.5nS at 16 MHz). We deduce the frequency by multiplying the
counts between the leading edges by 62.5.
An advantage of this method is the quick calculation. e.g. at 10kHz the period
is 1/10000sec (100µS) so we get our result in just 100µS.
Note: Beware the mismatch in interrupt numbers used on MEGA2560 versus the Arduino
Attach/DetachInterrupt commands, as follows:
Arduino MEGA2560
int.0 pin D2 interrupt/counter 4
int.1 pin D3 interrupt/counter 5
int.2 pin D21 interrupt/counter 0
int.3 pin D20 interrupt/counter 1
int.4 pin D19 interrupt/counter 2
int.5 pin D18 interrupt/counter 3 (THIS IS WHAT IS USED BELOW) */
volatile boolean first;
volatile boolean triggered;
volatile unsigned long overflowCount;
volatile unsigned long startTime;
volatile unsigned long finishTime;
void isr () { // here on rising edge
unsigned int counter = TCNT3; // quickly save it
if (triggered) return; // wait until we noticed last one
if (first) {
startTime = (overflowCount << 16) + counter;
first = false;
return;
}
finishTime = (overflowCount << 16) + counter;
triggered = true;
detachInterrupt(5); // interrupt 3 off
}
ISR (TIMER3_OVF_vect) {overflowCount++;}// timer overflows (every 65536 counts)
void prepareForInterrupts (){ // get ready for next time
EIFR = bit (INTF3); // clear flag for interrupt 3
first = true;
triggered = false; // re-arm for next time
attachInterrupt(5, isr, RISING); // initialise interrupt 3
}
void setup () {
Serial.begin(115200); Serial.println(CJ_ID);
Serial.println("Calculate frequency on pin D18 from wavelength");
TCCR3A = 0; // reset Timer 3
TCCR3B = 0;
TIMSK3 = bit (TOIE3); // Timer 3 - enable interrupt on overflow
TCNT3 = 0; // zero it
overflowCount = 0;
TCCR3B = bit (CS30); // start Timer 3, no prescaling
prepareForInterrupts (); // set up for interrupts
}
void loop (){
if (!triggered) return;
unsigned long elapsedTime = finishTime - startTime;
float freq = F_CPU / float (elapsedTime); // each tick is 62.5 nS at 16 MHz
Serial.print ("Counts: "); Serial.print (elapsedTime);
Serial.print (" Freq: "); Serial.print (freq); Serial.println ("Hz. ");
delay (500);
prepareForInterrupts ();
}