Attiny13A Timer overflow interrupt weird behavior

I am using an Attiny13A and I can not get the timer overflow interrupt to work properly.
This is a small version of the full version of the code (quite large) but reproduces the problem.

#define F_CPU 128000
#include <avr/io.h>
#include <util/delay.h>
volatile unsigned long x=0;
SIGNAL(TIMER0_OVF_vect){x=1;} //Set x to 1 
int main(){
	TCCR0B |= _BV(CS01); //Prescaler to F_CPU/8
	TCCR0A |= _BV(WGM00)| _BV(WGM01); 
	TIMSK0 = _BV(TOIE0); //Enable timer overflow interrupt
	DDRB = 0x18; //PB3 and PB4
	asm("sei"); //Enable interrupts
	while(1){
		PORTB ^= 0x8; //Invert vale on PB3
		if(x){PORTB |= 0x10;} //Turn on PB4 after the interrupt 
		_delay_ms(500); //Blink delay
	}
}

Expected behavior is that PB3 would blink and PB4 would light. Actual behavior is PB3 would flicker at about 20 times per second and PB4 does not light.
But if I change it to:

#define F_CPU 128000
#include <avr/io.h>
#include <util/delay.h>
volatile unsigned long x=0;
SIGNAL(TIMER0_OVF_vect){x=1;} //Set x to 1 
int main(){
	TCCR0B |= _BV(CS01); //Prescaler to F_CPU/8
	TCCR0A |= _BV(WGM00)| _BV(WGM01); 
	TIMSK0 = _BV(TOIE0); //Enable timer overflow interrupt
	DDRB = 0x18; //PB3 and PB4
	while(1){
		PORTB ^= 0x8; //Invert vale on PB3
		if(x){PORTB |= 0x10;} //Turn on PB4 after the interrupt 
		_delay_ms(500); //Blink delay
               asm("sei"); //Enable interrupts *moved*
	}
}

Again I expect the same behavior as before but now PB3 actually blinks at the correct rate but PB4 still does not light.
I have been Googling for hours and can not find a solution.
It seems to match the examples as well.

SIGNAL is deprecated. Use ISR.

Try this…
ISR(TIM0_OVF_vect){x=1;} //Set x to 1

Access to x needs to be protected in main or x needs to be changed to a single byte data-type.

Wow! That was a fast response.

No difference.

Access to x needs to be protected in main or x needs to be changed to a single byte data-type.

I am afraid I do not understand what this means.

How are you getting that to compile without the requisite…

#include <avr/interrupt.h>

smeezekitty:
Wow! That was a fast response.

I like browsing the forum when I eat my evening snack; which is what I was doing. I've developed a sweat spot for the 13 processor. I noticed your title and pounced. Serendipity.

No difference.

As far as I can tell, it should work. It looks like you are setting the registers correctly and the code is certainly not complicated. I'll look again later.

Access to x needs to be protected in main or x needs to be changed to a single byte data-type. ... I am afraid I do not understand what this means.

Look over this...
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1261124850/all

Especially the section that starts "Data that cannot be accessed atomically". If you're still confused, report back or search for Nick Gammon's write-up.

I do not know. It compiled ok without it.
When I include it, no change in behavior but the compiler throws a weird warning:

6: warning: 'TIMER0_OVF_vect' appears to be a misspelled signal handler

I like browsing the forum when I eat my evening snack; which is what I was doing. I’ve developed a sweat spot for the 13 processor. I noticed your title and pounced. Serendipity.

Out of curiosity, what country do you live in?

As far as I can tell, it should work. It looks like you are setting the registers correctly and the code is certainly not complicated. I’ll look again later.

I thought the same thing :slight_smile:

Look over this…
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1261124850/all

Especially the section that starts “Data that cannot be accessed atomically”. If you’re still confused, report back or search for Nick Gammon’s write-up.

Will do.

Thank you. You are always very helpful. I am still a noob at standalone microcontrollers.

smeezekitty:
I do not know. It compiled ok without it. ... When I include it, no change in behavior but the compiler throws a weird warning:

Your program will not work unless you make the change above...

ISR(TIM0_OVF_vect){x=1;} //Set x to 1

