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 CCS Technical Support

pwm

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







pwm
PostPosted: Mon Jan 13, 2003 2:40 am     Reply with quote

Dear all,

I would like to use pwm to control the speed of my dc motor, so that I can start the motor immediately/ faster when I switch it on. However, when I control the speed by sending pulses, eg:

do
{
portb=0xC0; //high
delay_us(40);
portb=0;
delay_us(40);
}while( );

I couldn't do anything else. I would like to continuously sense the movement of an optical mouse using pic 16f876, and move the motor whenever movement occurs. How can I do these 2 actions (sensing and control the speed of the motor by sending pulses) in the same time?

Is it any other better ways to do a fast switching for the motor?

Thanks for your help.
___________________________
This message was ported from CCS's old forum
Original Post ID: 10637
R.J.Hamlett
Guest







Re: pwm
PostPosted: Mon Jan 13, 2003 3:44 am     Reply with quote

:=Dear all,
:=
:=I would like to use pwm to control the speed of my dc motor, so that I can start the motor immediately/ faster when I switch it on. However, when I control the speed by sending pulses, eg:
:=
:=do
:={
:=portb=0xC0; //high
:=delay_us(40);
:=portb=0;
:=delay_us(40);
:=}while( );
:=
:=I couldn't do anything else. I would like to continuously sense the movement of an optical mouse using pic 16f876, and move the motor whenever movement occurs. How can I do these 2 actions (sensing and control the speed of the motor by sending pulses) in the same time?
:=
:=Is it any other better ways to do a fast switching for the motor?
:=
:=Thanks for your help.
Yes.
Use the hardware PWM.
The chip contains two hardware PWM modules, designed to perform exactly this sort of task. Set up something like this (I am only posting the 'PWM' guts, so you will have to add your own code 'round' this, to give the required effect):

int power;

#int_TIMER2
TIMER2_isr() {
//Update the motor pulse width
set_pwm1_duty(power);
}

//Then in main
//The timing values here will need to be set
//according to the clock you are using, and the
//PWM rate you require. These values give a PWM
//pulse that is at about 4KHz with a 4MHz clock,
//((clock/16)/64)=3906Hz, and an 'update' interval
//at 244Hz.
setup_timer_2(T2_DIV_BY_4,63,16);
setup_ccp1(CCP_PWM);
set_pwm1_duty(0); //disable PWM to start.
power=0;
enable_interrupts(INT_TIMER2);
enable_interrupts(global);


Now loop monitoring your inputs, and when you want to change the power, simply set 'power', equal to the value you require - 0=power off, 256=max. In the example given, the PWM 'resolution', is 8 bits. Look at Microchip AN539, for a good description of how this all works.
When you change 'power', the next time the TIMER2 interrupt occurs, this value, will be applied as the value to use. This happens every 16 pulses of the output, so there is a maximum of just over 4mSec delay (again at 4MHz), before the power changes. The PWM output is on pin C2.
The actual frequencies available, resolution, and update intervals you can use, depend on the clock rate you are running your chip. For instance if you change the setup line to:

setup_timer_2(T2_DIV_BY_4,15,16);

On the same 4MHz clock, the PWM rate, now rises to 15625Hz, and the 'update' interval becomes just under 1KHz. However the available resolution falls to only 6bits (0-64). Hence the choice of values, depends on the frequency you need to make the drive smooth for your motor, and the number of resolution steps required.
You can update the PWM frequency without using the interrupt, by just using 'set_pwm1_duty'. The use of the interrupt driven version, is especially useful, when you are performing a lot of arithmetic to set the speed required, and want to keep the update 'rate' constant, especially since you can generate a 'tick' counter in the insterrupt code, to keep the rest of the code 'in sync'. Whether this is the better solution for you will depend on the details of your application.

Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 10641
sliders_alpha



Joined: 03 Mar 2008
Posts: 55

View user's profile Send private message

