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

sine PWM inverter code going crazy
Goto page 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
GOBER



Joined: 22 Jul 2010
Posts: 41

View user's profile Send private message

sine PWM inverter code going crazy
PostPosted: Sun Dec 09, 2012 9:25 am     Reply with quote

Hello everybody

I'm trying to implement a sine wave inverter at 20KHz. I used 40 duty cycle values that are repeated 5 times each during every half cycle. that is, 0 is sent 5 times, then 21 is sent 5 times and so on. The code is going crazy. What am I missing or doing wrong?. Could you please check it out.

I'm using PIC12F683. There are 600 point in the array to be used for feedback later, which I have not implemented yet. For now I'm only using the first 40 points in an attempt to see weather i will get a sine wave or not at the output of the transformer.

If I decrease the number of points to 40 in the array, i.e. delete all other point, everything works fine. Just when I increase the number of points in the array above 90 I think problems start.

Instead of i==5, i use i==4 to count. it counts five times correctly. i==5 counts six times!!!!

I had to use a delay of 150us in order to make the switch open and close symmetrically!!!!!

Here is the code. I hope someone will try it and let me know what's happening.
Code:

#include "D:\Projects\CCS C Software projects\Sine Wave Inverter\main.h"

int i=0,j=0;   //'i' will count for how many times each point is sent and 'j'                    will count for the total number of points

const int16 duty_cycle[600]={0, 21, 42, 62, 82, 101, 120, 138, 156, 172, 187, 201, 213, 225, 234, 242, 249, 254, 257, 259, 259, 257, 254, 249, 242, 234, 225, 213, 201, 187, 172, 156, 138, 120, 101, 82, 62, 42, 21, 0,   
                             0, 22, 43, 64, 85, 105, 125, 144, 162, 179, 194, 206, 221, 234, 243, 252, 259, 264, 267, 269, 269, 267, 264, 259, 252, 243, 234, 221, 206, 194, 179, 162, 144, 125, 105, 85, 64, 43, 22, 0,
                             0, 22, 45, 66, 88, 109, 129, 149, 168, 185, 202, 216, 230, 242, 252, 261, 268, 274, 277, 279, 279, 277, 274, 268, 261, 252, 242, 230, 216, 202, 185, 168, 149, 129, 109, 88, 66, 45, 22, 0,   
                             0, 23, 46, 69, 91, 113, 134, 154, 174, 192, 209, 224, 238, 251, 261, 270, 278, 283, 287, 289, 289, 287, 283, 278, 270, 261, 251, 238, 224, 209, 192, 174, 154, 134, 113, 91, 69, 46, 23, 0,   
                             0, 24, 48, 71, 94, 117, 139, 160, 180, 199, 216, 232, 246, 259, 270, 280, 287, 293, 297, 299, 299, 297, 293, 287, 280, 270, 259, 246, 232, 216, 199, 180, 160, 139, 117, 94, 71, 48, 24, 0,   
                             0, 25, 50, 74, 98, 121, 143, 165, 186, 205, 223, 239, 254, 268, 279, 289, 297, 303, 307, 309, 309, 307, 303, 297, 289, 279, 268, 254, 239, 223, 205, 186, 165, 143, 121, 98, 74, 50, 25, 0,   
                             0, 26, 51, 76, 101, 125, 148, 170, 192, 212, 230, 247, 262, 277, 288, 298, 306, 313, 317, 319, 319, 317, 313, 306, 298, 288, 277, 262, 247, 230, 212, 192, 170, 148, 125, 101, 76, 51, 26, 0,   
                             0, 26, 53, 78, 104, 129, 153, 176, 198, 219, 238, 255, 271, 285, 297, 307, 316, 323, 327, 329, 329, 327, 323, 316, 307, 297, 285, 271, 255, 238, 219, 198, 176, 153, 129, 104, 78, 53, 26, 0, 
                             0, 27, 54, 81, 107, 133, 157, 181, 204, 225, 254, 263, 279, 294, 306, 317, 326, 332, 337, 339, 339, 337, 332, 326, 317, 306, 294, 279, 263, 254, 225, 204, 181, 157, 133, 107, 81, 54, 27, 0, 
                             0, 28, 56, 83, 110, 136, 162, 186, 210, 232, 252, 270, 287, 303, 315, 326, 335, 342, 346, 349, 349, 346, 342, 335, 326, 315, 303, 287, 270, 252, 232, 210, 186, 162, 136, 110, 83, 56, 28, 0, 
                             0, 29, 58, 85, 113, 140, 166, 191, 216, 238, 259, 278, 295, 311, 324, 335, 345, 352, 356, 359, 359, 356, 352, 345, 335, 324, 311, 295, 278, 259, 238, 216, 191, 166, 140, 113, 85, 58, 29, 0, 
                             0, 30, 59, 88, 117, 144, 171, 197, 222, 245, 266, 286, 303, 320, 333, 345, 354, 362, 366, 369, 369, 366, 362, 354, 345, 333, 320, 303, 286, 266, 245, 222, 197, 171, 144, 117, 88, 59, 30, 0, 
                             0, 30, 61, 90, 120, 148, 176, 202, 228, 252, 274, 294, 312, 329, 342, 354, 364, 371, 376, 379, 379, 376, 371, 364, 354, 342, 329, 312, 294, 274, 252, 228, 202, 176, 148, 120, 90, 91, 30, 0, 
                             0, 31, 62, 93, 123, 152, 180, 208, 234, 258, 281, 301, 320, 337, 351, 367, 372, 381, 386, 389, 389, 386, 381, 372, 367, 351, 337, 320, 301, 281, 258, 234, 208, 180, 152, 123, 93, 62, 31, 0, 
                             0, 32, 64, 95, 126, 156, 185, 213, 240, 265, 288, 309, 328, 346, 360, 373, 383, 391, 396, 399, 399, 396, 391, 383, 373, 360, 346, 328, 309, 288, 265, 240, 213, 185, 156, 126, 95, 64, 32, 0
                            };


