AtTiny13 running really slow

Go To Last Post
30 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi guys
I have a small problem (irony)
I've programmed a tiny13 uC, and selected Div. by 8 OFF and the int. osc. 9.6 MHz

But the uC is running way below 1 MHz (guess as highest ISP speed is 127kHz before failing at 250kHz)

I'm using AVR studio 5 if it matters ?
and using the tiny13 for PWM.. but right now its blinking on and off every 3-5 sec. :-/

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm using the Timer Overflow interrupt for PWM and prescaling 1024 times

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Show code.
Show dump of reading out the clock selection fuses.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#include 
#include 
#include  
#include 





uint8_t r_value = 0;
uint8_t g_value = 60;
uint8_t b_value = 0;
uint8_t pwm_counter = 0;
uint8_t color_state = 0;
uint16_t button_delay = 0;



ISR(TIM0_OVF_vect)		//Timer int for LEDs
{

	if(g_value <= pwm_counter)
	{
		(PORTB &= ~0x01);
	}
	else
	{
		(PORTB |= 0x01);
	}
	
	if(r_value <= pwm_counter)
	{
		(PORTB &= ~0x02);
	}
	else
	{
		(PORTB |= 0x02);
	}
	
	if(b_value <= pwm_counter)
	{
		(PORTB &= ~0x04);
	}
	else
	{
		(PORTB |= 0x04);
	}
	
	
	if(pwm_counter == 255)
	{
		pwm_counter = 0;
	}
	else
	{
		pwm_counter++;
	}
}



void init(void)
{	
	/////////////PORT_SETUP/////////////DDRn > 0 input|1 output| PORTn > 0 low|1 high|
//	  DDRA  = 0x00;
//    PORTA = 0x00;
	DDRB  = 0x07;		//
    PORTB = 0x18;		//
//    DDRC  = 0x00;
//    PORTC = 0x00;
//    DDRD  = 0x00;		//
//    PORTD = 0x00;
	
	MCUCR = (0<<PUD);		//Pull-Up enable
	////////////////////////////////////


	/////////////Timer_Setup////////////
	TCCR0A = (0<<WGM01);							//Normal mode
	TCCR0B = (0<<CS02)|(0<<CS01)|(1<<CS00);		//clk/??
	TIMSK0 = (1<<TOIE0);							//Overflow int0
	
	
	sei();
	////////////////////////////////////

	//ADC_Init();
}

int main(void)
{
	init();

	
    while(1)
	{
		uint8_t r_value = 128;
		uint8_t g_value = 128;
		uint8_t b_value = 128;

		
	}
}


SELFPRGEN = [ ]
DWEN = [ ]
BODLEVEL = DISABLED
RSTDISBL = [ ]
SPIEN = [X]
EESAVE = [ ]
WDTON = [ ]
CKDIV8 = [ ]
SUT_CKSEL = INTRCOSC_9MHZ6_14CK_4MS

HIGH = 0xFF (valid)
LOW = 0x76 (valid)

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
MCUCR = (0<<PUD);
This statement (and the others like it) do not do what you think. This sets ALL bits of MCUCR to 0, not just the PUD bit. Use this instead:

MCUCR &= ~(1<<PUD);
    while(1)
   {
      uint8_t r_value = 128;
      uint8_t g_value = 128;
      uint8_t b_value = 128;

These statements do nothing. The variables defined here are NOT the same as the variables defined globally, they are separate local variables. The golbal versions (the ones being seen in the ISR) are never changed. Remove the uint8_t from these statements. Also, any variable that is used both inside and outside of an ISR must be declared "volatile" or else any local changes in main may not be seen in the ISR.

   if(pwm_counter == 255)
   {
      pwm_counter = 0;
   }
   else
   {
      pwm_counter++;
   }

No real need to do this. pwm_counter is an 8 bit value. If you increment it when the value is 255, it will automatically roll over to 0.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have not written TCNT0 with any value, nor do you re-load it, so that delay will be at it's absolute maximum value (256),
giving you a default period rather than one that you planned. I am not sure if that is what you intended. I always prefer to use CTC mode, where no reloading is required.

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Koshchi: Thanks alot ! :)
I have always used MCUCR = (1<<PUD); to set a bit.. is that still correct ? just the clearing of bits theres wrong ?

