Problems with attiny13a

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

Hello!

Do you have any idea why this doesn't work? Seems like variable mV will be calculated incorrectly. Maybe running out of stack?

#include 
#include 
#include 

#define TIM0_OVF_US 213


const int16_t mV_lo = 500;
const int16_t mV_hi = 4500;

const int16_t hz_hi = 150;
const int16_t hz_lo = 50;

const int16_t mV_ocr_lo = 193;
const int16_t mV_ocr_hi = 4065;

const uint8_t ocr_lo = 10;
const uint8_t ocr_hi = 200;


volatile unsigned int alc_period=0;
volatile unsigned int alc_duty=0;

volatile unsigned int timer200us=0;

ISR(TIM0_OVF_vect)
{
	timer200us++;
}


ISR(PCINT0_vect)
{
	static unsigned int last_lo_ts = 0;
	static unsigned int last_hi_ts = 0;
	unsigned int timer = timer200us;
	
	if(PINB&(1<<PINB4))
	{
		/* Pin state rising */
		alc_period = timer - last_hi_ts;
		last_hi_ts = timer;
	}
	else
	{
		/* Pin state falling */
		alc_period = timer - last_lo_ts;
		last_lo_ts = timer;
		alc_duty = timer - last_hi_ts;
		
	}


}

void init_hardware(void)
{
	/* Enable interrupt for PWM input (PB4) */
	PCMSK |= (1<<PCINT4);

	/* Clear pending interrupts */
	GIFR |= (1<<PCIF);

	/* Enable Pin change interrupt */
	GIMSK |= (1<<PCIE);
	
	TIFR0 &= ~(1<<TOV0);

	/* Enable timer overflow interrupt */
	TIMSK0 |= (1<<TOIE0);

	/* Fast PWM mode */
	TCCR0A |= (1<<WGM01) | (1<<WGM00);

	/* Set OC0A on Compare Match, clear OC0A at TOP; Set OC0B on Compare Match, clear OC0B at TOP; presacler 4 */
	TCCR0A |= (1<<COM0A1) | (0<<COM0A0) | (1<<COM0B1) | (0<<COM0B0);
	
	TCCR0B |= (1<<CS01)|(0<<CS00);
	
	DDRB |= (1 << PINB0) | (1<<PINB1);
	PORTB |= (1<<PINB0);
} 

int main(void)
{
	uint16_t hz;
	uint16_t mV=0;
	uint16_t ocr;

	init_hardware();
	sei();
	
	
	while(1)
	{
		hz = (1000000/TIM0_OVF_US)/alc_period;

		mV = (mV_lo * (int16_t)(hz - hz_hi))/(int16_t )(hz_lo - hz_hi) + (mV_hi * (int16_t )(hz - hz_lo))/(int16_t )(hz_hi - hz_lo);
		
		
		
		
		if(mV > 1000)
		{
		ocr = 10;
		}
		else 
		{
		ocr = 200;
		}
		
		
		OCR0A = (uint8_t)(ocr);
	};

}
Last Edited: Mon. Jul 29, 2019 - 08:11 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why go through all the trouble of converting alc_period to engineering units?

Just set ocr based on alc_period (and reverse the sense).

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

Well.. The program isn't ready written yet...

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

It seems to be problem with stack. When I simplify code (remove code and variables) it works.

How can I change size of stack??

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

This version should work. It should measure frequency and convert it to PWM. BUT.. it doesn't work. Any ideas?

#include 
#include 
#include 

#define HZ_LO 50
#define HZ_HI 150
#define TIMER_TICK_NS 833


#define OCR_LO (uint8_t)32
#define OCR_HI (uint8_t)247
#define OCR_RANGE (OCR_HI - OCR_LO)
#define PERIOD_MAX ((1000000000UL/HZ_LO)/TIMER_TICK_NS)
#define PERIOD_MIN ((1000000000UL/HZ_HI)/TIMER_TICK_NS)
#define PERIOD_RANGE (PERIOD_MAX - PERIOD_MIN)
#define OCR_SCALE (PERIOD_RANGE/OCR_RANGE)


volatile uint16_t alc_period=0;
volatile uint16_t alc_pulse_length=0;


volatile uint16_t timer200us=0;

ISR(TIM0_OVF_vect)
{
	timer200us++;
}


ISR(PCINT0_vect)
{
	static uint32_t last_lo_ts = 0;
	static uint32_t last_hi_ts = 0;
	uint16_t timer = timer200us<<8;
	
	timer |= TCNT0;
	
	if(PINB&(1<<PINB4))
	{
		/* Pin state rising */
		alc_period = timer - last_hi_ts;
		last_hi_ts = timer;
	}
	else
	{
		/* Pin state falling */
		alc_period = timer - last_lo_ts;
		last_lo_ts = timer;
		alc_pulse_length = timer - last_hi_ts;
		
	}


}

