+ Post New Thread
Results 1 to 12 of 12
  1. #1
    Newbie level 4
    Points: 283, Level: 3

    Join Date
    Dec 2017
    Location
    MG, Brazil
    Posts
    7
    Helped
    0 / 0
    Points
    283
    Level
    3

    sPWM waveform distortion next to zero crossing

    Hi all!

    First of all, I want to tell that I've been facing this problem for a month and did a lot of things and search without any potential results.
    Click image for larger version. 

Name:	DS1Z_QuickPrint1.jpg 
Views:	9 
Size:	87.0 KB 
ID:	152291

    I'm developing an sPWM voltage inverter using the AVR Atmega 328P with timer configuration.

    There are two tables implemented. Table lookUp_1[] carries the values for the complementary side of the PWM and also implements the dead time for the lookUp_2[] that contain the active pulses to be applied at IR2110 Mosfet Drivers.

    The sPWM was implemented using phase correct mode to maintain the pulses center aligned.

    Click image for larger version. 

Name:	DS1Z_QuickPrint4.jpg 
Views:	3 
Size:	84.2 KB 
ID:	152292
    Click image for larger version. 

Name:	DS1Z_QuickPrint6.jpg 
Views:	4 
Size:	83.8 KB 
ID:	152293

    The other outputs (Yellow and fresh bold Blue) are just fundamental signals at 60Hz. The SPWM are applied on M1 and M3 (pink and blue waveforms)

    Click image for larger version. 

Name:	DS1Z_QuickPrint13.jpg 
Views:	5 
Size:	91.7 KB 
ID:	152294

    I'm using the single topology for the inverter.

    The control and power schematic, some photos, and algorithm are attached to this thread.

    Click image for larger version. 

Name:	Esquema potencia.png 
Views:	9 
Size:	49.0 KB 
ID:	152295
    Click image for larger version. 

