variable frequency inverter (sine wave)

Hi,

I am a complete noob, so please shut this topic down if it goes nowhere.

As the subject says, I am would like to use arduino as a driver for h-bridge circuit (4 MOSFETs - output would be 12V AC). If it is possible i would like to produce phase and frequency correct PWM using 16 bit timer. outputs would have to be:
-output AC freq.: 10 - 100 Hz (variable and controllable),
-sampling (carrier) freq.: at least somewhere around 5 kHz.

I would like to have possibility to:

  • continuously vary frequency from 10-100 Hz, to
    -hold it at minimum frequency and also to
  • be able to control the speed of frequency changing.

The thing is, that what this circuit (h-bridge) requires is actually two outputs, that are never on at the same time and both are actually PWM sine with 180deg delay, also some deadtime is required between them.

I have been looking into arduinOSC first release / shaduzLABS (and similar project using Atmega8 at: Generate sine wave modulated PWM with AVR microcontroller - Do It Easy With ScienceProg) and also official Atmel guide: http://www.atmel.com/dyn/resources/prod_documents/doc2542.pdf but have not found an h-bridge inverter driver example anywhere.

Sooo, no one has ever written anything like this (or has, but is hiding it :D), so I am planning on doing it, but since i never did anything but hello world on parallel LCD, one servo and few LEDs on arduino, I don't really know how to start...

Any suggestion would be more than welcome!

Thx in advance!

Regards, Sandi

What is confusing me is you say:- "PWM sine"
PWM is pulse width modulation and by definition it is a rectangular wave see:- PWM

So I don't understand what a PWM sine wave is.

A H bridge works with on / off signals and connects a point to either one of two voltage points, a H bridge can't be used with a sine wave so again I am puzzled.

Do you mean a Class B amplifier:-

If you were a bit more forthcoming with what you are trying to do rather than what you think you want to produce maybe we could help you more.

Sorry Mike, English is not my first language since pictures are like 1000 words i guess i should have posted some pics firtst. Also it would be correct for me to use the word SPWM (Sinusoidal PWM) instead of PWM sine. I understand the theory of H-bridges, but programming is really not what i am any good at... Here's a SPWM uC theory (but this uC is for 3 phase control, i need just one fase ie. just two control signals): http://www.infineon.com/dgdl/AP1609710_different_PWM_for_three_phase_ACIM.pdf?folderId=db3a304412b407950112b408e8c90004&fileId=db3a304412b407950112b40a1bf20453

It's not a amplifier i am trying to build, it is actually an inverter (look at the picture of H-bridge inverter circuit with transistor switches and antiparallel diodes here:http://encon.fke.utm.my/nikd/SEM4413/inverter/draw-spwm.pdf) with variable frequency that is going to be used to run a small single phase AC motor.

Oh, thx for replying even if i had so many stupidities in my post :wink:

Hi, I have same problem: I need to generate PWM signal on two pins, but when on the first pin is logical 1, on second must by 0 and vice-versa.
In other words, these two PWM signals can be never in state ON in the same time.

So: I can generate signal for first PWM:
analogWrite(pin, value)

  • it will be ON for time some times (calculated from value) and than closed till end of period
    But how to generate signal, which will be OFF for times calculated from value and than On till end of period?

Because whole stuff is done inside one function so I don't know, what to use to create second PWM signal.

Thank you and I am sorry for my English

I need to generate PWM signal on two pins, but when on the first pin is logical 1, on second must by 0 and vice-versa.
In other words, these two PWM signals can be never in state ON in the same time.

Hey srnka,

You have 3 methods which i'm myself using but there require you to program in low level AVR, not from IDE.

Method 1 which is software time oriented

int outputPin5 = 5;   // PORTE - Pin #3
int outputPin2 = 2;   // PORTE - bit #4
int charge_on, charge_off, extract_on, extract_off;
int duty_charge_on, duty_charge_off, duty_extract_on, duty_extract_off;
long freq;

void setup()
{
  Serial.begin(9600);
  pinMode(outputPin5, OUTPUT);
  pinMode(outputPin2, OUTPUT);
  scene(3);
}

