Level Up Your Arduino Code: Timer Interrupts

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] welcome back to leveling up your Arduino code or leveling it down however you want to see it this time we're gonna talk about timer interrupts if you're not familiar with writing directly to registers or how interrupts work in general I recommend watching the previous two episodes microcontroller timers are like kitchen timers they continue to count while you're off doing other things like prepping a salad or explaining how interrupts work when they go off you need to stop what you're doing and go get that casserole out of the oven before it burns excuse me if we look at the various interrupt vectors available to us in the 18 mega 328p we see that there are three different timers labeled timer zero timer 1 and timer to scroll down to the register map and we see that each timer lives in memory as a special function register timer 0 is TC NT 0 which stands for timer counter 0 timer 1 is TC NT 1 and notice that it takes up 2 bytes in memory finally timer 2 is TC NT 2 let's see how these timers get automatically incremented without any code each of these 3 timers can be directly or indirectly connected to the system clock this system clock is a square wave that is produced internally in the microcontroller based on your settings it could be generated inside the microcontroller itself or from a connected oscillator or crystal the system clock is vital to the operation of almost everything in the microcontroller the Arduino Uno for example has a 16 megahertz crystal connected to the microcontroller the 328p generates a 16 megahertz square wave from this which is used to feed many functions including our timer's the timers can be connected directly to the system clock which means the value in the timer register increments once every 60 2.5 nanoseconds which we get by dividing 1 over 16 megahertz the system clock is also fed into another piece of hardware known as a pre scalar the pre scalar divides the clock by producing a pulse every eight system clock cycles or every 16 clock cycles however we define the prescaler let's say that we don't have a pre scaler set every time the system clock pulse is high each of our timers increment by one will be focusing on timer one in this example let's say we set the prescaler to eight now timer one increments only once every eight system clock pulses as you can see we can play with these pre scalar values to adjust how fast each of our timers counts now the question is what do we do with these counting timers timer zero and timer two are both eight bits each which means they count from zero to 255 note that once a timer reaches its maximum value it starts over again from zero timer one however takes up two registers in memory so it's actually 16 bits meaning it can count from 0 to 65,535 before rolling over each timer can generate one or more interrupts we can write a value in another register so that when one of the timer's equals that value it throws an interrupt this is known as a compare match interrupts and all of the timers can make this interrupts happen similarly we can tell the processor to generate an interrupt when each of the timer's overflows which means rolls over from its max value to zero finally timer 1 can be configured to store its current count to another register whenever an external event happens on a pin this is known as input capture if you are working in Arduino note that several functions rely on timers to operate so if you begin playing with timer 0 the delay Milly's and micros functions will no longer work properly the same applies to the servo and tone functions for timers 1 and 2 the analog write function uses all three timers in the uno but which timer depends on which pin you're using for example if you want to manually control timer 1 for other things you probably shouldn't use analog right on pins 9 and 10 let's see how these different interrupts might be generated using timer 1 as example as we run our program and time progresses we'll see the value in timer one continually increasing at each system clock pulse or at a pulse from the prescaler one thing that happens is each time timer one is incremented its value is compared to the value in the output compare registers for example we might have 65,000 531 stored in the OCR 1a register when timer one's value equals that number a compare match interrupt is generated in this case the interrupt source would be timer 1 comp a next every time the timer one counter goes from its max value to zero an overflow interrupt is generated which is known as the timer one OVF source finally if we have the input capture set up for timer 1 whenever a logic level change occurs on a specific pin such as the ICP 1 pin in this example which is port B pin 0 an input capture interrupt is generated at the same time the value of the timer 1 counter is stored in the ICR 1 register so you can refer to it later if you want to see exactly when that event occurred compare and overflow interrupts are useful if you want to say toggle a pin or read from a sensor at precise regular intervals capture interrupts are great if you need to measure the time between pulses or measure the frequency of an unknown signal to see how to set up timer interrupts let's look at an example that is the classic blinky program to do that you will need an Arduino with an 80 mega 328p such as the uno or red board will be using pin 13 this time as it's already connected to an onboard LED notice that Arduino pin 13 is actually port B pin 5 on the 328p we'll start with this simple example here we set pin 13 as an output and tell it to go to 5 volts wait 500 milliseconds go to 0 volts and wait another 500 milliseconds if we run this we see that it has the effect of blinking the LED at a 1 Hertz rate first up let's change this to be direct register rights instead of pin 13 we'll use P b5 this is another unique number that's defined by the AVR library's PB 5 refers to bit 5 so we can use it when we're dealing with the data direction and port registers delete pin mode and change it to DDR be vertical bar equals 1 left shift led pin notice that we're using de RB here we're using port B instead of port D like last time delete everything in loop and write port B caret equals 1 left shift led pin followed by delay 500 this flips bit 5 in the port B register which turns the LED from on to off or vice versa the processor then does nothing for 0.5 seconds before flipping the bit again run this again and you'll see that the LED blinks the same way take a look at your 328p datasheet will use timer 1 as it can count the highest and it's not used by delay in Milly's in arduino go to the register description section under TC 1 we don't need the TCC r1 a register for what we're doing but we will need to reset all of its bit values to 0 as arduino has a habit of setting these by default for the analog write functions note that you can set up output compare pins which allow you to toggle pins without calling anything in code this can be useful for things like pulse width modulation and it's how analog write works in Arduino we won't cover that here though scroll down and take a look at TCC r1b we don't need the input capture or waveform generation mode bits but we do need to be concerned with the prescaler select this notice that we can disable the prescaler or set it to eight 64 256 or 1024 to divide the clock what we'll be doing is setting the timer 1 counter to 0 and letting it count up from there we'll also set the output compare register 1a to some value that's less than the timer 1 max value of 65 5 35 when timer 1 reaches this value a compare a interrupts is generated and will execute our interrupt service routine in the ISR will reset the timer one value to zero and toggle our led timer one will continue counting up and when it reaches the value in our compare register again another interrupts will trigger we just repeat this process forever to get a blinking LED ideally we want the time between compare interrupts to be 500 milliseconds so we need to find which value to load into the output compare registers to make the time between interrupts be 500 milliseconds to do that we need to do a little map we know that the time it takes for one cycle of the clock with no prescaler is 1 divided by the frequency or 16 megahertz this means the period is 62.5 nanoseconds with a prescaler we divide the clock speed or multiply the period for example with a prescaler of 8 we see that the timer will now increment every 500 nanoseconds we want to see how many timer counts is needed to get to 0.5 seconds with no prescaler we can divide 0.5 seconds by 1 over 16 megahertz to get 8 million counts well eight million won't fit in our 16-bit counter as that can only store up to about 65,000 okay what about a pre scalar of 8 well we can multiply 0.5 seconds by 16 megahertz and divide that result by the prescaler to get the number of timer counts it'll take for a pre scalar of 8 we see that it'll take about 1 million still too much let's check the other available pre scalar values of 64 256 and 1024 125,000 is still too much and 7800 12.5 isn't a whole number which means the timing will be slightly off that gives us a pre scalar of 256 which will take 30 1250 timer 1 counts to give us point 5 seconds perfect so we'll load this value into the output compare register and whenever timer 1 reaches it an interrupt will happen so now we know that we need to set the CS 1 0 1 1 and 1 2 bits to binary one zero zero to select a 256 prescaler keep scrolling down we don't need to worry about TCC r1c because timer one is 16 bits it actually takes up two registers so the lower eight bits and upper eight bits are in separate registers lucky for us the AVR libraries help us out and we can just write a single value to TC NT one instead of having to worry about the upper and lower bytes we don't need the input capture registers but we do need to write our target number into the output compare registers on every timer one increment its value is compared to the OCR 1a and OCR 1b registers if the values are equal to either one of those then an interrupt is generated keep scrolling down until you find the timer counter one interrupt mask register these bits control the individual interrupt enables for the various functions associated with timer one we just need to set the output compare a match interrupt enable bit back in our code let's create some constant variables to hold our initial timer value and our calculated compare match value right Const you int 16 T t1 load equals 0 then write Const you int 16 T t1 comp equals 30 1250 which is our compare value we make it an unsigned integer with 16 bits as that constant is too big for a single byte in setup after we set our LED pin as output right TCC r1 a equals 0 to reset the timer 1 control register a to its default value under that right TCC r1 b vertical bar equals 1 left shift C s12 then TCC r1 b ampersand equals tilde open parenthesis 1 left shift c s1 1 close parenthesis and TCC r1 b ampersand equals tilde open parenthesis 1 left shift cs10 close parenthesis these set the cs bits to binary 1 z zero to select a preschooler of 256 right TC n t1 equals t1 load to load the actual timer with zero under that right OC r1a equals t1 comp to store our match value into the output compare one a register then T IMS k1 equals one left shift OCIE one a to set the output compare interrupt enable bit for timer 1 compare match a finally right sei to enable global interrupts delete our port B bit flip in loop leaving the delay 500 to pretend the processor is doing something important under loop right is our open parenthesis timer 1 comp a Veck close parenthesis open curly brace to create our interrupt service routine for the timer 1 compare match a vector in that right TC and t1 equals t1 load to reset timer 1 to 0 then port B caret equals 1 left shift led pin to toggle our led and with a curly brace and upload this code not surprisingly our little LED continues to blink at the same rate just to show you that we really are blinking at a rate of 1 Hertz I've set up this oscilloscope and as you can see it's about 1 second measured from 1 rising edge to the next using timer interrupts are great for when you need to run pieces of code at exact intervals we can make this even slightly more efficient by using the clear timer on compare mode all this does is tell the hardware to automatically reset the timer back to zero whenever a compare match interrupt happens I know we skipped the TCC r1 a register initially but let's go back to it in the datasheet scroll down to the waveform generation mode table there are many fun ways to control how the timers interact with pins but we want mode 4 if you look at this row you see CTC which means that the timer is reset to zero when ever it reaches the top in this case the top is set at whatever value is in the OCR one a register our compare match value to use this mode we need to write a 1 to the wgm 1/2 bit funny enough the wgm 1/2 bit is actually in the TCC r1v register so we just need to update it there in our code just before we set the prescaler right TCC r1b ampersand equals tilde open parenthesis 1 left shift wgm 1 3 close parenthesis to make sure it's cleared and right TCC r1b vertical bar equals 1 left shift wgm 1 2 to set the wgm 1/2 bit in our is our delete the line where we reset t cnt1 let's run this code sure enough we are still blinking at a 1 Hertz rate using CTC mode only saves you 1 instruction but when you need to make your is ours as short as possible every instruction counts there are many more ways to use the interrupts that we didn't cover here like input capture or overflow if you want to see more fun videos like this make sure you subscribe to our Channel good luck and happy hacking we can make dicks we can make and we connect this know that was T similarly don't make this word bother me again since between two points and when two trains connect in Cincinnati how fast are they going awkward pauses thumb thumb as a real word that wasn't right by the way no one second measured form
Info
Channel: SparkFun Electronics
Views: 169,379
Rating: 4.9346991 out of 5
Keywords:
Id: 2kr5A350H7E
Channel Id: undefined
Length: 17min 22sec (1042 seconds)
Published: Mon Feb 19 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.