1 2 3 4 5 6 84 Replies Latest reply on Feb 22, 2013 7:07 AM by userc_38527 Go to original post
• ###### 45. Re: Simple PWM

It does rotate but can not return to center position even I put in a code :

/* Divide by eight function */
void GenerateCenterPosition(void)
{
/* set period to eight clocks */
//PWM8_1_WritePeriod(10);

/* set pulse width to generate a 33% duty cycle */
PWM8_1_WritePulseWidth(30);

/* ensure interrupt is disabled */
PWM8_1_DisableInt();

/* start the PWM8! */
PWM8_1_Start();
}

/* Divide by eight function */
void GenerateLessThan90(void)
{
/* set period to eight clocks */
//PWM8_1_WritePeriod(199);

/* set pulse width to generate a 33% duty cycle */
PWM8_1_WritePulseWidth(25);

/* ensure interrupt is disabled */
PWM8_1_DisableInt();

/* start the PWM8! */
PWM8_1_Start();
}

/* Divide by eight function */
void GenerateMoreThan90(void)
{
/* set period to eight clocks */
//PWM8_1_WritePeriod(35);

/* set pulse width to generate a 33% duty cycle */
PWM8_1_WritePulseWidth(35);

/* ensure interrupt is disabled */
PWM8_1_DisableInt();

/* start the PWM8! */
PWM8_1_Start();
}

main :

GenerateCenterPosition();
Delay10msTimes(90);
GenerateLessThan90();
Delay10msTimes(90);
GenerateMoreThan90();
Delay10msTimes(90);

• ###### 46. Re: Simple PWM

How much did it rotate? Were the rotation direction for more than and less than 90 degree opposite? Provide a delay more than 200 ms. (as it takes 131 ms to rotate 60 degrees - if the rotation angle is more than 60 degree than provide a higher delay)

• ###### 47. Re: Simple PWM

Bianchi, you are a bit relucant against hints we gave you:

We told you not to change the period value, since it will be stable at 20ms / 50Hz.

The pulse width is the time the output signal is high. So it cannot be more than the period value

Your calculation of duty-cycle are darn wrong

Your servo is not controlled by a duty-cycle arithmetic, but by a formula similar to

ValueFor1ms + ValueFor1ms * Percentage / 100 (of course this formula can be simplified, I leave that to you)

Take care, that your comments in the program do reflect the actual coding.

Something to make life easier:

Set the period value in the PWMs properties window and do not change it anymore.

For your application you may set the pulse width in the property dialog to 1ms or 1.5ms (both need some calculations) so that at start of the PWM a defined value is already taken.

Change (only!!) the pulse-width programatically on-the-fly, that will work for your application.

Take enough time to watch your servo moving.

Bob

• ###### 48. Re: Simple PWM

To simplify things more, did you know that the compiler is able to calculate formulas for you?

You may write

#define ValueFor1ms 20 // Insert your correktly calculated value here

#define PulseWidth(Percent) (ValueFor1ms + ValueFor1ms * Percent / 100)

Now you can write in your program

PWM8_1_WritePulseWidth(PulseWidth(50)); // Midst position

and so on...

Happy coding

Bob

• ###### 49. Re: Simple PWM

How much did it rotate? Were the rotation direction for more than and less than 90 degree opposite? Provide a delay more than 200 ms. (as it takes 131 ms to rotate 60 degrees - if the rotation angle is more than 60 degree than provide a higher delay)

It can rotate to 60 degree but can't return to 0 position, I don't know why since I put 900ms delay and ask it to return to 0 position on the code, do you have idea ?

Is the code or hardware issue ?

thanks

• ###### 50. Re: Simple PWM

How about do it one step a time

1. You need to set the PWM up with 10khz clock (0.1ms clock) - you need to change the VC1, VC2 and VC3 divider accordingly.
2. Set the period in the designer to 199 (period of 20ms)
3. Set the Pulse width value in desiger to 14 which gives you 1.5ms (ie middle position)
4.DONT WRITE any thing in your main.c, just let the PWM started, let it run, the servo should stay in the middle