void loop()
{
  cli(); // turn off interrupts

  while (true) { // start critical loop
// Turns ON coil charging opto-coupler #1 
    PORTE |= B1000;
    _delay_loop_2(charge_on);

// Turns OFF coil charging opto-coupler #1 
    PORTE &= B11110111;
    _delay_loop_2(charge_off);

// Turns ON coil FE extracting opto-coupler #2 
    PORTE |= B00010000;
    _delay_loop_2(extract_on);

// Turns OFF coil FE extracting opto-coupler #2 
    PORTE &= B11101111; 
    _delay_loop_2(extract_off);

// check usb port and if there is data.  Break out of loop to handle it
   if (UCSR0A & _BV(RXC0)) break; 
  } // end of time critical loop

  sei();  // interrupts back on

// gets new parameter from USB Serial Monitor connected to Macintosh then update on board
  change_param();
}

Method 2 which is timer oriented, please read http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1252073278 plus AVR data sheet to understand specific way to generate inverted toggle signals with timers.

Method 3 is a mix of method 1 and method 2 by using interupts.

With method 1, you can control in sync up to 8 pins.

For both method, I suggest you use this excellent doc giving internal AVR allocation pins & other signals.

if the 2 PWM outputs are synchronized (which I'm assuming to be the case), couldn't you just put a NOT gate on one? I may have no idea what I'm talking about, but that was the first solution that came to mind.

well, what you propose works but it is a hardware solution whereas here, a software solution works perfectly so you save electronic components (cheaper & smaller PCB) plus have a better phase purity between 2 PWM signals because a NOT gate always some some time delays. With low power H-bridge no problem but if high power... Boum :frowning:

You need:-
http://tams-www.informatik.uni-hamburg.de/applets/hades/webdemos/12-gatedelay/40-tpcg/two-phase-clock-gen.html

Just to mention that if you have a filter of a PWM signal, then the phase shift through the filter is frequency dependent.

Thanks everybody for help,
I used selfonlypath's help - method two.
So I only needed to know how to work with (or set) registers in Arduino software and than read the datasheet of microcontroller to find how to set inverted PWM signals generating.

So now it works perfectly.

srnka, can you post how you did it? As i already wrote here, i still have no clue how to get the final result.

THX in advance!

Sandi

Sandi,
I programmed it to the project to school, and I am afraid, they couldn't accept it, if they would find it in the internet. (Maybe I am paranoic, but I don't want to explain, that "srnka" is me).
So I can post it to forum in month, when I finish my project.
But you can write me a mail and I will send you that code.

My final code: FORNAX Magazín | Články o produktoch a službách na internete

Here's the code i managed to write, but the problem is, that i am not so sure it will work, so i decided to post it here for you to see it and tell me what you think. For now only the speed of frequency changing can be set by "s", future plan is to make code that will allow me to control the speed of frequency alternation (form 33-61Hz) and min and max output frequency (to set higher f_min than 33Hz and lower f_max than 66Hz) by reading analog values. That's next, I am in no hurry...

Please comment - suggestions are more than wellcome!

/* based on code by srnka
 Generating of PWM signals for single phase inverter circuit
 generating of sine signals with freq from 33 Hz to 61 Hz
 output values: PWM signals on 2 PWM outputs: one inverted and one non-inverted
*/
int i;  //i...for cycle
int j=64; //for setting the correct number of steps for the selected frequency (initial is the nr. of samples at 61Hz)
int z=0; //for selecting the correct value from the sinetable
int x=0;  //frequency selector - setting initial freq to 61 Hz 
int y=0;  //setting of loop counter
int s=30;  //this value is the speed of frequency changing - later it could be controlled by a variable resistor connected to analog input 
float phase;      // For calculating value of phase
//setting of sin table for half-period of 8 frequencies

//      steps     frequency
//sin1      64      61,03515625
//sin2      70      55,80357143
//sin3      78      50,08012821
//sin4      86      45,42151163
//sin5      94      41,55585106
//sin6      102      38,29656863
//sin7      110      35,51136364
//sin8      118      33,10381356