#int_TIMER2
void  TIMER2_isr(void)
{
   set_pwm1_duty(duty_cycle[j]);
   ++i;
   if(i==4)
   {
      i=0;
      ++j;
      if(j==40)
      {
         j=0;
         delay_us(150);
         output_toggle(PIN_A1);
         output_toggle(PIN_A5);
      }
   }
}

void main()
{

   setup_adc_ports(sAN3|VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_32);
   set_adc_channel(3);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DIV_BY_1,99,1);
   setup_ccp1(CCP_PWM);
   set_pwm1_duty(0);
   setup_comparator(NC_NC);
   setup_vref(FALSE);
   clear_interrupt(INT_TIMER2);
   enable_interrupts(INT_TIMER2);
   enable_interrupts(GLOBAL);
   setup_oscillator(OSC_8MHZ);

   output_high(PIN_A1);
   output_low(PIN_A5);
   while(1);
}
gpsmikey



Joined: 16 Nov 2010
Posts: 588
Location: Kirkland, WA

View user's profile Send private message

PostPosted: Sun Dec 09, 2012 10:37 am     Reply with quote

Well, to answer your question about why the count seems off ... it isn't - you are testing for the value 4 for example - that gives you 5 because you are starting at 0 --- 0,1,2,3,4 -- I also prefer to write my code to test for a value less (or more depending) than my target value instead of testing for the exact target value ( ==4) because sooner or later, you will manage to do something to your code that causes it to miss the exact terminal value then it gets away and keeps going.

It is also a bad practice typically to have delays inside ISR's - you normally want an ISR to be as quick as possible - many times, it simply sets a flag and exits that your main code is watching, although in your case where the timing is important, setting the pulse is fine, but the delay can be an issue.

mikey
_________________
mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3
Mike Walne



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

View user's profile Send private message

PostPosted: Sun Dec 09, 2012 1:32 pm     Reply with quote

You code is not complete and compilable.

I presume you mean that your PWM frequency is 20kHz.

What output sinewave frequency do you intend?

Mike
GOBER



Joined: 22 Jul 2010
Posts: 41

View user's profile Send private message

PostPosted: Mon Dec 10, 2012 3:09 pm     Reply with quote

HELLO MIKE

THE CODE WON'T COMPILE AS YOU DON'T HAVE THE HEADER FILE.
HERE IT IS. SAVE IT AT ANY LOCATION AND CHANGE THE FIRST LINE IN THE PROGRAM TO POINT TO THAT DESTINATION