PostPosted: Thu May 01, 2008 6:46 am     Reply with quote

i've tried your program but it's not working.

Code:

#include <16F877.h>
#device ADC=10
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#int_TIMER2

int power;

TIMER2_isr(){
set_pwm1_duty(power);
}

void main(void){

setup_timer_2(T2_DIV_BY_4,63,16);  //
setup_ccp1(CCP_PWM);               //
set_pwm1_duty(0);                  //
power = 0;                         // PWM INIT
enable_interrupts(INT_TIMER2);     //
enable_interrupts(global);         //

setup_adc(ADC_CLOCK_INTERNAL);     //
setup_adc_ports(RA0_ANALOG);       // ADC INIT
set_adc_channel(0);                //

long adcvalue;
output_drive(C2);

while(1){
adcvalue = read_adc();
power = adcvalue/4;
}

}


did i miss something?

also, my simulation software is returning me an error (isis 6.8 SP2) :

at 60µs (PC = 0x0049) : attemp to write an uniplanted memory location 0x009C with 0x07 ignored
_________________
yup, i know, i don't speak english very well

CCS V4.057
Gerhard



Joined: 30 Aug 2007
Posts: 144
Location: South Africa

View user's profile Send private message Send e-mail

PostPosted: Thu May 01, 2008 7:08 am     Reply with quote

Firstly just try a small program that just switches on your output as a pwm to the motor and check that this is working.

#define P1C PIN_B1
Code:
#define P1B PIN_B2
setup_timer_2(T2_DIV_BY_1, 124, 1); 
output_low(P1C);
output_low(P1B);


while(1){
       
set_pwm1_duty(124);
setup_CCP1(CCP_PWM_H_H | CCP_PULSE_STEERING_C
                                          | CCP_PULSE_STEERING_B);

}


This should generate a pwm with a duty cycle of 100% on pins B1 and B2
sliders_alpha



Joined: 03 Mar 2008
Posts: 55

View user's profile Send private message

PostPosted: Thu May 01, 2008 7:28 am     Reply with quote

B1 and B2 not C2 ans C3? well, i've got nothing on them with that

Code:

#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#int_TIMER2
#define P1C PIN_B1
#define P1B PIN_B2

void main(void){

setup_timer_2(T2_DIV_BY_1, 124, 1);
setup_ccp1(CCP_PWM);               
enable_interrupts(INT_TIMER2);     
enable_interrupts(global);         

output_low(P1C);
output_low(P1B);

while(1){
set_pwm1_duty(124);
setup_CCP1(CCP_PWM_H_H | CCP_PULSE_STEERING_C
                                          | CCP_PULSE_STEERING_B);
}

}

_________________
yup, i know, i don't speak english very well

CCS V4.057
Gerhard



Joined: 30 Aug 2007
Posts: 144
Location: South Africa

View user's profile Send private message Send e-mail

PostPosted: Thu May 01, 2008 7:39 am     Reply with quote

Check the data sheet.
Quote:
RC1/T1OSI/CCP2 12 12 I/O ST RC1 can also be the Timer1 oscillator input or Capture2
input/Compare2 output/PWM2 output.
RC2/CCP1 13 13 I/O ST RC2 can also be the Capture1 input/Compare1 output/
PWM1 output.
RC3/SCK/SCL 14 14 I/O ST RC3 can also be the synchronous serial clock input/output

If you want to use the internal PWM of the pic you need to use pin c1 or c2 as outputs to a motor. So try this but only c2 will generate a pwm on your setup.
Code:
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#int_TIMER2
#define P1C PIN_c2 

void main(void){

setup_timer_2(T2_DIV_BY_1, 124, 1);
setup_ccp1(CCP_PWM);               

output_low(P1C);

while(1){
set_pwm1_duty(124);
setup_CCP1(CCP_PWM_H_H | CCP_PULSE_STEERING_C);
                                         
}

}
sliders_alpha



