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

Using 2 PWM Modules With Distinct Duty Cycles

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



Joined: 14 Oct 2005
Posts: 4

View user's profile Send private message

Using 2 PWM Modules With Distinct Duty Cycles
PostPosted: Fri Oct 14, 2005 11:46 pm     Reply with quote

Great forum, it's helped me a tonne with getting up on my feet pretty quick with PIC programming.

I've seen a lot of posts on topics similar to this, but am having trouble finding a solution to the current problem I'm having. I'm a bit of an amateur, so maybe it'll just be a quick code tweak - who knows?

Without further adieu:

I'm using a PIC16F877A (40 pin PDIP) chip and want to use 3 digital inputs to control the duty cycles on the PWM pins (CCP1 & 2). I got it to work pretty well with a single PWM channel on the PIC16F88, but when I use two channels, they seem to stay at the same duty cycle, no matter the input. The duty cycles change on the scope - but it appears that PWM 1 is the same as PWM 2 no matter what I do!

My code is below - I'd appreciate any help someone can give.
Code:

CODE REMOVED


Oh yeah - here's the det's on the compiler I'm using:
IDE V3.40
PCB V3.18
PCM V3.18
PCH V3.18

And I'm aware that the values I have set in duty_## don't represent the values that the if statement says - I just wanted it to be very obvious on the scope.

Thanks for any help you can offer!


Last edited by chAli on Sun Oct 16, 2005 4:06 pm; edited 1 time in total
Ttelmah
Guest







PostPosted: Sat Oct 15, 2005 7:28 am     Reply with quote

What you show, ought to basically work. However there are some comments:
First you drive the A0 to A3 pins as outputs, with the comments that you are setting them as inputs. You are not. As soon as you use an output on a pin, it's tris control is set for it to be an output. This should be overriden latter when you use the pins as inputs, but shows perhaps a slight misunderstanding of how the I/O control works.
You then set the tris yourself for the same registers, and have the bottom four bits as '0' in the value sent to tris_A, which configures these pins as outputs again. Same comment applies.
Now you don't say how the pins are actually driven, so the possibility exists that the problem may be the levels are not what you think.
You then do a similar thing with the TRIS bits for portC. When used as a PWM output, the TRIS bit for the pin, must be cleared. You set it instead. Generally the compiler is smart enough, to everride errors like this, but you are pushing your luck by generating so many...
Now as a general comment stepping on, why read the three bits seperately, and with intervals between?. Just declare an 8bit value to hold the inputs (called for example 'pins'), and have something like:

Code:

pins=input_a() & 0x7;
switch (pins) {
    case 0:
         set_pwm1_duty(duty_0); // 0% Duty Cycle
         set_pwm2_duty(duty_0); // 0% Duty Cycle
        break;
   case 4:
         set_pwm1_duty(duty_90); // 90% Duty Cycle
         set_pwm2_duty(duty_100); // 100% Duty Cycle
         break;
   case 2:
         set_pwm1_duty(duty_0); // 0% Duty Cycle
         set_pwm2_duty(duty_0); // 0% Duty Cycle
         break;
   case 6:
         set_pwm1_duty(duty_95); // 95% Duty Cycle
         set_pwm2_duty(duty_100); // 100% Duty Cycle
         break;
   case 1:
         set_pwm1_duty(duty_100); // 100% Duty Cycle
         set_pwm2_duty(duty_95); // 95% Duty Cycle
         break;
   case 5:
         set_pwm1_duty(duty_100); // 100% Duty Cycle
         set_pwm2_duty(duty_100); // 100% Duty Cycle
         break;
   case 3:
         set_pwm1_duty(duty_100); // 100% Duty Cycle
         set_pwm2_duty(duty_90); // 90% Duty Cycle
         break;
   case 7:
         set_pwm1_duty(duty_0); // 0% Duty Cycle
         set_pwm2_duty(duty_0); // 0% Duty Cycle
         break;
   }

