Arduino CTC timer interrupt ~2x fast - timer

Afternoon all
I'm looking for some assistance please with something that has been confusing me whilst trying to learn timer interrupts
You'd be best treating me as a novice. I have no specific goal here other than learning something that I think would be useful feather to add to my cap!
I have written the below sketch as a stab at a rigid framework for executing different fcns at different rates. I've done something similar using millis() and whilst that worked I found it inelegant that a) there was no obvious way to check for task overruns and backing-up the execution rate and b) the processor is bunged up by checking millis() every program cycle.*
Essentially what I think should be a 1ms timer interrupt on Timer2 (16MHz/64 prescaler /250 compare register =1000hz) is coming out around 0.5ms. I've been confused for hours on this but I'm prepared to accept it could be something fundamental/basic!
What's also throwing a spanner in the works is that using serial comms to try and debug the faster task rates seems to slow things down considerably, so I'm inferring the problem by counting up 1ms tasks to call 10,100 and 1000ms tasks and debugging at the slower level. I suppose chewing through a few characters at 9600baud probably is quite slow.**
I've pasted the code below. Any pointers highly appreciated. Be as harsh as you like :)
cheers
Al
*Whilst not what I'm confused about - any comments on my logic here also welcome
** Although I don't get how Serial.println manages to slow the program down. It's driven from interrupts so it should surely just drop the comms and perform the next ISR - effectively a task overrun. Any comments here also welcome
//NOTES
//https://www.robotshop.com/letsmakerobots/arduino-101-timers-and-interrupts
//https://sites.google.com/site/qeewiki/books/avr-guide/timers-on-the-atmega328
//http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf
//
//INITIALISE EVERYTHING
const int ledPin = 13;
volatile int nStepTask1ms = 0; // init 0 - to be used for counting number of 1ms tasks run and hence calling 10ms task
volatile int nStepTask10ms = 0;
volatile int nStepTask100ms = 0;
volatile int nStepTask1000ms = 0;
volatile int LEDFlashState = 0; // init 0 - variable to flip when LED on
volatile int millisNew = 0; // to store up to date time
volatile int millisOld = 0; // to store prev time
volatile int millisDelta = 0; // to store deltas
//
void setup()
{
Serial.begin(9600); //set up serial comms back to PC
pinMode(ledPin,OUTPUT); //to flash the embedded LED
noInterrupts(); //turn off interrupts while we set the registers
//set up TIMER first
TCCR2A = 0; //sets TCCR1A byte to zero, bits to be later individually mod'd
TCCR2B = 0; //sets TCCR1B byte to zero, bits to be later individually mod'd
TCNT2 = 0; //ensures counter value starting from zero
Serial.println("Timer1 vars reset");
TCCR2B |= (1<<WGM12); // bitwise or between itself and WGM12. TCCR2B = TCCR2B | 00001000. Sets WGM12 high. (CTC mode so WGM12=1, WGM 13,11,10 all 0) https://stackoverflow.com/questions/141525/what-are-bitwise-shift-bit-shift-operators-and-how-do-they-work
Serial.println("Mode 4 CTC set");
Serial.println("TCCR2B=");
Serial.println(TCCR2B,BIN);
TCCR2B |= (1<<CS11); // sets CS11 high
TCCR2B |= (1<<CS10); // sets CS10 high (i.e. this and above give /64 prescaler)
Serial.println("Prescaler set to 64");
OCR2A = 250; //compare match register for timer2
Serial.println("Compare Register set");
Serial.println("OCR2A=");
Serial.println(OCR2A);
TIMSK2 |= (1 << OCIE2A); //enables interrupts - https://playground2014.wordpress.com/arduino/basics-timer-interrupts/
Serial.println("Interrupt Mask Register Set");
Serial.println("TIMSK2=");
Serial.println(TIMSK2);
interrupts(); //enable interrupts again - not sure if this is required given OCIE1A being set above?
}
//set up ISR for Timer2 - timer structure called every interrump (1ms) that subsequently calls 1,10,100 and 1000msec task fcns
ISR(TIMER2_COMPA_vect)
{
TASK_1ms();
if (nStepTask1ms>9)
{
TASK_10ms();
if (nStepTask10ms>9)
{
TASK_100ms();
if (nStepTask100ms>9)
{
TASK_1000ms();
}
}
}
}
void TASK_1ms()
{
// 1ms tasks here
nStepTask1ms++;
}
void TASK_10ms()
{
//10ms tasks here
nStepTask1ms=0;
nStepTask10ms++;
}
void TASK_100ms()
{
//100ms tasks here
nStepTask10ms=0;
nStepTask100ms++;
//Serial.println(nStepTask100ms);
}
void TASK_1000ms()
{
//1000ms tasks here
nStepTask100ms=0;
//do something
changeLEDFlashState();
//check timing tick of this task
millisNew=millis();
millisDelta=millisNew-millisOld;
Serial.println(millisDelta);
millisOld=millisNew;
nStepTask1000ms++;
}
void changeLEDFlashState()
{
if(LEDFlashState==0)
{
digitalWrite(ledPin,HIGH);
LEDFlashState=1;
//Serial.println("LED Turned On");
}
else
{
digitalWrite(ledPin,LOW);
LEDFlashState=0;
//Serial.println("LED Turned Off");
}
}
void loop()
{
// empty
}