void init_hardware(void)
{
	/* Enable interrupt for PWM input (PB4) */
	PCMSK |= (1<<PCINT4);

	/* Clear pending interrupts */
	GIFR |= (1<<PCIF);

	/* Enable Pin change interrupt */
	GIMSK |= (1<<PCIE);
	
	TIFR0 &= ~(1<<TOV0);

	/* Enable timer overflow interrupt */
	TIMSK0 |= (1<<TOIE0);

	/* Fast PWM mode */
	TCCR0A |= (1<<WGM01) | (1<<WGM00);

	/* Set OC0A on Compare Match, clear OC0A at TOP; Set OC0B on Compare Match, clear OC0B at TOP; presacler 4 */
	TCCR0A |= (1<<COM0A1) | (0<<COM0A0) | (1<<COM0B1) | (0<<COM0B0);
	
	TCCR0B |= (1<<CS01)|(0<<CS00);
	
	DDRB |= (1 << PINB0) | (1<<PINB1);
	
	PORTB |= (1<<PINB0) | (1<<PINB1);
} 


int main(void)
{
	uint16_t temp = 0;
	uint16_t pros = 0;
	


	init_hardware();
	sei();
	
	
	while(1)
	{
		pros = alc_period;
		if(pros < PERIOD_MIN) pros = PERIOD_MIN;
		if(pros > PERIOD_MAX) pros = PERIOD_MAX;
		
		temp = (PERIOD_MAX-pros)/OCR_RANGE;
		
		OCR0B = (uint8_t)(OCR_LO + temp);
	}

}
Last Edited: Mon. Nov 21, 2011 - 08:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Which half doesn't work? The frequency measurement or the PWM? (and please don't say you simply tried to get both working at the same time!)

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

As you see, they are both implemented.

PWM generation itself seems to be working as seems also frequency measurement. But conversion from frequency to PWM calculation fails for some reason.

I don't have debugging tools (ICE), so I can't exaclty say which part fails..

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

Quote:

I don't have debugging tools

if you don't have an ICE then you need to debug some other way. This could be outputting a bit pattern on 8 LEDS, using a coulpe of 7-seg LED displays, using a LCD character or graphic display or sending info from the AVR to the PC probably using UART though USB is also a possibility. You need to print the intermediate values from the point at which you read the frequency to the value you then use to set the PWM and see where things "look wrong".

EDIT oh another way to debug is to have the program write intermediate results into EEPROM then after a run read out the EEPROM contents.

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

Quote:
How can I change size of stack??
Change to a chip that has more than 64 bytes of ram. Try a tiny25, 45 or 85. I think that the only significant difference between these and the tiny13 (aside from the added functionality) is that INT0 is on a different pin. But since you are not using INT0, that shouldn't be a problem.

Edit: By the way, moving these two definitions to global variables:

   uint16_t temp = 0; 
   uint16_t pros = 0; 

Will free up 4 bytes of stack. That really won't help you though since it will just be moved to a different part of RAM.

Regards,
Steve A.

The Board helps those that help themselves.

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

Finally got it working by moving variables to global and fixed a calculation.

Now the problem is that i'm using PWM for DAC and it isn't linear. Linearization with interpolation won't probably fit in memory?

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

Just lighten a heavy load (including a capacitive one) and it shall become linear.

Warning: Grumpy Old Chuff. Reading this post may severely damage your mental health.

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

Only load is input of opamp. Maybe I'll try to change bit smaller capacitor.

EDIT: What do you suggest when I'm running PWM channel ~5kHZ? I don't need to generate any high frequency signals, less than 1Hz

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

Quote:
Only load is input of opamp. Maybe I'll try to change bit smaller capacitor.
Then you could use the OpAmp as lowpass and get rid of the capacitor on the MCU output completely.

Quote:
EDIT: What do you suggest when I'm running PWM channel ~5kHZ? I don't need to generate any high frequency signals, less than 1Hz
That depends on the acceptable ripple of the analog out. The higher the PWM, the easier it is to filter away the carrier frequency.

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

OpAmp lowpass could be an option to next version, but not for this one :)

Ripple voltage should not be more than 0.1V

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

Hello i just need a frequency calculation and i am new in programming. Can you please post a code with only frequency measurement that works

george

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

You already have an active thread about this here:  https://www.avrfreaks.net/forum/split-attiny13-timer-and-interrupts-reading-rc-receiver-signal

 

So please stop spamming and cross posting every other thread that mentions tiny13.

 

Going to lock this one and will also lock any further cross posts you make.

 

Moderator

 

Topic locked