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 CCS Technical Support

sine PWM inverter code going crazy
Goto page Previous  1, 2, 3, 4, 5, 6  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Ttelmah



Joined: 11 Mar 2010
Posts: 19569

View user's profile Send private message

PostPosted: Wed Dec 19, 2012 4:09 pm     Reply with quote

GOBER wrote:
T check this

http://www.4shared.com/photo/HSMUphwe/Untitled.html?

Doesn't work for me. It is probably blocked by the firewalls I run inside (NSA4), but the funny thing is that the scope pictures are fine.

Best Wishes
GOBER



Joined: 22 Jul 2010
Posts: 41

View user's profile Send private message

PostPosted: Wed Dec 19, 2012 4:22 pm     Reply with quote

mike
wether fifth or first. there i a problem that i must solve. please help me work it out

thanks
GOBER



Joined: 22 Jul 2010
Posts: 41

View user's profile Send private message

PostPosted: Wed Dec 19, 2012 4:32 pm     Reply with quote

Ttelmah, try this. i hope it will work

http://www.4shared.com/photo/ZtYzIMm5/DSO_Proteus_32-point_array.html?
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Wed Dec 19, 2012 4:49 pm     Reply with quote

GOBER wrote:
mike
wether fifth or first. there i a problem that i must solve. please help me work it out

thanks
Yes. I agree, but:-

You can't get the right answer 'til you ask the right question.

It doesn't help if you're looking in the wrong place.

Gpsmikey's idea should help you pin down where the problem lies.

I'll dig out some gear out and try a few ideas.

Mike
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Thu Dec 20, 2012 3:52 am     Reply with quote

OK. So I've slept on it.

Try this:-
Code:
while (get_timer2() >10) {};
set_pwm1_duty(duty_cycle[i]);
Normally when you get to the setting duty cycle stage timer2 has counted to at least 40. Your set duty cycle code itself takes 10's of cycles to execute.

The idea here is that the code waits till timer2 overflows, then sets the duty cycle with less risk of being near timer2 overflowing again.

Even better, lookup the array value, then feed that into 'set_pwm1_duty()' and save the array manipulation time.

Mike
Ttelmah



Joined: 11 Mar 2010
Posts: 19569

View user's profile Send private message

PostPosted: Thu Dec 20, 2012 5:16 am     Reply with quote

and (obviously), reduce the count before interrupt, from 5 to 4. The interrupt will now load the duty on the second cycle after it is called.

I'd actually suggest:

Code:

int_TIMER2
void TIMER2_isr(void) {
   static int1 toggle=0;
   int16 new_value;
   if(++i==32) {
       i=0;
       toggle^=1;
   }
   if (i==1) {
       output_low(PIN_A1);
       output_low(PIN_A5);
       if (toggle) {
          output_high(PIN_A5);
       }
       else {
          output_high(PIN_A1);
       }   
   }
   new_value=duty_cycle[i]; //all the slow work of the table lookup
   //has now been done
   while (get_timer2() >10) ;
   set_pwm1_duty(new_value);
}

This way you lookup the next value to load (takes the longest time), _then_ wait for the next cycle update.

Best Wishes
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Thu Dec 20, 2012 6:39 am     Reply with quote

Ttelmah wrote:
and (obviously), reduce the count before interrupt, from 5 to 4. The interrupt will now load the duty on the second cycle after it is called.

I'd actually suggest:

Code:

int_TIMER2
void TIMER2_isr(void) {
   static int1 toggle=0;
   int16 new_value;
   if(++i==32) {
       i=0;
       toggle^=1;
   }
   if (i==1) {
       output_low(PIN_A1);
       output_low(PIN_A5);
       if (toggle) {
          output_high(PIN_A5);
       }
       else {
          output_high(PIN_A1);
       }   
   }
   new_value=duty_cycle[i]; //all the slow work of the table lookup
   //has now been done
   while (get_timer2() >10) ;
   set_pwm1_duty(new_value);
}

This way you lookup the next value to load (takes the longest time), _then_ wait for the next cycle update.

Best Wishes


I think the count before interrupt stays at 5. It should not matter that one of the overflows is now inside the ISR.

I was leaving GOBER to work out the new_value section.

Mike
Ttelmah



Joined: 11 Mar 2010
Posts: 19569

View user's profile Send private message

PostPosted: Thu Dec 20, 2012 7:39 am     Reply with quote

Yes, the postscaler is independant of the interrupt being cleared.
Was forgetting this. Smile

As another comment, I wonder if he has considered not having an ISR at all. Just polling the interrupt bit in the main loop. Then all the preloading etc., can be done here, then pause waiting for the update, and loop again. Potentially much better timings.

Best Wishes
GOBER



Joined: 22 Jul 2010
Posts: 41

View user's profile Send private message

PostPosted: Thu Dec 20, 2012 2:46 pm     Reply with quote

Guys I went with your suggestion but still having the same problem. I will try T's idea of doing everything n the main loop. Will feed you back with results. If any other ideas please Let me know
Ttelmah



Joined: 11 Mar 2010
Posts: 19569

View user's profile Send private message

PostPosted: Thu Dec 20, 2012 3:53 pm     Reply with quote

