CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

PWM - Pulse Width Modulation issues

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
LearningPIC
Guest







PWM - Pulse Width Modulation issues
PostPosted: Fri Jun 15, 2007 8:13 pm     Reply with quote

I'm trying to get PWM working. I am using a Tower Hobbies system 3000 (STD TS-53) servo motor. I figure this should be easy enough to do. I tried two ways to do this. One I used the code below which should correspond to 50Hz and 7% duty cycle. However the motor just grinds for a few seconds, then squeeks and doesn't do much. I tried varrying the frequencies and duty cycles. But according to the datasheet and other people that used this motor 50Hz and 7% should work.

I even tried using a delay of 2ms for outputing PIN_B7 on and then a delay of 18ms for leaving PIN_B7 low. But once again, does not work and the worst part is that I can't produce consistent results. Anyone have an idea what might be wrong?


#include <16F877A.h>
#fuses HS
#use delay(clock=20000000)

void main()
{
setup_timer_2(T2_DIV_BY_1, 99999, 1);

set_pwm1_duty(28000);

setup_ccp1(CCP_PWM);

while(1)
{
} // Prevent PIC from going to sleep.
}
RA
Guest







PostPosted: Fri Jun 15, 2007 8:32 pm     Reply with quote

In PWM mode the pic16f877A is only capable of 10 bits of PWM resolution
(0-1023).

Your values exceed that of the hardware.

Also, at 20Mhz and div/16 prescaler the lowest possible repetition rate is 1.22Khz.

You could possibly use an interrupt driven software PWM or substantially lower your clock frequency if you wish to use the hardware PWM with 10 bit of resolution.

-Richard
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jun 15, 2007 8:33 pm     Reply with quote

Quote:
setup_timer_2(T2_DIV_BY_1, 99999, 1);
set_pwm1_duty(28000);

Download the CCS manual and look at the allowable size of the
parameters that can be used with the setup_timer_2() function
and the set_pwm1_duty() function. Link to CCS manual:
http://www.ccsinfo.com/downloads/ccs_c_manual.pdf

A key point is: This compiler is used with small microcontrollers.
The typical data type is an unsigned 8-bit number. This is not MSVC++.
Sometimes larger data types are used, but not often, with the PIC
hardware modules. If you keep that in mind, you will do well.
LearningPIC
Guest







PostPosted: Fri Jun 15, 2007 9:17 pm     Reply with quote

Ok so I can't get the hardware to count high enough unless I maybe cascade more than one timer together?

My other question is, couldn't I just use the following code:

Code:

#include <16F877A.h>
#fuses HS
#use delay(clock=20000000)

void main()
{
set_tris_b(0);

while(1)
{
output_high(PIN_B7);
delay_ms(2);
output_high(PIN_B7);
delay_ms(18);
}
}


That should be enough to make the motor have a 2ms pulse with 20ms period (50 Hz frequency). Or is there something about using delays that won't make this work as I intend?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jun 15, 2007 9:32 pm     Reply with quote

You have to use software PWM to get a low frequency like 50 Hz.
http://www.ccsinfo.com/forum/viewtopic.php?t=20050
Guest








PostPosted: Fri Jun 15, 2007 11:15 pm     Reply with quote

I'm assuming this code should give me a frequency of 50Hz and a duty cycle of 8.2%. However when I run it, it does not produce the result I am expecting. Motor is trying to turn, but it can't. If only I could get my hands on an oscilliscope.


Code:

#include <16F877A>
#fuses HS
#use delay(clock = 20000000)

#define PWM_PIN  PIN_B1

#define LOOPCNT 390

int8 width;

//-------------------------------
#INT_RTCC
void tick_interrupt(void);

//====================================
main()
{
width = 32;

setup_counters(RTCC_INTERNAL | RTCC_8_BIT, RTCC_DIV_1);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
 
while(1);
}