#include <12F683.h>
#device adc=10

#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES CPD //Data EEPROM Code Protected
#FUSES PROTECT //Code protected from reads
#FUSES MCLR //Master Clear pin enabled
#FUSES PUT //Power Up Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOFCMEN //Fail-safe clock monitor disabled

#use delay(clock=8000000)


YES IT IS 20KHz AND MY INTENDED OUTUT FREQUENCY IS 50Hz
PLEASE CHECK WHAT'S HAPPENING
GOBER



Joined: 22 Jul 2010
Posts: 41

View user's profile Send private message

PostPosted: Mon Dec 10, 2012 3:12 pm     Reply with quote

HELLO GPSMIKEY

I WILL GO WITH YOU AS FOR THE FIRST POINT YOU TALKED ABOUT.
AS FOR THE SECOND POINT, WELL I KNOW IT'S BAD BUT IT IS THE ONLY WAY TO MAKE MY PROGRAM SWITH CORRECTLY AT THE END OF THE HALF CYCLE PWM CORRECTLY. I POSTED THE HEADER FILE AND RECENTLY THE PROGRAM. CHEK IT OUT PLEASE

REGARDS
Mike Walne



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

View user's profile Send private message

PostPosted: Mon Dec 10, 2012 3:53 pm     Reply with quote

Quote:
AS FOR THE SECOND POINT, WELL I KNOW IT'S BAD BUT IT IS THE ONLY WAY TO MAKE MY PROGRAM SWITH CORRECTLY AT THE END OF THE HALF CYCLE PWM CORRECTLY

I usually find it's dangerous to say "this is the ONLY way" to do a particular task!!!!!!!!!

Your 150us delay is ~3 switching cycles. Maybe you need to work on that.

In your first post you say that the code goes crazy. Exactly what do you mean by that. In other words, what are we looking for?

Mike
GOBER



Joined: 22 Jul 2010
Posts: 41

View user's profile Send private message

PostPosted: Tue Dec 11, 2012 12:19 pm     Reply with quote

hey mike

thanks for trying to help.

well as for "the only way", this is what i could came up with. inserting this delay, knowing that it is three times the duty cycle, is what made my code act correctly!

as for going crazy, well i don't know how to attach a file here to show you, so will you please post your email and i will send you the c file, h file. hex file and a picture showing what is going wrong.

regards and thanks in advance
Ttelmah



Joined: 11 Mar 2010
Posts: 19454

View user's profile Send private message

PostPosted: Tue Dec 11, 2012 2:52 pm     Reply with quote

Seriously, you do understand that a duty cycle remains set, until changed?.
All you need do, is get rid of your delay, and modify the timer2 setup, with:
Code:

setup_timer_2(T2_DIV_BY_1,99,5);

This way the interrupt will be called every fifth cycle of the PWM.

Best Wishes


Last edited by Ttelmah on Tue Dec 11, 2012 3:24 pm; edited 1 time in total
Mike Walne



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

View user's profile Send private message

PostPosted: Tue Dec 11, 2012 3:23 pm     Reply with quote

Ttelmah wrote:
Seriously, you do understand that a duty cycle remains set, until changed?.
All you need do, is get rid of your delay, and modify the pwm2 setup, with:
Code:

setup_timer_2(T2_DIV_BY_1,99,5);

This way the interrupt will be called every fifth cycle of the PWM.

Best Wishes
Yes, but he's got two issues:

1) Running each duty cycle five times.
2) Handing over from non-inverted to inverted versions of his waveform, and vice-versa.

Your code deals with 1) but not exactly as he's done 2).

I haven't had time to look at what the nature of problem 2) is.

I have to agree, there is probably a simpler solution, which does not need the delay_ms(xx).

Mike
Ttelmah



Joined: 11 Mar 2010
Posts: 19454

View user's profile Send private message

PostPosted: Wed Dec 12, 2012 2:19 am     Reply with quote

Yes.
I suspect the second problem relates to how he inverts. Toggling two lines one after the other. Depending where he is in the cycle, this probably gives a momentary short circuit, and makes the system 'go crazy'.....
If you think about it, he'd need to break before make, on the drivers, and the order of the changes would therefore need to be the opposite way round every alternate cycle.