and the uint8_t is a typo :/
but forgot everything about the volatile declaration.

I'll try the stuff when I get home

LDEVRIES:
I'm aware of this, and just using the overflow interrupt

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I have always used MCUCR = (1<<PUD); to set a bit.. is that still correct ?

No. It will set the bit, and clear all other bits. You should use

MCUCR |= (1<<PUD);

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

okay, so setting bits is
MCUCR |= (1<<Bit1)|(1<<Bit2)|(1<<Bit3);

and clearing is
MCUCR &= ~(1<<Bit1)|(1<<Bit2)|(1<<Bit3);
correct ?

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
and clearing is
MCUCR &= ~(1<<Bit1)|(1<<Bit2)|(1<<Bit3);
correct ?

No. You are only negating the mask for Bit1. You want to combine (or) the bitmasks first, and then negate that combined result. You need another set of parenthesis.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay :)

MCUCR &= ~((1<<Bit1)|(1<<Bit2)|(1<<Bit3));

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Whenever in doubt on this stuff, go over to the Tutorials forum and locate the piece on "Bit manipulation".

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I actually have that one as a bookmark :D
just didn't relate it to setting up my bits :)
but thanks alot, looking forward to try the hints on my tiny13 and see if it helps with my problem

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I'm using the Timer Overflow interrupt for PWM and prescaling 1024 times

TCCR0B = (0<<CS02)|(0<<CS01)|(1<<CS00);      //clk/?? 

You are not prescaling your timer clock. CS02 bit should also set to 1(for a prescale value of 1024).

Quote:
but right now its blinking on and off every 3-5 sec.

This is weird because even if you run with 128 KHz internal oscillator and timer prescale of 1024 and pwm counter maximum value to be 255, you LED should be blinking for every one second.

-Krishna Balan S

-------------------------------------------------------------------------

"Heroes are ordinary people with extraordinary commitment"

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I change the CS02 bit to zero trying to locate my problem, forgot to change it back :(

The other thing... that's what I thought, so I'm really confused.. but going to rewrite the program from scratch and see if it starts working then

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I'm really confused.. but going to rewrite the program from scratch and see if it starts working then

It is more educational to debug your existing program. What makes you think that you won't have a bug in your "from scratch" program.
OK on just using overflow. Try using CTC! It is easy & very precise.

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

but is that usefull when I'm only using the interrupt as a timebase for my pwm ?

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Quote:
I'm really confused.. but going to rewrite the program from scratch and see if it starts working then

It is more educational to debug your existing program. What makes you think that you won't have a bug in your "from scratch" program.


I have a differing opinion. If B4Me starts from scratch, and then uses the "small steps" approach, testing incrementally and continuously, he will probably:
i) Get a working program within reasonable time, and
ii) Learn a very rewarding way to work on software development, and perhaps
iii) See where he went wrong the first time.

He could of-course also do something similar with his existing code: Cutting away pieces of functionality until it starts working again, and then learn where he went wrong.

Just as I held the opinion "both" in the "top-down or bottom-up?" debate a few months ago, I hold the opinion "both" here too. The golden trick re software development isn't to have one working method, but to have several and (the really difficult part) master when to use one or the other and understanding what/when they contribute to progress.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I did combine the ways :)
rewrote and reworked my old code...
the biggest mistake was that I were missing the "volatile" statement ! :/

but is it just my code thats slow... or does it makes sense that with
Osc = 9.6 MHz
prescaler at 256
and using normal mode on the timer
and a byte as my PWM count
I can see the off-time with the naked eye using 128 as my set value (50% duty cycle) ?

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am probably of the same opinion, however I find that the small steps approach is not favoured with "y" geners. They want their code now and they want it running now.
My emphasis was on debugging it by, systematically breaking it down and debug it and then fix it(probably by patching out code until it is simplified). Debugging is a very important skills as we will always have bugs!. However I should also say, that the "y" gener's don't like debugging as it is time consuming and does not help in getting their code running "now".