//====================================
#INT_RTCC
void tick_interrupt(void)
{
static int8 loop = LOOPCNT;
static int8 pulse;

if(--loop == 0)
  {
   loop = LOOPCNT;
   pulse = width;
  }

if(pulse)
  {
   output_high(PWM_PIN);
   pulse--;
  }
else
  {
   output_low(PWM_PIN);
  }

}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Jun 16, 2007 2:05 am     Reply with quote

Quote:
#define LOOPCNT 390

static int8 loop = LOOPCNT;

You need to learn your data types. What's the largest value an
unsigned 8-bit integer (int8) can hold ?


Also, you need to add NOLVP to your #fuses statement.
Without it, you risk having random lockups of the PIC.
LearningPIC
Guest







PostPosted: Sat Jun 16, 2007 8:46 am     Reply with quote

I modified static int8 loop = LOOPCNT; to static int16 loop = LOOPCNT; I added NOLVP. However the motor has the same problems as before, just jittering in the same spot. Thanks for all your help.

I guess the only thing left for me to do is to find an oscilliscope to make sure that I'm getting the correct output. If that is not the problem, then maybe try and find a function generator.

Code:

#include <16F877A>
#fuses HS, NOLVP
#use delay(clock = 20000000)

#define PWM_PIN  PIN_B1

#define LOOPCNT 390

int8 width;

//-------------------------------
#INT_RTCC
void tick_interrupt(void);

//====================================
main()
{
width = 20;

setup_counters(RTCC_INTERNAL | RTCC_8_BIT, RTCC_DIV_1);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
 
while(1);
}

//====================================
#INT_RTCC
void tick_interrupt(void)
{
static int16 loop = LOOPCNT;
static int8 pulse;

if(--loop == 0)
  {
   loop = LOOPCNT;
   pulse = width;
  }

if(pulse)
  {
   output_high(PWM_PIN);
   pulse--;
  }
else
  {
   output_low(PWM_PIN);
  }

}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jun 17, 2007 2:33 pm     Reply with quote

I tested your latest code posted above, on a PicDem2-Plus board.
I get an approximately 50 Hz waveform, with a 5% duty-cycle positive
pulse (1 ms). I tested this with vs. 4.041 of the compiler. So, it is
working.
Guest








LearningPIC
PostPosted: Mon Jun 18, 2007 12:53 pm     Reply with quote

I just checked on the oscilliscope and it worked fine. I also learned out why it wouldn't work properly Smile I'm so dumb. The motor I used I received from a friend and didn't know it wasn't a continuous rotation motor. I never even imagined anything else. But once I realized that, I found out that it does work properly. Thanks for your help PCM Programmer.
LearningPIC
Guest







PostPosted: Mon Jun 18, 2007 4:42 pm     Reply with quote

I spoke too soon. When I try it with the PIC it still doesn't work properly. I'm guessing that the way I have it setup the frequency is 50.08Hz, and this thing need an exact frequency to work properly. I'll have to find a way to increase the resolution.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jun 18, 2007 5:04 pm     Reply with quote

I guess I didn't read your initial post very carefully. You're actually
just trying to drive a servo.

This is the TS-53 servo:
http://www2.towerhobbies.com/cgi-bin/wti0001p?&I=LXUK84

Here is a project page which shows how use that servo.
It has oscillscope waveforms.
http://www.dprg.org/projects/2003-05a/


CCS has a servo driver program. Here's the filename and location:
Quote:
c:\Program Files\Picc\Drivers\Servos.c


Here's a demo program for it. The servo output pins are defined
near the start of the Servos.c file. The default pins are D6 and D7.
I tested the program below with PCM vs. 4.041 and it works.
You can see the servo pulses on pins D6 and D7 of the PIC.
Code:

#include <16F877.h>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 4000000)

#include <servos.c>

//======================================
void main()
{

init_servos(); 

while(1)
  {
   set_servo(LEFT,  FORWARD, 2);
   set_servo(RIGHT, FORWARD, 3);
   delay_ms(500);

   set_servo(LEFT,  FORWARD, 1);
   set_servo(RIGHT, FORWARD, 2);
   delay_ms(500);
  }

}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group