If your driver to your servo is "ON" when the pulse is high, it should work. If it isn't you might have the driver inverted.
Then you change the pulse wide value from 14 to to 185.

Come back and tell us what you find and upload your project here as well so people can check.

• ###### 51. Re: Simple PWM

How about do it one step a time

1. You need to set the PWM up with 10khz clock (0.1ms clock) - you need to change the VC1, VC2 and VC3 divider accordingly.
2. Set the period in the designer to 199 (period of 20ms)
3. Set the Pulse width value in desiger to 14 which gives you 1.5ms (ie middle position)
4.DONT WRITE any thing in your main.c, just let the PWM started, let it run, the servo should stay in the middle

If your driver to your servo is "ON" when the pulse is high, it should work. If it isn't you might have the driver inverted.
Then you change the pulse wide value from 14 to to 185.

Come back and tell us what you find and upload your project here as well so people can check.

I've done your suggestion, nothing is happened,

Please find my project attached, may be you guys can see what to do...

• ###### 52. Re: Simple PWM

Attached is a project partial re-write to look at with

You had a number of typos, and un-necessary functions. The calculations

for duty cycle did not follow the datasheet equations for reference.

Regards, Dana

• ###### 53. Re: Simple PWM

If you modify the routine I wrote to -

void DCset( unsigned char dc ) {

// Pulsewidth value = Duty Cycle X ( Period value + 1 ) = Duty Cycle X 200
// But Duty Cycle is fractional (% expressed as a fractional, like .35 for 35%),
// so lets convert whole equation to integer by multiplying by 100, so we have
// 100 x Pulsewidth value = Dutycyle (as integer now) X ( Period value + 1 ) or
// Pulsewidth value = ( Dutycyle (as integer now) X ( Period value + 1 ) ) / 100
// Period value = 199, so
// Pulsewidth value = ( Dutycyle (as integer now) X 200 ) / 100 so
// Pulsewidth value = Dutycyle (as integer now) X 2
// So to get a DC of 75 we write "DCset( 75 );" in our code

dc = ( dc > 100 ) ? 100 : dc;     // Make sure if dc typed > 100 it is limited to 100
// Note a dc of 0 or 100 results in a fixed low or high on output

PWM8_1_WritePulseWidth( dc * 2 );     /* set pulse width to generate a dc% duty cycle */
}

Examples -

DCset( 0 );        // Produces a DC =   0 %, a constant low on pin, no pulses
DCset( 1 );        // Produces a DC =   1 % on pin
DCset( 99 );      // Produces a DC =  99 % pn pin
DCset( 100 );    // Produces a DC = 100 %, a constant high on pin, no pulses

Regards, Dana.

• ###### 54. Re: Simple PWM

Hi bianchi,

In your project,  you didn't start the PWM.

Dana's sugestions is useful and make the firmware more easily understand.

Do you have access to a CRO, if may be helpful if you can acually see the output waveform.

• ###### 55. Re: Simple PWM

HL, the project I did a partial re-write did start PWM.

Regards, Dana.

• ###### 56. Re: Simple PWM

Dana,

Thanks for the response, I tried your code, I didn't see any movement on my motor,

is there something missing here ?

Cheers

• ###### 57. Re: Simple PWM

Hi Dana,

Yes, you code has the PWM started.

I think it would be better for him/her to understand why the program not working, rather then give him/her a working code.

• ###### 58. Re: Simple PWM

Hi bianchi,

Use the one you uploaded, change it so the PWM started function is called.

( Again, you may need to change the Pulse width if your ouput is inverted).

If it works, then change the pulse width in the DESIGNER to be between 10 to 20 (1 to 2 ms). and run the program after compiling.

YOu should be able to see the servo moved to a different angle.

Here is a reference you may be intertested in.

http://gekogeek.com/embedded/servo-motor-control/

• ###### 59. Re: Simple PWM

You might confirm the wiring to the servo is correct.

Additionally, use a scope, set up a function generator for 20 mS period,

1.5 mS high pulse, and see if servo is OK.

Regards, Dana.

1 2 3 4 5 6