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 getc slow code

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



Joined: 16 Jan 2016
Posts: 17
Location: Brazil

View user's profile Send private message

Pwm getc slow code
PostPosted: Sat Jan 16, 2016 10:10 am     Reply with quote

Good morning, I'm doing a PWM controlled via RS232 to control a servo motor, however when using the getc () command the code is slow and generates pulses with more than 1sec. If you assign a fixed value to control variable, it can pulse in microseconds. I used RDA interrupt Timer and nothing. PWM is slow with getc command, which can be made precise pulse with 1 to 2 ms and 50 Hz.
Thank you for your help
Here is the code.

Code:
//PWM over rs232 RF433

#include <16F877A.h>
#fuses HS, NOWDT, NOPROTECT, NOLVP, NOPUT
#fuses NOBROWNOUT, CPD, NODEBUG, NOWRT
#use delay(clock=20MHz)
#use rs232(baud=9600, rcv=PIN_C7, bits=8, parity=N)

void main()
{
    int32 x = 0; 
   // int8 c = 0;    //code slow
 int8 c = 20;       // code fast
   while (true)
   {
   
      for (x = 0; x < 100; x++)
      {
         if (x > c)
         {
            output_low (pin_b1);
         }

         if (x < c)
         {
            output_high (pin_b1);
         }
                if (x == 100)
         {
           
            x = 0;
         }
        // c= getc ();      //make code slow, I need this to work fast PWM
      }
         }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Jan 16, 2016 10:44 am     Reply with quote

Laus wrote:

// c= getc (); //make code slow, I need this to work fast PWM

Add the parameters shown in bold below:
Quote:
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=N, ERRORS)

This will make the compiler use the hardware UART.

And also call kbhit() to see if a character is ready:
Code:

if(kbhit())
 c=getc();     
 
Laus



Joined: 16 Jan 2016
Posts: 17
Location: Brazil

View user's profile Send private message

PostPosted: Sat Jan 16, 2016 11:03 am     Reply with quote

Ok perfect PCM programmer thank you! So one more thing the pulse is a bit unstable it increases and decreases few microseconds alone there is something that can be done to stabilize?
Ttelmah



Joined: 11 Mar 2010
Posts: 19219

View user's profile Send private message

PostPosted: Sat Jan 16, 2016 2:48 pm     Reply with quote

Obvious answer. Use the hardware PWM.

Functions all take time. It takes a few instructions to read a value if it is available, so 'of course' the PWM will change.

The way to do a 'slow' PWM (for servos etc.), is to use the CCP, rather than the PWM itself. Remember the CCP, in 'compare' mode, is a programmable timer, that allows you to select to change a pins state, or just to trigger an interrupt at a precisely defined interval. You can if you want just trigger the interrupt (and if you want, just 'poll' this, rather than calling a interrupt handler), to give times that are hardware determined, rather than dependant on instruction counts. Alternatively, you can use a similar approach, but just setting a timer to a value, and wait for the timer to wrap (again polling the interrupt bit for the timer), to give hardware determined times. Other thing to remember is that most servos don't actually 'care' how long the gap is between pulses. It is the pulse width that determines position. So do things that involve indeterminate times, in the 'gap'.
Laus



Joined: 16 Jan 2016
Posts: 17
Location: Brazil

View user's profile Send private message

PostPosted: Sun Jan 17, 2016 1:53 pm     Reply with quote

Almost going to the dark side of the force, AVR.
Ttelmah



Joined: 11 Mar 2010
Posts: 19219

View user's profile Send private message

PostPosted: Sun Jan 17, 2016 3:14 pm     Reply with quote

Which would do the same unless you use the hardware....
Laus



Joined: 16 Jan 2016
Posts: 17
Location: Brazil

View user's profile Send private message

PostPosted: Sun Jan 17, 2016 3:39 pm     Reply with quote

Exactly avr has 6 PWM hardware for the same price for a pic with 1, but I still insist on the pic already made investment.
Ttelmah