Name:	esquema controle.png 
Views:	7 
Size:	79.5 KB 
ID:	152296
    My main problem is with the shape of the waveform next to zero crossing.

    Suggestions will be amazing.

    Thanks.
    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    volatile static char theTCCR1A = 0b10110010; //varible for TCCR1A
    int analogValue = 0;
    int storageAnalogValue = 0;
    volatile char cycle = 1;    // Variável que irá mudar de acordo com o ciclo para alterar o Dead-Time
    volatile int value = 0;
    
    // 200 values
    int lookUp_1[] = {20, 24, 28, 31, 35, 39, 43, 46, 50, 54, 58, 61, 65, 69, 72, 76, 80, 83, 87, 91, 94, 98, 101, 105, 108, 112, 115, 119, 122, 126, 129, 132, 136, 139, 142, 145, 149, 152, 155, 158, 161, 164, 167, 170, 173, 176, 179, 182, 184, 187, 190, 192, 195, 198, 200, 202, 205, 207, 210, 212, 214, 216, 218, 221, 223, 225, 227, 228, 230, 232, 234, 236, 237, 239, 240, 242, 243, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 256, 257, 258, 258, 259, 259, 259, 260, 260, 260, 260, 260, 260, 260, 260, 260, 259, 259, 259, 258, 258, 257, 256, 256, 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 243, 242, 240, 239, 237, 236, 234, 232, 230, 228, 227, 225, 223, 221, 218, 216, 214, 212, 210, 207, 205, 202, 200, 198, 195, 192, 190, 187, 184, 182, 179, 176, 173, 170, 167, 164, 161, 158, 155, 152, 149, 145, 142, 139, 136, 132, 129, 126, 122, 119, 115, 112, 108, 105, 101, 98, 94, 91, 87, 83, 80, 76, 72, 69, 65, 61, 58, 54, 50, 46, 43, 39, 35, 31, 28, 24};
    int lookUp_2[] = {2, 4, 8, 11, 15, 19, 23, 26, 30, 34, 38, 41, 45, 49, 52, 56, 60, 63, 67, 71, 74, 78, 81, 85, 88, 92, 95, 99, 102, 106, 109, 112, 116, 119, 122, 125, 129, 132, 135, 138, 141, 144, 147, 150, 153, 156, 159, 162, 164, 167, 170, 172, 175, 178, 180, 182, 185, 187, 190, 192, 194, 196, 198, 201, 203, 205, 207, 208, 210, 212, 214, 216, 217, 219, 220, 222, 223, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 236, 237, 238, 238, 239, 239, 239, 240, 240, 240, 240, 240, 240, 240, 240, 240, 239, 239, 239, 238, 238, 237, 236, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 223, 222, 220, 219, 217, 216, 214, 212, 210, 208, 207, 205, 203, 201, 198, 196, 194, 192, 190, 187, 185, 182, 180, 178, 175, 172, 170, 167, 164, 162, 159, 156, 153, 150, 147, 144, 141, 138, 135, 132, 129, 125, 122, 119, 116, 112, 109, 106, 102, 99, 95, 92, 88, 85, 81, 78, 74, 71, 67, 63, 60, 56, 52, 49, 45, 41, 38, 34, 30, 26, 23, 19, 15, 11, 8, 4};
    
    void setup() {
      // Register initilisation, see datasheet for more detail.
      // Timer Counter Control Register 1 A
      TCCR1A = theTCCR1A; // 0b10110010;
      /*10 Desliga OC1A (D9) no valor de comparação, Liga OC1A em 0V (Modo Não Invertido) Tabela 15-3 Datasheet
        11 Liga OC1B (D10) no valor de comparação, Desliga OC1B em 0V (Modo Invertido)  Tabela 15-3 Datasheet
        00 Bits 3 e 2 Não possuem função
        10 WGM11=1 e WGM10=0 for waveform 10 - Phase Correct mode - Garante o tempo morto
      */
      // Timer Counter Control Register 1 A
      TCCR1B = 0b00010001;
      /*000
        10 WGM13=1 e WGM12=0 Para a forma de onda 10 Phase Corretc PWM mode
        001 Sem preescale para o contador.
      */
      // Timer Interrupt Mask Register 1
      TIMSK1 = 0b00000001;
      /*0000000
        1 TOV1 Flag interrupt enable.
      */
      ICR1 = 333;
      sei();             // Enable global interrupts.
    
      // Set outputs pins.
      // Data Direction Register PORTB
      // 1 -> Saída
      // 0 -> Entrada
      // Configura os pinos PB1(D9), PB2 (D10), PB3 (D11), PB4 (D12) como saidas
      DDRB   = 0b00011110;
      // Inicialização das saídas
      PORTB |= 0b00001000; // Escreve HIGH no PB3 (D11) sem afetar os outros pinos
      PORTB &= 0b11101111; // Escreve LOW no bit  PB4 (D12) sem afetar os outros pinos
    }
    
    void loop() {
    
      value = (analogRead(A0) / 10);
    }
    
    // Interrupt Service Routine
    ISR(TIMER1_OVF_vect) {
      static int num;
      static int i;
      static int delay1;
      static char trig;
    
      if (num >= 200) {
        TCCR1A ^= 0b01010000;
    
        if (cycle) {
          OCR1A = lookUp_2[192] + value; // PIN D9 (2HO) -> Canal 4 (AZUL ESCURO) do Ciclo 1, onde Amarelo está em ON e Azul Escuro Modula Junto ao Amarelo. Rosa é o complemento
          OCR1B = lookUp_1[num] + value ; // PIN D10 (2LO) -> Canal 3 (ROSA) do cilco 1, onde Azul claro está em OFF e Rosa é o complemento do Azul escuro
          //num ++;
        } else {
          OCR1A = lookUp_1[num] + value ; // PIN D9 (2HO) -> Canal 4 (AZUL ESCURO) do ciclo 2 onde Amarelo está em OFF e é o complemento de ROSA
          OCR1B = lookUp_2[192] + value; // PIN D10 (2LO) -> Canal 3 (ROSA) do cliclo 2, onde Azul Claro está em ON e ROSA modula junto com Azul Claro.
          //num ++;
        }
    
        // Delay  for 2000 entries on table
        // Just to sincronize
        for ( int i = 0; i <= 43; i++ ) {
          asm volatile ("nop");
        }
    
        if (cycle) {
          PORTB ^= 0b00001000;  //Faz um togle no pino PB3 (D11) e PB4 (D12) Sem afetar os outros Pinos
          for ( int i = 0; i <= 6; i++ ) {
            asm volatile ("nop");
          }
          PORTB ^= 0b00010000;  //Faz um togle no pino PB3 (D11) e PB4 (D12) Sem afetar os outros Pinos
        } else {
          PORTB ^= 0b00010000;  // Faz um togle no pino PB3 (D11) e PB4 (D12) Sem afetar os outros Pinos
          for ( int i = 0; i <= 6; i++ ) {
            asm volatile ("nop");
          }
          PORTB ^= 0b00001000;  // Faz um togle no pino PB3 (D11) e PB4 (D12) Sem afetar os outros Pinos
        }
        cycle  ^= 0b00000001;
        num = 0;
      }
    
      if (cycle) {
        OCR1A = lookUp_2[num] + value; // PIN D9 (2HO) -> Canal 4 (AZUL ESCURO) do Ciclo 1, onde Amarelo está em ON e Azul Escuro Modula Junto ao Amarelo. Rosa é o complemento
        OCR1B = lookUp_1[num] + value ; // PIN D10 (2LO) -> Canal 3 (ROSA) do cilco 1, onde Azul claro está em OFF e Rosa é o complemento do Azul escuro
        num ++;
      } else {
        OCR1A = lookUp_1[num] + value ; // PIN D9 (2HO) -> Canal 4 (AZUL ESCURO) do ciclo 2 onde Amarelo está em OFF e é o complemento de ROSA
        OCR1B = lookUp_2[num] + value; // PIN D10 (2LO) -> Canal 3 (ROSA) do cliclo 2, onde Azul Claro está em ON e ROSA modula junto com Azul Claro.
        num ++;
      }
    }

  2. #2
    Super Moderator
    Points: 72,488, Level: 65
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    14,734
    Helped
    3365 / 3365
    Points
    72,488
    Level
    65

    Re: sPWM waveform distortion next to zero crossing

    Hi,

    The values of lookUp_1 are DC shifted by a value (about 18) with respect to the values of lookUp_2.
    You output the values to OCR1A and OCR1B
    But depending on "cycle" you interchange OCR1A with OCR1B .... thus... the values for OCR1x will jump..
    Isn't it expectable that this causes some jump in the resulting waveform?

    Btw: OCRx registers seem to be single byte registers ... with a valid range of 0...255 ...but lookUp_1 values go up to 260, which is beyond the valid range. How can this work?

    Klaus

    Added:
    I recommend to use Excel to "simulate" what your OCR1x values look like.
    Then let Excel draw a chart.
    It should be done within a couple of minutes.

    Klaus
    Please don´t contact me via PM, because there is no time to respond to them. No friend requests. Thank you.


    2 members found this post helpful.

    •   AltAdvertisment

        
       

  3. #3
    Super Moderator
    Points: 253,760, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    44,210
    Helped
    13454 / 13454
    Points
    253,760
    Level
    100

    Re: sPWM waveform distortion next to zero crossing

    The zero crossing discontinuity is mainly caused by the huge dead time (> 1 us) in your pwm pattern and the respective magnitude offset in the tables. Useful MOSFET deadtime is in a 10 ns to 100 ns range. You have asymmetrical gate driver which possibly allows down to zero deadtime.

    Using an unipolar pwm pattern which applies pwm to all four switches will probably improve the zero crossing because it has 50% duty cycle for zero output.


    1 members found this post helpful.

  4. #4
    Newbie level 4
    Points: 283, Level: 3

    Join Date
    Dec 2017
    Location
    MG, Brazil
    Posts
    7
    Helped
    0 / 0
    Points
    283
    Level
    3

    Re: sPWM waveform distortion next to zero crossing

    Hi KlausST!

    Thanks for your kindly answer!

    The values of lookUp_1 are DC shifted by a value (about 18) with respect to the values of lookUp_2.
    You output the values to OCR1A and OCR1B
    But depending on "cycle" you interchange OCR1A with OCR1B .... thus... the values for OCR1x will jump..
    Isn't it expectable that this causes some jump in the resulting waveform?
    These tables are used to store the values for the duty cycle applied to MOSFET drivers. They are changed dynamically as the counter of the time overflows inside the ISR(TIMER1_OVF_vect) routine.

    I'm interchanged the OCR1A and OCR1B when the counter reaches the table limit value, in this case, 200 iterations for the ICR1 = 333. So, I'm changing each semi-cycle of the sinusoidal waveform.

    Btw: OCRx registers seem to be single byte registers ... with a valid range of 0...255 ...but lookUp_1 values go up to 260, which is beyond the valid range. How can this work?
    In this case, the size of timer 1 of the ATMEGA 328P is 16 bit so the OCRx register can store a 16 bit value.

    About the tables, only the lookUp_2[] is effectively applying the duty cycle to the MOSFETs at each semi cycle. As you said, when the semi cycle changes, we change the output and the int lookUp_2[] is the same for the other output also.

    The int lookUp_1[] is just the complementary side of int lookUp_2[] for this kind of modulation type is named unipolar modulation. The picture below shows the result of lookUp_2[], in blue, and lookUp_1[] in pink. The dead time is also shown.

    Click image for larger version. 

