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

Control DCmotor with PWM and feedback on the LCD(16F877A)

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



Joined: 02 Sep 2008
Posts: 2

View user's profile Send private message Yahoo Messenger

Control DCmotor with PWM and feedback on the LCD(16F877A)
PostPosted: Tue Sep 02, 2008 9:56 am     Reply with quote

I use the PWM in PIC-16F877A to control rate of DCmotor and use encoder(motor) to feed back the rate of motor on the LCD.But I I have a problem to transfer rate on the LCD..I don't know why the rate not feedback.
Help me.
Thank's you..
Version of your compiler: CCSC 4.065
Target PIC Microcontroller:16F877A
Target voltage 5V
Target oscillator speed, type 8MHz
C source code:
Code:
#include <16f877a.h>
#include <def_877a.h>
#FUSES NOWDT, HS, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=8000000)
#include <lcd_lib_4bit.c>
int16 cnt,cnt2,x,v;
int8 a,b,c;
#int_TIMER0
void  TIMER0_isr(void) //TIMER0 counting
{
set_timer0(255);
if(tmr0if==1)
 {
 cnt++;
 tmr0if=0;
 }
}
#int_TIMER1           //TIMER1 timing
void  TIMER1_isr(void)
 {
 set_timer1(5565);
 if(tmr1if==1)
   {
    x=get_timer0()*4;   
    v=(x*60)/((100*60*0.001));
     tmr1if=0; 
  }
 }
void Lcd()
{
while(1)
   {
   a=(int)v/100;
   b=(int)(v-a*100)/10;
   c=(int)v%10;
   LCD_putcmd(0xC0);
   LCD_putchar("xung encoder");
   LCD_putcmd(0x80);
   LCD_putchar(a+48);
   LCD_putcmd(0x81);
   LCD_putchar(b+48);
    LCD_putcmd(0x82);
    LCD_putchar(c+48);
   }   
}
void interrupt()
{
   set_timer0(255);
   setup_timer_0(RTCC_EXT_L_TO_H|RTCC_DIV_4);
   enable_interrupts(INT_TIMER0);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_2);
   set_timer1(5565);
   enable_interrupts(INT_TIMER1);
  enable_interrupts(GLOBAL);
  }
void PWM()
{
   setup_timer_2(T2_DIV_BY_16,255,1);
   setup_ccp1(CCP_PWM);
   setup_ccp2(CCP_PWM);
   set_pwm1_duty(1000);
   set_pwm2_duty(1022); 
}
void main()
{
   set_tris_d(0);
   set_tris_a(0xff);    // RA4
   set_tris_c(0);
   LCD_Init();
   PWM();
   interrup();
   Lcd();
   delay_ms(100);
}

_________________
RBCteam
Ttelmah
Guest







PostPosted: Wed Sep 03, 2008 2:50 am     Reply with quote

First, in the timer0 ISR, the ISR, will _only_ be called if the interrupt flag is set. You do not need to test for this. Unwanted extra time. Also, the compiler will automatically clear the flag, unless told not to. Another waste.
Big problem then. You are setting the counter to 255. The chip will interrupt as soon as the counter advances by just one. You have the /4 prescaler, but don't say what frequency the external clock feeding this is?. If it is anything faster than perhaps 80KHz, the processor will basically never get out of this interrupt...
Then in timer1, you set it 'to' a count. Do a search here about this. Your timings here will never be accurate. Again you waste time testing the interrupt flag. You then show a stupid maths operation!... Fortunately the compiler ought to optimise most of this away. Why 'stupid'. You have a _floating point_ value in the sum. Floating point arithmetic is _slow_. Most of the sum can be pre-calculated, and the compiler will do this for you. However, it'll still result in a floating point sum for the remaining part. Look at it for a moment. 100*60*0.001 = 6. Perform this yourself. The compiler will do this, but will end up with _6.0_. Notice the decimal point. As a result the compiler will perform the next bit of arithmetic using floating point. All you have is (x*60)/6. Why not just use x*10, and do the whole thing in integer, which is reasonably fast...
Again you clear the interrupt unnecessarily.
You show the 'main' calling a routine called 'interrup', but don't have one of this name. Typing error?.
Then in your timer1 code, you read timer0. Now, the value on this, can only be 255, or 0 (or the small amount about this, corresponding to any counts made since timer1 interrupted), since you are setting it to 255, and resetting it whenever it counts to 0...
Then in the LCD code, you take the value in 'v' (timer0 *10), convert it to an int8, throwing away anything above 255, and then divide this by 100. You are never going to see anything making much sense from this....
You then take the v value again, subtract the result of the above, _convert this to int8_, again throwing away any high bits, and divide by 10. Then you finally take the modulus of v (again converted to int8 first...)/10.
I think you need to understand how bracketing affects when things like the cast operation apply...

Best Wishes
popeye_ts22



Joined: 02 Sep 2008
Posts: 2

View user's profile Send private message Yahoo Messenger

PostPosted: Wed Sep 03, 2008 12:23 pm     Reply with quote

Hi. I see. I've do it well. Thank's you very much. Razz
_________________
RBCteam
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