Author Topic: diy arduino inverter  (Read 8469 times)

0 Members and 1 Guest are viewing this topic.

Offline noneyabussiness

  • Full Member
  • ***
  • Posts: 155
  • Karma: +7/-0
  • I think it works....
diy arduino inverter
« on: January 06, 2017, 08:21:14 am »
Hey all,

been playing around with the idea of a Arduino (atmega328p) inverter driver, so here is rough draft 1..

now im trying to fully understand how SPWM works with these inverters so it may be completely wrong, but i took the same approach as i would with "standard" PWM and vary the "duty cycle" of the pulses but use a fixed frequency... AKA modulate the SPWM.... :o.... using both 8 bit timer interrupts as fixed frequency for SPWM and Feedback....

if it is incorrect could someone please explain to me how it does work, in language that us humans talk.. i have read MANY "thesis papers" etc. but im still lost... so i went with my gut and wrote the above...

it uses a fixed table for sine wave however with a little math it scales it down to the feedback line, 20khz carrier frequency, and about 90% (10 bit ADC of course) adjustable (10% - 100%). and "softstart" version 1 .. All mostly configurable...

something OZ explained to me about the EG80010 not having as good Dynamic Range as the PJ boards and i thought i wanted to give it a go coding something similar to the PJ ...

i also have a similar code for the STM32F1 as well and ill post once i know im on the right track.... i just fed both pin 9 and 10 into a poly 4.7uf cap to clean up the sine and it looks good to me (obviously only testing at mo, proper RC or LC filter later).

Offline frackers

  • Full Member
  • ***
  • Posts: 239
  • Karma: +9/-0
  • If it moves - computerise it!
Re: diy arduino inverter
« Reply #1 on: January 06, 2017, 01:44:09 pm »
I'd forget the Atmel AVR CPU and concentrate on the STM32F1 as it has MUCH more capable timers including complementary outputs with 'dead time' built into the hardware and more accurate ADC (12 bits and self calibrating).

Being clocked at up to 72MHz (from 16 for the AVR) also helps in having plenty of CPU time to calculate (or look up) the next value to go into the compare registers to adjust the PWM depending on where in the cycle and the load.

The Arduino software for the STM32 is somewhat lacking for 'real time' processing like this so experimenting with the HAL (Hardware Abstraction Level) software will lead to improved performance. STM32CubeMX is a handy tool supplied by ST Micro which will write all the initialisation code (can be quite complex!!) for you and is useful to help visualise the interface from the chip to the rest of the world.
Robin Down Under (or are you Up Over!)

Offline noneyabussiness

  • Full Member
  • ***
  • Posts: 155
  • Karma: +7/-0
  • I think it works....
Re: diy arduino inverter
« Reply #2 on: January 06, 2017, 06:49:42 pm »
Thx for the feedback, the stm32 arduino is very lacking (no bad blood to Roger,  he and others have done an awsome job) , little documentation and a heap of the features are not supported. .. i really just want to make sure im barking up the right tree first...

And in all honesty the humble 8 bit would be sufficient here, its not an overly fast algorithm needed.. even at 16mhz, 20ms is a long time to do a lot... but i digress. .. also it would be awsome to have a open source avr doing the hard work, guess the nostalgia coming out ::)..

Offline noneyabussiness

  • Full Member
  • ***
  • Posts: 155
  • Karma: +7/-0
  • I think it works....
Re: diy arduino inverter
« Reply #3 on: January 07, 2017, 01:43:18 am »
in fact the PJ board uses a 8 bit MCU (mc908mr32cfue) :o, which what i have read ,has a strikingly similar datasheet to the avr stuff... only it has two 16 bit timers instead of 1...

Offline frackers

  • Full Member
  • ***
  • Posts: 239
  • Karma: +9/-0
  • If it moves - computerise it!
Re: diy arduino inverter
« Reply #4 on: January 07, 2017, 04:04:46 am »
even at 16mhz, 20ms is a long time to do a lot..

Unfortunately you don't have 20ms - the PWM has to be updated at the PWM frequency so in fact you only have 42us to scale the next value (assuming 23.4KHz as per the EG8010) - you can't just use a lookup table directly, you have to adjust it according to load which you calculate by checking the output voltage.

Once I've finished my mesh radio moisture sensor project (that I hope to start when I finish building the new barn), I'm going to have a go myself :)