You have two lines here:
TCCR2B |= (1<<CS11); // sets CS11 high
TCCR2B |= (1<<CS10); // sets CS10 high (i.e. this and above give /64 prescaler)
These two lines set the lower three bits of TCCR2B to 011, which is a /32 prescaler.
Note that for Timer1 and Timer2, the prescaler settings are different than Timer0.
For Timer0, the settings above would give you a /64 prescaler.

Related

TIMER1 to measure the delay accurracy in avr atmega328p?

unsigned long slptime=0;
unsigned long wdttime_count = 0;
void timer1_init()
{
//TCNT1=0xFF4E;//16ms
TCNT1=0xFFF5;//1ms
// TCNT1=0xFF9B; //10ms
TIMSK1=0x01;
TCCR1A &= ~(1<<WGM10); // RV09_H, Date: 05-May-2022, set Normal mode operation
TCCR1A &= ~(1<<WGM11);
TCCR1B &= ~(1<<WGM13);
TCCR1B &= ~(1<<WGM12);
TCCR1B |= (1<<CS12) | (1<<CS10); //1024 prescalar; fosc=11059200hz; freq=fosc/1024 = 10800hz; t=0.092ms;
}
void timer1_stop()
{
TCCR1B = 0x00;
TIMSK1 = 0x00;
}
ISR(TIMER1_OVF_vect)
{
//TCNT1=0xFF4E;//16ms
TCNT1=0xFFF5;
//TCNT1=0xFF9B;
wdttime_count=wdttime_count+1;
}
void main()
{
timer1_init();
_delay_ms(250);
timer1_stop();
sendtimediff((wdttime_count*1000)/1080);
}
The timer1 is configured for 1080Hz by counting upto 10 at 10800hz. I was just checking the timer accuracy but the above code return 227ms instead of 250ms.
What I am missing in it? Or _delay_ms() is causing the error?
When you set timer value to 0xFFF5 it increments 11 times before the overflow.
11059200 / 1024 / 11 = 981,8 Hz == 1,0185 ms.
It counts 245 times.
245 * 1000 / 1080 = 227
You probably want to set value to 0xFFF6
There is no need to set the timer in each interrupt. Instead, you can use CTC mode, forcing the timer to count from zero to a value in OCR1A (Mode 4) or ICR1 (Mode 12). E.g.:
void timer1_init()
{
TCNT1=0;
OCR1A = 9; // from 0 to 9 == 10 timer (prescaled) clock cycles
TIMSK1 = (1 << OCIE1A); // Use Output Compare interrupt
TCCR1A &= ~(1<<WGM10); // Set Mode 4 (CTC)
TCCR1A &= ~(1<<WGM11);
TCCR1B &= ~(1<<WGM13);
TCCR1B |= (1<<WGM12);
TCCR1B |= (1<<CS12) | (1<<CS10); //1024 prescalar; fosc=11059200hz; freq=fosc/1024 = 10800hz; t=0.092ms;
}
ISR(TIMER1_COMPA_vect) // use Output Compare A vector, instead of Overflow
{
// No need to reset the timer
wdttime_count=wdttime_count+1;
}
...
Keep in mind that _delay_ms macro just counts CPU cycles, therefore if there are interrupts happened during the delay, the delay can take longer time. _delay_ms and _delay_us macros are generating plain CPU loop, which counts with accuracy up to single CPU clock cycle, but only when the loop itself is not interrupted.
There is no point to compare _delay_ms to timer clocked from the same main clock, as the CPU itself. The comparison result will be always the same, no matter what actual CPU speed is.
Classic bug for free running timers, TCNT1=interval; in the ISR won't work. It needs to be something like:
volatile uint16_t next_TCNT1 = TCNT1;
next_TCNT1 += interval;
TCNT1 = next_TCNT1;
The reason for this is: you have set the interrupt to trigger when the timer compare hits a certain value. That's the point when the timer flag is set, but from the point where that happens until you reach the actual code inside the ISR, a lot of time has passed, interrupt latency. This was particularly nasty on the various old, crap architecture 8-bitters.
So by the time you update the timer counter, it isn't sitting at "interval", but rather at "interval plus interrupt latency plus execution overhead" which means the next interrupt will come much sooner than expected.
By reading the current value inside the ISR and adding the timer interval to it, you compensate for interrupt latency. Now the only real-time delay you have is those few lines inside the ISR, which are likely negligible.