TIM0_OVF really is the name of the interrupt on an ATtiny13. For future reference, the various names (interrupt, register, etcetera) always match what's in the datasheet.

Out of curiosity, what country do you live in?

Oh, you are going to get razzed for that. While there are several scattered around the country, Google Maps takes you to the true one. Hint: Look left and just a bit up.

Thank you. You are always very helpful.

You are welcome and thank you!

I am still a noob at standalone microcontrollers.

Not even Bill Gates was born knowing how to program. (And arguably, he never learned. :P)

Wow that was it!!
Thank you for that. I spent 5 hours on that :frowning:
You probably saved me another 5 hours!

Out of curiosity, what country do you live in?

Oh, you are going to get razzed for that. While there are several scattered around the country, Google Maps takes you to the true one. Hint: Look left and just a bit up.

Alaska?

Not even Bill Gates was born knowing how to program. (And arguably, he never learned. :P)

LOL
Now back to the project: writing an Arduino core for the Attiny13!
I know it has limited resources but still it is possible to implement a subset.
Newest code - Works!

#define F_CPU 128000
#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>
volatile unsigned long x=0;
ISR(TIM0_OVF_vect){x=1;} //Set x to 1
int main(){
	TCCR0B |= _BV(CS01); //Prescaler to F_CPU/8
	TCCR0A |= _BV(WGM00)| _BV(WGM01);
	TIMSK0 |= _BV(TOIE0); //Enable timer overflow interrupt
	DDRB = 0x18; //PB4 and PB4
	asm("sei");
	while(1){
		PORTB ^= 0x8; //Invert value on PB3
		asm("cli");//Disable interrupts to get value
		if(x){PORTB |= 0x10;}
		asm("sei");//Re-enable interrupts
		_delay_ms(500); //Blink delay
	}
}

smeezekitty:
Wow that was it!!

Did you also have to include the…
#include <avr/interrupt.h>

Thank you for that. I spent 5 hours on that :frowning: You probably saved me another 5 hours!

You are welcome. That’s about the same amount of time I spent on the problem. I really do hate that Atmel changed those names so many times.

Out of curiosity, what country do you live in? Alaska?

Nope. Second hint: Look left and just a bit up before going to Google Maps.

Newest code - Works!

Excellent!

Now back to the project: writing an Arduino core for the Attiny13! I know it has limited resources but still it is possible to implement a subset.

I built a battery powered tea-timer for my wife using one. I managed to squeeze…

  • Auto-off #1. When the time expires, clicking the button shuts it off.
  • Auto-off #2. One minute after the time expires, it automatically shuts itself off.
  • Auto-on. Click the button it wakes and starts timing.
  • Two beep tones. One for “hello” and one for “done”.

…onto an ATtiny13. There are 20 bytes of Flash left.

It has some personality. I forgot to enable the internal pull-ups on the unused pins. Every once in a while, it wakes on its own.

Yes. I copied it wrong.

Out of curiosity, what country do you live in? Alaska?

Nope. Second hint: Look left and just a bit up before going to Google Maps.
[/quote]
LOL Dallas Texas?

Now back to the project: writing an Arduino core for the Attiny13! I know it has limited resources but still it is possible to implement a subset.

I built a battery powered tea-timer for my wife using one. I managed to squeeze…

  • Auto-off #1. When the time expires, clicking the button shuts it off.
  • Auto-off #2. One minute after the time expires, it automatically shuts itself off.
  • Auto-on. Click the button it wakes and starts timing.
  • Two beep tones. One for “hello” and one for “done”.

…onto an ATtiny13. There are 20 bytes of Flash left.

It has some personality. I forgot to enable the internal pull-ups on the unused pins. Every once in a while, it wakes on its own.

[/quote]
Can’t you attach an ISP and reprogram it?

LOL Dallas Texas?

Yup. Why do you ask?

Can't you attach an ISP and reprogram it?