Best Wishes
Mike Walne



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

View user's profile Send private message

PostPosted: Wed Dec 12, 2012 2:45 am     Reply with quote

Ttelmah wrote:
Yes.
I suspect the second problem relates to how he inverts. Toggling two lines one after the other. Depending where he is in the cycle, this probably gives a momentary short circuit, and makes the system 'go crazy'.....
If you think about it, he'd need to break before make, on the drivers, and the order of the changes would therefore need to be the opposite way round every alternate cycle.

Best Wishes

Ttelmah's got a point. We need to see how you are doing the inversion.
I know it's done at the zero crossing, but I'd still like to see it.

I haven't run your code yet, but as I see it, this is what you were doing before.

1) Running each value of duty 0, 21, 42 .....for 5 lumps of 50us each (i.e. 250us).
2) Running the last 0 for 150us
3) Inverting your signal.
4) Looping from here.

Which does not quite make sense. I think you need to either:-

a) Run the last zero for 250us.
OR
b) Not run the last zero at all.

I can see you're trying to avoid cross-over distortion.
I'm having difficulty seeing why you have to run zero twice at the cross-over.

If you do what Ttlemah suggested, then you'll get a full 250us run of the last zero, and won't need the delay_us(150).
Or you can get rid of it by changing the value at which you terminate 'j'.

Mike
Ttelmah



Joined: 11 Mar 2010
Posts: 19454

View user's profile Send private message

PostPosted: Wed Dec 12, 2012 4:29 am     Reply with quote

My feeling is that if he is reversing one half of the bridge before the other, he could well be thumping a dead short, even though he is at the zero crossing point. We need to see the circuit being driven, but I'd expect to have to reverse the order of the switchover, according to whether the system is going up or down the cycle.

Other comments:
1) Why have the array larger than a half cycle?. What is the point/advantage of having 600 elements, rather than sticking to just 40?. Disadvantage of the larger array, is it almost certainly involves the table look-up into page switching.
2) Stick to just 40 elements, and don't store them as const. Uses 80 bytes of RAM, but potentially faster.
3) Does the sine really want two zero elements?.

Best Wishes
Mike Walne



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

View user's profile Send private message

PostPosted: Wed Dec 12, 2012 6:23 am     Reply with quote

OK. I've had time to look at the code in more detail.

I don't have any PIC12 parts, so I've used an 18F458 ('cos it's what I happen to have).

1) I don't think there's not enough time to process the ISR in 100 machine cycles. (Time to get into the ISR, time to do things like the big look-up table, get out of ISR.)
2) The value of 'i' is going 0,1,2,3 reset to 0. So only executing 4 loops per cycle. I suspect 'j' is incrementing at 250us intervals because there's a missing ISR.
3) Using Ttelmah's suggestion of interrupting every 5 times TIMER2 overflows HAS to be the way to go.
4) Toggling the two PORT_A bits is NOT the way to control the inversion. If they accidentally get out of step then they'll sometimes run as compliments to each other, other times they'll be in sync.
5) We need to see the inverter schematic.
6) I'm also uneasy with running the zeros twice.
7) The big table allows for different amplitude sine-waves, ready for the project's feedback phase.

Mike
Ttelmah



Joined: 11 Mar 2010
Posts: 19454

View user's profile Send private message

PostPosted: Wed Dec 12, 2012 8:01 am     Reply with quote

Realistically, I'd just clip the pulse width. Reducing it by an integer value to reduce the output. Given that the tweak factor involved is usually small, this is fast, and gives the effect as if the whole waveform was shifted down relative to the zero point. It will mean you have to test if the pulse width is longer than the tweak you require. One test, one subtraction.

Best Wishes
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Wed Dec 12, 2012 9:39 am     Reply with quote

this is a swell thread , but the discourse so far would make me implement this in external hardware, with at most, only pic management.
surely not with all this high overhead table manipulation, and dense pwm change.

Say with a 16F15xx NCO source and external counter/DAC combo--
or AD9833 ++ comparator slicer


Larry Niven paraphrase
"when all you have is a PIC, every problem looks like a program...."
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, 3, 4, 5, 6  Next
Page 1 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