Attiny85: Task scheduling without timers

Hello I'm programming for an ATTiny85 chip. The project i'm working on uses a servo and the 433Mhz wireless modules.

To use the servos i'm using the 8bit servo library from:
http://www.cunningturtle.com/attiny4585-servo-library/

To use the wireless modules i'm using the virtual wire library

My issue now is both Timer0 and Timer1 are being used by these libraries. Before you can use the Millis() function to get a time and use this for task scheduling. However it is my understanding that the Millis library built into the Arduino IDE uses the Timer0 interrupt to update the software time variables.

Any advice on how to schedule without the use of timers? :slight_smile:

My current idea is to use task counters with values on akin to clk_freq/1000 for a task interval of 1 ms. Granted this won't be exact as code execution time will differ greatly every loop.

For example my led heartbeat uses this code. It works but I feel it's a bit clunky

//in header.h
#define CLOCK_SPEED 8000000
#define CLOCK_MS_INTERVAL (CLOCK_SPEED / 10000 + 200)  // 200 is a calibration offset.
#define NOP __asm__ __volatile__ ("nop\n\t")  // alternate form is just("nop")


 //1-status light shows its working
 // blinks ~ every second
 static unsigned long heartbeat_task = 0;
 if (y==1 && heartbeat_task == 0){
   digitalWrite(LED_Pin, HIGH);
   delay(50);
   digitalWrite(LED_Pin, LOW);
   heartbeat_task = CLOCK_MS_INTERVAL * 1000;
 }
 else if (y == 1){ //only decrement if this is a heartbeat function call
  if (heartbeat_task > 0)
    heartbeat_task--;
 }

TL:DR I'm out of clocks, How do I get the time

Find out if mills/micros still work or not, instead of waving your hands around!

Mark

Its not that it does not work. I believe millis reads the current time of the timer then does some magical math in the library to keep track of the time. But since Timer0 is used for one of the libraries as an interrupt, that Timer can get reset at any time thus invalidating what ever time it's keeping track of.

Also the chip tends to crash/freeze around code using the millis function. so ya maybe it doesnt work.
(hard to tell with limited debugging and no serial connection)

Have you considered adding a realtime clock chip. Many of these can deliver an scheduled interrupt back to your program, which could do away with the need for any internal timer.

jrdoner:
Have you considered adding a realtime clock chip. Many of these can deliver an scheduled interrupt back to your program, which could do away with the need for any internal timer.

Thats a good idea. however I already have a board made and all 5 pins are used up already. :frowning: So Good solution if you had spare pins which i dont have..

ts not that it does not work. I believe

It does not matter what you believe or not. This is not politics or some half baked oligy This is engineering. Your job is to find out!

Mark

holmes4:
It does not matter what you believe or not. This is not politics or some half baked oligy This is engineering. Your job is to find out!

Mark

First I;m here in part to find out. That is why I'm taking the time to make this post. Second you dont know my background and third i'm not here to make philosophical debate. I'm simply asking a question. Forth there is a period in that quote that should be looked at. I stated

CyberZoid:
I believe millis reads the current time of the timer then does some magical math in the library to keep track of the time. But since Timer0 is used for one of the libraries as an interrupt, that Timer can get reset at any time thus invalidating what ever time it's keeping track of.

Anywas this is off topic which is how to schedule without Timers or use of the Millis function which is dependent on a timer.

I wonder if the watchdog timer interrupt could be used.

watchdog timer interrupt

Seems like you need something internal to make time ticks that you can count to see how much time is elapsing.
Can you use Timer1 for that with a millis() function revision?
There's no magical math - an interrupt is created when the time tick is up, and a 64-bit counter is incremented. When you call millis(), that count is returned to you.

Take a look here too:
http://forum.arduino.cc/index.php?topic=355719.msg2452054#msg2452054

groundfungus:
I wonder if the watchdog timer interrupt could be used.

Ill have to look into this. tx

CrossRoads:
Seems like you need something internal to make time ticks that you can count to see how much time is elapsing.

Basicaly what im looking for.

CrossRoads:
Can you use Timer1 for that with a millis() function revision?

I could but both libraries want their own timer interrupt vector. So i'm assuming that millis wouldnt work reliably. I could be wrong on this though.

CrossRoads:
There's no magical math - an interrupt is created when the time tick is up, and a 64-bit counter is incremented. When you call millis(), that count is returned to you.

