Timer 0 and Timer 1

Hello,

I am hoping someone can give me some advice on how to use Timer 0 and Timer 1 as counters. I want to use it to count the amount of time that a pressure is applied to a FSR and the amount of time inbetween pressures been applied. So maybe Timer 0 for the time pressure is applied, and Timer 1 for the time between pressures.

I have been reading over the datasheet for the ATmega328, but honestly, it's not helping much, and I am used to datasheets, but mostly for PIC16s. Maybe that's my problem, I have been looking for the equivalent of a Global Interrupt Enable bit etc. And I have been looking for info on prescalers etc.

Hope someone can give me some advice.

Thanks in advance.

Seán

How precise must your timing be?

Hmm pretty accurate.

I am measuring every 10ms, so, along the same lines as that.

Seán

Have you considered using millis() or micros() ?

unisgned long before = micros(); // do something Serial.println(micros() - before);

note: * micros() allways return a multiple of 4 and overflows quite fast ~30 millis 70 mins;) * millis() will overflow once per ~49 days

update -- fixed wrong info

I am using the millis() function at the minute, and it’s kind of working …but kind of not also. The applied pressure is always lasting for more than 10ms, so that causes problems in the data.

My supervisor suggested using timers as counters …So I want to investigate that path. Plus, I am not great with Timers, so this could be a good way to learn …jumping in at the deep end so to speak.

Seán

There are some libraries on the playground, you should check..

note: * micros() allways return a multiple of 4 and overflows quite fast ~30 millis * millis() will overflow once per ~49 days

micros() overflows in about 70 mins.

http://arduino.cc/en/Reference/Micros

Lefty

Oops my mistake, it was late yesterday ;)

Seán, can you post code?

Hey,

I haven't got any code for the timers yet. I am still not sure what registers I need to use etc.

Seán

In this case I don’t see anything to be gained by accessing the timers directly. I assume your trigger is connected to an ADC pin, so you’d still need to start and stop the timer in software.

Much easier to let the timers run as normal and access the counters via the built-in timing functions. For millisecond-precision timing the millis() function should be fine.

The applied pressure is always lasting for more than 10ms, so that causes problems in the data.

Can you explain a bit more?

tim7: In this case I don't see anything to be gained by accessing the timers directly. I assume your trigger is connected to an ADC pin, so you'd still need to start and stop the timer in software.

Much easier to let the timers run as normal and access the counters via the built-in timing functions. For millisecond-precision timing the millis() function should be fine.

The applied pressure is always lasting for more than 10ms, so that causes problems in the data.

Can you explain a bit more?

Well, the time the pressure is being applied for is a variable. It could last for, roughly, half a second, or it could last five minute. However, I need (or have been asked to) gather data every 10ms. I have been using the millis() function, with a delay after it, for testing that the system worked ...i.e. pressure 1 is applied at x time ....pressure 2 is applied at y time, y - x = time between pressures, and it works fine with me waiting long enough past the delay before I apply pressure. However, because I cannot know how long a pressure will be applied for, I cannot build in a correct delay which will allow me to get good readings.

So, if I use a timer, and the reading on the analogRead goes above a specific value, I can start a time, and when it goes below a specific value, I can stop the timer, therefore getting the time the pressure is applied for. This can go on in the background while other sensor data is been read at 10ms.

Hope that makes sense :fearful:

Seán

Is this no good?

#include <Streaming.h>

void setup() {
  Serial.begin(19200);
  Serial << "Start..." << endl;
}

void loop() {
  unsigned long t_down;
  unsigned long t_up;
  unsigned long t_lastcheck;
  unsigned long t_lastchange;
  int state_new;
  int state_old;
  
  state_new = getbutton();
  t_lastcheck = millis();

  state_old = state_new;
  t_lastchange = t_lastcheck;
  
  while (1) {
    // loop every 1ms:
    while ( millis() == t_lastcheck ) {}
    state_new = getbutton();
    t_lastcheck=millis();
    
    // this part must take less than 1ms:
    if (state_new != state_old) {
      if (state_new) { // button pressed
        t_up = t_lastcheck - t_lastchange;
        Serial << "Time up = " << t_up << " [ms]" << endl;
      } else {
        t_down = t_lastcheck - t_lastchange;
        Serial << "Time down = " << t_down << " [ms]" << endl;
      }
      state_old = state_new;
      t_lastchange = t_lastcheck;
    }
  }
  
}

int getbutton() {
  //return state of button: false = up, true  = down
  return( analogRead(A0) < 512 );
}

The Global Interrupt Enable bit is bit 7 in the status register. I think the datasheet is mostly well-written, but often I find myself jumping around between sections to solve a particular problem. Here is a paper on AVR timers that I really liked.

From the datasheet, Rev. 8271D–AVR–05/11:

7.3.1 SREG – AVR Status Register The AVR Status Register – SREG – is defined as: • Bit 7 – I: Global Interrupt Enable The Global Interrupt Enable bit must be set for the interrupts to be enabled. The individual interrupt enable control is then performed in separate control registers. If the Global Interrupt Enable Register is cleared, none of the interrupts are enabled independent of the individual interrupt enable settings. The I-bit is cleared by hardware after an interrupt has occurred, and is set by the RETI instruction to enable subsequent interrupts. The I-bit can also be set and cleared by the application with the SEI and CLI instructions, as described in the instruction set reference.

[quote author=Jack Christensen link=topic=69252.msg513640#msg513640 date=1313329907] The Global Interrupt Enable bit is bit 7 in the status register. I think the datasheet is mostly well-written, but often I find myself jumping around between sections to solve a particular problem. Here is a paper on AVR timers that I really liked.

From the datasheet, Rev. 8271D–AVR–05/11:

7.3.1 SREG – AVR Status Register The AVR Status Register – SREG – is defined as: • Bit 7 – I: Global Interrupt Enable The Global Interrupt Enable bit must be set for the interrupts to be enabled. The individual interrupt enable control is then performed in separate control registers. If the Global Interrupt Enable Register is cleared, none of the interrupts are enabled independent of the individual interrupt enable settings. The I-bit is cleared by hardware after an interrupt has occurred, and is set by the RETI instruction to enable subsequent interrupts. The I-bit can also be set and cleared by the application with the SEI and CLI instructions, as described in the instruction set reference.

[/quote]

Thanks for that, I didn't see it when I was looking through it.

And tim7, thanks for the code, I am new to think, so will take some time to figure out what you wrote :)

Seán

[quote author=Jack Christensen link=topic=69252.msg513640#msg513640 date=1313329907] Here is a paper on AVR timers that I really liked. [/quote]

Just getting to look at this now!

Thanks!!

Seán