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 controlling in matlab with 16f877a problem

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



Joined: 14 Jul 2011
Posts: 4

View user's profile Send private message

pwm controlling in matlab with 16f877a problem
PostPosted: Thu Jul 14, 2011 5:12 am     Reply with quote

Hi there. I'm dealing with the speed control of a dc motor. I use pic 16f877a working together matlab. In my project, i give a constant from -1024 to +1024 that + values are for right, - values are for left side circulation. I use rs232 in order to communicate with the pc. I know that pic only uses 8bit informations. So, my range is totally 10 bit (-1024...+1024). I write the code below of the page. Please, help about this problem.
regards...
Code:

#include <16F877A.H>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay(clock=20000000)
#use rs232(baud=115200, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

char high_bit,low_bit;
long int a,real_number,x;

#int_rda
void pwm()
    {
     high_bit=getc();
     low_bit=getc();
     a=high_bit<<8;
     real_number=a|low_bit;
     x=65535-real_number;
   
     if(x>=32767)
     {
      set_pwm1_duty(real_number);
      set_pwm2_duty(0);
     }
     else
     {
      set_pwm2_duty(x);
      set_pwm1_duty(0);
     }     
    }
     
void main()
 { 
    setup_psp(PSP_DISABLED);
    setup_timer_1(T1_DISABLED);
    setup_ccp1(CCP_PWM);
    setup_ccp2(CCP_PWM);
    setup_timer_2(T2_DIV_BY_1,255,1);
   
    enable_interrupts(int_rda);
    enable_interrupts(GLOBAL);
   
    while(TRUE)
 {
 output_high(pin_b0);
 }
 }
deperkin



Joined: 04 Feb 2009
Posts: 83
Location: PA

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

make
PostPosted: Thu Jul 14, 2011 11:28 am     Reply with quote

i believe a better name for your variables would be 'byte' instead of bit...

also you can use the make16() function for this.

also your pwm duty cycle cannot be up to ~32000.... you need to normalize this value... probably best to normalize it so it is between 0 and 100... that way you can see it as a percent duty cycle.
sametyildiz1989



Joined: 14 Jul 2011
Posts: 4

View user's profile Send private message

10bit adc 10bit pwm
PostPosted: Thu Jul 14, 2011 2:05 pm     Reply with quote

In this project, it is not wanted to use 8bit pwm. It is wanted 10 bit pwm that is synchronized with the adc 10bit values. It is said that 10 bit pwm that is commanded from the matlab constant part as -1024 to +1024 is more precise than the values that you talked about as 0 to 100. I wrote the code, I think my thinking about the code flow is right, but I don't understand what the problem is. I'm gonna try the make16() function but except from this function usage, what can the problem be about my code?
deperkin



Joined: 04 Feb 2009
Posts: 83
Location: PA

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

duty
PostPosted: Thu Jul 14, 2011 2:36 pm     Reply with quote

you are welcome to use the larger 10bit duty cycles if you like that is not an issue, but first of all you have not exactly stated what the problem is yet...

What are you seeing wrong? are you getting any outputs ?

One thing i would suggest is looking at how much time you may be spending in the interrupt.
Ttelmah



Joined: 11 Mar 2010
Posts: 19339

View user's profile Send private message

PostPosted: Thu Jul 14, 2011 3:00 pm     Reply with quote

There are several problems with the code:
First, an int_rda, means _one_ character is waiting to be read. Not two. The code will therefore have to sit and wait for the second character. Not too long at 115200, bt longer than is really desirable.
Then there is nothing to ensure synchronisation. If a byte is missed, high_bit (byte...), and low_bit (byte...), will be reversed. Perhaps you need to send a marker?.
Then, big problem with the maths. the high_bit value, is defined as a char. If you rotate a char 8 times, all the bits go out the end. You have lost your high byte, before you perform the or operation. _You_ need to ensure numeric values are large enough before performing operations. Correct sequence for the rotation is:
a=(int16) high_bit<<8;
converting the byte to an int_16 before performing the rotation.
However make_16 is much better, or a union (best). Just assemble the bytes into the required locations when they are loaded.
Finally, how can 65536, minus a 16bit value (max 65536) ever be greater than 0?. Possibly you mean to offset by 32767?.
So:
Code:

union combine {
   int16 word;
   int8 b[2];
} val;

#int_rda
void pwm(void) {
     static int1 high=TRUE;
     if (high) {
        val.b[1]=getc(); //get high byte
        high=FALSE; //Second interrupt, look for low byte
     }
     else {
         val.b[0]=getc(); //get second low byte
         //Offset X as required here
         x=val.word;
         if(x>=32767) {
            set_pwm1_duty(real_number);
            set_pwm2_duty(0);
        }
        else {
            set_pwm2_duty(x);
            set_pwm1_duty(0);
        } 
        high=TRUE; //look for high byte again   
     }
 }

I'll leave you to work out the real offset required for 'real_number'.

Best Wishes
sametyildiz1989



Joined: 14 Jul 2011
Posts: 4

View user's profile Send private message

PostPosted: Thu Jul 14, 2011 3:11 pm     Reply with quote

I'm dealing with this problem for a few days and I'm sorry for forgetting about what the problem is. My problem is exactly because of the negative pwm set values. i wrote the code for only positive pwm values that is from 0 to 1024 and it was working clearly. After i wrote the code for both negative and positive pwm values together, there was a problem about the pwm synchronization (ccp1 and ccp2). I want to change running direction between ccp1 and ccp2 for negative or positive value. and also in interrupt section. I want to finish the whole part of the pwm section in the interrupt part. I, on the other hand, take clearly the negative and positive set values -1024 to +1024 clearly and i can see the values on the display in matlab. Although the values are right that is exactly the same form with the +positive pwm values, i can take only %33,%66,%99 pwm values for the each three consecutive numbers like that"for 23=%33,24=%66,25=%99". It is not sensitive situation and my problem is absolutely composed with these situations. I hope it may be clear now.
regards..
sametyildiz1989



Joined: 14 Jul 2011
Posts: 4

View user's profile Send private message

PostPosted: Thu Jul 14, 2011 3:33 pm     Reply with quote

First of all, thanks about your sense. The offset is 32767 as you said. The negative values is set between 32767 and 65536. But I did not understand why the pwm cannot occur for the negative values while it is working for the positive values. I'm gonna try the code with the circuit tomorrow, Ttelmah. I did not understand the "val;". What can the "val;" do that you used with the "val.b[1]=getc();" ?
Regards.
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