The waveform generation I think is the easy bit - the tricky one is getting the overall loop gain right to keep a stable output under varying loads and to monitor for over temperature and over current at the same time.
Robin Down Under (or are you Up Over!)

Offline noneyabussiness

  • Full Member
  • ***
  • Posts: 155
  • Karma: +7/-0
  • I think it works....
Re: diy arduino inverter
« Reply #5 on: January 07, 2017, 05:09:44 am »
If you have a look at the code i have posted, to scale the SPWM is only 1 extra line of code (to percentageish), the second isr takes the actual ADC measurement (which i have sped up, i still dont think overly processor consuming). ... 20ms in a life of a avr is a long time, even if the pwm has to be updated every 50us (20Khz). Over temp and over current also depends how "accurate" and "fast" u want it.. using a interrupt it can be instant (eg.).

Again, i do understand the stm32 would be faster, better etc. But for PJ to implement what they have done with the humble 8 bit seems very doable, and we have seen how powerful they are... anyhoo getting off topic, is the code i have posted roughly what the SPWM is supposed to do??

Offline frackers

  • Full Member
  • ***
  • Posts: 239
  • Karma: +9/-0
  • If it moves - computerise it!
Re: diy arduino inverter
« Reply #6 on: January 07, 2017, 06:15:03 am »
I've only had a quick look but I've spotted one problem:

Code: [Select]
  x = sinPWM[i]; // x take the value from vector corresponding to position i(i is zero indexed)
  i = i + 1; // go to the next position
  x2 = x / 100 * feedback; // adjust total to modulate pulse according to feedback...

That third line is a killer - been there, done that!! The 1st 6 values read from the lookup table are all less than 100 and dividing by 100 will  return zero. Evaluation is done from left to right with operators of equal precedence. Putting the "* feedback" first could result in overflow of the 16 bit intermediate value depending on how large the value of 'feedback' gets. That could be overcome by either using a cast to 32 bits or by declaring 'x2' to be 32 bits but that involves a lot of putting stuff on the stack on an 8 bit AVR to free up enough registers to do 32 bit arithmetic.

Because of the potential for overflow I'd also suggest using explicit storage types such as uint16_t, int32_t etc rather than 'int' and 'long int' so it becomes clearer what the size of the operands is.

Don't you just love integer maths!!

Robin Down Under (or are you Up Over!)

Offline noneyabussiness

  • Full Member
  • ***
  • Posts: 155
  • Karma: +7/-0
  • I think it works....
Re: diy arduino inverter
« Reply #7 on: January 07, 2017, 06:47:32 am »
I will be changing the sine table to a much more appropriate table to include the "lost digits" , int math is fun, except when it truncates important digits :-\

But it that what we are going for, in terms of modulation? ?

Offline peter

  • Newbie
  • *
  • Posts: 19
  • Karma: +6/-0
Re: diy arduino inverter
« Reply #8 on: January 17, 2017, 05:33:56 pm »
Hi noneyabussiness

I've been doing the same thing that you have, using the ATMega328 and I have got a running prototype working quite nicely.

The reasons why I built this is to explore how a pure sinewave inverter works and the influence of various factors on it's efficiency including
- 1/2 bridge dead time
- SPWM frequency
- SPWM modulation depth
- Mosfet bridge DC bus bulk capacitance
- DC bus supply voltage
- control loop design
and more

I highly recommend the use of a DSO when playing with this stuff.

The inverter uses IR21844 half bridge 2 Amp gate drivers which have variable dead time, taking 3 inputs. First is dead time (from 0.5 to 5 us, set by a trimpot), next is pwm, and the last is enable which is active HIGH.
The code has a soft start and hard stop that only occurs at zero AC voltage output thereby reducing stress on the mosfets.

See attached code and I will detail how it works.

Firstly, you will see two #defines, NPWM is the number of PWM cycles for 1/4 sinewave. I based it all on using a 1/4 wave. This saves memory and it's simple to use symmetry to obtain the other half of the 1/4 wave
PPWM is the PWM clock speed counter.
Next is a 14 bit lookup table of 1/4 sine wave values and a few globals. The table is stored in program memory so it does not chew up all the ram.

The setup() block does a few things, firstly it initialises the working pwm lookup table to zero power, programs timer2 to fire at 100Hz, programs timer1 to fire at
16Meg/NPWM Hz, in this case it will be 20kHz but this can be changed to anything you like. In testing I have run this code at 10, 20 and 40 kHz
but it could be anything (if NPWM = 123, then the SPWM freq would be 12.3kHz). Further setup code initialises a few output pins, counters and flags, disables the arduino clock interrupt (for smoother running of the 20K PWM)
and enables interrupts. These are running at all times. I control the inverter output via the enable signal sent to the mosfet drivers.

