|
|
View previous topic :: View next topic |
Author |
Message |
GOBER
Joined: 22 Jul 2010 Posts: 41
|
sine PWM inverter code going crazy |
Posted: Sun Dec 09, 2012 9:25 am |
|
|
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
|
|
Posted: Sun Dec 09, 2012 10:37 am |
|
|
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
|
|
Posted: Sun Dec 09, 2012 1:32 pm |
|
|
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
|
|
Posted: Mon Dec 10, 2012 3:09 pm |
|
|
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
|
|
Posted: Mon Dec 10, 2012 3:12 pm |
|
|
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
|
|
Posted: Mon Dec 10, 2012 3:53 pm |
|
|
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
|
|
Posted: Tue Dec 11, 2012 12:19 pm |
|
|
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: 19496
|
|
Posted: Tue Dec 11, 2012 2:52 pm |
|
|
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
|
|
Posted: Tue Dec 11, 2012 3:23 pm |
|
|
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: 19496
|
|
Posted: Wed Dec 12, 2012 2:19 am |
|
|
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
|
|
Posted: Wed Dec 12, 2012 2:45 am |
|
|
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: 19496
|
|
Posted: Wed Dec 12, 2012 4:29 am |
|
|
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
|
|
Posted: Wed Dec 12, 2012 6:23 am |
|
|
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: 19496
|
|
Posted: Wed Dec 12, 2012 8:01 am |
|
|
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
|
|
Posted: Wed Dec 12, 2012 9:39 am |
|
|
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...." |
|
|
|
|
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
|