I have ordered these in the same arrangment used in your code.
Generally the more complex you make something like this, the more chance there is of errors.
Now you should remember that the signals will only update on the _next_ cycle of the PWM, so it is worth either delaying for a significant time, or even better possibly synchronising the loop to the PWM. This can be done by using the interrupt flag.
If you code:
Code:

#bit TMR2IF = 0xC.1

//Then change the timer setup to:
setup_timer_2( T2_DIV_BY_16, 255, 10 );

//And loop with:

while (1) {
    while (TMR2IF==0) ;
    TMR2IF=0;
    //Rest of loop here



The interrupt flag will be set every tenth PWM loop, and the code will wait at the start of the loop till this happens.
Now as for why it doesn't actually work, I'm afraid the most likely cause is a fault with yout compiler version. I don't know of one for 3.180 (I am assuming the extra digit, since version numbers are normally 3 digit), but there was one at V3.200. If this is 3.018, then a compiler fault is very likely indeed (the early V3 compilers did have problems in many cases).It may be necessary to recode the set_pwm_duty function yourself if this is the case.

Best Wishes
chAli



Joined: 14 Oct 2005
Posts: 4

View user's profile Send private message

PostPosted: Sat Oct 15, 2005 11:18 am     Reply with quote

Thanks for having a look at this for me - I'm going to try this stuff out tonight for sure!

And yeah - it's v3.180, and I wasn't sure which way to set the pins as I/O, so I tried both (apparently backwards!). Thanks for clarifying the issues.

I'll let you know how it goes.

Cheers,
Charlie
Ttelmah
Guest







PostPosted: Sat Oct 15, 2005 2:48 pm     Reply with quote

The 'way' to remember the tris directions, is '1' = 'I', and 0' = 'O'. It is a sensible bit of design by MicroChip to keep it simple. :-)
However since you are not using 'fast_io', all the setting is unnecessary. The compiler automatically generates the tris controls.

Best Wishes
chAli



Joined: 14 Oct 2005
Posts: 4

View user's profile Send private message

PostPosted: Sat Oct 15, 2005 8:15 pm     Reply with quote

I've encorporated your first suggestion into my code (Thanks!) - and thanks a lot for pointing out those errors, misunderstandings, and oversights. The informed look at my understanding of the I/O settings was key. In re-reading your post and re-writing my code, I realized that I not only messed up the '1 for Input' and '0 for Ouput' settings, but I had the MSB and LSB order reversed when I converted the binary values to hex for setting the tris.

None the less the revised version of my code is below:

Code:

CODE REMOVED


Pretty huge improvement (looks nicer too!).

I'll be scoping the outputs from the chip tomorrow afternoon, and I'll add the interrupt rountine (excellent suggestion!) if I need it. I'm trying to stick to one step at a time right now.

Again - thanks for the suggestions. What do you suggest if it turns out that these suggestions don't change the output? Is there a site/thread that you know of that can help me get started on changing the set_pwm_duty function myself as you suggested?

I'll post tomorrow evening and let you know how it turns out.

Thanks again.

Cheers


Last edited by chAli on Sun Oct 16, 2005 4:05 pm; edited 1 time in total
Ttelmah
Guest







PostPosted: Sun Oct 16, 2005 2:47 am     Reply with quote

I would add a delay in the loop, or the wait for the interrupt flag (not an interrupt routine as such). The value fed to the two registers, is latched into the actual comparison reisters at the end of each cycle of the PWM, and the possibility does perhaps exist of some sort of 'hiccup' if the values are being set/changed all the time.
It looks a lot tidier. :-)

Best Wishes
chAli



Joined: 14 Oct 2005
Posts: 4

View user's profile Send private message

PostPosted: Sun Oct 16, 2005 4:01 pm     Reply with quote

HUGE thanks. I just tested the circuit and things worked great. I'm going to move to the interrupt rountine next I think. This was a great excercise in setting the I/O registers, and an ... errr ... hilarious(?) revelation in hex-binary conversion.

Again - thanks so much 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