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

Help with software PWM
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
picer



Joined: 25 Jan 2005
Posts: 28
Location: Taxahoma

View user's profile Send private message

Help with software PWM
PostPosted: Sun Feb 06, 2005 12:49 am     Reply with quote

I got it to work but I'm probably leaving alot on the table as far as processing power or maybe I'm not?

20MHz crystal
16F819

this seems to put out about a 500Hz PWM 50% duty on 3 channels, I want to have full duty cycle control and selectable freq from say 50Hz - 600Hz. 500Hz is all I can get, I put a simple serial code at the end just to see if it effects the freq and it doesn't seem to so that leads me to believe I still have some room left and maybe can make some routines that will accept the desired freq/duty via serial. Am I doing this right? Trying without interupts, with interupts I can only get around 300Hz for two channels so this is obviously much quicker. Seems as tho I need to break out of the loop somehow because I'm wasting alot of clocks counting when I no longer need to be but nothing I do makes it work right. Ideas? Just seeing how fast I can make the PWM and how many channels I can do, want at least 600Hz but 3 channels already zaps that. Just counting to 255 doesn't allow me to go to 50Hz which I'd like to be able to do so I'm using timer1 which can go 65K. I thought setting set_timer1(xxx) to a high number would do this for me but it doesn't affect the freq one bit, guess I don't understand it's function.

Thanks, hope this makes sense.

Code:

void main()
{
   int status;
      char value;
   long OnTime = 100;
   long OnTime1 = 50;
   long OnTime2 = 100;
   long OffTime = 100;
   long OffTime1 = 50;
   long OffTime2 = 50;

   setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
   set_timer1(0);

   while (true)
   {
      while ( get_timer2() < 65536 )
      {
         if (OnTime > 0)
                  {
                 output_high(PIN_B3);
           OnTime--;
                  }
         else                       
                  if (OnTime == 0 && OffTime > 0)
         {
                     output_low(PIN_B3);
            OffTime--;
         }
         else
         if (OnTime == 0 && OffTime == 0)
         {
           OnTime = 100;
           OffTime = 50;
         }


         if (OnTime1 > 0)
                 {
               output_high(PIN_B0);
           OnTime1--;
                 }
         else                       
                  if (OnTime1 == 0 && OffTime1 > 0)
         {
                    output_low(PIN_B0);
           OffTime1--;
         }
         else
         if (OnTime1 == 0 && OffTime1 == 0)
         {
           OnTime1 = 100;
           OffTime1 = 50;
         }


         if (OnTime2 > 0)
                  {
               output_high(PIN_B1);
           OnTime2--;
                  }
         else                       
                  if (OnTime2 == 0 && OffTime2 > 0)
         {
                    output_low(PIN_B1);
           OffTime2--;
         }
         else
         if (OnTime2 == 0 && OffTime2 == 0)
         {
           OnTime2 = 100;
           OffTime2 = 50;
         }
      }
                status=1;
            printf("\r\nStart typing:\r\n");
            printf("Hello");
           printf("Hello");
         while(!kbhit());

            while(status==1)
            {
               value=timed_getc();
               if(value==0)
                  status=0;
               else
               {
                  status=1;
                  putc(value);
               }
            }
            printf("\r\nToo slow!\r\n");
   }
}
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

Re: Help with software PWM
PostPosted: Sun Feb 06, 2005 1:32 am     Reply with quote

First,

Let me suggest the 16F628 as it has a hardware UART onboard... when you write/read RS232, it won't suck horrible amounts of time bit-banging data in and out of your PIC.

As for your routine, you could make it an ISR which would help a bunch as you would only jump to do something on intervals accordingly.

I don't know if one way compiles better than the other, but look at the timer0 code included with PIC-C. It uses a global var and a constant for "INTS_PER_SECOND" (which you divide CLK/4/prescalr and so on) and then has an ISR (could be timer0 or timer1, whichever) that auto-counts down to zer0 then resets. You could easy have:

Code:

void timer1_isr() {

      if (!counter--) {
          output_low(PIN_B0);
          output_low(PIN_B1);
          output_low(PIN_B2);
          counter = INTS_PER_SECOND;
       } else {
            if (counter == duty1) {
                output_hi(PIN_B0);
            }

            if (counter == duty2) {
                output_hi(PIN_B1);
            }

            if (counter == duty3) {
                output_hi(PIN_B2);
            }
       }
}


