PWM is not Consistant in ATtiny204

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

Hi,

Microchip - ATtiny204

 

objective - working on the ATtiny204 AVR microcontroller for PWM generation.My requirement is to achieve the PWM ON period --> 14us and OFF period --> 56us.After 600ms PWM should be ON for 600 milli second. And again  PWM ON period for 14us and OFF period for 56us upto 600ms. the same procedure should be repeat.

 

Setup -  * Wrote  a TOP value to the Period register (TCAn.PER)
             * Write to Compare value to the Compare register  (TCAn.CMP0)
             * Enable the peripheral by writing a '1' to the ENABLE bit in the Control A register (TCAn.CTRLA).The counter will start counting clock ticks according to the prescaler setting in                    the Clock Select bit field (CLKSEL) in TCAn.CTRLA.
             * Enable Global interrupts.
             * Enable the compare and overflow Interrupts.

 

Problem Statement -  After few iteration pulses are not consistant.

 

note-- code Attached 

 

Thanks in advance.

Attachment(s): 

gireesha

Last Edited: Fri. Nov 22, 2019 - 06:27 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

What is the clock speed? How long does it take the isrs to execute? You can measure this in the AS7 simulator.

 

Note: 'flag' denotes a boolean value - not an integer. This confuses the reader.

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

thanks for the quick reply 

i changed integer flag to integer count. and i attached new code

clock frequency is 5 megahertz.

ISR executes within 4 to 5 micro second.

gireesha

Last Edited: Fri. Nov 22, 2019 - 12:56 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You should describe what you are wanting to do. It sounds ok for the 14us on and the 56us off, but after that it doesn't make much sense. You want a pwm period of 70us with a duty cycle of 14us ? and it runs for 600ms, then stops (low) for 600ms, repeat ?

 

You can also make a pwm output do your pin work and you have 3 outputs in tca so can use multiple pins. If you wanted 2 outputs with opposite polarity, you can invert one of the pins. I'm also not sure how a compare match of 300 with a period of 360 figures out- 5MHz = 200ns per clock tick, 300*200ns = 60us, 360*200ns = 72us, not sure how 14/56us fts in. It sounds like you want a period of 350 (349) (70us) with a compare of 70 (69) (14us)- 14us on/56us off.

Last Edited: Sat. Nov 23, 2019 - 11:54 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks for the reply 

In the above code we are using two counters i.e count 1 and count.So for the 1st condition in the if(count<=8500)

                                                                                                                                                                {count1=1;}

                                                                                                                                              elseif(count1<=8400)

                                                                                                                                                                {Count=1;}

There by the loop goes to elseif condition. And 56uS is achieved when counter value is 0 PB0 is low and when counter value reaches 300 PB0 is high, and 14uS is achieved by comparing counter value 300 to 360.

gireesha

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

That is my mistake, I saw the same var name. Someday I will learn to read.

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

curtvm wrote:
I saw the same var name. 

@ G_i_r_i_s_h  that goes to show the importance of choosing good variable names!

 

Names should be descriptive, and not easily confused!

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is what I meant about letting the pwm hardware handle the pwm. Just enable/disable the cmp0 output. The overflow can keep track of the time, but you probably could just as well use _delay_ms to do the job. Not sure what you actually want for high/low on the pin, but you can change as needed. The tca0 compare output can be inverted with the pinctrl inven.

 

#include <avr/io.h>
#include <avr/interrupt.h>

 

#define F_CPU 5000000ul
#define CLKPER600MS 0.6*F_CPU
#define TCA0_PER 360 //seems like this should be 350 for 70us period (14us+56us), for 5MHz (200ns*350=70us)
#define TCA0_DUTY 300 //and this should be 280 (56us) (200ns*280=56us)

 

void pwmON()    { TCA0.SINGLE.CTRLB |= TCA_SINGLE_CMP0EN_bm;  }
void pwmOFF()   { TCA0.SINGLE.CTRLB &= ~TCA_SINGLE_CMP0EN_bm; }
void pwmToggle(){
    if( TCA0.SINGLE.CTRLB & TCA_SINGLE_CMP0EN_bm ) pwmOFF();
    else pwmON();
}
void timerInit(void)
{
    TCA0.SINGLE.PER = TCA0_PER-1;
    TCA0.SINGLE.CMP0 = TCA0_DUTY-1;
    TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_SINGLESLOPE_gc;
    TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV1_gc|TCA_SINGLE_ENABLE_bm;
    TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm;
}

ISR(TCA0_OVF_vect)
{
    static uint32_t count;
    count += TCA0_PER;
    if( count >= CLKPER600MS ){
        pwmToggle();
        count = 0;
    }
    TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm;
}

int main(void)
{
    CPU_CCP = CCP_IOREG_gc;
    CLKCTRL.MCLKCTRLB = CLKCTRL_PDIV_4X_gc|CLKCTRL_PEN_bm;

    PORTB.PIN0CTRL = PORT_INVEN_bm; //invert pb0
    PORTB.OUTSET = PIN0_bm; //actually is low since invert

    PORTB.DIR = PIN0_bm;
    //Tca0 WO0 = PB0

 

    sei();
    timerInit();

    for(;;){

        // or without overflow irq

        //_delay_ms(600);

        //pwmToggle();

    }
}

Last Edited: Fri. Nov 22, 2019 - 04:56 PM