Name:	1DS1Z_QuickPrint8.jpg 
Views:	4 
Size:	75.7 KB 
ID:	152300

    The picture below shows an overview modulation waveform.

    Click image for larger version. 

Name:	DS1Z_QuickPrint20.jpg 
Views:	4 
Size:	93.0 KB 
ID:	152301

    So, I'm guessing doing this in the right way as the pulses are applied based on the lookUp_2[] that starts with a little value.

    If you guys have more suggestions, I'll be glad.

    Thanks.

    - - - Updated - - -

    Hi FvM,

    I have also tested this design with almost no dead time and the results were basically the same at zero crossing.

    I thought more dead time represents more safety for MOSFETs operation as the effective work is done by values inside lookUp_2 [].

    I'll also test switch four MOSFETs as you said and post here the results.

    By the way, I've seen a strange waveform at the output of the microcontroller when the prototype inverts starts using a battery or power supply. The picture below shows this. Is that interference applied to the oscilloscope or is this effectively contributing to the waveform shape problem?

    Click image for larger version. 

Name:	DS1Z_QuickPrint7.jpg 
Views:	6 
Size:	120.8 KB 
ID:	152302

    When only microcontroller is on, the output is like this:

    Click image for larger version. 

Name:	DS1Z_QuickPrint13.jpg 
Views:	1 
Size:	91.7 KB 
ID:	152303

    Just to refresh, yellow waveform works together with the dark blue and the light blue works with the pink waveform depending basically on which semi cycle is on course.

    Later I'll post the results that you sugested.

    Thanks.



  5. #5
    Advanced Member level 4
    Points: 7,717, Level: 20

    Join Date
    Aug 2015
    Posts
    1,217
    Helped
    454 / 454
    Points
    7,717
    Level
    20

    Re: sPWM waveform distortion next to zero crossing

    200nS is a min safe dead time - you need to look at your code behaviour around the zero crossing ,,,


    1 members found this post helpful.

    •   AltAdvertisment

        
       

  6. #6
    Newbie level 4
    Points: 283, Level: 3

    Join Date
    Dec 2017
    Location
    MG, Brazil
    Posts
    7
    Helped
    0 / 0
    Points
    283
    Level
    3

    Re: sPWM waveform distortion next to zero crossing

    Hi everyone,

    Thanks for the reply!

    Now I have this clear waveform shape.

    Click image for larger version. 