Sry I should of avoided that phrasing. I was meaning that a different library is configuring the timer for its own purposes. It's possible the library is overiding the millis ISR.

IF and only if one of those lib makes a mess of mills/micros do you need to use a complex work around.

The lessons you are being taught is to look in the documentation, not just think that it may be.

First I;m here in part to find out. That is why I'm taking the time to make this post.

No you made this post because you wanted to avoid doing the work!

You find out by looking in the documentation or if that fails by looking at the code.

Second you dont know my background and third i'm not here to make philosophical debate. I'm simply asking a question.

))sic) digthat missing ' I don't need to know your background nor do I care about it.

When I say this is not an issue where opinion matters, what is just what I mean. One of those lib may or may not affect mills/micros - find out - do the work!

Mark

CyberZoid:
My issue now is both Timer0 and Timer1 are being used by these libraries.

It is entirely possible for another library to use Timer0 without upsetting the millis() function.

As others have said, the first thing is for you to do some tests to see if millis() works properly. If it does then you are wasting your time in this Thread.

And if the library using Timer0 does interfere with millis() it is still possible that you can use half of Timer1 to provide an equivalent capability.

You need to study the Attiny datsheet and the code in the libraries you are using very carefully.

...R

So I can confirm using the information compiled from:

And reading the attiny core file wiring.c source file

The that the millis function uses the Timer0 Overflow interrupt vector (TIMER0_OVF) on the ATtiny85

So theoretically you could call millis as it just returns the current count, the count may or may not increment depending on how the timer is configured. ie overflow or comparter & reset. If the library uses the timer as a comparater then resets the millis function would never increment.
Virtuallibrary uses CTC settings for the timer--resets timer on every compare match.
The servo8Bit library explicitly sets the timer to 0 on compare.

So basically it seems that the millis function is unreliable to use as a scheduler.

It seems my only option is to use software counters on the order of task_count = clk_freq/1000 (~1 ms). Then calibrate the background task to the interval I want.

CyberZoid:
So theoretically you could call millis as it just returns the current count, the count may or may not increment depending on how the timer is configured. ie overflow or comparter & reset. If the library uses the timer as a comparater then resets the millis function would never increment.
Virtuallibrary uses CTC settings for the timer--resets timer on every compare match.
The servo8Bit library explicitly sets the timer to 0 on compare.

I suspect you have not studied the Atmel datasheet in detail.

Each Timer has 2 parts to it so that it can time two different tasks. What counter (Register) does the servo8Bit library set to zero?

Have you written any test code to see how millis() actually behaves?

...R

Robin2:
I suspect you have not studied the Atmel datasheet in detail.

Have I studied it? yes i have (its been bookmarked). Have I memorized it no. Is it possible to be missing a key detail yes --I'm not a robot.

Robin2:
Each Timer has 2 parts to it so that it can time two different tasks. What counter (Register) does the servo8Bit library set to zero?

I might be wrong but I dont think this is correct in this context. The timer0 has 2 compare registers but only one register that holds the count.

Figure 11-1 pg 65, Registers pg 80

timer definition for servo8bit

#ifdef USE_TIMER0
    #define TCNTn   TCNT0
    #define OCRnx   OCR0A
    #define OCFnx   OCF0A
    #define OCIEnx  OCIE0A
#endif

In the servo8bit SW FSM compare function
//reset the counter to 0
TCNTn = 0; //the timer register

Robin2:
Have you written any test code to see how millis() actually behaves?

I made a quick test sketch on the Uno and setting the timer0 timer to ctc. The sketch did not run. but i'm thinking I need to create a more involved timer setup and usage to properly test it.
(Using the uno since the timer architecture and millis implementation is nearly identical +- a few features-- uno has a built in serial.)

I'll have to test this tomorrow night. I only have a short amount of time per day to work on this project.

CyberZoid:
Have I studied it?
...SNIP....
In the servo8bit SW FSM compare function
//reset the counter to 0
TCNTn = 0; //the timer register

That seems fairly clear. I just needed to get you to be precise about what the code does. Unfortunately a lot of Arduino libraries are written without any consideration for other uses of the hardware.

Do you know if the other library you are using prevents Timer1 from being used for your timing?

OR, perhaps you could convert the code in the servo8Bit library to use Timer1 and leave Timer0 available for millis().

OR, if you only want to control a single servo maybe you could write your own servo code using micros().

I made a quick test sketch on the Uno

I meant that you should do the tests on your Attiny.

...R