Then comes timer2 overflow interrupt code. This creates a 50hz signal by toggling the flag f50, and it outputs the enable/disable signal through pin5.
It resets the SPWM lookup table pointer to the start point and checks for a change in the enable/disable input switch.

timer1 overflow code will toggle the 50hz output pin as needed and update timer1 OCR1A counter appropriately with the first or second part of the 1/4 wave spwm lookup table.

pwm_mod(v) is something you might find interesting. This produces the working lookup table data for SPWM.
The input value is used to scale the sin wave from 0 to maximum. All calculations are performed in 32bit integer.
step 1 calculate the location of the needed value from the sine table
step 2, fetch it from program memory
step 3 scale it, with a result that is converted to 16 bits for storage into working table. And mirror it for the other 1/2 of the 1/4 wave.
The last line tidies up a bit of crap in the middle of the data due to poor programming.

 Next comes loop() where two values are read from ADC inputs.
 ch0 is the inverter output, scaled so that 220VAC = 3.5V DC roughly
 ch2 is the setpoint where I control the output voltage. I like to run it at 220VAC but is can go to anything you want.
 The toroid used in this prototype is a 1500VA unit from an aerosharp and I find it starts saturating at about 235VAC onwards.
 The function of this code block is to update the working lookup table so that the desired AC voltage is maintained.
 I choose to update the table at zero crossing times in the AC wave, so that means it gets updated 100 times a second.
 the variable "uf" is used to flag when to run the update code, and this code only runs if the inverter is enabled.
 
 update code first clears the update flag, then pulls pin6 high to show to the human that it's running this code.
 I use a simple so called "bang-bang" control scheme with a small dead band. I could use PID or something else but first let's crawl before I walk.
 If setpoint is larger than ACV then increase the power level by a small amount. If smaller, decrease by a tad.
 It setpoint is close to ACV then just leave it alone. I found that not using a dead band creates annoying flicker in ACV output when hooked up to lights.
 I then clamp the power level to something that will never cause problems in the integer scale code (and these issues will cause blown mosfets)
 pwr is a float, I obtain my scale factor, call pwm_mod and print a few interesting numbers.
 And pull pin6 low to show the human the job is done.
 
The last code is to give a nice debounced input from a very noisy push button switch.
This gets called 100 times a second. It toggles on and off the inverter.
When changing either on or off it zeros the pwr accumulator, ready for the next soft start.
the variable odis is mapped directly to the IR21844 enable pins and the arduino LED. This is useful and saves me from applying DC bus power
when the inverter is "on". Bad things happen when this occurs.

The control loop is clearly not great. While experimenting with an aliexpress EGS002 based inverter board I found that they take a low voltage sample
of the AC output voltage, rectify it and filter it so that is has very small AC ripple, then this is fed into the EGS002 board, where more low pass filtering occurs
and this nearly DC signal is fed into Vfb pin of the controller.

So it indicates to me the EGS002 based inverters use and expect a DC feedback signal.
The control loop will need to be designed with this slowly changing feedback signal in mind.
Future work on this project will look at filtering of AC feedback, the frequency response of the control loop
and what is really needed from an inverter from a transient response point of view.

The video of oscilloscope traces when operating.
soft start with no load - soft start with test load of 114W - SS with sudden application of load (can see SPWM in lower zoomed view) - Yellow is 50Hz gate drive
Light Blue is output AC volts (100V/div)
other blue is DC bus current (0.041V/Amp)
Pink is 20kHz SPWM gate drive

The DSO screen capture shows the transient behavior when apply the test load. Notice how the voltage drops for one or two cycles then the control loop regains the upper hand.

Offline eraser3000

  • Full Member
  • ***
  • Posts: 70
  • Karma: +2/-0
Re: diy arduino inverter
« Reply #9 on: January 17, 2017, 05:57:33 pm »
Very cool, very skillful peter.

Offline MadScientist267

  • Impossible Condition Curator
  • Hero Member
  • *****
  • Posts: 1514
  • Karma: +44/-4
  • Rules? What rules?
Re: diy arduino inverter
« Reply #10 on: January 17, 2017, 06:19:26 pm »
Very nice indeed. Even got the bench meeting all the insanity requirements ;D

