With your code you only allow for two possibilities, >setV and not>setV. Because of this your duty cycle will all ways be oscillating. The frequency and amplitude of this oscillation will depend on how many times you run the above code in one update period.
I suggest adding some hysteresis to you code. So >SetVMax or <SetVMin, for anything else do nothing.
No that wont work. The voltage will increase and then as soon as it is greater than SetVoltage+offset it will start decreasing the duty cycle until it is less than SetVoltage+offset and then it will increase again. i.e. its not stable and will just oscillate.
Try this,
Code:
if(InvVoltage>SetVoltage+offset)
{
if (DutyStep > 0)
DutyStep--;
} else if(InvVoltage<SetVoltage-offset)
{
DutyStep++;
if (DutyStep > 99) DutyStep = 99;
}
Not sure what you're InvVoltage resolution is but I'd set it to maybe 5LSB depending on how much noise you have in the system
I tried that too (the moment i posted it i realised it was wrong and corrected and tested it)
My o/p voltage varies around a value with this.
My InvVoltage too is a 10-bit value although it is just a filtered replica of the o/p voltage and has some ripple.
I'm not sure what DutyStep is controlling? presumably the peak duty cycle for you sin wave?
For the feedback you have to be carful with the frequency:
-It has to be less than the fundamental frequency of the sine wave you are trying to create and you will need to average the o/p voltage over that period.
-It also has to be a derivative of the fundamental frequency of the sine wave.
this is due to the beat effect, basically if the frequency's aren't well matched then you might be measuring a peak voltage and working out the duty cycle based on that.
so if you are making a 100Hz sine wave you'll need a 50Hz refresh rate, 100Hz might work but is likely to be more unstable.
Good filtering will help but you'll always get some ripple.
Usually space vector modulation is used and the feedback would have a PI controller to ensure a good response. At the moment you only have a P controller which will always have an offset.
DutyStep controls peak duty cycle for you sine wave as you correctly speculated.
My sine freq is 50Hz and my refresh rate is 1KHz.
Can you throw some light on your last sentences
"Usually space vector modulation is used and the feedback would have a PI controller to ensure a good response. At the moment you only have a P controller which will always have an offset."
You'll have 100Hz ripple on your output due to the rectified sine, even with the best filtering. So at one point you'll measure the peak and thus reduce Dutystep and at another point you'll measure the trough and thus increase Dutystep. This will cause oscillation.
You'll want to collect measurements over at least one sine period and average these measurements. From the calculated average you'll then update your dutystep at a frequency of 50Hz
Tried this.
Oscillations have stopped completely.
Although recovery on loaded conditions is poor.
I have a 625 us timer loop.On each interrupt ,i collect a sample of the feedback voltage.I add 32 samples(20ms) and average.
On this value, i update the duty.
Is this right? or am i missing something?
That's right, well done great to hear you've got rid of oscillation.
Now lets improve that transient response.
Currently you change your Dutystep by a fixed value of 1 LSB every 20ms. So if you suddenly load your output and Dutystep needs to increase by 10LSB that's going to take 200ms to do ... which is a slow recovery. At a guess I'd say we could get this down to 60ms, any faster and we'd need to use significantly more complex code.
The first step is to implement proportional control, google it and you'll find some good websites.
The basic idea is that the amplitude of your correction factor is proportional to the difference between desired and measured output.
So for example you'll want to have something like the following for increasing Dutystep
Start off with a low gain and gradually increase it until you start to see slight oscillation during transient step response (sudden application of a load). Be aware that you may well need a gain of less than 1, you'll need to know the basics of bit multiplication.
pPIparams.propGain : unsigned char 0...100%
pPIparams.propGainShift: signed char positive value - shift left
negative value - shift right
pPIparams.intGain : unsigned char 0...100%
pPIparams.intGainShift : signed char positive value - shift left
negative value - shift right
pPIparams.upperLimit : signed int upper limitation value
pPIparams.lowerLimit : signed int lower limitation value
pPIparams.integralPortionK_1: signed int integral portion sum
With my settings
1)I get oscillations free o/p at 230Vac
2)Once a Load is added at o/p, recovery is not possible, voltage stays at 223Vac
Changing the parameters have some undesired response like oscillations are introduced, but recovery is good.
When i set intgain = 0, the o/p voltage never rises above 70-80VAC at the o/p
in my earlier post i have placed a link to the pdf file of the library ..if you are kind enough to take a look ...
gainshift will provide the step increase or decrease to the gain values (as i understood)
My Battery voltage had dropped to a hazardous low. Due to which what i was measuring was totally wrong.
I installed new batteries and took few readings which i would like to share.
I started with
-> Prop gain at max 100% and integral gain at 0.
= O/P voltage doesn't rise above 20Vac
->Prop gain at max 100% and integral gain at 10%
= O/p voltage increases a bit but no major difference.
->Gradually decreased Prop gain and increased integral gain
= At no load on o/p, voltage is 230VAC and if it is loaded by a 100w load, voltage shoots to 256Vac and stays there
with load removed, the voltage goes back to 230Vac
Revisiting after a long time...
Was hooked up with other things so could not invest time in this project.
After everything failing in my feedback correction algorithm.I have done this.
I generate a sinewave and get a full rectified feedback (as in attached PDF document)
At exact peak i measure the voltage- INV_VOLT
I have a variable voltage SET_V through a pot (0-5v)
I have 100 rows of 32 sine weighted variables each (1-100% duty)
At every ZCD event , i compare the SET_V and INV_VOLT and increase or decrease the row index.
This has a good effect a better stable sine wave, but not very stable , some oscillations are present within 1v.
another effect is on loading, the voltage drops by 4-5 volts (NO LOAD = 230VAC)
You seem to be making changes in a somewhat random fashion. I suggest you sit back and think about how the control loop is really working. You may want to try a type of control which basically uses a series of If-Then-Else loops, with typically no multiplication/division required, and is fairly intuitive to tune for optimum response.
Did you look at the tutorial Fuzzy Logic page I posted?
The simplest way is to do IF-Then-Else statements of the form: If the error is large Then the correction change is large Else
If the error is medium Then the correction change is medium Else
If the error is small Then the correction change is small Else
If the error is zero Then the correction change is zero Else
Etc.
You use as many If-Then-Else statements as needed while tweaking the "error" and "change" parameter value ranges to get the desired response. This can generally be most easily determined by trial and error.