Joined: 11 Mar 2010
Posts: 19219

View user's profile Send private message

PostPosted: Mon Jan 18, 2016 4:20 am     Reply with quote

Start at the beginning. Why use such an old chip?. The 877A, is about 15 years old. Many of the modern replacements have four or six PWM's.

Second the 877A, has two PWM's not one. However for the slow times needed for the servo, the CCP itself is the 'better' peripheral. To just do this in software/hardware using the CCP:
Code:

//PWM over rs232 RF433

#include <16F877A.h>
#fuses HS, NOWDT, NOPROTECT, NOLVP, PUT
#fuses NOBROWNOUT, CPD, NODEBUG, NOWRT
//You should always use PUT when the crystal is used
#use delay(clock=20MHz)
#use rs232(BAUD=9600, UART1, ERRORS, BITS=8, PARITY=N) //ensure hardware UART used

#inline
int16 times_fifty(int8 val)
{
   //efficient multiply by 50 from an int8 0 to 100
   int16 result;
   result=(int16)val*32;
   result+=(int16)val*16;
   result+=val*2;
   return result;
}

void main()
{
   int8 c = 20;
   int1 flag=FALSE; //loop flag
   //Now generating a 50Hz master loop, with pin b1 having controlled
   //width in 100 steps from 1 to 2mSec at the start of this loop
   setup_timer_1(T1_DIV_BY_1 | T1_INTERNAL);
   //Timer1 now running from 5MHz. So 100000 counts/1/50th second
   setup_CCP1(CCP_COMPARE_INT); //CCP1 will now set it's interrupt when the
   //count is reached
   while (true)
   {
      set_timer1(0);
      output_high(PIN_B1); //turn pulse on
      //Now need to program how long I want the pulse to be. At 100000 counts
      //per 50th second, 1mSec = 5000 counts
      //Using 'c' as the width, based on 0-100 = 1 to 2mSec
      CCP_1=times_fifty(c)+5000; //now 5000 to 10000
      clear_interrupt(INT_TIMER1);
      clear_interrupt(INT_CCP1);     
      while (!interrupt_active(INT_CCP1))
         ; //wait for 'CCP_1' counts
      output_low(PIN_B1); //and turn pulse off
      //Now need to wait for the residue of 100000 counts
      //also check serial while waiting
      flag=FALSE; //For the first 65536 counts
      while (TRUE)
      {
          if (flag && interrupt_active(INT_CCP1)) //Now have 65536+34464 counts
             break; //exit loop
          if (interrupt_active(INT_TIMER1))
          {
             //timer has reached 65536
             flag=TRUE;
             CCP_1=34463; 
             //100000 = 65536+34464
             clear_interrupt(INT_TIMER1);
             clear_interrupt(INT_CCP1);
          }
          if (kbhit())
          {
             c=getc();
             if (c>100)
               c=100; //in case character>100 arrives
          }
      }
   }
}


Last edited by Ttelmah on Mon Jan 18, 2016 2:26 pm; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19219

View user's profile Send private message

PostPosted: Mon Jan 18, 2016 10:02 am     Reply with quote

As a further comment, since it needs 5000 counts for 1mSec as setup here, if 'c' could be ASCII 0 to 156, then *32 could be used instead of *50.
Code:

          CCP_1=t(int16))c*32+5000;

//and when getting the character
          if (c>156)
               c=156; //in case character>156 arrives


Finer resolution, and more efficient.
Laus



Joined: 16 Jan 2016
Posts: 17
Location: Brazil

View user's profile Send private message

PostPosted: Mon Jan 18, 2016 5:49 pm     Reply with quote

Really 877 is an old pic but it is cheap and has no use for professional purposes it serves well. I have done many projects with him and set as a base, not yet had the need to use a more sophisticated pic. I am still learning to program, I have over 20 years experience in electronics but just over 3 in programming and the time and very short to dedicate. With a simple pic I learn more because I have to make up for the lack of hardware with software. Your code is very nice I will study it and extends it to my project.
Thank you for your help.
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