Pages: [1]   Go Down
Author Topic: Arduino-tiny UserTimer example  (Read 951 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 1
Posts: 1
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've been learning about and playing with AVR timers, and I found a number of great references and tutorials. Here's one that taught me a lot:

http://maxembedded.com/category/microcontrollers-2/atmel-avr/avr-timers-atmel-avr/

I have been using the arduino-tiny core (http://code.google.com/p/arduino-tiny/ -- thank you so much Coding Badly!) with an ATTiny85, and I found the UserTimer headers. These create a nice abstraction from which timer is appropriate for which chip, simplify code readability, etc. There are some posts that mention it in conjunction with PWM, but I wanted to use the "Clear Timer on Compare (CTC)" mode and Interrupts, so I put together the following simple example.

I hope this can help others, and perhaps we can get corrections and expansions in this thread.

Code:
/*
Classic one-second 'blink' example
 Using an ATTiny85 running the "arduino-tiny" core
 UserTimer function with CTC & Interrupts
 1MHz clock w/prescale of 1024, 244 ticks = .249856 seconds
 so 4 iterations is fairly close to one second
 */

#include <UserTimer.h>

#define LEDPIN 0
#define QUARTER_SECOND_TICKS 244

// To work in an interrupt, it needs to be global and volatile
volatile uint8_t i = 0;

void setup()
{
  pinMode(LEDPIN, OUTPUT);
  // Initialize UserTimer
  cli(); // Disable global interrupts
  UserTimer_SetToPowerup(); // Reset all timer stuff
  UserTimer_SetOutputCompareMatchAndClear( QUARTER_SECOND_TICKS ); // Set compare match value
  UserTimer_SetWaveformGenerationMode( UserTimer_(CTC_OCR) ); // Clear Timer on Compare
  UserTimer_ClockSelect( UserTimer_(Prescale_Value_1024) ); // Set prescaler to 1024
  UserTimer_EnableOutputCompareInterruptA(); // Enable timer compare interrupt
  sei(); // Enable global interrupts
}

void loop()
{
  // Do whatever is needed here
}

/* The Interrupt Service Routine
 When the timer/counter hits the 'match' value this interrupt code
 executes (essentially) immediately. This could be anything, but don't
 take too long because (almost) everything else stops.
 */
ISR(USERTIMER_COMPA_vect)
{
  if (i++ >=3) {
    digitalWrite(LEDPIN, !digitalRead(LEDPIN));
    i=0;
  }
}

There are some other interesting things in the UserTimer functionality like Overflows and using the current timer/counter value. I'm also interested in the various sleep functions. (Perhaps in a similar "veneer"?) I'll add those examples as I cobble them together.
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 209
Posts: 13016
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
thank you so much Coding Badly!

You are welcome.  I'm glad you like it.

Quote
...perhaps we can get corrections and expansions in this thread.

Not really either ... let's call them "notes" ...

If you call UserTimer_ClockSelect last, disabling interrupts is not necessary.  UserTimer_SetToPowerup shuts off the timer and it is not restarted until UserTimer_ClockSelect is called.

Things like UserTimer_(CTC_OCR) and UserTimer_(Prescale_Value_1024) were meant to be UserTimer_CTC_OCR and UserTimer_Prescale_Value_1024.  I got tired of creating the macros and decided to finish them if there was ever enough interest in the veneers.

I kept the veneer idea for version 2 but I'm using (static) classes instead of macros.  The syntax is very similar (tcToneTimer::ClockSelect instead of ToneTimer_ClockSelect).  It eliminates the need to create all those macros and the syntax can be made more Arduino-like (create and use one instance the same way Serial is handled).

Now that I know someone is actually using the veneers I'll continue maintaining "UserTimer".
Logged

Bagshot, UK
Offline Offline
Full Member
***
Karma: 1
Posts: 114
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi guys, just wanted to say thanks for the simple example (and for the veneer in the first place Coding Badly!)

I am working on getting the correct values for an 8MHz clock speed so trying to learn as I go!

Cheers.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

the keyword volatile caused me a lot of troubles and removing it was the only solution.
As far as I know, the keyword makes the variable used directly in registers instead of RAM.
I was using KnockBang serial and whenever I try to print the variable the mcu hangs. even without printing the variable it caused a lot of instabilities. I removed that darn keyword and everything works just fine smiley

Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 308
Posts: 26472
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
As far as I know, the keyword makes the variable used directly in registers instead of RAM.
Usually, it's pretty much the opposite of that - the volatile keyword prompts the compiler to load the variable from RAM (a relatively expensive operation) each time it is referenced, instead of optimising it, and loading it once into a register and leaving it there.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Exactly, thank for the correction.
I just wanted to pointout that if you got a lot of bugs while using that keyword and UserTimer then removing it might be a solution, at least in my case.
Logged

Valencia, Spain
Offline Offline
Faraday Member
**
Karma: 150
Posts: 5635
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Exactly, thank for the correction.
I just wanted to pointout that if you got a lot of bugs while using that keyword and UserTimer then removing it might be a solution, at least in my case.

Nope.

I can't think of a single situation where removing 'volatile' would fix a bug, but it can cause plenty (and of the worst sort...)

More likely your "cure" was really that you're running out of RAM and changing the code changed the amount of RAM being used (or something like that). If it was in some print() statements then you probably need to read the section "Using Flash Memory for string storage" on this page: http://playground.arduino.cc/Main/Printf

PS: Please don't post voodoo code fixes. These forums stick around a long time and other people read what you post.
Logged

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

printing the value of the timer freezes the program.
removing that keyword made it work normally again and prints a correct value of the counter, how is that vodoo fixing? what is your better non-vodoo fix for this problem?
Even if the cause is low memory then this is a fix until someone hopefully fixes the real cause that prevent freezing the program when trying to print the volatile timer counter.
if this still difficult to accept then consider this: Someone is using the UserTimer, using Attiny45 and needs to debug the value of the counter. He or she can not because of this bug?? but removing the volatile keyword from the timer counter made everything working again.
Also I was hoping to see some explanation why is the volatile a must and why removing it is will brings other problems.
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 308
Posts: 26472
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Also I was hoping to see some explanation why is the volatile a must and why removing it is will brings other problems
We (well, I was - I guess I can't speak for everyone else) were hoping to see some justification (source code,preferably) for your claim.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 209
Posts: 13016
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I just wanted to pointout that if you got a lot of bugs while using that keyword and UserTimer then removing it might be a solution, at least in my case.

Specious reasoning.  Let's try something different...

UserTimer is a thin veneer over the timer.  There is essentially no difference between using it and accessing the registers directly.  It is syntax candy.  That leaves four possibilities...

1. There is a bug in UserTimer.  However, the symptoms you have described would not be characteristic of that kind of bug.  In addition, there are thousands of folks using UserTimer without problems.  A strong indication that this is not the case.

2. There is a problem with the hardware.  AVR processors are robust and have very few errata.  In addition, there are millions of folks using ATtiny processors without problems.  A strong indication that this is not the case.

3. The code presented in the original post is flawed.  That seems unlikely because two people (E. Cardinal and Easty) are both pleased with it.

Which leaves just one possibility...

4. You have a bug in your sketch.

If you would like help with your bug post your sketch.
Logged

Pages: [1]   Go Up
Jump to: