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

efficient code for multiple PWM signals?

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



Joined: 11 Feb 2008
Posts: 13

View user's profile Send private message

efficient code for multiple PWM signals?
PostPosted: Tue Feb 09, 2010 1:56 pm     Reply with quote

I'm trying to implement multiple PWM outputs in software with a different period and duty cycle for each signal, but am having trouble getting the code to run fast enough. I have the values for the period and duty cycle stored in arrays, but accessing them this way just takes up more time than I have between timer overflows for my interrupt routine.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Feb 09, 2010 3:34 pm     Reply with quote

How many PWM signals do you need ?

What are the frequencies of the PWM signals ?

What resolution do you need on the duty cycles ?

What PIC are you using ? What is the oscillator frequency ?
bmoore



Joined: 11 Feb 2008
Posts: 13

View user's profile Send private message

PostPosted: Mon Feb 15, 2010 10:51 am     Reply with quote

I like at least eight PWM signals

PWM frequency probably needs to be around 100 Hz

Resolution will vary from 1/32 to 1/64 (length of a "tick" will remain the same, but number of ticks in a duty cycle will vary from 32 to 64).

Currently using a 16F887 with the internal oscillator (8Mz)
SimpleAsPossible



Joined: 19 Jun 2004
Posts: 21

View user's profile Send private message

Will this get you where you want to go?
PostPosted: Fri Feb 19, 2010 2:44 pm     Reply with quote

How about you use a 6400 Hz interrupt and get rid of the arrays (for speed in the interrupt service routine)?

Code:
#INT_TIMER0
void timer0( void )
{
   TMR0 = 100; // or whatever you need to do to overflow at 6400 Hz
   PeriodCounter1++;
   if ( PeriodCounter1 > Period1 )
   {
      PeriodCounter1 = 0;
      Output1 = 0;
   }
   if ( PeriodCounter1 > DutyCycle1 )
      Output1 = 1;
   // repeat for PeriodCounter2, etc.
}


This only works if your other periods and duty cycles fit into the 6400 Hz scheme. And there will be some cycles of jitter, which will be worse on the outputs you set later in the interrupt routine, because of variation in the earlier ones. (You can eliminate that with NOPs in assembly code -- I've done that before, to ensure that every path through a certain section of code took the same amount of time. I didn't get the impression you would be that particular.)

The easiest solution is to throw more hardware at the problem. Add more PICs with hardware PWMs, with settings provided by your master PIC. Add a CPLD or FPGA with multiple PWMs. Add dedicated motion-controller ICs that have PWMs.
Ttelmah
Guest







PostPosted: Fri Feb 19, 2010 3:46 pm     Reply with quote

Funnily enough, look for code for something completely different!.
Search here for RTC code.
There was a basic algorithm posted here some time ago, for generating an accurate RTC, based upon simple integer arithmetic, to generate a rolling count, which then gave 'long term', an accurate output, from a very fast integer addition and test. The same algorithm can be used in a tick interrupt to control the setting of a PWM bit. Repeat for multple bits, and you have the basis of what is required.

Best Wishes
John P



Joined: 17 Sep 2003
Posts: 331

View user's profile Send private message

PostPosted: Sat Feb 20, 2010 8:37 am     Reply with quote

I think SimpleAsPossible has it backward--a higher duty cycle would actually lead to a smaller pulse width. To deal with that, and synchronization, and add a test for a duty cycle of 0 or >= 100% (assuming the outputs appear on Port D):

Code:

#INT_TIMER0
void timer0( void )
{
   static int8 hold_output;

   portd = hold_output;  // Do this first, before any variations occur
                         // Results calculated in previous cycle
   TMR0 = 100; // or whatever you need to do to overflow at 6400 Hz
               // but this wouldn't be necessary if you use TMR2
   PeriodCounter1++;
   if ( PeriodCounter1 > Period1 )
   {
      PeriodCounter1 = 0;
      if (DutyCycle1 != 0)
         bit_set(hold_output, 0);
   }
   if (( PeriodCounter1 > DutyCycle1 )  && (DutyCycle1 < Period1))
      bit_clear(hold_output, 0);
   // repeat for PeriodCounter2, etc.
}

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