However as at this time, they are smarter than we are, they should be allowed to quickly do it their own way, before they become as dumb as we are! :)

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have noticed much the same as LDEVRIES, though I might attribute a slightly different cause than "impatience". I have worked with a number of EE grad students, age range early 20s to late 20s. A common, though hardly universal trait seems to be difficulty or reluctance to think through things in a logical, sequential manner, associating cause and effect. Or, using available tools to investigate in a logical manner.

Here is a recent example. The output of a 78L05 was lower than it should have been. What could cause it to be low?

Current limit? No evidence of that because it was quite cool and current required to limit would have gotten it warm.

Thermal limit? No, again, because it was quite cool.

Input voltage? It was large enough by a good margin, so no.

So, what could it be? I dunno.

Have you looked at the output with a scope? No.

Duuh! Its oscillating! Why? Inspection reveals that the pad on the ground side of the output cap is not connected to ground plane. Bit of solder - done.

I do not suggest that this is the case with B4Me. Instead, it is simply an unjustified, over-broad generalization. For, what ever it is worth.

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, it is a very broad brush generalization.
I hope Dean does not take my comments to heart and "out" me! :)

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I can make sure its not the same with me :)
I have a former education as electronic technician and right now halfway through my master in Mechatronics Engineering (with embedded as specialty)

But could we stick to my latest question buddys ? :)

I fixed my code, the biggest problem was the missing "volatile" statement, and thanks a lot for that note, cause It's some time since I last programmed on my AVR's :( (stupid school, stealing all my precious time)

The weird thing in my opinion now is:
9.6MHz clock / 256 prescaler / 256 pwm ticks (one byte)
that gives a switch frequency of
146.48 Hz or period time of 0.00683 s

so why can I see flickering here ?
should be impossible right ?
So is the problem that my code inside the interrupt is to big ?

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I love stereotypes. I for one am part of gen y and I do prefer the small steps approach and enjoy debugging.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
so why can I see flickering here ?

You should not be able to see flickering if refresh is > 25-30 Hz.
Quote:
should be impossible right ?

I would have thought so!

Quote:
So is the problem that my code inside the interrupt is to big ?

It does not look as if it is that long, but its is preferable to make interrupts really small & fast ... Ie. one statements is all that is required to set a flag and then do the main processing in your main loop where you have oodles of time. Somewhere in the main loop, toggle a pin, so that you can measure the loop processing time with a CRO.
Perhaps post your code again so that we can see what it looks like now that you have made some changes.

Quote:
but is that usefull when I'm only using the interrupt as a timebase for my pwm ?

Not really, but it is a nice way to do it, if you ever want an accurate time which cannot be achieved by counter overflow( which is what happens 99.6% of the time). I prefer to teach you have to fish, rather than feeding you a fish! :)

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

Last Edited: Mon. Aug 29, 2011 - 07:47 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

LDEVRIES wrote:

Perhaps post your code again so that we can see what it looks like now that you have made some changes.

I'll do that when I come home from work :)
Sometimes I get the idea of that I'm making really bad coding :-/ making big interrupt codes instead of flag's and so...

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do the simplest test for verifying the AVR clock:

Write the "1 second blinky", and run it (sketchy, not at my AVR dev machine):

#define F_CPU 9600000UL
#include 

int main(void)
{
   DDRB = 0x01;      // LED pin is an output
   while (1)
   {
      _delay_ms(500);
      PORTB ^= 0x01; // Toggle LED
   }
   return 1;
}

(Adjust the DDRB and PORTB manipulations to fit where your LLED is wired up.

If the led isn't blinking with a frequency of 1 Hz then your AVR is not running at 9.6 MHz.

I'd still like to see a proper screen dump of the fuses read out from the AVR.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Currently working code, with prescalling value at 8 !

#include 
#include 
#include  
#include 





volatile uint8_t r_value = 0;
volatile uint8_t g_value = 0;
volatile uint8_t b_value = 0;
volatile uint8_t new_r_value = 0;
volatile uint8_t new_g_value = 0;
volatile uint8_t new_b_value = 0;
volatile uint8_t pwm_counter = 0;
uint8_t color_state = 0;
volatile uint8_t intensity = 1;
volatile uint16_t button_delay = 0;



ISR(TIM0_OVF_vect)		//Timer int for LEDs
{

	if(g_value <= pwm_counter)
	{
		(PORTB &= ~0x08);
	}
	else
	{
		(PORTB |= 0x08);
	}
	
	if(r_value <= pwm_counter)
	{
		(PORTB &= ~0x04);
	}
	else
	{
		(PORTB |= 0x04);
	}
	
	if(b_value <= pwm_counter)
	{
		(PORTB &= ~0x10);
	}
	else
	{
		(PORTB |= 0x10);
	}
	
	if(pwm_counter == 255)
	{
		if(r_value != new_r_value)
		{
			if(r_value < new_r_value)
			{
				r_value++;
			}
			else
			{
				r_value--;
			}
		}
		if(g_value != new_g_value)
		{
			if(g_value < new_g_value)
			{
				g_value++;
			}
			else
			{
				g_value--;
			}
		}
		if(b_value != new_b_value)
		{
			if(b_value < new_b_value)
			{
				b_value++;
			}
			else
			{
				b_value--;
			}
		}
	}
	
	if(button_delay < 25000)		//cycles since last button was pressed
	{
		button_delay++;
	}
	pwm_counter++;

}



void init(void)
{	
	/////////////PORT_SETUP/////////////DDRn > 0 input|1 output| PORTn > 0 low|1 high|
//	  DDRA  = 0x00;
//    PORTA = 0x00;
	DDRB  = 0x1c;		//
	PORTB = 0x03;		//
//    DDRC  = 0x00;
//    PORTC = 0x00;
//    DDRD  = 0x00;		//
//    PORTD = 0x00;
	
	//MCUCR = (0<<PUD);		//Pull-Up enable
	////////////////////////////////////


	/////////////Timer_Setup////////////
	TCCR0A &= ~(1<<WGM01);				//clear bits	//Normal mode
	TCCR0B |= (1<<CS00);				//set bits		//clk/8
	TIMSK0 |= (1<<TOIE0);								//Overflow int0
	
	
	sei();												//enable interupts
	////////////////////////////////////

}

int main(void)
{
	init();

	
    while(1)
	{
		
		if ( ( PINB & 0x01 ) == 0 && button_delay == 25000)
		{
			button_delay = 0;
			
			if(color_state == 7)
			{
				color_state = 0;
			}
			else
			{
				color_state++;
			}
		} 
		else
		{
			if ( ( PINB & 0x02 ) == 0 && button_delay >= 5000)
			{
				button_delay = 0;
				if(intensity == 25)
				{
					intensity = 1;
				}
				else
				{
					intensity++;
				}
			}
		} 
		
		switch(color_state)
		{
			case 0:
			new_r_value = 255/intensity;
			new_g_value = 255/intensity;
			new_b_value = 255/intensity;
			break;
			case 1:
			new_r_value = 255/intensity;
			new_g_value = 0;
			new_b_value = 0;
			break;
			case 2:
			new_r_value = 255/intensity;
			new_g_value = 255/intensity;
			new_b_value = 0;
			break;
			case 3:
			new_r_value = 0;
			new_g_value = 255/intensity;
			new_b_value = 0;
			break;
			case 4:
			new_r_value = 0;
			new_g_value = 255/intensity;
			new_b_value = 255/intensity;
			break;
			case 5:
			new_r_value = 0;
			new_g_value = 0;
			new_b_value = 255/intensity;
			break;
			case 6:
			new_r_value = 255/intensity;
			new_g_value = 0;
			new_b_value = 255/intensity;
			break;
			case 7:
			new_r_value = 10/intensity;
			new_g_value = 10/intensity;
			new_b_value = 10/intensity;
			break;
			default:
			break;
		}

		
	}
}

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The

 if(button_delay < 25000)      //cycles since last button was pressed 
    { 
       button_delay++; 
    }

should not be in your ISR. It will slow your controller down.

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

its just an increment with a if statement before ? where else then ?

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system