So I have this code fragment working on my Arduino Uno outputting frequency to pin 9, but when uploading to the Mega 2560 I do not see any frequency output to pin 9 of the Mega 2560. Please help:
void setup() {
pinMode(9, OUTPUT);
Serial.begin(9600);
TCCR1A = _BV(COM1A0)
| _BV(COM1B0) // toggle OC1B on compare match
| _BV(WGM10)
| _BV(WGM11);
TCCR1B = _BV(WGM12)
| _BV(WGM13); // Fast PWM mode, OCR1A as TOP
OCR1B = 0; // toggle when the counter is zero
OCR1A = 15383; // set top to the initial 65Hz
OCR1A = 50000;
TCCR1B |= _BV(CS11); // set prescale to div 8 and start the timer
}
void loop(){
for (unsigned long frequency = 17; frequency <= 10000; frequency=frequency+resolution) // from 16hz to 2KHz
{
if(frequency <=99){
top = (16000000 / (frequency * 2 * 8)) -1;
OCR1A = top;;
.......
}
Moderator edit: [code] ... [/code] tags added. (Nick Gammon)
So you're saying that the code that was written on the UNO was addressing pin 9, but when uploaded to the Mega2560, OCR1A is now mapped to pin 11? and OCR1B is mapped to pin 12?
To work with an arduino mega using the 1280 chip, and it does not seem to want to count anything.....
I am injecting a 1 Mhz square wave to PWM pin 12, but the freq displayed on the serial monitor still says zero..I am sure I am missing something obvious?
BTW: Nick, I can't thank you enough for all the work on your site...the information there is ABSOLUTELY awesome, for anyone playing around with an arduino...thank you so much for the content, you are an interrupt and timer guru!!
Which sketch on that page? I have two counting sketches, at least. Probably the pin number is different. Those sketches were definitely tested on the Uno, not the Mega.
// Timer and Counter example
// Author: Nick Gammon
// Date: 17th January 2012
// 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 = _BV (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 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
TCNT1 = 0; // Both counters to zero
TCNT2 = 0;
// Reset prescalers
GTCCR = _BV (PSRASY); // reset prescaler now
// start Timer 2
TCCR2B = _BV (CS20) | _BV (CS22) ; // prescaler of 128
// start Timer 1
// External clock source on T1 pin (D5). Clock on rising edge.
TCCR1B = _BV (CS10) | _BV (CS11) | _BV (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 1ms = 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)
// see if we have reached timing period
if (++timerTicks < timerPeriod)
return; // not yet
// 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 = (overflowCount << 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 () {
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.println ((unsigned long) frq);
// let serial stuff finish
delay(200);
} // end of loop
The pin assignments for the Mega are given in the relevant datasheet. They are all different from the Uno. My shorthand list of pin outs (which may have mistakes, note) is given below. Note that "pack" means the package pin numbers, not Arduino pin numbers which are in the final column. For some crazy reason the code tagged text isn't coming out in a fixed-width font alas... I've marked important pin names like OC1A, RX, MISO etc
Thank you very much for posting this....Yes, if you look at the .pdf I attached, it also shows the same pinout....so where I am confused is how the sketch I posted can translate to the mega..TCCR1B which is used on the Uno..seems to map to PIN 12 on the mega..but again, injecting a pure sin wave at about 1 Mhz, does not display anything...
Also tried pin 11, 12, 13, etc to see if it made a difference, but again, no results....I do not understand enough yet about the timers, so I think Nick might be able to help us out a bit here to get his sketch working on the mega.....
thank you again MarkT for posting this....very helpful!
Neither was T3, lol. OK, Timer 5 is connected to an external pin (D47 at the end). So this works:
// Timer and Counter example for Mega2560
// Author: Nick Gammon
// Date: 24th April 2012
// input on pin D47 (T5)
// 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 (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.println ((unsigned long) frq);
// let serial stuff finish
delay(200);
} // end of loop
Works like a charm....I can only go as high as 5Mhz on my Function Generator for a square wave, and the output measured 4993152...Pretty damn Accurate!!
With decade/divider chips, the sky is the limit!!
Thank you again for looking into this.....works very well!
Hi Nick, thank you so much for your work.
I've tryed your sketch on Mega 2560, 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 freq:
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ì