There are two potential issues with ISP and that particular gadget...

  1. Voltage. The gadget is powered directly from two AA batteries. When the batteries are fresh, it may be possible to program the target from a five volt programmer but doing so definitely violates the limits specified in the datasheet. I did not try. Instead, I use a voltage divider on SCK and MOSI to cut the voltage in half and a pair of transistors to raise the MISO voltage to +5V. RESET can be left as-is because it either floats (INPUT w/ no pullup) or sinks (OUTPUT / LOW). Being able to program at battery voltage allowed me to get a very good tune on the internal oscillator.

  2. Piezoelectric buzzer. The buzzer is connected to MOSI. Directly driving a piezoelectric buzzer is a bad idea. I am certain the peak current exceeds the maximum specification. But, I typically do it anyway. The buzzer is much louder without a current limiting resistor. However, without the current limiting resistor, it is impossible to program the target. So, this gadget includes the resistor.

Rats. I just finished writing all that crap above and I just noticed that you asked "Can't you" not "Can you". Oh well. I guess you get an extra verbose answer to a question you did not ask.

Yes, I can reprogram it. Easily. The thing's personality is too entertaining so it's been left as-is.

Because you respond at odd hours :stuck_out_tongue:

  1. Voltage. The gadget is powered directly from two AA batteries. When the batteries are fresh, it may be possible to program the target from a five volt programmer but doing so definitely violates the limits specified in the datasheet. I did not try. Instead, I use a voltage divider on SCK and MOSI to cut the voltage in half and a pair of transistors to raise the MISO voltage to +5V. RESET can be left as-is because it either floats (INPUT w/ no pullup) or sinks (OUTPUT / LOW). Being able to program at battery voltage allowed me to get a very good tune on the internal oscillator.

I don't think raising the MISO voltage would be necessary since ~2.8v will register as a logic high on a 5v device.
Even with a calibrated internal oscillator, it will still drift as the batteries go dead. Attinys are limited for timing applications because external crystals or resonators eat up valuable I/O pins and the internal oscillator is all over the place as input voltage changes.

  1. Piezoelectric buzzer. The buzzer is connected to MOSI. Directly driving a piezoelectric buzzer is a bad idea. I am certain the peak current exceeds the maximum specification. But, I typically do it anyway. The buzzer is much louder without a current limiting resistor. However, without the current limiting resistor, it is impossible to program the target. So, this gadget includes the resistor.

Piezoelectric devices are high resistance. I do not know what how much capacitance they have but if its not to high, then direct driving should be no problem.

Rats. I just finished writing all that crap above and I just noticed that you asked "Can't you" not "Can you". Oh well. I guess you get an extra verbose answer to a question you did not ask.

Yes, I can reprogram it. Easily. The thing's personality is too entertaining so it's been left as-is.

LOL

smeezekitty:
Because you respond at odd hours :stuck_out_tongue:

Vampire in training. :smiley:

I don't think raising the MISO voltage would be necessary since ~2.8v will register as a logic high on a 5v device.

I thought that as well. Even with fresh batteries, I just could not get it to work reliably. Added the "voltage-leveler" and it became rock-solid.

In addition, I wanted to be able to program the gadget even when the batteries were very low and I wanted to perform "run dead" testing. The voltage-leveler allowed me to send serial data as the batteries ran down to 1.6 volts (dead for the batteries I use). At about 1.7 volts the status LED stopped lighting but the processor kept sending serial data. Sweet.

Even with a calibrated internal oscillator, it will still drift as the batteries go dead.

It stays within ±1% over the entire voltage range which is more than good enough for the gadget. I wanted to get it as accurate as I could so it's tuned at the midpoint in the battery life.

Attinys are limited for timing applications because external crystals or resonators eat up valuable I/O pins

I agree. And they require more power.

and the internal oscillator is all over the place as input voltage changes.

I disagree. The internal oscillator is a fairly predictable animal. From my testing, there is a bit of jitter, the oscillation rate depends on voltage, the rate depends on temperature (of the processor), and there is no noticeable drift (at a given voltage and temperature the average oscillation rate is stable). The various charts in the datasheet provide an accurate representation of how it behaves. It certainly is not good enough for a time-of-day clock but for most timing (e.g. serial communications, tea-timer, generating tones, blinking an LED) it works well.

Piezoelectric devices are high resistance. I do not know what how much capacitance they have but if its not to high, then direct driving should be no problem.

So far nothing has been smoked but it definitely interferes with ISP.