What's nice about this is that you don't need the both ON and OFF constants. This is PWM, which typically isn't symmetrical.

Make sure your ISR's are as short as they can be.

You could even write this in a struct kinda way to make all PWM's go to 0 at the same time (now they're an instruction apart)... making them synchronous. Might be handy. For the frequency you want, this might work ok... this is what I would shoot for first. Interrupts are fun. ;)

Then again, I'm writing this as 1:26amCST. I could be crazy.
picer



Joined: 25 Jan 2005
Posts: 28
Location: Taxahoma

View user's profile Send private message

PostPosted: Sun Feb 06, 2005 10:19 am     Reply with quote

Doing interupts simply isn't fast enough, I've tried everything I can and simply can't even get two pwm greater than 300Hz and actually can't even get > 600Hz with 8bit resolution with one pwm either hense trying without interupts. I've certainly learned alot about interupts trying all this, I admit I need to know more about how a pic works and this is getting me there pretty fast, just wondering if I'm missing something with how i'm doing it now (non interupts).
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Sun Feb 06, 2005 2:21 pm     Reply with quote

picer wrote:
Doing interupts simply isn't fast enough, I've tried everything I can and simply can't even get two pwm greater than 300Hz and actually can't even get > 600Hz with 8bit resolution with one pwm either hense trying without interupts. I've certainly learned alot about interupts trying all this, I admit I need to know more about how a pic works and this is getting me there pretty fast, just wondering if I'm missing something with how i'm doing it now (non interupts).


Er, ok...

Have you consider some of the multi-output I2C based PWM drivers from folks like Maxim IC?

If you told us more about your application, perhaps we could make some alternate suggestions?

-Ben
picer



Joined: 25 Jan 2005
Posts: 28
Location: Taxahoma

View user's profile Send private message

PostPosted: Sun Feb 06, 2005 2:33 pm     Reply with quote

I've yet to find any that will go down to 50Hz but maybe I've missed a few, been looking.
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Sun Feb 06, 2005 3:08 pm     Reply with quote

picer wrote:
I've yet to find any that will go down to 50Hz but maybe I've missed a few, been looking.


The fact that you say 50Hz leads me to believe you want a signal generator - not a PWM.

PWM is constant freq w/adj duty cycle.
DDS is constant duty cycle with adjustable frequency.

If you want a DDS, look on Analog Devices website. They have DDS's that work down to millihertz if you need it.

I just recently finished designing a 200MHz DDS with a PIC controlling it via SPI. Works great.

This one looks like a good fit and it's only $4 (in quantity - I'm sure you could get a sample or two)

http://www.analog.com/en/prod/0,,770_843_AD9833%2C00.html

Might be overkill - but boy it'd work!
picer



Joined: 25 Jan 2005
Posts: 28
Location: Taxahoma

View user's profile Send private message

PostPosted: Sun Feb 06, 2005 4:59 pm     Reply with quote

No, constant freq but selectable with variable duty. I had it in another thread but since this was a software (non interupt) solution I seperated it. I would love a hardware solution but like I said have yet to find a chip that will do what I need, 50Hz-650Hz (selectable) with precision duty cycle (0-100). Like i said i can do two channels but that seems to be the limit for 20MHz. I found one but you set freq with a res/cap and hense it's not software selectable.
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Sun Feb 06, 2005 7:32 pm     Reply with quote

picer wrote:
No, constant freq but selectable with variable duty. I had it in another thread but since this was a software (non interupt) solution I seperated it. I would love a hardware solution but like I said have yet to find a chip that will do what I need, 50Hz-650Hz (selectable) with precision duty cycle (0-100). Like i said i can do two channels but that seems to be the limit for 20MHz. I found one but you set freq with a res/cap and hense it's not software selectable.


Ok, you are now saying opposing things. "Constant frequency", "but selectable" and "(50-650Hz)"

That's not constant frequency.

As for the precision duty cycle, how precision??

Better details would help us help you...
picer



Joined: 25 Jan 2005
Posts: 28
Location: Taxahoma

View user's profile Send private message

PostPosted: Sun Feb 06, 2005 7:56 pm     Reply with quote

