Attiny45: How to measure delay using Timer 1

Hello Forum,

I'm trying to measure short delay, around 5-50us to generate a single pulse.
I tried a while loop with micros(), but time spent in each iteration takes too much time to ensure an accurate measure.
So I tried to use Timer1 to improve accuracy. Here is the code:

byte pin=0;

void loop() {
digitalWrite(pin,HIGH);
delay(100);
digitalWrite(pin,LOW);
timer(200);
delay(3000);
}

void timer(byte b) {
byte portb1mask=1<<PORTB1;

PORTB|=portb1mask;
TCCR1=B00001111;
TCNT1=0;
while(TCNT1<=b);
PORTB&=~portb1mask;
TCCR1=B00000000;
}

void setup() {
pinMode(pin,OUTPUT);
pinMode(PB1,OUTPUT);
}

Two leds:

  • pin0: blink on each loop() iteration
  • pin1: pulse generated using timer1.

The strange behaviour is this works only for half of the loop iteration:
iteration n: pin0: blink, pin1: blink
iteration n+1: pin0: blink, pin1: -
iteration n+2: pin0: blink, pin1: blink
iteration n+3: pin0: blink, pin1: -

Do you have an idea about this phenomena ?

Best regards,

Grégoire.

Hello forum,

I want to generate a pulse with an good accuracy using Timer1:

  1. I set PB1
  2. I enable Timer1, configured to clear PB1 when TCNT1 reach OCR1A.

The only "unpredictable" time is how many cycles it takes between 1 and 2. I will do more investigation later, this is not the purpose on my post (but if you have a clue, please send it!).

My problem comes with the following implementation:

byte ocf1amask=1<<OCF1A;
byte portb1mask=1<<PORTB1;
TCCR1=B00000000; // Stop counter
OCR1A=b;
TCNT1=0; // Reset counter
// TODO: reset prescaler
TIFR = ocf1amask; // Write a 1 to reset OCF1A
PORTB = PORTB | portb1mask; // Set PB1
TCCR1 = B00101111; // Start counter, clear PB1 when OCR1A
while(TIFR & ocf1amask==0); // Wait for comparison
TCCR1=B00000000; // Stop counter

Problem: This does not work, output PB1 is always on.
I suspect the problem from the two last lines: incorrect TIFR read so the counter to stopped to early before clear PB1. But if remove them, the output is always off. It looks like the counter TCNT1 immediately reaches OCR1A.

Do you have any suggestion ?

Best regards,

Grégoire.

Please edit your post, select the code, and put it between [code] ... [/code] tags.

You can do that by hitting the "Code" button above the posting area (It looks like a scroll with < > inside it).

Please do not cross-post. This wastes time and resources as people attempt to answer your question on multiple threads.

Threads merged.

How to use this forum

  • Moderator

Re your second post, post all your code please.

http://snippets-r-us.com/

Hello Nick,

Sorry for the bad formatting.

Here are the two full code:

First code: I do not understand why led controlled by timer1 works only for half of the main loop iteration:

byte pin=0;

void loop() {
  digitalWrite(pin,HIGH);
  delay(100);
  digitalWrite(pin,LOW);
  timer(200);
  delay(3000);
}

void timer(byte b) {
  byte portb1mask=1<<PORTB1;

  TCCR1=B00000000;
  PORTB|=portb1mask;
  TCNT1=0;
  TCCR1=B00001111;
  while(TCNT1<=b);
  PORTB&=~portb1mask;
  TCCR1=B00000000;
}

void setup() {
  pinMode(pin,OUTPUT);
  pinMode(PB1,OUTPUT);
}

Second code: Here the timer1 do not clear PB1:

byte pin=0;

void loop() {
  digitalWrite(pin,HIGH);
  delay(100);
  digitalWrite(pin,LOW);
  timer(200);
  delay(3000);
}

void timer(byte b) {
  byte ocf1amask=1<<OCF1A;
  byte portb1mask=1<<PORTB1;

  TCCR1=B00000000; // Stop counter
  OCR1A=b;
  TCNT1=0; // Reset counter
  // TODO: reset prescaler
  TIFR  = ocf1amask; // Write a 1 to reset OCF1A
  PORTB = PORTB | portb1mask; // Set PB1
  TCCR1 = B00101111; // Start counter, clear PB1 when OCR1A
  while(TIFR & ocf1amask==0); // Wait for comparison
  TCCR1=B00000000; // Stop counter
}

void setup() {
  pinMode(pin,OUTPUT);
  pinMode(PB1,OUTPUT);
}

Thank you for helping !

First code: I do not understand why led controlled by timer1 works only for half of the main loop iteration:

What do you mean by that? What happens? What do you expect to happen?

  while(TIFR & ocf1amask==0); // Wait for comparison

Personally I wouldn't be sitting there waiting for a match.

You don't seem to be in CTC mode. Is this intentional?

I'm not sure if you can manually enable port B1 and then have the timer turn it off. I may be wrong, but once you assign control of the port to the timer, the timer may control its on/off state.

Maybe read this: ATtiny85 Timer/Counter1 Compare Match Interrupts (Timer1/Timer0) - Microcontrollers - Arduino Forum

Hello,

For the first code, the corresponding schematic is:

  • led0 connected to PB0: it blink shortly every 3sec for each loop() iteration.
  • led1 connected to PB1: normally it should blink shortly immediatly after PB0. Blink duration is built by comparing TCNC1 register.

It works only for half of the loop() iteration:

Expected Got
led0 led0
led1 led1
delay 3sec delay 3sec
led0 led0
led1
delay 3sec delay 3sec
led0 led0
led1 led1
delay 3sec delay 3sec
led0 led0
led1
delay 3sec delay 3sec
led0 led0
led1 led1
delay 3sec delay 3sec
led0 led0
led1
delay 3sec delay 3sec

I do not understand why led1 does not blink for all loop() iteration.

Regards,

Grégoire.