PWM doesn't seem to work?

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

I been trying to get a servo, one that I got from parallax, working with my ATMeag8, I was use the code from the SoR members tutorial. When I power up the circuit the servo is suppose to center but instead the servo ticks once and stops. Does anyone know what could the problem?

http://www.societyofrobots.com/member_tutorials/node/231

#include 

int main (void)
{
	TCCR1A = 0;
	DDRB = 0b11111111;
	
	TCCR1B |= (1 << CS10) | (1 << WGM11) | (1 << WGM12) | (1 << WGM13);// no prescaler, running in fast PWM
	TCCR1A |= (1 << COM1A0);//non-inverted
	ICR1 = 19999;//top
	
	OCR1A = ICR1 * 2 /1.5;
	
	while(1)
	{
		
	}
}

Life Is Like A Bucket Of Chicken.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1
TCCR1B |= (1 << CS10) | (1 << WGM11) | (1 << WGM12) | (1 << WGM13);

WGM11 is not in TCCR1B.

OCR1A = ICR1 * 2 /1.5; 

Using a float constant is not very wise here. It will blow up you code significantly. And what sense does it make to let OCR1A be higher than the top value?

Stefan Ernst

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

This code doesn't even make the servo tick. I'm running at 1Mhz from the internally crystal. Could my servo be screwed-up?

int main (void)
{
	TCCR1A = 0;
	DDRB = 0b11111111;
	
	TCCR1B |= (1 << CS10) | (1 << WGM12) | (1 << WGM13);
	TCCR1A |= (1 << COM1A0) | (1 << WGM11);
	ICR1 = 19999;
	
	OCR1A = ((ICR1 * 10) * 15 / 200) / 10;
	//OCR1A = ICR1 * 1.5 / 20;
	
	while(1)
	{
		
	}
}

Life Is Like A Bucket Of Chicken.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
ICR1 = 19999;
(ICR1 * 10)

So how big is that? And how big is an int (which is what "10" will force promotion to)? Maybe try:

(ICR1 * 10UL)

By the way I make:

* 10 * 15 / 200 / 10

to simply be *0.075 which is the same as

* 3 / 40

Cliff

Last Edited: Sat. Mar 28, 2009 - 11:28 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The result of your OCR1A calculation is 25 (due to an overflow).

For testing the PWM use a constant value:

OCR1A = 1500;

Or a calculation at compile time:

#define PWM_TOP  19999
...
ICR1 = PWM_TOP;
...
OCR1A = PWM_TOP * 1.5 / 20;

Stefan Ernst

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

And check the recommended PWM frequency as Servo control can not work if frequency is too big.

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

I put my servo to OCCRB, not A, and used A to reset the count:

   // Timer 1 works the servo
   TCCR1A = 0b00100011 ;
   TCCR1B = 0b00011001 ;
   OCR1A = 20000 ;
   OCR1B = 1000 ;

This puts it at 1 end. Then I vary OCR1B between 1000 and 2000 to move the servo. 1500 is the middle.

(It seems I have to post a question here any time I fiddle with the timers It always turns out to be the bits. Always the control register bits.)

The largest known prime number: 282589933-1

Without adult supervision.

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

Quote:

It always turns out to be the bits. Always the control register bits.

Well, what/where else would it be? That is what determines how the timer will operate. I guess it could be something lkike reading/writing the CONTOL registers in the wrong order--oops, back to them again.

How about this summary: In nearly all cases, AVR timers operate exactly as described in the applicable chapter(s) of the datasheet.

Lee

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

Torby wrote:
(It seems I have to post a question here any time I fiddle with the timers It always turns out to be the bits. Always the control register bits.)

You're right, I had COM1A0 set high instead of COM1A1(non-inverting mode) in the Timer/Counter 1 Control Register A, TCCR1A.

When I tried to center(I know it not good to use float constants) the servo it didn't move completely to the center is a little closer to the left then the right by around twenty degrees. Is this because the specs aren't the same as a standard servo? If so does some know where I can get the data sheet for the Parallax's servo?

#include 

#define  PwmTop 19999

int main (void)
{
	DDRB = 0b11111111;
	
	TCCR1A |= (1 << COM1A1) | (1 << WGM11);
	TCCR1B |= (1 << CS10) | (1 << WGM12) | (1 << WGM13);
	
	ICR1 = PwmTop;
	
	OCR1A = ICR1 * 1.5 / 20; // centering code
	
	while(1){}
}

Life Is Like A Bucket Of Chicken.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
OCR1A = ICR1 * 1.5 / 20; // centering code 

Argh. Why are you using ICR1 here and not PwmTop?
With ICR1 the calculation must be done at run time, with PwmTop it can be done at compile time. In the latter case you can use floats without any extra costs.

Stefan Ernst

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

Looks like you're setting to 1/2 the center, rather than the center.

Try OCR1A = 1.5 * 1000

The largest known prime number: 282589933-1

Without adult supervision.

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

Hi! I had some troubles controlling servos, some time ago.

https://www.avrfreaks.net/index.p...

maybe you find something that could help you.

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

Torby wrote:
Looks like you're setting to 1/2 the center, rather than the center.

Try OCR1A = 1.5 * 1000


The same thing happens, the servo moves twenty degrees to the left of center. I might be able to dig out my basic stamp book and try to translate their example code to avr-gcc.

Life Is Like A Bucket Of Chicken.

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

Quote:
I'm running at 1Mhz from the internally crystal.
There is no "internally crystal". The internal oscillator is a RC one and can give you a significant amount of error. Measure the actual length of the impulse and calibrate the oscillator.

Stefan Ernst

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

Sounds like you need an oscilloscope, I don't own one. If I used an external crystal would I need to calibrate it?

Life Is Like A Bucket Of Chicken.

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

Could be your internal clock is off.

Don't have an O'scope? Mine sadly has passed away. I tried "Zelscope" and a "probe" made from the cord of an old computer microphone, a couple resistors and a clip lead. I don't like to talk to my computer anyhow.

Aside from everything being AC coupled, it works great for seeing a noisy line, a frequency or a pulse width. The program cost $10 and the probe came from the junk box.

It's amazing how easy it is to troubleshoot when you see what a signal is doing, rather than guessing. "Oh. The pulse is only 1/2 ms, not 1 1/2 ms..."

http://www.zelscope.com

The largest known prime number: 282589933-1

Without adult supervision.