//======================:.-"-.:    S I N E T A B L E   :.-"-.:====================================
//values are calculated from sinus values and amplidude is corrected based on tests
int sinus[]= {127, 133, 140, 146, 152, 158, 164, 170, 176, 182, 188, 193, 199, 204, 209, 213, 
      218, 222, 226, 230, 234, 237, 240, 243, 245, 247, 249, 251, 252, 253, 254, 254, 254, 254, 253, 
      252, 251, 249, 247, 245, 243, 240, 237, 234, 230, 226, 222, 218, 213, 209, 204, 199, 193, 188, 
      182, 176, 170, 164, 158, 152, 146, 140, 133, 127, 
      
      127, 132, 138, 143, 148, 153, 158, 163, 168, 173, 178, 183, 187, 192, 196, 200, 204, 208, 212, 
      215, 219, 222, 225, 227, 230, 232, 234, 236, 238, 239, 241, 242, 242, 243, 243, 243, 243, 242, 
      242, 241, 239, 238, 236, 234, 232, 230, 227, 225, 222, 219, 215, 212, 208, 204, 200, 196, 192, 
      187, 183, 178, 173, 168, 163, 158, 153, 148, 143, 138, 132, 127, 
      
      127, 131, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 188, 192, 195, 199,
      202, 205, 208, 211, 213, 216, 218, 220, 222, 224, 226, 228, 229, 230, 231, 232, 233, 233, 234,
      234, 234, 234, 233, 233, 232, 231, 230, 229, 228, 226, 224, 222, 220, 218, 216, 213, 211, 208, 
      205, 202, 199, 195, 192, 188, 185, 181, 177, 173, 169, 165, 161, 157, 153, 149, 144, 140, 136, 
      131, 127, 
      
      127, 131, 134, 138, 142, 145, 149, 152, 156, 159, 163, 166, 169, 173, 176, 179, 182, 185, 188, 
      191, 194, 196, 199, 201, 204, 206, 208, 210, 212, 214, 216, 217, 219, 220, 221, 222, 223, 224, 
      225, 225, 226, 226, 226, 226, 226, 226, 225, 225, 224, 223, 222, 221, 220, 219, 217, 216, 214, 
      212, 210, 208, 206, 204, 201, 199, 196, 194, 191, 188, 185, 182, 179, 176, 173, 169, 166, 163, 
      159, 156, 152, 149, 145, 142, 138, 134, 131, 127, 
      
      127, 130, 133, 136, 139, 142, 145, 148, 151, 154, 157, 160, 163, 166, 168, 171, 174, 176, 179, 
      181, 184, 186, 189, 191, 193, 195, 197, 199, 201, 203, 204, 206, 207, 209, 210, 211, 212, 213, 
      214, 215, 216, 216, 217, 217, 218, 218, 218, 218, 218, 218, 217, 217, 216, 216, 215, 214, 213, 
      212, 211, 210, 209, 207, 206, 204, 203, 201, 199, 197, 195, 193, 191, 189, 186, 184, 181, 179, 
      176, 174, 171, 168, 166, 163, 160, 157, 154, 151, 148, 145, 142, 139, 136, 133, 130, 127, 
      
      127, 130, 132, 135, 137, 140, 142, 145, 147, 150, 152, 155, 157, 160, 162, 164, 167, 169, 171, 
      173, 175, 177, 179, 181, 183, 185, 187, 189, 190, 192, 194, 195, 197, 198, 199, 201, 202, 203,
      204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 210, 210, 210, 210, 210, 210, 210, 209, 209, 
      208, 208, 207, 206, 206, 205, 204, 203, 202, 201, 199, 198, 197, 195, 194, 192, 190, 189, 187, 
      185, 183, 181, 179, 177, 175, 173, 171, 169, 167, 164, 162, 160, 157, 155, 152, 150, 147, 145, 
      142, 140, 137, 135, 132, 130, 127, 
      
      127, 129, 131, 133, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 
      166, 168, 170, 171, 173, 175, 176, 178, 180, 181, 183, 184, 185, 187, 188, 189, 190, 192, 193, 
      194, 195, 196, 196, 197, 198, 199, 199, 200, 200, 201, 201, 201, 202, 202, 202, 202, 202, 202, 
      202, 202, 201, 201, 201, 200, 200, 199, 199, 198, 197, 196, 196, 195, 194, 193, 192, 190, 189, 
      188, 187, 185, 184, 183, 181, 180, 178, 176, 175, 173, 171, 170, 168, 166, 164, 162, 160, 158, 
      156, 154, 152, 150, 148, 146, 144, 142, 140, 138, 136, 133, 131, 129, 127, 
      
      127, 129, 131, 132, 134, 136, 138, 140, 141, 143, 145, 147, 148, 150, 152, 153, 155, 157, 158, 
      160, 161, 163, 164, 166, 167, 169, 170, 171, 173, 174, 175, 177, 178, 179, 180, 181, 182, 183, 
      184, 185, 186, 187, 188, 188, 189, 190, 190, 191, 191, 192, 192, 193, 193, 193, 194, 194, 194, 
      194, 194, 194, 194, 194, 194, 194, 193, 193, 193, 192, 192, 191, 191, 190, 190, 189, 188, 188, 
      187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 175, 174, 173, 171, 170, 169, 167, 166, 
      164, 163, 161, 160, 158, 157, 155, 153, 152, 150, 148, 147, 145, 143, 141, 140, 138, 136, 134, 
      132, 131, 129, 127};