Not opposing in my mind, of course you can't read my mind Smile Range is 50Hz to 650Hz, user selectable, 1% duty increments. So I want to select 50Hz (0-100% duty) on one channel, 100Hz (0-100% duty) on another, etc. As many channels as i can get out of one pic which to date has only been two channels because if I go 3 channels the max freq only makes it to around 400Hz then. I could do probably 4-5 50Hz channels pretty easy but want to at least be able to do one at 650Hz. clear as mud? I might just be at the limit of the pic at this point.
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

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

PostPosted: Sun Feb 06, 2005 8:07 pm     Reply with quote

Any frequency between 50 and 650Hz?
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Sun Feb 06, 2005 8:08 pm     Reply with quote

picer wrote:
Not opposing in my mind, of course you can't read my mind Smile Range is 50Hz to 600Hz, user selectable, 1% duty increments. So I want to select 50Hz (0-100% duty) on one channel, 100Hz (0-100% duty) on another, etc. As many channels as i can get out of one pic which to date has only been two channels because if I go 3 channels the max freq only makes it to around 400Hz then. I could do probably 4-5 50Hz channels pretty easy but want to at least be able to do one at 600Hz. clear as mud? I might just be at the limit of the pic at this point.


Ok.. gotcha... Now it's clear.

Hmmm.. 20MHz. is a 200nS instruction. If it was coded right, I think it could be done... but I'd have to dig into it with you.

I think it could be done. Make sure you're using fast_io. Looks at the .ASM to see how efficient what you're doing is...

I wouldn't bother using the hardware timers.. just run your code flat out. Check the instructions you're using for the IO high/low. I've found structures mapped onto IO ports like the examples in the PIC-C code are nice and fast.

That might help ya...

-Ben
picer



Joined: 25 Jan 2005
Posts: 28
Location: Taxahoma

View user's profile Send private message

PostPosted: Sun Feb 06, 2005 10:09 pm     Reply with quote

I've tried fast_io and when I do the pic does absolutly nothing but suck up 5 volts. Not sure if the 819 or the compiler is at fault but that doesn't work. Trying to drive some solenoids that call for certain freqs but figured why stop there and make it user selectable and learn something in the process. My first real venture into pics, done some led flashing before but that's about it. Also finding C is just a little different in the pic world. wish I knew assembly well enough, I can somewhat read and follow it but can't program in it.
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Mon Feb 07, 2005 12:20 am     Reply with quote

picer wrote:
I've tried fast_io and when I do the pic does absolutly nothing but suck up 5 volts. Not sure if the 819 or the compiler is at fault but that doesn't work. Trying to drive some solenoids that call for certain freqs but figured why stop there and make it user selectable and learn something in the process. My first real venture into pics, done some led flashing before but that's about it. Also finding C is just a little different in the pic world. wish I knew assembly well enough, I can somewhat read and follow it but can't program in it.


fast_io works, but it makes assumptions that the programmer is in control of everything and thus if you don't set everything up properly, it does nothing.

So, it's neither the 819 or the compiler. It's how you're doing it. Look at the PIC-C docs for better detail. I use it all the time.

Actually, C for a lot of micro's is the same way. Programmers coming from OS's like Windows or Linux think it's going to be the same. It is not. Not by a long shot. Shocked

I would say that PIC-C is the best I've seen. The others are pretty much no fun. But then again, I'm a hardware guy.. I just program cause I'm the one designing the circuits.

Assembly is good for hand-tuning critical stuff... but for the most part, with PIC-C, unnecessary.

Just keep at it... the more one practices anything, the better they get at it.

-Ben
picer



Joined: 25 Jan 2005
Posts: 28
Location: Taxahoma

View user's profile Send private message

PostPosted: Tue Feb 08, 2005 9:09 am     Reply with quote

I've tried every example I could with fast_io and everytime I try it the pic does nothing, must be a bug. I've optimized my routines a little and now have it faster but guess I'm stuck with one pic per PWM for what I want. I can use the very little time left to do some i2c reads and a/d so guess that will work.
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

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

PostPosted: Tue Feb 08, 2005 9:39 pm     Reply with quote

picer wrote:
I've tried every example I could with fast_io and everytime I try it the pic does nothing, must be a bug. I've optimized my routines a little and now have it faster but guess I'm stuck with one pic per PWM for what I want. I can use the very little time left to do some i2c reads and a/d so guess that will work.


Did you set the tris register? Must be a bug doesn't cut it! Look at the LST file to see what is going on. Keep it simple, that will make it easier.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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