Using Timers for Blink & Count

I'm creating part of a program right now for a personal project. This is my first year ACTUALLY coding and have been studying for hours to understand many concepts so please be nice and try not to be rude as others have...
The project of mine is an AVRDUDE using a chip called ATMEGA328P in a program called Microchip studios.
[This project is having 3 LED count every time a switch is pressed, I should have them count continuously and change to the next number every second using a TIMER 1.
**counting in binary from 0-8 then rolling over **
I need some help on one aspect of it which is using interrupts after I have already created a blinking LED to use a TIMER0 instead of delays.
I have made my fourth LED flash at 5Hz which is the blinking part of my code include below at the end of this question.
Now the problem I am running into is trying to create interrupts for the 3 LEDS count every time a switch is pressed, I should instead have them continually count, changing to the next number approximately every second, using TIMER1.]
This is my code for the project
Again please be nice and at least lead me in some type of direction...
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 1000000UL
int global = 0 ;
volatile uint8_t overflow0; // Variable for counting overflows for first timer
volatile uint8_t overflow1; // Variable for counting overflows for second timer
void FirstTimer() // Initialize Timer 1
{
TCCR0B |= (1<<CS02) | (1<<CS00); // Prescaler of 1024
TCNT0 = 0;
}
void SecondTimer() //Initialize Timer 2
{
TCCR1B |= (1<<CS11) | (1<<CS10);
TCNT1 = 0;
}
int main(void)
{
DDRB |= (1 << DDB0);
FirstTimer(); // Calling timer 1 and 2 initialization
SecondTimer();
while (1)
{
{
if (TCNT0 >= 195) // Amount of ticks needed
{
PORTB ^= (1 << PORTB0); //LED on
TCNT0 = 0; //Reset counter
}
}
{
if (TCNT1 >= 15625) // Ticks needed
{
TCNT1 = 0; // Timer reset
}
}
}
}
An approach you could use is keeping a count variable (unsigned char - assuming 8 bit register width) and in your Timer ISR simply increment the count and write that value to the output register. Once count > 8 set to zero.
Configure the Timer mode to trigger on overflow w/ reset to zero.
Then you do some basic math using the clock speed and timer ceiling (overflow value) to calculate the frequency you want the overflow ISR to occur (increment the LED count values).
Note that for this to work the LEDs need to be on the first 3 pins.
i.e.
P1.0 = LED1
P1.1 = LED2
P1.2 = LED3
...
If not connected like this then you can still make it work with additional bit manipulation (shifts and masks).

Attiny85, microsecond timer implemented on timer0 does not count the correct time