Name:	DS1Z_QuickPrint21.jpg 
Views:	6 
Size:	87.0 KB 
ID:	152314

    I've just adjusted the dead time for 200ns as you guys said.

    Click image for larger version. 

Name:	DS1Z_QuickPrint15.jpg 
Views:	5 
Size:	104.9 KB 
ID:	152315

    Click image for larger version. 

Name:	DS1Z_QuickPrint16.jpg 
Views:	4 
Size:	87.7 KB 
ID:	152316

    And in the zero crossing, the modulation looks like this:

    Click image for larger version. 

Name:	DS1Z_QuickPrint17.jpg 
Views:	4 
Size:	84.0 KB 
ID:	152317

    Click image for larger version. 

Name:	DS1Z_QuickPrint18.jpg 
Views:	4 
Size:	88.9 KB 
ID:	152318

    Now I have another doubt: When I'm trying to adjust the amplitude of the waveform using a potentiometer attached to analog channel 0, I'm having the waveform shape indicated below.

    Click image for larger version. 

Name:	DS1Z_QuickPrint22.jpg 
Views:	8 
Size:	88.9 KB 
ID:	152319

    I know that I'm just adjusting the duty cycle by adding some values from the Analog Channel.

    What could be the cause of this issue?

    Do you guys have some suggestion for me about the correction and adjustment of the amplitude of the waveform?

    Thanks in advance.
    Eduardo.



  7. #7
    Super Moderator
    Points: 28,804, Level: 41
    andre_teprom's Avatar
    Join Date
    Nov 2006
    Location
    Brazil
    Posts
    8,584
    Helped
    1087 / 1087
    Points
    28,804
    Level
    41
    Blog Entries
    6

    Re: sPWM waveform distortion next to zero crossing

    At a glance I could not find any potentiometer at the above schematic, anyway is there any capacitor (e.g ceramic) in parallel with the pot cutting of high frequencies due to contact glitches?
    --------------------------------------------------------------------------------------------------
    Part of the world that you live in, You are the part that you're giving ( Renaissance )


    1 members found this post helpful.

  8. #8
    Newbie level 4
    Points: 283, Level: 3

    Join Date
    Dec 2017
    Location
    MG, Brazil
    Posts
    7
    Helped
    0 / 0
    Points
    283
    Level
    3

    Re: sPWM waveform distortion next to zero crossing

    Hi André!

    Thanks for the reply.

    I've not updated the schematic for the potentiometer but is just a pot attached to Analog 0 without any special component.

    Inside the void loop() we can see the value been getting and storage in the value variable. It is just a test for a kind of amplitude correction.

    Is there necessary to put a ceramic cap in parallel with the Analog input?

    I've designed other kinds of stuff using the analog channel and just a moving average to filter.

    Thanks



  9. #9
    Super Moderator
    Points: 72,488, Level: 65
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    14,734
    Helped
    3365 / 3365
    Points
    72,488
    Level
    65

    Re: sPWM waveform distortion next to zero crossing

    Hi,

    Is there necessary to put a ceramic cap in parallel with the Analog input?

    I've designed other kinds of stuff using the analog channel and just a moving average to filter.
    Nyquist applies to every ADConversion.
    This means, if there is higher frequency noise than fs/2, then alias frequencies will be generated.
    The alias frequency range is from DC to fs/2. Thus you have no chance to filter out all alias frequencies on the digital side.
    --> use an anti aliasing filter to get more stable signal at the digital side.
    Often this is just a C, or an RC .... is this too much effort?

    ******
    You know your voltage scheme is "dirty" because it just adds DC to each half wave and generates exctly the waveform you are worried in post#1.
    Depending on filter this "step" may cause ringing.
    --> do the clean amplitude regulation by multiplying the PWM values.

    Klaus
    Please don´t contact me via PM, because there is no time to respond to them. No friend requests. Thank you.


    1 members found this post helpful.

  10. #10
    Newbie level 4
    Points: 283, Level: 3

    Join Date
    Dec 2017
    Location
    MG, Brazil
    Posts
    7
    Helped
    0 / 0
    Points
    283
    Level
    3

    Re: sPWM waveform distortion next to zero crossing

    Hi KlausST,

    I've just added an RC Low pass filter with a ceramic Cap about 200nF and a resistor with 10K Ohms as Atmega 328 datasheet recommends input impedance lower than this for analog channels.

    The waveform glitches are the same as without filter.

    --> do the clean amplitude regulation by multiplying the PWM values.
    What do you mean with "multiplying the PWM values"?

    At the moment, I'm just getting the values of the conversion and adding that at all values of the table.

    Thanks.



    •   AltAdvertisment

        
       

  11. #11
    Super Moderator
    Points: 72,488, Level: 65
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    14,734
    Helped
    3365 / 3365
    Points
    72,488
    Level
    65

    Re: sPWM waveform distortion next to zero crossing

    Hi,

    What do you mean with "multiplying the PWM values"?

    At the moment, I'm just getting the values of the conversion and adding that at all values of the table.
    You didn't do the Excel calculations yet.
    If you did, you know (see) what I mean.

    You currrently do sonething like this:
    OCRx = tablevalue + ADCvalue

    But you should do:
    OCRx = tablevalue x ADCvalue

    More precise:
    OCRx = tablevalue x ( 1+ 0.2 × ADCvalue / 1024)
    (This is the formula for a 0%...+20% amplitude adjust for a 10 bit ADC)

    But on a microcontroller you try to avoid division and you need to limit the values thus one may optimize:
    * Your table values currently are 0..260, this is 9 bits wide.But you only have an 8 bit hardware multiplier. Thus I recommend to shift them 1 bit right. Now you get only half of the value: 0..130 (one byte)
    * Your ADC values are 10 bit. I recommend to use "left aligned mode" and just take the upper byte for further calculations. Range: 0..255.
    Now you can multiply the (8 bit) ADCvalue with the (8bit) tablevalue...you get a 16 bit result. (Range: 0...33150)
    Take the upper byte: (range 0..129) and shift it one bit right. (The range now is 0...64)
    Now add this value to the initial table value.
    ..and move this value to the OCR register.
    Finished

    This results in a 100% to 125% amplitude adjust according ADC input.

    With inline assembler this may take just about 10 clock cycles. On an 8MHz AVR less than 1.5us

    Klaus
    Please don´t contact me via PM, because there is no time to respond to them. No friend requests. Thank you.


    1 members found this post helpful.

  12. #12
    Newbie level 4
    Points: 283, Level: 3

    Join Date
    Dec 2017
    Location
    MG, Brazil
    Posts
    7
    Helped
    0 / 0
    Points
    283
    Level
    3

    Re: sPWM waveform distortion next to zero crossing

    Hi everyone!

    * Your table values currently are 0..260, this is 9 bits wide.But you only have an 8 bit hardware multiplier. Thus I recommend to shift them 1 bit right. Now you get only half of the value: 0..130 (one byte)
    * Your ADC values are 10 bit. I recommend to use "left aligned mode" and just take the upper byte for further calculations. Range: 0..255.
    Now you can multiply the (8 bit) ADCvalue with the (8bit) tablevalue...you get a 16 bit result. (Range: 0...33150)
    Take the upper byte: (range 0..129) and shift it one bit right. (The range now is 0...64)
    Now add this value to the initial table value.
    ..and move this value to the OCR register.
    KlausST, I've done every part as described from you and works just Fine!

    Thanks a lot for your tips.

    Below is the part of the code suggested.

    Code:
    void setupADC() {
      DDRC   = 0x00;         // Make ADC port as input
    
      ADMUX = (1 << REFS0) | // Select reference voltage as AVcc
              (1 << ADLAR) | // Select Left Adjust Mode (8 bits)
              (1 << MUX0)  | // Select Bit 0 for ADC5
              (1 << MUX2);   // Select bit 2 for ADC5
    
      ADCSRA = (1 << ADEN)  | // Enables de ADC
               (1 << ADIE)  | // Enables the ADC interrup routine
               (1 << ADPS0) | // Set the Preescaler bit S0 for 128 division factor
               (1 << ADPS1) | // Set the Preescaler bit S1 for 128 division factor
               (1 << ADPS2);  // Set the Preescaler bit S3 for 128 division factor
    
      DIDR0 = (1 << ADC5D);   // Disable the digital input buffer for this specific AD5
      startConversion();
    }
    
    void startConversion() {
      ADCSRA |= (1 << ADSC);  // Start single conversion mode of the ADC
    }
    
    // ADC Interrupt Service Routine
    ISR(ADC_vect) {
      valueADC = ADCH;
      startConversion();
    }
    
    // Timer Interrupt Service Routine
    ISR(TIMER1_OVF_vect) {
      valueAdjusted_1 = (valueADC * lookUp_3[num]);         // Take the value
      valueAdjusted_1 = (valueAdjusted_1 & 0xFF00) >> 8;    // Take the high side of the int
      valueAdjusted_1 =  valueAdjusted_1 >> 1;              // shift them 1 bit right
      valueAdjusted_1 =  valueAdjusted_1 + lookUp_2[num];   // Add the new value to the original table
    
      valueAdjusted_2 = (valueADC * lookUp_4[num]);         // Take the value
      valueAdjusted_2 = (valueAdjusted_2 & 0xFF00) >> 8;    // Take the high side of the int
      valueAdjusted_2 =  valueAdjusted_2 >> 1;              // shift them 1 bit right
      valueAdjusted_2 =  valueAdjusted_2 + lookUp_1[num];   // Add the new value to the original table
    
      if (num >= 200) {
        TCCR1A ^= 0b01010000; // Toggle the way timer works doing an XOR operation
    
    
        if (cycle) {
          OCR1A = valueAdjusted_1; // PIN D9 (2HO) -> Channel 4 (DARK BLUE)
          OCR1B = valueAdjusted_2; // PIN D10 (2LO) -> Channel 3 (PINK)
        } else {
          OCR1A = valueAdjusted_2; // PIN D9 (2HO) -> Channel 4 (DARK BLUE)
          OCR1B = valueAdjusted_1;  // PIN D10 (2LO) -> Channel 3 (PINK)
        }
    
        // Delay  for 200 entries on table
        // Just to sincronize
        for ( int i = 0; i <= 27; i++ ) {
          asm volatile ("nop");
        }
        asm volatile ("nop");
        asm volatile ("nop");
        asm volatile ("nop");
    
        // This way we can garantee a "dead time" between pin toggle
        if (cycle) {
          PORTB ^= 0b00001000;  //Toggle PB3 pin (D11) without afect others pins
          PORTB ^= 0b00010000;  //Toggle PB4 pin (D12) without afect others pins
        } else {
          PORTB ^= 0b00010000;  // Toggle PB4 pin (D12) without afect others pins
          PORTB ^= 0b00001000;  // Toggle PB3 pin (D11) without afect others pins
        }
        cycle  ^= 0b00000001;   // Toggle cycle variable to define with semi cycle is on course
        num = 0;                // Resets num variable
      }
    
      if (cycle) {
        OCR1A = valueAdjusted_1;  // PIN D9 (2HO) -> Channel 4 (DARK BLUE)
        OCR1B = valueAdjusted_2; // PIN D10 (2LO) -> Channel 3 (PINK)
      } else {
        OCR1A = valueAdjusted_2;  // PIN D9 (2HO) -> Channel 4 (DARK BLUE)
        OCR1B = valueAdjusted_1;  // PIN D10 (2LO) -> Channel 3 (PINK)
      }
      num ++;
    }
    Nyquist applies to every ADConversion.
    Also, I've just added a low pass filter at the input of this analog channel and the signal became more stable.

    Now, I have another doubt: When the time reaches 200 counts, I change the state of pins PB3 and PB4 by XOR operation. Before this, I also change the way of OCRx works (Non inverting and inverting mode) by another XOR as we can see here: TCCR1A ^= 0b01010000.

    if (cycle) {
    OCR1A = valueAdjusted_1; // PIN D9 (2HO) -> Channel 4 (DARK BLUE)
    OCR1B = valueAdjusted_2; // PIN D10 (2LO) -> Channel 3 (PINK)
    } else {
    OCR1A = valueAdjusted_2; // PIN D9 (2HO) -> Channel 4 (DARK BLUE)
    OCR1B = valueAdjusted_1; // PIN D10 (2LO) -> Channel 3 (PINK)
    }

    // Delay for 200 entries on table
    // Just to sincronize
    for ( int i = 0; i <= 27; i++ ) {
    asm volatile ("nop");
    }
    asm volatile ("nop");
    asm volatile ("nop");
    asm volatile ("nop");
    he lines above were used to synchronize all changes at the zero cross.

    If I don't do that, the output waveform of the microcontroller is like in the picture below, as pink and dark blue are the OCRx.

    Click image for larger version. 

Name:	DS1Z_QuickPrint25.jpg 
Views:	2 
Size:	91.4 KB 
ID:	152389

    With the modification, the output is synchronized like this:

    Click image for larger version. 

Name:	DS1Z_QuickPrint28.jpg 
Views:	2 
Size:	90.1 KB 
ID:	152390

    So, It looks like a buffer of the OCRx.

    I need to "delay" the OCR using "asm volatile ("nop");" witch is a lost of macine cycles.

    Is that another way to sincronize the change of the pins PB3 and PB4 at the same time with OCRA and OCRB?

    Thanks in advance.



--[[ ]]--