Seriously, post what you are now using. With the array 'pre-read' into a local variable, the transfer will only take a couple of machine cycles. Timing should not be your problem, you have plenty of time to do what you were showing without problems, your fault is somewhere else. This is what Mike has been (strongly) hinting, and you really need to work out what is actually going on.

Best Wishes
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Thu Dec 20, 2012 5:37 pm     Reply with quote

Ttelmah wrote:
Seriously, post what you are now using. With the array 'pre-read' into a local variable, the transfer will only take a couple of machine cycles. Timing should not be your problem, you have plenty of time to do what you were showing without problems, your fault is somewhere else. This is what Mike has been (strongly) hinting, and you really need to work out what is actually going on.

Best Wishes
Yes. I agree, it's beginning to look like timing's not the real issue. Even with the array lookup, the entire ISR (getting in, code, getting out) takes less than the 125 cycles from one timer2 overflow to the next. (That is with the 16F and 18F parts I've tried. I guess the 12F performance should roughly match that for the 16F.)

Mike

I believe that the data transfer to the PWM takes somewhat more than a couple of cycles. When I tried the code on a 16F877A, my compiler created code with eight instructions between writing to CCPR1L and the CCP1CON register. The processor takes time to convert a 16bit value to an 8bit one for CCPR1L and the 2bits for the PWM LSBs in CCP1CON.
Ttelmah



Joined: 11 Mar 2010
Posts: 19569

View user's profile Send private message

PostPosted: Fri Dec 21, 2012 2:38 am     Reply with quote

Yes. That is (of course), because of the odd layout of the two extra bits.

As a further 'saves a hell of a lot of time' comment, 'why use 10bit PWM'?.
If the PWM table was 8bit, you would massively reduce the time needed to fetch the numbers, and get rid of this overhead as well. With the 125 being used for the divisor now, you'd still get more than 6bits of accuracy, and about halve the total time needed. You'd also double how large the table can be before page overflows occur, and make the tables small enough, that two could be fitted into RAM. So you could have the interrupt code using RAM tables (much faster to access), and selecting between two of these according to a 'flag', and then in the main, copy into the 'unused' table the one you want to use to adjust the power, and switch the flag to say 'use this one'.

Best Wishes
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Fri Dec 21, 2012 3:07 am     Reply with quote

I consider there's another good reason for going to 8bit.

With a 125 divisor there's only 7 bit resolution in the time direction, so little point in exceeding 8bit in amplitude.

But there's still the nagging question. What's the fundamental cause of the problem being encountered? My initial thought was it was somehow related to CCPR1L and CCP1CON registers being written at different times. If it was the case, the error should only be in the two LSBs, the amplitude error shown on the 'scope traces is much greater then that. So, the underlying cause is elsewhere.

As yet we've not been shown traces indicating whether the problem is with the fifth or first pulse. In that respect we don't know where to start looking.

Mike
Ttelmah



Joined: 11 Mar 2010
Posts: 19569

View user's profile Send private message

PostPosted: Fri Dec 21, 2012 4:28 am     Reply with quote

The PIC itself synchronises the two registers. When the timer match occurs, it latches the two extra bits 'into' the actually10bit CCPR1H register, and then copies the whole 10bit value into the timing register. Effectively the registers are double buffered to avoid the problem of the update timing.
However I wonder about the little erratum for the chip:

"The PWM module may generate a premature
pulse when changing the duty cycle.
For sensitive applications, disable the
PWM module prior to modifying the duty
cycle."

This is quite awkward to do. Given that the standard point at which the chip interrupts, is while the signal is driving high. I think you'd need to read the pin (use fast_io mode), till it goes low, and disable the PWM, then update the timing ASAP, and re-enable the module.

This only applied to older chips - wonder if Proteus is simulating a fault that is not there on current chips. Again the question 'does it do this for real' applies.... (pre 2007)

Might be the problem.

Best Wishes
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Fri Dec 21, 2012 6:28 am     Reply with quote

Ttelmah wrote:
The PIC itself synchronises the two registers. When the timer match occurs, it latches the two extra bits 'into' the actually10bit CCPR1H register, and then copies the whole 10bit value into the timing register. Effectively the registers are double buffered to avoid the problem of the update timing.
However I wonder about the little erratum for the chip:

"The PWM module may generate a premature
pulse when changing the duty cycle.
For sensitive applications, disable the
PWM module prior to modifying the duty
cycle."

This is quite awkward to do. Given that the standard point at which the chip interrupts, is while the signal is driving high. I think you'd need to read the pin (use fast_io mode), till it goes low, and disable the PWM, then update the timing ASAP, and re-enable the module.

This only applied to older chips - wonder if Proteus is simulating a fault that is not there on current chips. Again the question 'does it do this for real' applies.... (pre 2007)

Might be the problem.

Best Wishes

I did look through the data sheet but missed the errata you've found. Does the errata apply to 12F parts only, or is it more general? Certainly looks like a plausible reason for the fault.

However I can see it being very awkward to apply the work round. The duty cycle ranges from zero to 100%. So, sometimes you'ld be looking to update the PWM when the output signal was low, and others when it's high! I'm sure it could be done.

GOBER is showing some DSO traces from real silicon. Are the chips old? (Date codes?)
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 Previous  1, 2, 3, 4, 5, 6  Next
Page 5 of 6

 
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