This completely variable PWM base frequency thing catches my attention... Have you guys had any issues with duty jitter on the mega328?
Wanted: Schrödinger's cat, dead and alive.

Offline peter

  • Newbie
  • *
  • Posts: 19
  • Karma: +6/-0
Re: diy arduino inverter
« Reply #11 on: January 17, 2017, 07:35:40 pm »
MadScientist267:
what do you mean by duty jitter?

I know that small changes in pwm duty will make changes in output AC volts.
These small changes in output appear as a flickering light output when fed into incandescent lights.
Even changes from say 220V to 222V and back again will be easily perceived as "annoying" by anybody.

My control loop ensures the output AC volts track closely the setpoint. But nothing is exact in the Real World (tm).
So I implemented a dead-band in the control loop. It effectively thinks "the output is close enough to the setpoint? OK, I'll leave it alone"

I found that having the inverter achieve 222 or 218 when the setpoint is set to 220 is good enough, with the dead band being maybe +/- 2 Volts. In this example, when switching in and out the test load, the resulting output volts might be 218, then 220, 218,220, 222 etc. Just so long as it stays put once within the dead band.

Offline MadScientist267

  • Impossible Condition Curator
  • Hero Member
  • *****
  • Posts: 1514
  • Karma: +44/-4
  • Rules? What rules?
Re: diy arduino inverter
« Reply #12 on: January 18, 2017, 03:43:09 am »
My issue is in a slightly different direction, and I won't pollute this thread with all of the nitty gritty details since it's a different class of equipment (but I'll be posting a thread on it specifically soon, so possibly deal with it then)... but it sounds like you've come to the same conclusion I have...

Basically, I'm steering a TL494 based switcher's Vfb (primarily fed the traditional way, via pure analog divider), with filtered PWM -> 0-5V filter/converter... and I notice that output wags around a little and was able to nail it down to the PWM as the root cause (I can set the PWM hard in code and still observe the behavior, so it's not PID oscillation etc etc). If I sub out the PWM 0-5 for a 5k pot, the issue completely goes away. So just wondered if this is also noticed on the mega328, I'm currently using an uno R3.

My answer so far has been basically the same as yours... only translated to how it applies to my situation of course... Using hysteresis keeps the uno from going into oscillation.

I'll leave it there for this thread - definitely want to see how this ultimately comes out because I've got so many things in mind for these cute little controllers it's not even funny, and you guys speak of magic I haven't yet explored (like the arbitrary base PWM frequency etc)... Love this stuff! ;)

Wanted: Schrödinger's cat, dead and alive.

Offline peter

  • Newbie
  • *
  • Posts: 19
  • Karma: +6/-0
Re: diy arduino inverter
« Reply #13 on: January 20, 2017, 07:33:45 pm »
So I have jumped into PID control of the inverter.

The two attached images show transient response when the test load is switched in.
The X axis is time, each tick is 1/100 of a second which corresponds to each control loop cycle.
Red is the setpoint, blue is output AC volts (ch0 and ch2 as seen in the code)
purple is pwm power setting.
green is PID control output, to be added to the pwm power each control cycle.

The first graph shows the bang-bang code response and it takes about 20 100Hz control loops to get back to the setpoint.
Note that is overshoots and rings a little. Ignore the green line, it's junk.

The second graph shows PID control and note the far less overshoot and ringing. The green curve does now show the pwm power setting changes applied to the device. PID seems to be about 5x faster.

I also attach the current version of the code. I now calculate the SPWM values within the 20Khz interrupt service block.
No temporary arrays.
The single statement requires 10us to complete. This means there is now a much lower upper limit on PWM frequency

I welcome any discussion on this. Control theory is beyond my ken.

Offline frackers

  • Full Member
  • ***
  • Posts: 239
  • Karma: +9/-0
  • If it moves - computerise it!
Re: diy arduino inverter
« Reply #14 on: January 21, 2017, 04:43:46 am »
Wow - made me realise its nearly 45 years since I studied closed loop systems - Bode plots, Nyquist are just names now. I'lll have to see if any of the brain cells from those days have survived (I doubt it, during the 70s was when I discovered beer, motorcycles and girls!!)

Who would have thought that a 4 year computer engineering course then could be taught without a computer in sight!! (although it did include electrical power, electronic and solid state physics modules)

Robin Down Under (or are you Up Over!)