Arduino Timer
Arduino UNO (ATmega328p) has three 8bit timers
[INDENT]Timer0 - used for millis() micros() delay()… and is on pin 5, 6
Timer1 - 16bit timer is on pin 9, 10
Timer2 - 8bit timer is on pin 3, 11[/INDENT]
Arduino Mega has six 8bit timers
[INDENT]Timer0 - millis, micros… and is on pin 4, 13
Timer1 - is on pin 11, 12
Timer2 - is on pin 9, 10
Timer3 - is on pin 2, 3, 5
Timer4 - is on pin 6, 7, 8
Timer5 - is on pin 46, 45, 44[/INDENT]
Note: Don’t mess with Timer0 since we need to use millis() or micros() for measuring time
Software timer interrupt service routine
Arduino UNO cannot do complex timer like a computer can. It heavily depends on frequency oscillator, ie 16MHz. Then we have divisor to scale down main clock and then 8bit counter to help with the PWM or Timer.
There are 3 vectors for each timer that we can use to set up 3 ISRs
ISR(TIMER2_COMPA_vect){}
ISR(TIMER2_COMPB_vect){}
ISR(TIMER2_OVF_vect){}
Setup Overflow vector ISR to use it like a timer in PC
void setup() {
TIMSK2 = (TIMSK2 & 0b11111110) | 0b00000001; // set only TOIE bit for overflow vector
// Fast PWM without reset TCNT2 : WGM02, WGM01, WGM00 = 0,1,1
// default is Phase-correct PWM with WGM: 0,0,1
// TCNT2 will be reset, when it matchs OCR2A, if WGM02 is set to 1
TCCR2A = (TCCR2A & 0b11111100) | 0b00000011; // set WGM00, WGM01 to 1: xxxxxx11
TCCR2B = (TCCR2B & 0b11110111) | 0b00000000; // set WGM02 to 0: xxxx0xxx
// note : prescale bits may be different between timers,
// divisor = 64, for Timer2 = xxxxx100, for Timer0 = xxxxx011
TCCR2B = (TCCR2B & 0b11111000) | 0b00000100; // 3 bits CS2 = xxxxx100 which is divisor 64
// ISR(TIMER2_OVF_vect) will run every 1ms
// overflow time = (1/16M)*(2^8)*divisor = 256*64/16000000 = 0.001024s or aprox 1ms
// overflow time = 2 * (1/16M)*(2^8)*divisor for Phase-correct PWM
}
ISR(TIMER2_OVF_vect){
//do something
}
void loop() {
}
Or we can use COMPARE VECTOR A and B which is compare to value of OCR2A , OCR2B
void setup() {
TIMSK2 = (TIMSK2 & 0b11111000) | 0b00000110; // use TIMER2_COMPA_vect, TIMER2_COMPB_vect
TCCR2B = (TCCR2B & 0b11111000) | 0b00000100; // prescale 64
// each period is approx 2ms for default mode phase-correct PWM
OCR2A = 192; // compare value A
OCR2B = 168; // compare value B
}
void loop() {
}
//when TCNT2 == OCR2A
ISR(TIMER2_COMPA_vect){}
//when TCNT2 == OCR2B
ISR(TIMER2_COMPB_vect){}
The only problem in phase-correct PWM (by default), the counter, e.g. TCNT2, goes from 0 to 255 and goes back from 255 to 0 then it overflows. So that each TIMER2_COMPA_vect and TIMER2_COMPB_vect happens twice when it is in Phase-correct PWM (default) but TIMER2_OVF_vect happens only once.
Anyway, we can set the value of counter TCNT2 manually to *mess* up time and thus changing timer or frequency, depends on what you want. But it is kinda messed up. You know, its hard to predict *butterfly*, if you’re watching too much movies about time travelling.
Read datasheet of atmega328 to know how to set bits for TCCR2A, TCCR2B or TIMSK2 and so forth.
Arduino PWM
Arduino UNO (ATmega328p) has six 8bit PWMs (on 3 timers: timer0 - timer2)
// For Arduino using ATmega8, 168 or 328* (m8, m168, m328, m238p)
// Phase-corrected PWM by default
// B00000xxx - 3 last bits (least significant bit or LSB) decide the divisor of the timer
// Frequency = 16Mhz / (256 * divisor)
// Example: divisor = 1, frequency = 16Mhz / (256) = 62.5Khz,
//----- PWM frequency for D5 & D6 -----
//Timer0 divisor = 1, 8, 64, 256, 1024
//TCCR0B = TCCR0B & B11111000 | B00000001; // 62.5KHz
//TCCR0B = TCCR0B & B11111000 | B00000010; // 7.8KHz
TCCR0B = TCCR0B & B11111000 | B00000011; // 976Hz (default)
//TCCR0B = TCCR0B & B11111000 | B00000100; // 244Hz
//TCCR0B = TCCR0B & B11111000 | B00000101; // 61Hz
//----- PWM frequency for D9 & D10 -----
//Timer1 divisor = 2, 16, 128, 512, 2048
//TCCR1B = TCCR1B & B11111000 | B00000001; // 31KHz
//TCCR1B = TCCR1B & B11111000 | B00000010; // 3.9KHz
TCCR1B = TCCR1B & B11111000 | B00000011; // 490Hz (default)
//TCCR1B = TCCR1B & B11111000 | B00000100; // 122.5Hz
//TCCR1B = TCCR1B & B11111000 | B00000101; // 30.6Hz
//----- PWM frequency for D3 & D11 -----
//Timer2 divisor = 2, 16, 64, 128, 512, 2048
//TCCR2B = TCCR2B & B11111000 | B00000001; // 31KHz
//TCCR2B = TCCR2B & B11111000 | B00000010; // 3.9KHz
//TCCR2B = TCCR2B & B11111000 | B00000011; // 980Hz
TCCR2B = TCCR2B & B11111000 | B00000100; // 490Hz (default)
//TCCR2B = TCCR2B & B11111000 | B00000101; // 245Hz
//TCCR2B = TCCR2B & B11111000 | B00000110; // 122.5Hz
//TCCR2B = TCCR2B & B11111000 | B00000111; // 30.6Hz
Arduino Mega (ATmega2560) has fifteen 8bit PWMs (on six timers: timer0 - timer5)
//For Arduino using ATmega2560* (m1280, m1281, m2560, m2561)
// Phase-corrected PWM by default
// B00000xxx - 3 LSBs decide the divisor of the timer
// Frequency = 16Mhz / (256 * divisor)
// Example: divisor = 1, frequency = 16Mhz / (256) = 62.5Khz
//----- PWM frequency for D4 & D13 ------------------------------
//Timer0 divisor = 1, 8, 64, 256, 1024
//TCCR0B = TCCR0B & B11111000 | B00000001; // 62.5KHz
//TCCR0B = TCCR0B & B11111000 | B00000010; // 7.8KHz
TCCR0B = TCCR0B & B11111000 | B00000011; // 976Hz (default)
//TCCR0B = TCCR0B & B11111000 | B00000100; // 244Hz
//TCCR0B = TCCR0B & B11111000 | B00000101; // 61Hz
//----- PWM frequency for D11 & D12 -----------------------------
//Timer1 divisor = 1, 8, 64, 256, 1024
//TCCR1B = TCCR1B & B11111000 | B00000001; // 31KHz
//TCCR1B = TCCR1B & B11111000 | B00000010; // 3.9KHz
TCCR1B = TCCR1B & B11111000 | B00000011; // 490Hz
//TCCR1B = TCCR1B & B11111000 | B00000100; // 122.5Hz
//TCCR1B = TCCR1B & B11111000 | B00000101; // 30.6Hz
//----- PWM frequency for D9 & D10 ------------------------------
//Timer2 divisor = 2, 16, 64, 128, 256, 512, 2048
//TCCR2B = TCCR2B & B11111000 | B00000001; // 31KHz
//TCCR2B = TCCR2B & B11111000 | B00000010; // 3.9KHz
//TCCR2B = TCCR2B & B11111000 | B00000011; // 980Hz
TCCR2B = TCCR2B & B11111000 | B00000100; // 490Hz
//TCCR2B = TCCR2B & B11111000 | B00000101; // 245Hz
//TCCR2B = TCCR2B & B11111000 | B00000110; // 122.5Hz
//TCCR2B = TCCR2B & B11111000 | B00000111; // 30.6Hz
//----- PWM frequency for D2, D3 & D5 ---------------------------
//Timer3 divisor = 2, 16, 128, 512, 2048
//TCCR3B = TCCR3B & B11111000 | B00000001; // 31KHz
//TCCR3B = TCCR3B & B11111000 | B00000010; // 3.9KHz
TCCR3B = TCCR3B & B11111000 | B00000011; // 490Hz
//TCCR3B = TCCR3B & B11111000 | B00000100; // 122.5Hz
//TCCR3B = TCCR3B & B11111000 | B00000101; // 30.6Hz
//----- PWM frequency for D6, D7 & D8 ---------------------------
//Timer4 divisor = 2, 16, 128, 512, 2048
//TCCR4B = TCCR4B & B11111000 | B00000001; // 31KHz
//TCCR4B = TCCR4B & B11111000 | B00000010; // 3.9KHz
TCCR4B = TCCR4B & B11111000 | B00000011; // 490Hz
//TCCR4B = TCCR4B & B11111000 | B00000100; // 122.5Hz
//TCCR4B = TCCR4B & B11111000 | B00000101; // 30.6Hz
//----- PWM frequency for D44, D45 & D46 ------------------------
//Timer5 divisor = 2, 16, 128, 512, 2048
//TCCR5B = TCCR5B & B11111000 | B00000001; // 31KHz
//TCCR5B = TCCR5B & B11111000 | B00000010; // 3.9KHz
TCCR5B = TCCR5B & B11111000 | B00000011; // 490Hz
//TCCR5B = TCCR5B & B11111000 | B00000100; // 122.5Hz
//TCCR5B = TCCR5B & B11111000 | B00000101; // 30.6Hz
Above are settings for Phase-corrected PWM (by arduino default).
analogWrite(PWMpin, value);
Default frequencies of analogWrite():
[INDENT]Arduino Pins 5 and 6: 976Hz
Arduino Pins 9, 10, 11, and 3: 490Hz[/INDENT]
Too low for switch mode power supply (buck converter) and generate audible noise when use for motor or brushless fan (audible tone around 490Hz).
One trick is use the commands above (eg: TCCR1B = TCCR1B & B11111000 | B00000011;) after calling analogWrite() to change the default frequency.
You can double the frequency if we switch to fast PWM.
TCCR2A = (TCCR2A & 0b11111100) | 0b00000011; // set WGM00, WGM01 to 1: xxxxxx11 for fast PWM
Otherwise, a custom analog output function should be used instead.
The input value (stored in OCRnA or OCRnB for first and second PWM pin) is compared against the value in an 8bit counter (0-255 and wrap around in register TCNTn).
[INDENT]If value <= counter, output HIGH
If value > counter, output LOW[/INDENT]
In Phase-correct PWM mode
+----+ +----+
| | | |
| | | |
| | | |
+ +------------++------------+ +
0 value 255/255 value 0
OR
-----+ +-----
| |
| |
| |
+--------------------------+
0 value 255/255 value 0
In Fast PWM mode
+-------+ +-------+
| | | |
| | | |
| | | |
+ +------------+ +------------+
0 value 255/0 value 255