There is Attiny85, with an internal clock source at 8 MHz.
I am trying to implement a microsecond timer based on the hardware timer timer0.
What is my logic:
Since the clock frequency is 8 MHz and the prescaler is off, the time of one clock cycle will be about 0.1us (1/8000000).
Initially, the timer overflows and causes interruptions when passing 0 ... 255, it takes more than 0.1us and is inconvenient for calculating 1μs.
To solve this, I thought about the option to change the initial value of the timer instead of 0 to 245. It turns out that in order to get to the interruption, you need to go through 10 clock cycles, which takes about 1us in time.
I load this code, but the Attiny LED obviously does not switch for about 5 seconds, although the code indicates 1 second (1000000us).
Code:
#include <avr/io.h>
#undef F_CPU
#define F_CPU 8000000UL
#include <avr/interrupt.h>
// Timer0 init
void timer0_Init() {
cli();
//SREG &= ~(1 << 7);
// Enable interrupt for timer0 overflow
TIMSK |= (1 << 1);
// Enabled timer0 (not prescaler) - CS02..CS00 = 001
TCCR0B = 0;
TCCR0B |= (1 << 0);
// Clear timer0 counter
TCNT0 = 245;
sei();
//SREG |= (1 << 7);
}
// timer0 overflow interrupt
// 1us interval logic:
// MCU frequency = 8mHz (8000000Hz), not prescaler
// 1 tick = 1/8000000 = 100ns = 0.1us, counter up++ after 1 tick (0.1us)
// 1us timer = 10 tick's => 245..255
static unsigned long microsecondsTimer;
ISR(TIMER0_OVF_vect) {
microsecondsTimer++;
TCNT0 = 245;
}
// Millis
/*unsigned long timerMillis() {
return microsecondsTimer / 1000;
}*/
void ledBlink() {
static unsigned long blinkTimer;
static int ledState;
// 10000us = 0.01s
// 1000000us = 1s
if(microsecondsTimer - blinkTimer >= 1000000) {
if(!ledState) {
PORTB |= (1 << 3); // HIGH
} else {
PORTB &= ~(1 << 3); // LOW
}
ledState = !ledState;
blinkTimer = microsecondsTimer;
}
}
int main(void)
{
// Set LED pin to OUTPUT mode
DDRB |= (1 << 3);
timer0_Init();
while (1)
{
ledBlink();
}
}
Attiny85 Datasheet
What could be the mistake? I have not yet learned how to work with fuses, so I initially loaded the fuses at 8 MHz through the Arduino IDE, and after that I already downloaded the main code (without changing the fuses) through AVRDUDE and Atmel Studio.
And another question, should I check the maximum value when updating my microsecond counter? I know that in Arduino, the micro and millis counters are reset when they reach the maximum value. For example, if I do not clear the TimerMicrosecond variables variable and it exceeds the size of the unsigned long, will it crash?
As pointed out by #ReAI, your ISR does not have enough time to run. Your ISR will take more than 1 microsecond to execute and return, so you always are missing interrupts.
There are other problems here too. For example, your microsecondsTimer variable is accessed in both the ISR and the foreground and is a long. long variables are 4 bytes wide and so are not updated atomically. It is possible, for example, that your foreground could start reading the value for microsecondsTimer and then in the middle of the read, the ISR could update some of the unread bytes, and then when the foreground starts again it will end up with a mangled value. Also, you should avoid messing with the count register since updating it can miss ticks unless you are very careful.
So how could you implement a working uSec timer? Firstly you'd like to call the ISR as infrequently as possible, so maybe pick the largest prescaller you can get get the resolution that you want and only ISR on overflow. In the case of the ATTINY85 Timer0, you can pick /8 prescaller which gets you one tick of the timer per microsecond with an 8Mhz system clock. Now your ISR only runs once every 256 microseconds and when it runs, it need only increment a "microseconds * 256" counter in each call.
Now to read the current microseconds in the foreground, you can get the number of microseconds mod 256 by directly reading the count register, and then read the "microseconds * 256" counter and multiply this by 256 and add that the counter and you'll have the full count. Note that you will need take special precautions to make sure your reads are atomic. You can do this either by carefully turning off the interrupts, quickly reading the values, and then turning the interrupts back on (save all the math for when interrupts are back on), or looping on the read values to make sure you get two full reads in a row that are the same (time means that have not updated while you were reading them).
Note that you can check out the source code to Arduino timer ISR for some insights, but note that theirs is more complicated because it can handle a wide range of tick speeds whereas you are able to keep things simple by specifically picking a 1us period.
why you didn't use pre-scaler ?!
your code need a relly relly big delay intervall(1 sec it's huge time according to cpu speed) .... so it's not wisdom choose to interrupt microcontroller every 1 us !!.. so it will be great if we could slow down your microcontroller clock and make interrupt for example every 1 ms
calculation
the microcontroller clock speed is 8 mega Hz so if we chose the preScaller to 64 then the timer clock will be 8MHz/64=125 KHz so that mean each tik (timer clock) time will be 1/125KHZ=8 us
so if we like to have inturrpt every 1ms then we need 125 tik
modify code
try this code it's more clear to understand
#undef F_CPU
#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
volatile int millSec;
void timer0_Init();
void toggleLed();
int main(void)
{
// Set LED pin to OUTPUT mode
DDRB |= (1 << 3);
timer0_Init();
millSec = 0; // init the millsecond
sei(); // set Global Interrupt Enable
while (1)
{
if(millSec >= 1000){
// this block of code will run every 1 sec
millSec =0; // start count for the new sec
toggleLed(); // just toggle the led state
}
// Do other backGround jobs
}
}
//#####Helper functions###########
void timer0_Init() {
// Clear timer0 counter
TCNT0 = 130; //255-125=130
// Enable interrupt for timer0 overflow
TIMSK = (1 << 1);
// set prescaler to 64 and start the timer
TCCR0B = (1<<CS00)|(1<<CS01);
}
void toggleLed(){
PORTB ^= (1 << 3); // toggle led output
}
ISR(TIMER0_OVF_vect) {
// this interrupt will happen every 1 ms
millSec++;
// Clear timer0 counter
TCNT0 = 130;
}
Sorry, i am late but i have got some suggestions. If you calculate the Timer0 with prescaler 1, the timer is counting up every 125ns. It is not possible to reach 1 us without a small divergence. But if you use prescaler 8 you reach exactly 1 us. I actually do not have your hardware but give this a try:
#ifndef F_CPU
#define F_CPU 8000000UL
#else
#error "F_CPU already defined"
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
volatile unsigned int microsecondsTimer;
// Interrupt for Timer0 Compare Match A
ISR(TIMER0_COMPA_vect)
{
microsecondsTimer++;
}
// Timer0 init
void timer0_Init()
{
// Timer0:
// - Mode: CTC
// - Prescaler: /8
TCCR0A = (1<<WGM01);
TCCR0B = (1<<CS01);
OCR0A = 1;
TIMSK = (1<<OCIE0A)
sei();
}
void ledBlink() {
static unsigned int blinkTimer;
if(microsecondsTimer >= 1000)
{
microsecondsTimer = 0;
blinkTimer++;
}
if(blinkTimer >= 1000)
{
PORTB ^= (1<<PINB3);
blinkTimer = 0;
}
}
int main(void)
{
// Set LED pin to OUTPUT mode
DDRB |= (1 << PINB3);
timer0_Init();
while (1)
{
ledBlink();
}
}
If you are using internal clock of attiny it may be divied by 8. To disable the clock division you have to disable the prescaler within 4 clock cycles (atomic operation):
int main(void)
{
// Reset clock prescaling
CLKPR = (1<<CLKPR);
CLKPR = 0x00;
// ...
Please try this solution an give feedback if it is working. Maybe you can verify it with an oscilloscope...
Notice that operations with unsigned long needs more than 1 clock cycle to handle on an 8 bit microcontroller. Maybe it would be better to use unsigned int or unsigned char. The main loop also should not contain lots if instructions. Otherwise error correction of microsecond timer has to be implemented.

how can I make multiple ultrasonic sensors work at the same time using atmega32

I am working on an auto-parking car robot and I am using 8 (hc-sr04) ultrasonic sensors (2 at each side) but the problem is that I am using atmega32 which has limited resources only 3 external interrupts and 3 timers (and even if using interrupts somehow works I might run into risk to have two interrupts triggered at the same time).
I am using this sensor : http://ram-e-shop.com/oscmax/catalog/product_info.php?products_id=907
I've tried using digital I/O pins with polling procedure but it didn't work.
here is the code for polling procedure:
unsigned int read_sonar(){
int dist_in_cm = 0;
init_sonar(); // Setup pins and ports
trigger_sonar(); // send a 10us high pulse
while(!(ECHO_PIN & (1<<ECHO_BIT))){ // while echo pin is still low
USART_Message("echo pin low\r\n");
trig_counter++;
uint32_t max_response_time = SONAR_TIMEOUT;
if (trig_counter > max_response_time){ // SONAR_TIMEOUT
return TRIG_ERROR;
}
}
TCNT1=0; // reset timer
TCCR1B |= (1<<CS10); // start 16 bit timer with no prescaler
TIMSK |= (1<<TOIE1); // enable overflow interrupt on timer1
overFlowCounter=0; // reset overflow counter
sei(); // enable global interrupts
while((ECHO_PIN & (1<<ECHO_BIT))){ // while echo pin is still high
USART_Message("echo pin high\r\n");
if (((overFlowCounter*TIMER_MAX)+TCNT1) > SONAR_TIMEOUT){
USART_Message("timeout");
return ECHO_ERROR; // No echo within sonar range
}
};
TCCR1B = 0x00; // stop 16 bit timer with no prescaler
cli(); // disable global interrupts
no_of_ticks = ((overFlowCounter*TIMER_MAX)+TCNT1); // counter count
dist_in_cm = (no_of_ticks/(CONVERT_TO_CM*CYCLES_PER_US)); // distance in cm
return (dist_in_cm );}
This method doesn't work if I want to read all sensors at the same time, because it gets stuck in the loop for a while.
I also tried using freeRTOS to build a task that checks the state of pins like every 1msec but this won't be a time accurate.
any help?
Assuming that You use internal clock which is 8MHz I would try to handle this inside timer overflow interrupt and would use whole port to connect the sensors.
Use Timer in normal mode or CTC mode (which I find quite intuitive) to ensure periodical interrupts. Set the appropriate period. Remember that the clock has pretty low frequency so don't exaggerate (I think that 0,25 ms will fit).
Connect the sensors to one port, e.g. PORTB. This is a nice situation because ATmega32 has 4 ports with pins numbered from 0-7 and you use 8 sensors so the register for the specific port can cover all of the pins and You can use one read to get states of all of the pins.
Implement the logic:
volatile uint8_t sensors_states;
volatile uint8_t read_flag = 0;
ISR(TIMER0_OVF_vect)
{
sensors_states = PORTB;
read_flag = 1;
}
int main()
{
// Initialize peripherals ...
// You must assume on your own how much time could the pin be held
// in the same state. This is important because the number must not
// be bigger than max value for the type of the array
uint8_t states_time[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t prev_sensors_states = PORTB;
while(1)
{
// Wait until the flag will be set in the ISR
if(read_flag)
{
for(uint8_t i = 0, mask = 0x80 ; i < 8 ; i ++, mask >>= 1)
{
states_time[i]++;
// Compare the previous state and present state on each pin
uint8_t state = mask & sensors_states;
if((mask & prev_sensors_states) != state)
{
// Here you can use the state of the pin and the duration of that state.
// Remember that when 'state' is > 0 it means that previous state of the
// pin was '0' and if if 'state' is == 0 then the previous pin state
// was '1' (negation).
do_something_with_pin_change(states_time[i], state);
states_time[i] = 0;
}
}
// Save the previous states of the pins
prev_sensors_states = sensors_states;
// Clear the flag to await next data update
read_flag = 0;
}
}
}
If You will try to use FreeRTOS You could use ulTaskNotifyTake and vTaskNotifyGiveFromISR, instead of using read_flag, to implement a simple mechanism which will notify a task from the interrupt that the port has been read. The processor will go into idle state for a while and you could then invoke a sleep function to minimize power consumption.
I don't know what You want to do with this data so I've invoked do_something_with_pin_change function to indicate the point where You can use the data.
To sum up for this solution You would only use one interrupt and of course 8 pins.

Timer1 on Arduino makes printing on Serial not work

Running the code below, when I send any character to the Arduino from the Serial Monitor, the Arduino does not print "a" back. I think it's something wrong with the timer1 code, but it should work because this code was given to me by my teacher in C class.
void setup() {
Serial.begin(115200);
// http://www.instructables.com/id/Arduino-Timer-Interrupts/?ALLSTEPS
noInterrupts();
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;//initialize counter value to 0
// set compare match register for 1000000hz increments with 8 bits prescaler
OCR1A = 1;// = (16*10^6) / (1000000*8) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS11 bit for 8 prescaler. Each timer has a different bit
// code to each prescaler
TCCR1B |= (1 << CS11);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
interrupts();
}
void loop() {
if (Serial.available()) {
Serial.println("a");
}
}
See also: http://www.instructables.com/id/Arduino-Timer-Interrupts/?ALLSTEPS
Side Note: your code comment about 8 bits prescaler is misleading. It is not an 8-bit prescaler, rather, it is simply a prescaler of 8, meaning the decimal value 8. All that means is the timer's clock tick rate is 8x slower than the main clock, since you divide the main clock frequency by the prescaler to get the timer's clock frequency.
Now for my answer:
The way you set TCCR1A and TCCR1B is all correct.
However, you have 2 major problems, 1 minor problem, and 1 recommendation.
See the 660-pg ATmega328 datasheet pgs. 132~135 for more help & info if you want to know where to look from now on for low-level help.
Update: the new ATmega328 sales page is here: https://www.microchip.com/wwwproducts/en/ATmega328. Its new datasheet is available here: https://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061B.pdf. So, the page numbers I mention above and below will likely no longer quite match since I was using an older version of the datasheet when I wrote this.
Here are the 2 major problems which are completely breaking your code:
Since you are enabling the Timer Compare Match 1A interrupt (TIMSK1 |= (1 << OCIE1A);), you MUST also define the Interrupt Service Routine (ISR) which will be called when this happens, or else you will have run-time (but not compile-time) problems. Namely, if you do not define the ISR for Output Compare Match A, once the Output Compare A interrupt occurs, the processor will get stuck in an infinite, empty, dummy ISR created for you by the compiler, and your main loop will not progress (see code below for proof of this).
Add this to the bottom of your code:
ISR(TIMER1_COMPA_vect)
{
// insert your code here that you want to run every time the counter
// reaches OCR1A
}
It takes a couple microseconds to step into an ISR, and a couple microseconds to step out of an ISR, plus whatever time is required to run your code IN the ISR, you need to use an OCR1A value that is large enough that the ISR even has time to execute, rather than being continually called so quickly that you never exit the ISR (this would lock up your code essentially into an infinite loop....which is happening in your case as well).
I recommend you call an ISR no more often than every 10us. Since you are using CTC mode (Clear Timer on Compare match), with a prescaler of 8, I recommend setting OCR1A to nothing less than 20 or so. OCR1A = 20 would call the ISR every 10us. (A prescaler of 8 means that each Timer1 tick take 0.5us, and so OCR1A = 20 would call the ISR every 20*0.5 = 10us).
If you set OCR1A = 20, and add the ISR code as described above, your code will run just fine.
1 Minor problem:
It is good practice to set OCR1A after you configure the rest of the timer, or else under some situations the timer may not start counting. See "Thorsten's" comment here (emphasis added):
Thorsten said...
Thanks for explaining this matter so extensively! I was looking for a way to generate 1 MHz on one of the Arduino-pins. Your post helped me a great deal to accomplish that.
The reason I am writing this comment is the following: It took me almost 6 hours till I found out (mainly in sheer desperation) that the order of setting the timer control registers TCCR2* and the output compare registers OCR2* seems to matter! If you assign an OCR before setting the corresponding TCCR the timer simply doesn't start counting.
February 13, 2011 at 11:47 AM
So, move OCR1A = 20; to after your last TCCR1B line and before your TIMSK1 line.
1 recommendation:
Get rid of your calls to noInterrupts() and interrupts(). They are not needed here.
Functional code:
Now, here is some functional code I wrote which will better demonstrate what you're trying to do, and what I'm talking about:
/*
timer1-arduino-makes-serial-not-work.ino
- a demo to help out this person here:
http://stackoverflow.com/questions/28880226/timer1-arduino-makes-serial-not-work
By Gabriel Staples
http://electricrcaircraftguy.blogspot.com/
5 March 2015
- using Arduino 1.6.0
*/
// Note: ISR stands for Interrupt Service Routine
// Global variables
volatile unsigned long numISRcalls = 0; // number of times the ISR is called
void setup()
{
Serial.begin(115200);
// http://www.instructables.com/id/Arduino-Timer-Interrupts/?ALLSTEPS
// noInterrupts(); // Not necessary
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; // initialize counter value to 0
// better to put this line AFTER configuring TCCR1A and TCCR1B below, but in
// Arduino 1.6.0 it appears to be ok here (may crash code in older versions),
// see comment by "Thorsten" here:
// http://www.righto.com/2009/07/secrets-of-arduino-pwm.html?showComment=1297626476152#c2692242728647297320
OCR1A = 20;
// SETTING OCR1A TO 1 OR 2 FOR SURE BREAKS THE CODE, as it calls the interrupt
// too often to even allow the main loop to run at all.
// OCR1A = 1;
// turn on CTC mode [Clear Timer on Compare match---to make timer restart at
// OCR1A; see datasheet pg. 133]
TCCR1B |= (1 << WGM12);
// Set CS11 bit for 8 prescaler [0.5us ticks, datasheet pg. 135]. Each timer
// has a different bit code to each prescaler
TCCR1B |= (1 << CS11);
// enable timer compare match 1A interrupt; NOW YOU *MUST* SET UP THE
// CORRESPONDING ISR OR THIS LINE BREAKS THE CODE
// IT IS RECOMMENDED TO SET OCR1A HERE, *after* first configuring both the
// TCCR1A and TCCR1B registers, INSTEAD OF ABOVE! Like this:
// OCR1A = 20;
TIMSK1 |= (1 << OCIE1A);
// interrupts(); // Not necessary
Serial.println("setup done, input a character");
}
void loop()
{
if (Serial.available())
{
// read and throw away the first byte in the incoming serial buffer (or else
// the next line will get called every loop once you send the Arduino a
// single char)
Serial.read();
Serial.println("a");
// also print out how many times OCR1A has been reached by Timer 1's counter
noInterrupts(); // turn off interrupts while reading non-atomic (> 1 byte)
// volatile variables that could be modified by an ISR at
// any time--incl while reading the variable itself.
unsigned long numISRcalls_copy = numISRcalls;
interrupts();
Serial.print("numISRcalls = "); Serial.println(numISRcalls_copy);
}
// Serial.println("test");
// delay(1000);
}
// SINCE YOU ARE ENABLING THE COMPARE MATCH 1A INTERRUPT ABOVE, YOU *MUST*
// INCLUDE THIS CORRESPONDING INTERRUPT SERVICE ROUTINE CODE
ISR(TIMER1_COMPA_vect)
{
// insert your code here that you want to run every time the counter reaches
// OCR1A
numISRcalls++;
}
Run it and see what you think.
Proof that "Major Problem 1" above is real
(at least as far as I understand it--and based on tests on an Arduino Nano, using IDE 1.6.0):
This code below compiles, but will not continue to print the "a" (it may print it once, however). Note that for simplicity-sake I commented out the portion waiting for serial data, and simply told it to print an "a" every half second:
void setup() {
Serial.begin(115200);
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; // initialize counter value to 0
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS11 bit for 8 prescaler. Each timer has a different bit code to each
// prescaler
TCCR1B |= (1 << CS11);
OCR1A = 20;
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
}
void loop() {
//if (Serial.available()) {
// Serial.println("a");
//}
Serial.println("a");
delay(500);
}
// ISR(TIMER1_COMPA_vect)
// {
// // insert your code here that you want to run every time the counter reaches
// // OCR1A
// }
This code below, on the other hand, works, and the "a" will continue to print out. The only difference between this one and the one just above is that this one has the ISR declaration uncommented at the bottom:
void setup() {
Serial.begin(115200);
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; // initialize counter value to 0
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS11 bit for 8 prescaler. Each timer has a different bit code to each
// prescaler
TCCR1B |= (1 << CS11);
OCR1A = 20;
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
}
void loop() {
//if (Serial.available()) {
// Serial.println("a");
//}
Serial.println("a");
delay(500);
}
ISR(TIMER1_COMPA_vect)
{
// insert your code here that you want to run every time the counter reaches
// OCR1A
}
If this answer solves your problem, please upvote it and accept it as the correct answer. Thanks!
Extra Resources:
I keep a running list of the most helpful Arduino resources I come across at the bottom of an article I wrote here: http://electricrcaircraftguy.blogspot.com/2014/01/the-power-of-arduino.html. Check them out.
Especially look at the first links, under the "Advanced" section, by Ken Shirriff and Nick Gammon. They are excellent!
Nick Gammon's answer here
[my answer] Which Arduinos support ATOMIC_BLOCK? And how can I duplicate this concept in C with __attribute__((__cleanup__(func_to_call_when_x_exits_scope))) and in C++ with class constructors and destructors?
[my own Question and answer] C++ decrementing an element of a single-byte (volatile) array is not atomic! WHY? (Also: how do I force atomicity in Atmel AVR mcus/Arduino)
Gabriel Staples is quite correct, the reason you are not seeing the "a" is because you have not provided an ISR handler for the interrupt. Thus, the compiler-generated code jumps back to address 0x0000 and your sketch restarts.
An alternative to providing the "empty" ISR handler is this:
EMPTY_INTERRUPT (TIMER1_COMPA_vect);
With the EMPTY_INTERRUPT handler there I got a response (the "a") with OCR1A as low as 1:
OCR1A = 1;
Although, one has to wonder why you enable interrupts if you aren't planning to do anything with them.
More information about interrupts on the Arduino.
Depending on what the program needs to do with such a fast interrupt, e.g. generating a high-speed clock on an output pin, one can set it in hardware using COM bits in TCCR1A (out of my memory the 4 most significant bits) to toggle the output on a pin associated with the timer without the need to write any ISR() callback to handle the timer interrupt in software.
You wrote this register 2 times:
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS11);
while I think that it could probably be:
TCCR1A |= (1 << WGM12);
TCCR1B |= (1 << CS11);
Probably the only mistake is there, because you forgot to set TCCR1A and you set the other one 2 times.
TCCR1A |= (1 << WGM12); is a bitwise operation (bitwise OR).
In this particular case is setting only one bit of TCCR1A, the one in position WGM12.
TCCR1B |= (1 << CS11); is setting a different bit in position CS11.

Resources