Timer1 works on Uno, but not Mega 2560

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)

OC1B is pin D12.

1 Like

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?

Yes. The mappings of the hardware timers to pins is different.

Hi,

I am also trying to get the sketch posted here:

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

Thanks!

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.

This is the sketch I am talking about...trying to decipher the pins for the mega...it compiles on the mega with no errors...

thanks!

PS: This might help: http://arduino.cc/en/uploads/Main/arduino-mega-schematic.pdf

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

Bump?

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

ARDUINO MEGA:
-------------

pack  port     pwm  arduino pin
 1     G5 OC0B  X    4

 2     E0 RX         0 RX
 3     E1 TX         1 TX
 4     E2
 5     E3 OC3A  X    5
 6     E4 OC3B  X    2  int4
 7     E5 OC3C  X    3  int5
 8     E6               int6
 9     E7               int7

10    Vcc
11    GND

12     H0 RX2        17
13     H1 TX2        16
14     H2 XCLK2
15     H3 OC4A  X    6
16     H4 OC4B  X    7
17     H5 OC4C  X    8
18     H6 OC2B  X    9

19     B0 SS         53
20     B1 SCK        52
21     B2 MOSI       51
22     B3 MISO       50
23     B4 OC2A  X    10
24     B5 OC1A  X    11
25     B6 OC1B  X    12
26     B7 OC0A,OC1C  X    13    ;; Arduino code ignorant of OC1C

27     H7

28     G3
29     G4

30    RES
31    Vcc
32    GND
33    Xtal2
34    Xtal1

35     L0            49
36     L1            48
37     L2            47
38     L3 OC5A  X    46
39     L4 OC5B  X    45
40     L5 OC5C  X    44    ;; note OC5C not supported by analogWrite....
41     L6            43
42     L7            42

43     D0 SCL        21  int0
44     D1 SDA        20  int1
45     D2 RX1        19  int2
46     D3 TX1        18  int3
47     D4
48     D5 XCLK1
49     D6
50     D7            38
     
51     G0 WR         41
52     G1 RD         40

53     C0 A8 RAMa    37
54     C1 A9         36
55     C2 A10        35
56     C3 A11        34
57     C4 A12        33
58     C5 A13        32
59     C6 A14        31
60     C7 A15        30

61    Vcc
62    Gnd

63     J0 RX3        15
64     J1 TX3        14
65     J2 XCLK3
66     J3
67     J4
68     J5
69     J6

70     G2            39

71     A7 AD7 RAMa/d 29
72     A6 AD6        28
73     A5 AD5        27
74     A4 AD4        26
75     A3 AD3        25
76     A2 AD2        24
77     A1 AD1        23
78     A0 AD0        22

79     J7
80    Vcc
81    GND

82     K7 ADC15      A15/69
83     K6 ADC14      A14/68
84     K5 ADC13      A13/67
85     K4 ADC12      A12/66
86     K3 ADC11      A11/65
87     K2 ADC10      A10/64
88     K1 ADC9       A9/63
89     K0 ADC8       A8/62

90     F7 ADC7       A7/61
91     F6 ADC6       A6/60
92     F5 ADC5       A5/59
93     F4 ADC4       A4/58
94     F3 ADC3       A3/57
95     F2 ADC2       A2/56
96     F1 ADC1       A1/55
97     F0 ADC0       A0/54

98    Aref           AREF
99    GND
100   VccA


PORT   0   1   2   3   4   5   6   7
-------------------------------------
  A   22  23  24  25  26  27  28  29
  B   53  52  51  50  10. 11. 12. 13.
  C   37  36  35  34  33  32  31  30
  D   21  20  19  18              38
  E   RX  TX       5.  2.  3.
  F   A0  A1  A2  A3  A4  A5  A6  A7
  G   41  40  39           4.
  H   17  16       6.  7.  8.  9.
  J   15  14
  K   A8  A9 A10 A11 A12 A13 A14 A15
  L   49  48  47  46. 45. 44. 43  42

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!

cyborgcnc:
Bump?

Sorry for the delay. I had parent/teacher interviews yesterday, and this wasn't going to be a 5-minute quick answer. :slight_smile:

First problem, the input T1 (PD6) on the Mega2560 isn't connected to the pins on the edge by the looks of the schematic.

So I'm going to have to choose another timer for the input. Bear with me a bit.

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

Nick,

You are a gentleman, and a SCHOLAR, especially when it comes to mastering the Arduino Timers...I think you should write a book :slight_smile:

Thank you very much for looking into this....I will test it this evening and report the findings....

All the best!

BINGO!!!

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!! :slight_smile:

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ì