#6 -- More Timer Examples

Bruce Land
2 followers
Oct 16, 2023
http://people.ece.cornell.edu/land/courses/ece4760/labs/f2012/lab1.html
http://people.ece.cornell.edu/land/courses/ece4760/labs/f2012/lab2.html
0:00 Final project questions
8:43 Button state machine code
26:43 Three timer example code
39:53 eeprom description
44:20 Lab 2 description
We still got a couple of minutes yet, but I wanted to pass around one of these target boards
This is an example of a board. This is a built version of the board you can build I
supply the the green circuit board and
I supply all the parts
You build it and you can keep it or I'll take it back if you don't want it
the this year's version instead of having a serial port here as a USB port and
And next year's version will have this end cut off with just a header for either a USB port a serial port or a radio
so
If you wanted to this year, you could cut the end off
but
But these will have enough of these that everybody can build one or two if they want you have to budget it
However, if you build it for the final project the budget cost of this completed is about $15
You don't pay $15. That's how much you have to subtract from your effective budget of $75
by the way, the
If you go over budget on the final project your score
Don't goes down as the square of the amount of money that you are over
So going over 10 cents doesn't matter
Going over $10. It turns out matters quite a lot
So I'll pass this around pass it around the class I
Like I like nonlinear relationships. It encourages certain kinds of behavior
so for instance the there for the final project there's going to be a
bonus I
said everybody
for finishing early
and
Especially the Friday group the slope day group
The 30 people who are going to be there all afternoon on slope day
So if you finish early
You get a score boost which is proportional to the square root of the number of days early
so it's it's it's
It's a fairly large boost for a few days and a fairly small boost for a lot of days
You finish 30 days early. I think it's worth 15 points
30 days early is you finish before you start?
There's one group that's already said they're going to do that
Any questions about lab one so far of the
three lab sessions we've had
Two groups have completely finished and checked out
It's not bad pretty good
Seems a pretty good progress
Again any questions about lab one or homework one
So there's three small topics
That are sort of lingering with respect to lab one before we start lab two
One of them is how do you generate a square wave?
This which is answered in the code example by the way on the on the lab
Another question is how do we use EEPROM exactly which is also answered?
In a demo code on lab one and the third one is how do you write a debounce state machine?
Which as of this morning has a code linked online?
but
Was actually linked online before but I didn't associate it with code with lab one
So which of those three would you like to hear about first?
show of hands
Now wake somebody up sorry EEPROM
square waves
Debounce oh well, okay, it's a clear winner debouncing the EEPROM is actually embarrassingly easy to use
The generating a square wave using timer two is
Also quite easy in fact. It's so easy that that's what's confusing people look at the code and say that can't possibly work
All you need is five lines of code, which is never repeated. It's in the header. It's in the init session section
Before the while one there is no interrupt service routine associated with it
You initialize the timer to make a square wave it makes a square wave forever
Oops, how do you turn it off?
And I know by the way it looks like the homework
What's the easiest way of turning off the square wave if it's a if it's an autonomous timer?
With no software that's generating square wave
Disable the pre-scaler you can set the Z pre-scaler to zero it stops counting
You turn it back on starts counting again. It's absolutely the simplest way
Oh, you can mess you can mess with
the
with the pin
There's three options for the pin set on match clear on match toggle on match
If you set it to toggle on match it produces a square wave if you set it to either clear or set on match
It does not so that would work also
Okay, debounce
Do I need to draw the debounce state machine again the diagram now that was the last thing I did last time I think
so let's now go back to a
version of the code which is very similar to
sketch one
Except that we're going to detect two buttons being pushed
button zero is going to be not debounced button one will be debounced and
Both of the buttons when pushed will increment a counter which is then displayed on the LEDs
So I'm not going to write the interrupt service routine. It's the usual one millisecond interrupt service routine
I'm not going to write main, which is just a
Dispatcher that dispatches three tasks all I'm going to write is the task of that
Absorbs the button push and turns it into an increment and then the two
the two tasks one of which does a
Debounced detect and the other does a non debounce to detect I
do not have a preference on it, but
People have a tendency to push really hard on buttons when they're trying to do it fast and
The board so you have this circuit board like this which is supported by a foot at each end
Button seven is here button zero is here and button three is in the center
Which one do you think breaks the board the fastest when you push hard on it?
Three so the flex on a board goes is what power of the distance from the support
Mechanical engineer
third power
Use seven or zero
Okay, so task one
task one is going to
Notice that a button has been pushed and increment the timer
in increment a counter
So or say if well
Task two and task three are both going to set a flag called push flag
so if push flag
We're going to set push flag together to zero
to
So there so that we get one increment per button push
We're going to then
increment the LED variable and
Then set port
B to not LED
because again the LEDs are active low and
Then we're going to end the if and then we're going to end
the task
so task two then is
going to do a
button detect without
Debounce no debounce and what we're going to do is we're going to
Say if not pin
D is
Equal to 0 X 0 1 that is to say button 0
then
flag equals 1 and
Straightforward and the behavior of
the system
when you push the button is that it will be
Impossible to get exactly one count per button push
so for
task 3
Will be the debounced version which will give you precisely
one count of the
LED every time you push and release the button
We're going to enter task 3
every 30 milliseconds
so it's going to
We're going to get into task 3 every 30 milliseconds. We're getting into task 2 every 30 milliseconds also
But with task 2 unless you happen to exactly hit
The button at the time the task executes
You miss it either miss the event if you have a very very fast finger
Or you get two events or six events
And what we're going to do over here is we're just going to build a big old state machine
Which switches off some variable called push state?
Push states going to have four possible values
Corresponding to the names of the states in the state diet state transition diagram. I did last time which I think was
Release may be pushed pushed may be released
So in the switch statement in the switch statement, then we're going to start with a case of no push or release
and that's a full colon and
In this state so we fall into the into the task every 30 milliseconds
We search for the state if we're in state not pushed
then we we do a
if
pin D
if not pin D is equal to
Equal equals 0 X 0 to
That being button 1 the value of button 1
then
push state
Goes to maybe
else
Where do we go?
In other words, I wouldn't actually have to put an else in here because the state doesn't change
But for symmetry, I'm going to say else
push state
Equals no push, which is probably is the state. It's already in and
Then because of the way
C handles case statements you have to put a break here
Otherwise it falls through to the next case by default
unlike MATLAB, which does exactly the opposite and
Verilog, which does
This does not fall through
Well, so case
the next case in the case statement is
Going to be case maybe push. I
Guess I just called it maybe down there
maybe
full colon and
Then boringly enough if not
pin D equals equals 0 X 0 2
now here we have to
need two statements one is
Push state
equals
What?
We had two successful pushes in a row
therefore we have a valid push and so we're going to go to state push and
We have to set the push flag
else
If it's not pushed
Where do we go?
Where?
Where what's the what's the consensus?
No push
break
case pushed
if
Pin D not pin D is equal to equals 0 X 0 2
push state equals
Pushed we stay in this state else
push state equals
Maybe release
break and then case
May release
if not
pin D equal equal
0 X 0 2
this this phrase here would be a perfect thing to put in a text macro a
Define, but I didn't do that if pin D is equal to 0 X 0 2
push state
Equals oh
We got it. We got a we got a release up here, but now we're back to push
Meaning that the button is still bouncing
So where do we have to go?
Say again
Nope
Go back to pushed
else
Else at this point now. We've gotten two releases in a row
Which means that the button is truly and really?
Released and so we go to
No push
and then we
end
the case statement, and then we end
the
task
You don't need to put a break there because it's the last one so falls through all over symmetry
I often do put a break there
This is only detecting one button oh
Yes, yes, it would fail. Yeah, no no you're quite right
It would fail, and that's probably correct behavior to have it fail
in this case
Right so what that does is to increment the LED variable and then output it so it's counting
So it's a counter and with the debounced version every ten every time you press button one you increment the count
Precisely once
with the undebounced
non-debounced
non-debounced button button zero
every time you push the button you get a count someplace between
zero and
the amount of latency that your
Finger has on the button divided by 30 milliseconds
So the debounce code gives you a way of detecting
Discrete events as push-button pushes or push-button pushes as discrete events
For lab 2 you absolutely have to debounce the entire
Keypad we're going to be using a 16 button keypad
instead of the the
Stk 500 buttons and you have to debounce them because you're going to be switching back and forth between
Functions using the keypad for the digital voltmeter
for this lab you
absolutely have to debounce the release of
the button
Not necessarily the push, but the release
Before you push again
It'll keep counting
Yeah, every 30 milliseconds
like a cell phone or a
Dialer of any sort you you don't want to if you if you're if you hold it down a little bit while you're thinking about
The number you don't want to get six digits all the same
so in this lab
You push once to start the system if you're still pushed two seconds later
You're either cheating or you've gone to sleep
All right, so you do not have to detect the button up
Unless you want so cheating could have two possibilities in this lab either which of which is okay either either alternative of which is okay
One is you push and release and if you push again?
before
the
Random timeout then you've cheated
The other interpretation is you can push and release as many times as you want
Before the random timeout as long as you are released at the moment that the timeout occurs
See the difference
Either one of those is a is okay one of them requires you to debounce the other one does not
Once you've pushed and released to start the process going a second and a half between one second and two seconds later
you're going to
The bells going to go off you have to push the button as fast as you can
That push button that push cannot be debounced because you can't tolerate the 30 millisecond ambiguity
Because you're timing down to the millisecond
The release of that button has to be debounced you have to have released it for at least two 30 millisecond
Intervals in a row before you can press again to send the system back to the ready state
So the only button transition that absolutely has to be debounced is the release after the timing
after after you've timed your
reflexes
anything else
Well, let's talk a little bit about
Just a little bit about square wave generation, then this is it like I said embarrassingly easy
The demo code that I produced the I think it's called timers GCC
Uses timers in three different ways because I wanted to put as much as I could in in one code
So the timer zero does it with the usual one millisecond time base?
timer one is sitting there waiting for a positive transition and
Every positive transition on its input pin it
Records its own value into a register called the capture register, and it throws an interrupt
the interrupt service routine then and goes and reads the capture register and gets a cycle accurate time of
occurrence of the transition
So the timer one is running continuously
very fast
16 times a microsecond
Takes five or six microseconds to get into the interrupt service routine
The error of service routine then looks back and says oh, I know the exact time that occurred because it's frozen in a separate register
So even though there's a software latency to read the the capture register
The capture register has the exact time of the pin transition
frozen in it
Very handy
so if I were to
measure
two transitions in a row I
Could get a time between them or a frequency therefore
Which you'll need for lab two because one of the things I want you to do is build a frequency meter
So you'll have to use timer one in capture mode
to build the frequency meter
but
for this lab
The frequency that's being generated
The square wave which is being generated that is being fed into timer one is being generated by timer two
Timer two is sitting in an autonomous square wave mode
generating a
200 cycle long square wave which is then being measured by timer one and guess what it measures 200 cycles
They actually gave me some faith that it was cycle accurate
It also meant that for purposes of demo
I didn't have to hook up a square wave generator and try and figure out which was more accurate the square wave generator of the
microcontroller
So the square wave generator then
first of all we choose the
we choose the
the half duration
OCR to a
output compare register
Timer to channel a I'm going to set to 99 so a half cycle is a hundred cycles
That's a hundred. That's a hundred. That's a hundred because I'm going to be toggling the I open I
set TC CR
to
be to one
Which is full speed?
That's a pre-scaler divided by one I set
TCC are to a
to
Turn on the
Calm
to a
zero bit and
or that
with the
Wg
M
21 bit
this
This commands the timer
This bit commands the timer to connect its compare register to the output pin
this can turn it connects the timer output the compare register output to the
To an IO pin so it physically makes IO
This one causes the timer to clear on compare match
so
It's going to count up to a compare match. It's going to flip the IO bit from one state to another
It's going to count up to an IO match. It's going to clear itself. It's going to flip the bit. It's going to
Count up to timer match clear itself flip the bit and so on
the only other thing we need to do is
to set
Ddrd the data direction register for
Port D to turn on pin d7 as an output
Why d7
It's the it's the pin
It's the pin the designers decided to connect from timer to to the output
There's no reason
Avr
The architecture we're using
stands for Arnie and Verne's risk machine
it's whatever Arnie and Verne decided to do and
They decided to hook timer to the pin d dot 7 and so that's what you get to do
There's no reason. It's just policy
Once you execute these four commands
Timer to starts to produce a square wave forever
The easiest way to toggle it on and off is
To toggle this between 1 0 1 and 0 turns it on and off
1 is no divide, so it's full speed
So what's 200 cycles? Let's see 200 cycles is
Divide that by 16 that's about
Mmm
There's a 16 millisecond 60 microseconds right 16 microseconds, so
That's what you said that's about 600 kilohertz
800 kilohertz I don't think you'd hear that
So you have to divide you're gonna have to set this to a different number to actually hear it of course
What do you have to set it to?
thousands
billions
20 you can hear 20 kilohertz
Yeah, that's enough to cause the th to come running over and say what's wrong with you
I
Can't hear 20 kilohertz anymore. I can't hear you know old to some televisions produce
15,725 Hertz because that's the high-frequency transformer that generates the high voltage. I can't hear that anymore
In fact I can't hear above about 9 kilohertz unless it's really loud
That's what happens when you listen too much loud music
on your earbuds or
You run a chainsaw for too long
Or you fire a shotgun too many times without earplugs all of which I've done
Not at the same time
You
Know when I was a kid nobody thought about ear protection you you went out, and you'd blast away with a chainsaw. Yeah, yeah
You can't hear so good when you come back or go to the go to the drag races and sit in the pitch
You know and you have these flames shooting six feet out of these v8 engines into your face
you know and your whole body's shaking like this because it's about 180 DB's and
The only ear protection is you put your you put your fingers in your ears
So it doesn't blow your eardrums out when they hit the throttle
Is this and then you wonder why you can't hear the traffic as you're driving home
Well
But it's worse with earbuds because it's constant and the damage is cumulative and it's never repaired
Enough preaching
Any questions on this
Easiest thing to do generate a square wave is of course write four lines of code and listen to what comes out
And tune it that way
Well, you can calculate
within point
0.005 percent
what frequency the
Square wave will be because that's about the accuracy of the crystal about 50 parts per million
any questions
If
So yes, they do sell higher accuracy ones, but to get much higher than 50 parts per million
You have to temperature regulate
so you're one reason that your wrist watch is rather accurate is that your wrist is always about the same temperature and
So and if the crystal is in thermal contact with your wrist, it always stays about 75 or 80 degrees or so
and
You can cut the crystal in a certain way so that it has a negative temperature coefficient below a certain
temperature and a positive temperature coefficient above the temperature or vice versa and
At the temperature you want to operate it has zero temperature coefficient. That's how they cut crystals for watches
So they have a zero temperature coefficient at about 80 degrees
the other way to do it is if you want extremely high accuracy is
You run them really hot
You run them at a temperature which is higher than any reasonable temperature you're gonna get in the environment say 50 C
and you put them in an oven and you keep them hot at that temperature and you let them stabilize for a month and
And then the clock you can get down to a part per million or so
Still not no atomic clock
But it's pretty accurate
You can do that with a with a with a crystal clock
it's it's probably not worth the trouble because you have to mechanically change the crystal and
Radio amateurs found out decades ago that you could modify
Slightly the frequency of a crystal oscillator by putting a set screw against it and torquing it
Pushing physically on the crystal you can bend the resonant frequency
But you don't want to get into that the control system for that's a mess
Okay, we have a little more time
You want to do you want to talk about EE prompt, or do you want to start on lab 2?
Lab 2 EE prompt how many for lab 2?
How many for EE prompt oh?
Man, it's about so almost split
Well, I'll spend 30 seconds to tell you everything. I know about EE prompt
First is
You can define
You don't have to do this. You can just use integers, but I like to define
Constants
Let's say I want to store data in
EE prom position address one I
Can define a constant EE prom data, and then I can do an EE prom later in the program?
Assuming ah assuming that I have included if I do it include of
AVR EE prom dot H
Then I can say EE prom right bite, and I'm doing a bite, so I'm going to
cast this to a
I'm going to cast this to a
bite pointer a
uint 8
star
EE prom data
So I'm going to cast that to the appropriate
pointer to EE prom and
Then write a data in it. Let's say
20
that's the data value and
that will
put a bite into EE prom and
It will be there even after you cycle the power on and off even if you pull the chip out of the board put it
Into another board it'll still be there as
You might guess there's an EE prom
right word
There's also EE prom
read byte
which takes a uint
8 pointer to
ROM
prom
It's a very easy user interface
very easy to do
Anything you want?
That's correct, I was wondering so is
Address one on the uint 16 pointer equal to address one on the bite pointer or two?
In other words it should be two okay, so we're addressing the
That
Would be the consistent way that the that the that the the uint 16 should work
I have to say I haven't tried that to see where the bits actually end up in this case
And did it work
So it might be in four
Yeah, who cares right? Yeah?
And tell you do we can tell you want to write dense stuff it doesn't matter yeah, yeah, I think you're doing it the right way
Or you just define another constant
Are you gonna write an array if you're gonna write an array? Yes, you're gonna increment the inner the pointer
Yeah, yeah
Typically you're only going to be putting a few values in EE prom
There's also some tutorials that are linked up on EE prom which you might want to look at
so for lab 2
For lab 2
we're going to build a
Digital digital multimeter with just three functions. We've got to draw the line somewhere
We could have done a lot more, but three is enough
There's going to be a voltmeter
We're going to have a resistance meter, and we're gonna have frequency
and
Keep things simple here
We're going to make that the voltage that we're going to define that the voltage you need to measure is 0 to 5 volts
That the resistance is going to be oh
perhaps in the 100 ohm to
100 K. Ohm range
So we're not going to get either ridiculously low or ridiculously high although. We could this is a little easier and
the frequency is going to be in the
Perhaps 10 Hertz to
100 K Hertz
region and
We're going to use a bunch of facilities
Excuse me a bunch of the facilities of the microcontroller. We're going to use
We're going to measure voltage. We're going to use an ADC an analog to digital converter
That directly converts a voltage on port a
Port a into a
Number I'm going to ask you to auto range this
It's going to have to be auto ranging
Which means that you're going to need for a lower voltage you're going to need to
Automatically get better sensitivity
either by changing a reference voltage
Internally or by using the internal amplifier, so there's going to be this so the voltage has to be auto ranging
To measure a resistance
Well, how do you measure resistance?
Given that we have a voltmeter
How do we measure a resistance?
Jeremy
Yeah, so we're going to have a current source of some kind
We have a current source
Which in this case is going to be just resistors
hook the output ports and
You're going to auto range the resistance
by choosing which of the resistors happens to be an active output and
which one is
Turned off which outputs are turned off. How do you turn off an input output make it an input?
Then it goes to high impedance
The frequency meter
Well, it would be nice to have that independent of amplitude. It would be nice to be able to
Not use the ADC because if you have some ugly input waveform
Then you have to do all this threshold detection and stuff
But built into the microcontroller chip as you may already know or maybe not is an analog comparator
There's an analog comparator that's quite fast
nanosecond fast and
It is pretty accurate a few millivolts
So we're going to hook up a circuit that compares
the
input to some handy reference value like VCC over 2 and
And
Generates for this ugly input. It's the output of the comparator is going to be a nice clean
square wave
Of course, but transitioning on the zero transitions or the VCC over 2 transitions
So we're going to be using the ADC for voltage
We're going to be using
The analog comparator to produce a square wave from ugly input to make a nice
Easily counted waveform and then we're going to use the timer one capture
Which very nicely can be triggered off of the output of the comparator?
the output of the comparator can trigger the timer one capture and
So we can capture every edge and once we have the positive edges or the negative edges of the waveform
We've got the time of the waveform and therefore the frequency
The period of the waveform and therefore the frequency
Oh
Okay
You cannot set it up as a Schmitt trigger. There's no way to get
The output signal from the comparator is not brought to the outside. So you cannot set it up as a Schmitt trigger
It doesn't have very much hysteresis. And so you could have noise problems
And that will be a limitation here
This will automatically calculate the period as long as it's a as long as it is a cyclic waveform as
Long as it's a cyclic waveform that crosses through VCC over 2
Then as long as periodic then the positive transitions should give you the period
If the waveform is noisy that's going to produce some jitter in the period and therefore some jitter in the frequency
But probably you'll be feeding in waveforms mostly from the signal generator, which will be
beautiful and clean oh
The chip is a
Is not a wonderful arithmetic tip or a DSP chip
But you can you can do an FFT at audio rate on this as long as you write it in integer arithmetic
and
Don't get too careful about scaling the output for optimum accuracy. You can get about a hundred and twenty eight points per
per
per window at 8 kilohertz sample rate
But you'll be able to measure frequency much more accurately by timing the period than by doing FFT
Now I'm going to talk about this a lot more. I'm just giving you the the nosebleed level overview of this right now
so
There's going to be three functions
You're going to be using you need to read up on as soon as possible
you need to read up on the analog digital converter section the
More about I open a little bit about the angle analog comparator
And I want to tell you the piece of the data sheet that describes the 80d converter is the most complicated piece of writing
I have read this side of Umberto echo
It is a mess is really hard at least for me to understand
It was so hard to understand that I couldn't tell if I got it right until I wrote the code
When the code ran I knew I understood it in fact in general. That's the way my brain works
I don't understand stuff until I write the code myself
And
Your brain is probably the same way
so
plow through some of the ADC documentation
But more importantly plow through the examples. I've seen a couple of people who have gone through the example codes very carefully and
By very carefully. I mean they've written more on it than I did
So there's more of their words written in red than I wrote in
Than characters I wrote in
Of source code that's about the level at which you have to read these codes
You can't just say oh yeah
four lines
You really have to take it apart
Why did he set this stupid bit?
Anything else any other questions?
Okay, see a bunch of you in the lab in a few minutes
