Problems with fast pwm atmega 328p

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

Hi.

I have problems with the control of a servo (atmega 328p), i was using fast pwm, a preescaler of 8 with a 14.7456 MHz crystal, the frecuency for the servo is  50 Hz.

but i have this signal in the output when i want 1.5 ms in duty cycle:

this is my code (in C):

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

#include <avr/io.h>

#define F_CPU 14745600UL

#include <util/delay.h>

void Ports_Setup();

void Timer1_Setup();

void Timer1_Start();

void Timer1_Stop();

 

void Ports_Setup()

{

DDRB = 0x02;

}

void Timer1_Setup()

{

TCCR1A = (1<<COM1A1)|(0<<COM1A0)|(0<<COM1B1)|(0<<COM1B0)|(1<<WGM11)|(0<<WGM10);

TCCR1B = (0<<ICNC1)|(0<<ICES1)|(1<<WGM13)|(1<<WGM12)|(0<<CS12)|(0<<CS11)|(0<<CS10);

TCCR1C = (0<<FOC1A)|(0<<FOC1B);

TCNT1 = 0;

OCR1A = 2765;    // PWM 1.5ms Duty cycle

OCR1B = 0;

ICR1 = 36863;    // 50Hz

TIMSK1 = 0x00;

TIFR1 = 0x00;

}

void Timer1_Start()

{

TCCR1B = (0<<ICNC1)|(0<<ICES1)|(1<<WGM13)|(1<<WGM12)|(0<<CS12)|(1<<CS11)|(0<<CS10); //N=8

}

void Timer1_Stop()

{

TCCR1B = (0<<ICNC1)|(0<<ICES1)|(1<<WGM13)|(1<<WGM12)|(0<<CS12)|(0<<CS11)|(0<<CS10);

TCNT1 = 0;

}

int main(void)

{

Ports_Setup();

Timer1_Setup();

Timer1_Start();

    

while (1) 

    {

    }

}

 

Please help.

Sorry for bad english.

This topic has a solution.
Last Edited: Tue. Aug 8, 2017 - 02:47 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Any chance your scope was set to AC coupling when it should have been DC?

 

Jim

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That (AC coupled oscilloscope) was also my guess. 

 

Also, I read period as about 320ms. That makes frequency (roughly) 3Hz. That is a long ways from 50Hz (period = 20ms). You say you also want 1.5ms as duty cycle but it looks like you have 30ms, give or take a bit. Lets see, that is 20X longer duty cycle and the period is close to 20X longer than it should be. 

 

Very often, we see 8X longer due to a clock that is expected at 8MHz but is really 1MHz. I'd say that your prescaler is off, at a very minimum.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

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

No, the scope it is in DC.

 

About the prescaler i use the formula of the datasheed for fast PWM to calculated TOP (ICR1) and i use N=8, fpwm=(fclk)/(N(1+TOP)).

 

This is my configuration for the register:

 

void Timer1_Start()

{

TCCR1B = (0<<ICNC1)|(0<<ICES1)|(1<<WGM13)|(1<<WGM12)|(0<<CS12)|(1<<CS11)|(0<<CS10); //N=8

}

 

Thanks.

Last Edited: Sun. Aug 6, 2017 - 08:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You're using FastPWM with ICR1 as TOP value. In other words, each falling edge (ICES1=0) on the ICP1 pin (PB0) will update ICR1 with the current value of the TCNT1 counter, thus messing up your PWM period.

ɴᴇᴛɪᴢᴇᴎ

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

Alex_ceron wrote:
About the prescaler i use the formula of the datasheed for fast PWM

I believe Jim is talking about the System Clock Prescaler (not the timer prescaler). Check the CLKPS register and the CKDIV8 fuse.

 

ɴᴇᴛɪᴢᴇᴎ

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

Alex_ceron wrote:
No, the scope it is in DC.

What pin are you looking at?

 

What speed is your AVR running at?  How have you verified that?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Alex_ceron wrote:
#define F_CPU 14.7456E6

14 Hz, apparently...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Try

#define F_CPU 14745600UL

int main(void)
{
   DDRB |= (1<<PB1);               // output (OC1A)

   TCCR1A = (1<<WGM11);            // pwm mode 14, top=ICR1
   TCCR1B = (1<<WGM12)|(1<<WGM13);
   TCCR1A |= (1<<COM1A1);          // non-inverted output
   TCCR1B |= (1<<CS11);            // prescaler 8 

   // period = 20 ms   
   // ICR1 = (F_CPU[MHz] * period[us]) / prescaler) - 1;
   ICR1 = 36863;
   
   OCR1A = 2764;  // servo_pulse 1.5 ms

   while(1);
}

 

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

netizen wrote:

You're using FastPWM with ICR1 as TOP value. In other words, each falling edge (ICES1=0) on the ICP1 pin (PB0) will update ICR1 with the current value of the TCNT1 counter, thus messing up your PWM period.

 

But that function its disabled when i set ICR1 as top, or not?

 

 

Thanks for your time.

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

Visovian wrote:

Try

#define F_CPU 14745600UL

int main(void)
{
   DDRB |= (1<<PB1);               // output (OC1A)

   TCCR1A = (1<<WGM11);            // pwm mode 14, top=ICR1
   TCCR1B = (1<<WGM12)|(1<<WGM13);
   TCCR1A |= (1<<COM1A1);          // non-inverted output
   TCCR1B |= (1<<CS11);            // prescaler 8 

   // period = 20 ms   
   // ICR1 = (F_CPU[MHz] * period[us]) / prescaler) - 1;
   ICR1 = 36863;
   
   OCR1A = 2764;  // servo_pulse 1.5 ms

   while(1);
}

 

 

I try it but the problem persist :/

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

Use CTC with top at OCR.
Or Phase correct with top at ICR
.
MG

I don't know why I'm still doing this hobby

Last Edited: Tue. Aug 8, 2017 - 01:37 AM