Joined: 03 Mar 2008
Posts: 55

View user's profile Send private message

PostPosted: Thu May 01, 2008 8:56 am     Reply with quote

Code:

#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#int_TIMER2
#define P1C PIN_c2 

void main(void){

setup_timer_2(T2_DIV_BY_1, 124, 1);
setup_ccp1(CCP_PWM);               

output_low(P1C);

while(1){
set_pwm1_duty(124);
setup_CCP1(CCP_PWM_H_H | CCP_PULSE_STEERING_C);
                                         
}

}


it's working! thanks

what is this line for?

Code:

setup_CCP1(CCP_PWM_H_H | CCP_PULSE_STEERING_C);

_________________
yup, i know, i don't speak english very well

CCS V4.057
Gerhard



Joined: 30 Aug 2007
Posts: 144
Location: South Africa

View user's profile Send private message Send e-mail

PostPosted: Thu May 01, 2008 9:12 am     Reply with quote

You need to read up about this functions. Look at the header file and data sheet p61-63 and read the ccs manual

Quote:
mode is a constant. Valid constants are in the devices .h file and are as follows:

Disable the CCP:

CCP_OFF



Set CCP to capture mode:

CCP_CAPTURE_FE
Capture on falling edge

CCP_CAPTURE_RE
Capture on rising edge

CCP_CAPTURE_DIV_4
Capture after 4 pulses

CCP_CAPTURE_DIV_16
Capture after 16 pulses




Set CCP to compare mode:

CCP_COMPARE_SET_ON_MATCH
Output high on compare

CCP_COMPARE_CLR_ON_MATCH
Output low on compare

CCP_COMPARE_INT
interrupt on compare

CCP_COMPARE_RESET_TIMER
Reset timer on compare




Set CCP to PWM mode:

CCP_PWM
Enable Pulse Width Modulator




Returns:
undefined



Function:
Initialize the CCP. The CCP counters may be accessed using the long variables CCP_1 and CCP_2. The CCP operates in 3 modes. In capture mode it will copy the timer 1 count value to CCP_x when the input pin event occurs. In compare mode it will trigger an action when timer 1 and CCP_x are equal. In PWM mode it will generate a square wave. The PCW wizard will help to set the correct mode and timer settings for a particular application.


and from the header file
Quote:
// CCP Functions: SETUP_CCPx, SET_PWMx_DUTY
// CCP Variables: CCP_x, CCP_x_LOW, CCP_x_HIGH
// Constants used for SETUP_CCPx() are:
#define CCP_OFF 0
#define CCP_CAPTURE_FE 4
#define CCP_CAPTURE_RE 5
#define CCP_CAPTURE_DIV_4 6
#define CCP_CAPTURE_DIV_16 7
#define CCP_COMPARE_SET_ON_MATCH 8
#define CCP_COMPARE_CLR_ON_MATCH 9
#define CCP_COMPARE_INT 0xA
#define CCP_COMPARE_RESET_TIMER 0xB
#define CCP_PWM 0xC
#define CCP_PWM_PLUS_1 0x1c
#define CCP_PWM_PLUS_2 0x2c
#define CCP_PWM_PLUS_3 0x3c
long CCP_1;
#byte CCP_1 = 0x15
#byte CCP_1_LOW= 0x15
#byte CCP_1_HIGH= 0x16
// The following should be used with the ECCP unit only (or these in)
#define CCP_PWM_H_H 0x0c
#define CCP_PWM_H_L 0x0d
#define CCP_PWM_L_H 0x0e
#define CCP_PWM_L_L 0x0f

#define CCP_PWM_FULL_BRIDGE 0x40
#define CCP_PWM_FULL_BRIDGE_REV 0xC0
#define CCP_PWM_HALF_BRIDGE 0x80


The only way to learn is to use the help file and ccs manual. The pro's are not going to spoon feed you to learn. So start reading up and using google to search for the solutions
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