//14 steps of frequency ramping (actually just 8 different freq. in loop)     
int fbase[]={64,70,78,86,94,102,110,118,110,102,94,86,78,70};        

//======================:.-"-.:    S E T U P   :.-"-.:============================================
void setup()
{
 
  
 //=====setting of timer0 for fast PWM method====
 //frequency PWM is fosc/(8*256) (by 16MHz oscil. = 7812,5)
 //timer 0, 8-bit timer, pins 5,6(+)   128us  
 TCCR0A=0b10110011;   // generate inverted PWM signals in output 
 TCCR0B=0b00000010;   // set of source of clock signal + prescaller
  
 //setting of PWM ports 5 and 6 to output (one is inverted - frequency is the same all the time)
 pinMode(5,OUTPUT);
 pinMode(6,OUTPUT); 
 
}

//======================:.-"-.:  M A I N   L O O P  :.-"-.:============================================ 
void loop()
{
 
 //when "2*s" number of loops are made, the frequency is changed 
 //(2*s to get whole sine wave - 360deg, no matter what the value of "s" is, 
 //since j is the number of steps in half of sine period (at startup it is set to 64, so the infinite loop can) start
 
  if(y==2*s*j)   //check if some frequency has been looped for 2*s times (since j is a number of steps in 1/2 period
   { x=x+1;     //here the frequency change is done with "x" (initial value is 0!)
   if(x==14){   //if x is higher than 13 i.e. when x==14 it needs to be set to 0 again
     x=0;}
   }
 
   j=fbase[x];   //setting the freq. to the selected one  / first the x=0, so j=64 (frequency is 61 Hz)
    //change of polarity
    TCCR0A = TCCR0A ^ 0b01010000;
   //cycle for half period
  for(i=0; i<j;i++)
  {
   //setting the correct "z" for the selected frequency
    if(j==64){                   //           61Hz
      z=i;                   
     }
    if(j==70){                  //           55Hz
      z=i+64;  //+64
     }
    if(j==78){          
      z=i+134; //70+64          //            50Hz
     }
    if(j==86){
      z=i+212;  //78+70+64      //            45Hz
     }
    if(j==94){
      z=i+298; //86+78+70+64      //            42Hz
     }
    if(j==102){
      z=i+392; //94+86+78+70+64     //      38Hz
     }
   if(j==110){
      z=i+494; //102+94+86+78+70+64      // 35Hz
     }
    if(j==118){
      z=i+604; //110+102+94+86+78+70+64    //33Hz
     }
   //generating of value OCR0x, but output frequency is the same, since they are toggled outputs
   //(it's just that when one sine wave raises the other decreases)
    phase=sinus[z];
    OCR0A=byte(phase);
    OCR0B=byte(phase);

 }  
 //******************************************************
 y=y++;  //loop counter
}

I think what you mean is about sinusoidal pulse width modulation(SPWM).

Right?