Unstable sine PWM output


Closed Thread
Results 1 to 30 of 30
  1. #1

    Question Unstable sine PWM output

    Hi everyone,

    I'm currently making a 3-phase VFD. I use the PIC18F4431 with a 10MHz crystal (PLL enabled, so 10*4=40MHz).

    My program works quite good, because I've tried it on a real 3-phase motor, the PIC was feeding the IGBT power module, and the motor ran very fine (thanks to Henrik for the timer reload routine).

    Unfortunately, I've discover a phenomenon on the oscilloscope : I've connected a RC filter and I obtain this :



    As you can see, sometimes the sine "jumps" randomly (it's very quick). It happens more often at high frequencies (here about 120Hz). I think it can be quite bad for the motor and the IGBT power module.

    My complete code :
    Code:
    ' PIC initialization
    DEFINE OSC 40      
    DEFINE LCD_DREG PORTC
    DEFINE LCD_EREG PORTD
    DEFINE LCD_RSREG PORTD
    DEFINE LCD_EBIT 0
    DEFINE LCD_RSBIT 1
    DEFINE ADC_BITS 10
    DEFINE USE_LOWPRIORITY 1
    
    
    ' BAS includes
    INCLUDE "DT_INTS-18.bas"
    INCLUDE "ReEnterPBP-18.bas"
    INCLUDE "ReEnterPBP-18LP.bas"
    INCLUDE "Sine_table.bas"
    
    
    ' ADC registers configuration
    ADCON0=%11101
    ADCON1=%10000    
    ADCON2=%10000110  
    ANSEL1=%0
    
    
    ' PCPWM registers configuration
    PTCON0=%10        
    PTCON1=%10000000  
    PWMCON1=%1
    
    
    ' Inverter variables
    ustep var byte
    vstep var byte
    wstep var byte
    uduty var word
    vduty var word
    wduty var word
    freq VAR word
    amp var word
    copy VAR WORD
    reload VAR WORD
    dum VAR WORD
    dum1 VAR WORD
    dum2 VAR wORD
    flag var bit
    flag1 VAR BIT
    flag2 VAR BIT
    flag3 var bit
    flag4 var bit
    flag5 var bit
    flag6 var bit
    flag7 var bit
    b var byte
    b1 var byte
    run VAR BIT
    rot var BIT
    menu var bit
    menupos VAR BYTE
    isense VAR WORD
    usense VAR WORD
    tsense VAR WORD
    potsense var word
    maxfreq var word
    minfreq var word
    imax var byte
    pwmf var byte
    res var byte
    fault var byte
    lastf var byte
    
    
    ' Default variables definition
    dum1=34696    
    dum2=32       
    menupos=1
    b=0
    b1=0
    flag=%1
    flag3=%1        
    run=%0           
    fault=%0
          
    
    ' Reading EEPROM
    read 0,rot              
    read 1,maxfreq.highbyte  
    read 2,maxfreq.lowbyte    
    read 3,minfreq.highbyte  
    read 4,minfreq.lowbyte    
    read 5,imax              
    read 6,pwmf            
    read 7,lastf              
    
    
    ' PWM carrier frequency configuration
    gosub pwmsub 
    
    
    ' Create interrupt processors 
    ASM
    INT_LIST_L macro
             INT_Handler TMR0_INT,_calcint,PBP,yes
             endm
             INT_CREATE_L     
    INT_LIST macro
             INT_Handler TMR1_INT,_pwmint,PBP,yes
             INT_Handler INT1_INT,_faultint,PBP,yes
             INT_Handler INT2_INT,_stopint,PBP,yes
             endm
             INT_CREATE
    ENDASM
    
    
    ' Interrupts and timers enable
    @ INT_ENABLE TMR0_INT
    @ INT_ENABLE TMR1_INT
    @ INT_ENABLE INT1_INT
    @ INT_ENABLE INT2_INT
    T0CON=%10000010
    T1CON=%1
    
    
    ' Inverter startup
    high PORTD.5
    HIGH PORTE.0
    pause 1000
    
    
    ' Turn LCD on and write custom characters to CGRAM
    LCDOUT $fe,$40,$0,$4,$e,$15,$4,$4,$4,$0
    LCDOUT $fe,$48,$0,$4,$4,$4,$15,$e,$4,$0
    LCDOUT $fe,1 
    
    
    ' Main program loop
    mainlp:
       
    ' Start ADC conversion
    ADCON0.1=%1       
    WHILE ADCON0.1=%1:WEND
    
    ' Store ADC results   
    isense.HighByte=ADRESH 
    isense.LowByte=ADRESL
    usense.HighByte=ADRESH 
    usense.LowByte=ADRESL
    tsense.HighByte=ADRESH 
    tsense.LowByte=ADRESL
    potsense.HighByte=ADRESH 
    potsense.LowByte=ADRESL 
    
    ' Security fault verifications
    if isense**19218>imax then fault=1
    if usense>820 then fault=2
    if tsense<330 then fault=3
    
    ' Security fault tripping
    IF fault>0 then goto faultsub
    
    ' Brake signal generation
    if usense>770 then PORTD.7=%1
    
    ' Run
    if run=%1 then 
       IF flag1=%0 then PWMCON0.6=%1:HIGH PORTD.6:flag1=%1
    endif
    
    ' Stop
    if run=%0 then
       if flag1=%0 then PWMCON0=%0:LOW PORTD.6:flag1=%1
    ENDIF
    
    ' FWD rotation
    if rot=%1 then
       if flag2=%0 THEN ustep=29:vstep=59:wstep=89:write 0,rot:flag2=%1
    endif
    
    ' RWD rotation
    if rot=%0 then
       if flag2=%0 THEN ustep=89:vstep=59:wstep=29:write 0,rot:flag2=%1
    endif
    
    ' - button
    Button PORTB.6,1,128,32,b,0,ret
       if menu=%0 THEN menupos=menupos-1
    ret:
    
    ' + button
    Button PORTB.7,1,128,32,b1,0,ret1
       if menu=%0 THEN menupos=menupos+1
    ret1:
    
    ' Run/stop button
    if PORTD.2=%1 then
       if run=%0 and menupos<6 and flag3=%0 then run=%1:flag1=%0:flag3=%1
       if run=%1 and flag3=%0 then run=%0:flag1=%0:flag3=%1
    endif
    
    ' FWD/RWD button
    if PORTD.3=%1 then
       if rot=%0 and run=%0 and flag4=%0 then rot=%1:flag2=%0:flag4=%1
       if rot=%1 and run=%0 and flag4=%0 then rot=%0:flag2=%0:flag4=%1
    endif
    
    ' Menu/OK button
    if PORTD.4=%1 then
       if menu=%0 and run=%0 and menupos>5 and flag5=%0 then menu=%1:flag5=%1
       if menu=%1 and flag5=%0 then menu=%0:flag5=%1
    endif
    
    ' Buttons released state
    if PORTD.2=0 then flag3=0
    if PORTD.3=0 then flag4=0
    IF PORTD.4=0 then flag5=0
    
    ' LCD first line writing
    if rot=%1 then LCDOUT $fe,$2,"+" 
    if rot=%0 then LCDOUT $fe,$2,"-"
       LCDOUT DEC freq DIG 3,DEC freq DIG 2,DEC freq DIG 1,".",DEC freq DIG 0,"Hz"
    IF run=%1 then LCDOUT rep 32\5,"RUN"
    IF run=%0 then LCDOUT rep 32\4,"STOP" 
    
    ' Inverter menu (LCD second line writing)
    select case menupos
    
    ' Menu limits
    if menupos<1 then menupos=1
    if menupos>10 then menupos=10
    if run=%1 then
       if menupos>5 then menupos=5
    endif
    
    ' Current sensing submenu
    CASE 1 
    isense=isense**19218
    lcdout $fe,$c0,$1,$20,"1 ISENS: ",DEC isense DIG 2,DEC isense DIG 1,".",DEC isense DIG 0,"A"
    
    ' Voltage sensing submenu
    case 2
    usense=usense**32030
    lcdout $fe,$c0,$1,$0,"2 USENS: ",DEC3 usense,"V",32
    
    ' Temperature sensing submenu
    case 3
    tsense=(tsense-1023)/7
    lcdout $fe,$c0,$1,$0,"3 TEMP: ",DEC tsense DIG 1,DEC tsense DIG 0,$df,"C",rep $20\2
    
    ' Last fault reading submenu
    case 4
    lcdout $fe,$c0,$1,$0,"4 LASTFAULT: ",DEC1 lastf
    
    ' Firmware reading submenu
    case 5
    IF run=%1 then
       lcdout $fe,$c0,$1,$20,"5 FW: V2011.00"
    else
        lcdout $fe,$c0,$1,$0,"5 FW: V2011.00"
    endif
    
    ' Maximum frequency adjust submenu
    case 6
    if menu=%1 then
       Lcdout $fe,$c0,$3e,$3e,"A MAX: ",DEC maxfreq DIG 3,DEC maxfreq DIG 2,DEC maxfreq DIG 1,".",DEC maxfreq DIG 0,"Hz"
       Button PORTB.6,1,128,4,b,0,ret2
              if maxfreq>minfreq THEN maxfreq=maxfreq-1
       ret2:
       Button PORTB.7,1,128,4,b1,0,ret3
              if maxfreq<1200 THEN maxfreq=maxfreq+1
       ret3:
       flag6=%0
    else
        lcdout $fe,$c0,$1,$0,"A MAX: ",DEC maxfreq DIG 3,DEC maxfreq DIG 2,DEC maxfreq DIG 1,".",DEC maxfreq DIG 0,"Hz"
        IF flag6=%0 then write 1,maxfreq.highbyte:write 2,maxfreq.lowbyte:flag6=%1
    endif
    
    ' Minimum frequency adjust submenu
    case 7
    if menu=%1 then
       Lcdout $fe,$c0,$3e,$3e,"B MIN: ",DEC minfreq DIG 3,DEC minfreq DIG 2,DEC minfreq DIG 1,".",DEC minfreq DIG 0,"Hz"
       Button PORTB.6,1,128,4,b,0,ret4
              if minfreq>10 THEN minfreq=minfreq-1
       ret4:
       Button PORTB.7,1,128,4,b1,0,ret5
              if minfreq<maxfreq THEN minfreq=minfreq+1
       ret5:
       flag6=%0
    else
        lcdout $fe,$c0,$1,$0,"B MIN: ",DEC minfreq DIG 3,DEC minfreq DIG 2,DEC minfreq DIG 1,".",DEC minfreq DIG 0,"Hz"
        IF flag6=%0 then write 3,minfreq.highbyte:write 4,minfreq.lowbyte:flag6=%1
    endif
    
    ' Current trip adjust submenu
    case 8
    if menu=%1 then
       Lcdout $fe,$c0,$3e,$3e,"C ITRIP: ",DEC imax DIG 2,DEC imax DIG 1,".",DEC imax DIG 0,"A"
       Button PORTB.6,1,128,8,b,0,ret6
              if imax>0 THEN imax=imax-1
       ret6:
       Button PORTB.7,1,128,8,b1,0,ret7
              if imax<150 THEN imax=imax+1
       ret7:
       flag6=%0
    else
        lcdout $fe,$c0,$1,$0,"C ITRIP: ",DEC imax DIG 2,DEC imax DIG 1,".",DEC imax DIG 0,"A"
        IF flag6=%0 then write 5,imax:flag6=%1
    endif
    
    ' PWM carrier frequency adjust submenu
    case 9
    if menu=%1 then
       Lcdout $fe,$c0,$3e,$3e,"D PWMFREQ: ",DEC1 pwmf,rep $20\2 
       Button PORTB.6,1,128,32,b,0,ret8
              if pwmf>1 THEN pwmf=pwmf-1
       ret8:
       Button PORTB.7,1,128,32,b1,0,ret9
              if pwmf<5 THEN pwmf=pwmf+1
       ret9:
       flag6=%0
    else
        lcdout $fe,$c0,$1,$0,"D PWMFREQ: ",DEC1 pwmf,rep $20\2
        IF flag6=%0 then write 6,pwmf:gosub pwmsub:flag6=%1
    endif
    
    ' Reset all settings submenu
    case 10
    if menu=%1 then
       if flag7=%0 then
          rot=%1:write 0,rot
          maxfreq=500:write 1,maxfreq.highbyte:write 2,maxfreq.lowbyte
          minfreq=10:write 3,minfreq.highbyte:write 4,minfreq.lowbyte
          imax=150:write 5,imax
          pwmf=3:write 6,pwmf
          Lcdout $fe,$c0,$3e,$3e,"E RESET? OK",REP $20\3:flag7=%1
       endif
    endif
    if menu=%0 then lcdout $fe,$c0,$20,$0,"E RESET?",rep $20\6:flag7=%0
    
    end select
    goto mainlp
    
    
    ' PWM update interrupt (Timer 1) 
    pwmint:
    
    ' Timer management
    T1CON.0=%0                          
    copy.HighByte=TMR1H                
    copy.LowByte=TMR1L 
    copy=copy+reload 
    TMR1H=copy.HighByte                
    TMR1L=copy.LowByte
    T1CON.0=%1  
                                   
    ' PWM U phase calculation
    uduty=sine[ustep]
    uduty=(uduty<<res)**amp
    
    ' PWM V phase calculation
    vduty=sine[vstep]
    vduty=(vduty<<res)**amp
    
    ' PWM W phase calculation
    wduty=sine[wstep]
    wduty=(wduty<<res)**amp
    
    ' PWM U, V and W update
    PDC0H=uduty.highbyte
    PDC0L=uduty.lowbyte
    PDC1H=vduty.highbyte
    PDC1L=vduty.lowbyte
    PDC2H=wduty.highbyte
    PDC2L=wduty.lowbyte
    
    ' Phase angle calculation
    @ decf _ustep,1
    @ decf _vstep,1
    @ decf _wstep,1
    
    ' Phase angle reinitialization
    if ustep=0 then ustep=89
    if vstep=0 then vstep=89
    if wstep=0 then wstep=89
    
    @ INT_RETURN
    
    
    ' PWM calculation interrupt (Timer 0)
    calcint:
    
    ' Recalculations
    if flag=%1 THEN
    
       ' Reload timer calculation
      dum=dum1*dum2
      reload=Div32 freq
      reload=(65535-reload)+8
    
      ' U/F calculation
      if freq<=500 then
         amp=(freq*131)+35
      ELSE
          AMP=65535
      ENDIF
    
      flag=%0
    ENDIF
    
    ' Frequency reference control by potentiometer
    potsense=((potsense<<6)**maxfreq)+5
    if potsense<>freq then freq=potsense:flag=%1
    
    ' Frequency limits
    if freq<minfreq then freq=minfreq
    if freq>maxfreq then freq=maxfreq
    
    @ INT_RETURN
    
    
    ' PWM carrier frequency configuration subroutine
    pwmsub:
     
    if pwmf=1 then PTPERH=$f:PTPERL=$ff:res=6
    if pwmf=2 then PTPERH=$7:PTPERL=$ff:res=5
    if pwmf=3 then PTPERH=$3:PTPERL=$ff:res=4
    if pwmf=4 then PTPERH=$1:PTPERL=$ff:res=3
    if pwmf=5 then PTPERH=$0:PTPERL=$ff:res=2 
    
    return
    
    
    ' IPM fault interrupt
    faultint:
    
    fault=4
    goto faultsub
    
    @ INT_RETURN
    
    
    ' Emergency stop interrupt
    stopint:
    
    fault=5
    goto faultsub
    
    @ INT_RETURN
    
    
    ' Inverter fault subroutine
    faultsub:
    
    ' Emergency stop of the inverter
    PWMCON0=%0
    T1CON.0=%0
    LOW PORTD.5
    low PORTD.6
    low PORTD.7
    low PORTE.0
    write 7,fault
    
    ' Disable interrupts
    @ INT_DISABLE TMR0_INT
    @ INT_DISABLE TMR1_INT
    @ INT_DISABLE INT1_INT
    @ INT_DISABLE INT2_INT
    
    ' LCD fault display
    lcdout $fe,$2,"FAULT!",rep $20\10
    lcdout $fe,$c0,"CODE: ",dec fault,rep $20\9
    
    ' Fault LED blink loop
    faultlp:
    HIGH PORTE.1
    PAUSE 500
    LOW PORTE.1
    pause 500
    goto faultlp
    The sine table :
    Code:
    ' Sine table (4 degrees/step, 90*4=360 degrees)
    sine VAR byte[90]
    sine[0]=128
    sine[1]=137
    sine[2]=146
    sine[3]=155
    sine[4]=163
    sine[5]=172
    sine[6]=180
    sine[7]=188
    sine[8]=196
    sine[9]=203
    sine[10]=210
    sine[11]=217
    sine[12]=223
    sine[13]=229
    sine[14]=234
    sine[15]=239
    sine[16]=243
    sine[17]=247
    sine[18]=250
    sine[19]=252
    sine[20]=254
    sine[21]=255
    sine[22]=255
    sine[23]=255
    sine[24]=255
    sine[25]=254
    sine[26]=252
    sine[27]=250
    sine[28]=247
    sine[29]=243
    sine[30]=239
    sine[31]=234
    sine[32]=229
    sine[33]=223
    sine[34]=217
    sine[35]=210
    sine[36]=203
    sine[37]=196
    sine[38]=188
    sine[39]=180
    sine[40]=172
    sine[41]=163
    sine[42]=155
    sine[43]=146
    sine[44]=137
    sine[45]=128
    sine[46]=119
    sine[47]=110
    sine[48]=101
    sine[49]=93
    sine[50]=84
    sine[51]=76
    sine[52]=68
    sine[53]=60
    sine[54]=53
    sine[55]=46
    sine[56]=39
    sine[57]=33
    sine[58]=27
    sine[59]=22
    sine[60]=17
    sine[61]=13
    sine[62]=9
    sine[63]=6
    sine[64]=4
    sine[65]=2
    sine[66]=1
    sine[67]=0
    sine[68]=0
    sine[69]=1
    sine[70]=2
    sine[71]=4
    sine[72]=6
    sine[73]=9
    sine[74]=13
    sine[75]=17
    sine[76]=22
    sine[77]=27
    sine[78]=33
    sine[79]=39
    sine[80]=46
    sine[81]=53
    sine[82]=60
    sine[83]=68
    sine[84]=76
    sine[85]=84
    sine[86]=93
    sine[87]=101
    sine[88]=110
    sine[89]=119
    And if you have some ideas and suggestions to improve the program... it will be good.

    Thanks.
    Last edited by pxidr84; - 8th May 2011 at 13:11.

  2. #2
    Join Date
    Nov 2005
    Location
    Perth, Australia
    Posts
    429


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    I'm assuming that the changing frequency shown on the scope was because you were changing the frequency yourself. If thats the case, does it ever glitch when the frequency is left the same or is it only when the frequency is changed?
    "I think fish is nice, but then I think that rain is wet, so who am I to judge?" - Douglas Adams

  3. #3


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Hi,

    Yes, I'm changing the frequency during the video. But when I'm in an idle state, the glitches also occurs.

  4. #4
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    If you don't have any Logic Analyser handy, I would use a PC soundcard and record the PWM waveform to see if it's a Scope Trigger problem first.

    Where your scope get it's trigger from?!? Internal or External?
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

  5. #5


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    The scope is trigerred to external (CH1), rising edge with noise rejection.

  6. #6


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    News :

    I've made some experiments, it's not an oscilloscope trigger problem.

    I think it comes from my code. But where?

  7. #7
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,615


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Hi, Pxidr84

    Something caught my attention ... in the reloading, you use DIV32; are you sure there's no possible interrupt while DIV32 works ???

    as timer0 is a low priority interrupt ... I'd check that two or three times.

    ... just an idea after a very quick browse ...

    Alain
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  8. #8


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Quote Originally Posted by Acetronics View Post
    Hi, Pxidr84

    Something caught my attention ... in the reloading, you use DIV32; are you sure there's no possible interrupt while DIV32 works ???

    as timer0 is a low priority interrupt ... I'd check that two or three times.

    ... just an idea after a very quick browse ...

    Alain
    Hi,

    Timer0 interrupt is used for the calculation of the inverter paramaters (like the V/F ratio, the timer reload variable, etc.) It's a low priority interrupt because the Timer1 interrupt (used for the PWM generation) is very critical and must be
    executed all of the time.

    The DIV32 is used for calculate the timer reload value (the timer routine is from Henrik). However this routine is needed for output the desired sine frequency. This routine directly controls the Timer1 interrupt frequency. It is possible to avoid this DIV32 command (because it seems to take a LOT of ressources)?

    Maybe it's better to use Timer0 as a high priority interrupt?

    Maybe a PWM register is misconfigured?

    I don't know

  9. #9


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    No ideas for this problem?

  10. #10
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Not sure of a solution yet, but from watching the posted video, I am guessing the problem is some kind of timing issue. I don't think you have things configured wrong as the output looks great most of the time. Rather I think there are some times when a counter gets reset of an interrupt gets interrupted. It glitches then goes right back to perfect wave.

    If you watch it and don't alter the frequency, does the glitch happen at regular intervals, or is it random in nature?
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  11. #11
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    I think Alain may have a point, I would try to skip the DIV32... let's say assign a fixed value there and let it run idle to see if the problem persist.
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

  12. #12
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Hi,
    I don't know if DT-Ints have any impact on DIV32, I'd guess no but I don't know. The manual says that it's not recomended to have interrupts enbles if using ON INTERRUPT because the system variables that DIV32 relies on might get changed by the ISR. But DT-Ints saves the system variables so I don't think it should be an issue.

    With that said I don't see the reason for calculating the interrupt frequency "all the time". If I read your code correctly your TMR0 interrupt executes at around 38Hz so it calculates the reload values 38 times per second. As long as the desired frequency isn't changed the reload value for TMR1 doesn't change so why keep calculating it?

    Instead, do it in your Main-loop and even better calculatie it only when the desired frequency have changed.

    Now, I think you think that you AREN'T calculating it "all the time" but look closely at your TMR0 interrupt service routine:
    Code:
    ' PWM calculation interrupt (Timer 0)
    calcint:
    ' Recalculations
    if flag=%1 THEN             '<----Calculate only when Flag=1
       ' Reload timer calculation
      dum=dum1*dum2
      reload=Div32 freq
      reload=(65535-reload)+8
      ' U/F calculation
      if freq<=500 then
         amp=(freq*131)+35
      ELSE
          AMP=65535
      ENDIF
      flag=%0
    ENDIF
    ' Frequency reference control by potentiometer
    potsense=((potsense<<6)**maxfreq)+5
    if potsense<>freq then freq=potsense:flag=%1
    ' Frequency limits
    if freq<minfreq then freq=minfreq
    if freq>maxfreq then freq=maxfreq
    @ INT_RETURN
    That flag=%1 is NOT part of the IF-THEN statement so flag will get set every interrupt no matter if the frequency have changed or not and therfor the calculations of the reload values will get executed every interrupt.

  13. #13


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Thanks for your help.

    So I've tried first to set a fixed reload value (64594) without calculations (to obtain 120Hz sine, the max. frequency). The sine wave was perfectly stable on the oscilloscope.

    This :
    dum=dum1*dum2
    reload=DIV32 freq
    reload=(65535-reload)+8
    was removed and replaced with :

    reload=64594
    I've also applied Henrik tips, like this :

    Code:
    ' Frequency reference control by potentiometer
    potsense=(potsense<<6)**maxfreq
    IF potsense<>freq THEN 
    freq=potsense
    flag=%1
    endif
    And set the reload calculation routine into the main loop.

    Results : it's more stable, but the glitches still appears when I change the frequency of the sine (so the reload calculation routine is executed during this time).

    I'm pretty sure that the problem is caused by DIV32. However this routine is needed :

    dum=dum1*dum2
    reload=DIV32 freq
    reload=(65535-reload)+8
    How to replace the "DIV32" by an another thing? It is possible to use that : http://melabs.com/resources/fp.htm ? Or anything else?
    Last edited by pxidr84; - 13th May 2011 at 17:28.

  14. #14
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Hi,
    It might be the DIV32, we'll have to get Darrel to answer that or have someone dig into the ASM code and figure out if the PBP registers used by DIV32 are being saved by DT-Ints or not (I still think they are).

    My guess is that it isn't actually DIV32 that is causing it but something else with the way the frequency is changed. Why not try constantly ramping the frequency up and down in your main loop? Don't use DIV32, just "sweep" the reload value up and down between your MIN and MAX values. Does it still glitch? If so we know that it's not DIV32 that's causing it but something else.

    If it turns out that it IS DIV32 then we can look at other solutions. The DIV32 thing was in response to your request of directly calculating the reload value based on the desired output frequency scaled in Hz. Simply rescaling to some arbitrary "unit" might allow the calculations to be done without DIV32 but it comes with a couple of commitments which I won't go into until we know that that DIV32 is the problem.

    Can you explain to me where the values 34696 and 32 comes from?

    /Henrik.

  15. #15
    Join Date
    Feb 2006
    Location
    Gilroy, CA
    Posts
    1,530


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    If for some reason you can't make it a one time calculation, you could use N-Bit math.

    http://www.picbasic.co.uk/forum/showthread.php?t=12433 This basically uses assembly routines, so it shouldn't bother the interrupts.

  16. #16


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Quote Originally Posted by HenrikOlsson View Post
    Hi,
    It might be the DIV32, we'll have to get Darrel to answer that or have someone dig into the ASM code and figure out if the PBP registers used by DIV32 are being saved by DT-Ints or not (I still think they are).

    My guess is that it isn't actually DIV32 that is causing it but something else with the way the frequency is changed. Why not try constantly ramping the frequency up and down in your main loop? Don't use DIV32, just "sweep" the reload value up and down between your MIN and MAX values. Does it still glitch? If so we know that it's not DIV32 that's causing it but something else.

    If it turns out that it IS DIV32 then we can look at other solutions. The DIV32 thing was in response to your request of directly calculating the reload value based on the desired output frequency scaled in Hz. Simply rescaling to some arbitrary "unit" might allow the calculations to be done without DIV32 but it comes with a couple of commitments which I won't go into until we know that that DIV32 is the problem.

    Can you explain to me where the values 34696 and 32 comes from?

    /Henrik.
    I've done like you said a simple ramp in the main loop :

    Code:
    reload=reload-1
    if reload<40000 then reload=64600
    The sine frequency ramped down, and after many cycles, no glitch appeared on the oscilloscope. During this time I've played with the potentiometer to vary the amplitude and also I navigate into the inverter menu, the sine wave was not disturbed at all.

    So the problem is clearly DIV32. Apparently this command disturbs DT Instant Interrupts.

    I've already changed the "34696" and "32" dummy values to "1120" and "1000", it's far better to understand.

  17. #17
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    So the problem is clearly DIV32. Apparently this command disturbs DT Instant Interrupts.
    Or the other way around, or there's a problem with the actual values being calculated like overflow/ underflow/whatever. I'm still not convinced but it seems you are so lets go with that for now.

    OK, you're using an analog input to set the desired output frequency, the ADC have a resolution of 10 bits giving you a value of 0-1023. If we're going to try to come up with an alternative way to calculate the reload value (not using DIV32) can you tell us:

    A) What is your minimum output frequency, ie what frequency should an ADC value of 0 give and what TMR1 reload value does that frequency require?

    B) What is your maximum output frequency, ie what frequency should an ADC value of 1023 give and what TMR1 reload value does that frequency require?

    /Henrik.

  18. #18


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Maybe it isn't DIV32... I don't know, but when I remove it, the glitches disapppears. I've also already tried to change the dummy values.

    My min. frequency is 1Hz (freq=10), reload value=about 0
    and my max. frequency is 120Hz (freq=1200), reload value=about 64600

    And I don't directly use the 0-1023 potentiometer value, first I convert it to the "freq" variable :

    Code:
    potsense=(potsense<<6)**maxfreq
    "maxfreq" correspond to the maximum frequency defined by the user. Here, "maxfreq"=1200. So here "freq" variable varies between 0 and 1200. Note I'm using an additional number to have the 0.1Hz accuracy (for exemple, 50.2Hz frequency equals freq=502).

    I have to said, your timer reload routine with DIV32 was pretty accurate and provides very good results. In terms of accuracy, I really had a 0.1Hz precision, both in low and high frequencies.
    Last edited by pxidr84; - 14th May 2011 at 10:52.

  19. #19
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Hi,
    OK, so when Freq is 10 you want Reload to be 0 and when Freq is 1200 you want Reload to be 64600. That's 64600 over 1190 or a reload value of 54.286 per unit Freq.
    Code:
    Reload = (Freq */13897) - 542
    When Freq is 10 you'll get (10*13897/256)-542 = 0
    When Freq is 1200 you'll get (1200*13897/256)-542 = 64600
    Do not allow Freq to be less than 10, you'll end up with a negative value.

    This is not perfect but it might work, at least you'll get rid of DIV32. If you use the exact reload values for Freq=10 and Freq=1200 instead of the aproximate ones it might get a bit better in between the two extreme ends.

    By the way, the lowest possible interrupt frequency, when running at 40Mhz and without changing the prescaler is 152.588Hz which equals an output frequency of 1.69Hz so Freq should really only be allowed to range from 17 to 1200 for 1.7 to 120Hz.

    /Henrik.

  20. #20


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Unfortunately, it doesn't work as expected but there is no glitch when I played with the potentiometer.

    For example, at 100.0Hz I obtain an 9.5Hz output,
    at 110.0Hz -> 17.6 Hz
    at 90.0Hz -> 6.5Hz...

    And there is no way to use this? http://www.picbasic.co.uk/forum/showthread.php?t=12433

    or this?
    http://melabs.com/resources/fp.htm

    (just a suggestion)

  21. #21
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Hi,
    Aaargh, sorry about that, temporary brain-fart on my behalf.

    At the moment I'm afraid I can't come up with an alternative solution. I'm sure there is one though and hopefully someone else will jump in.

    I've never used the floating point routines and I don't really see any reason to do it here. N-Bit math might be an option but I currently don't have the time to do the experiments for you so you're going to have to try it yourself. Darrels examples in the thread is pretty self explainatory.

  22. #22


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    To avoid an useless calculation, I would store the 1120*1000 result (1120000) into a 24-bit variable with the N-bit math function (but how?). And then divide this by the frequency, and so on.

    Thanks anyway. Now I know where is my problem. I think I will open a new thread, because the DIV32 problem is different than PWM and sines.

  23. #23
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Hi,
    I gave it a shot anyway:
    Code:
    PRECISION CON 3 SYSTEM          ' 24bits is sufficent for this
    INCLUDE "N-bit_Math.pbp"        ' Include the math routines.
     
    Dummy1 VAR BYTE[PRECISION]      ' Used by N-Bit math
    Dummy2 VAR BYTE[PRECISION]      ' Used by N-Bit math
    Result VAR BYTE[PRECISION]      ' Used by N-Bit math
     
    Frequency VAR WORD              ' Desired output frequency times 10 (123=12.3Hz)
    Reload VAR Word                 ' Caluclated timer reload value to get desired interrupt rate.
    i VAR BYTE                      ' General purpose counter
     
    HSEROUT ["Start",13]
     
    Main:
      For i = 0 to 20
        Lookup2 i, [18, 20, 22, 25, 30, 40, 50, 60, 80, 100, 150, 200, 300, 400, 500, 700, 800, 900, 1000, 1100, 1200], Frequency
        Gosub CalculateIt
        Gosub PrintIt
        Pause 100
      Next
    END
     
    CalculateIt:
      ' There's 90 "steps" for a complete sine-cycle. If we want 1Hz output frequency
      ' we need an interrupt frequency of 90Hz, 1/90=0.01111111111111s.
      ' At 40MHz each instruction cycle (and timertick when prescaler is 1:1) is 100nS
      ' so 0.0111111111111/100E-9 = 111111 but because we want one decimal place on the
      ' frequency variable (123 = 12.3Hz) we multiply that by 10 so 1111111.
     
      ' Load 1111111 into first 24bit math variable.
      Dummy1[2] = $10
      Dummy1[1] = $F4
      Dummy1[0] = $47
     
      'Load frequency variable into second math variable
      Dummy2[2] = 0
      Dummy2[1] = Frequency.HighByte
      Dummy2[0] = Frequency.LowByte
     
      'Perform the division.
    @ MATH_DIV _Dummy1, _Dummy2, _Result
     
      'Move the result to the Reload variable
    @ MOVE?PW  _Result, _Reload          ; Truncate Result into a WORD var
     
      'Negate the value to get the actual reload value.
    Reload = -Reload
     
    RETURN
    End
     
    PrintIt:
      HSEROUT ["Frequency: ", #Frequency/10, ".", #Frequency // 10, "Hz", "   Reload: ", #Reload, 13]
    Return
    1111111 is closer to the real deal than 1120000, upto around Freq=1100 the error is less than 0.01% while at Freq=1200 it "jumps" to 0.1% - pretty good.

    Remember that you can not allow the Frequency variable to be less than 17 or you'll end up with a negative reload value which means the frequency will be WAY off. Ie you can't allow Frequency to be 10 for 1Hz output.

  24. #24


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Henrik, you had right about the DIV32 command. It doesn't disturbs DT Instant Interrupts at all.

    Look at this routine :

    Code:
    dum=dum1*dum2
    reload=DIV32 freq
    reload=(65535-reload)+8
    The result of the division is stored into the "reload" variable.
    But if the TMR1 interrupt occurs BEFORE the end of the calculation (before reload=(65535-test)+8)), the timer management routine located in TMR1 interrupt will take the "unfinished" reload variable. So is how the sine "jumps".

    But now, with this :

    Code:
    dum=dum1*dum2
    store=DIV32 freq
    reload=(65535-store)+8
    The result of the division is stored into the "store" variable, so when "reload" is calculated, the routine calculation is really finished.

    I've tried this, and now, absolutely no glitch appears on the sine. So this fixed my problem.

    3 days for find that.

  25. #25


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Quote Originally Posted by HenrikOlsson View Post
    Hi,
    I gave it a shot anyway:
    Code:
    PRECISION CON 3 SYSTEM          ' 24bits is sufficent for this
    INCLUDE "N-bit_Math.pbp"        ' Include the math routines.
     
    Dummy1 VAR BYTE[PRECISION]      ' Used by N-Bit math
    Dummy2 VAR BYTE[PRECISION]      ' Used by N-Bit math
    Result VAR BYTE[PRECISION]      ' Used by N-Bit math
     
    Frequency VAR WORD              ' Desired output frequency times 10 (123=12.3Hz)
    Reload VAR Word                 ' Caluclated timer reload value to get desired interrupt rate.
    i VAR BYTE                      ' General purpose counter
     
    HSEROUT ["Start",13]
     
    Main:
      For i = 0 to 20
        Lookup2 i, [18, 20, 22, 25, 30, 40, 50, 60, 80, 100, 150, 200, 300, 400, 500, 700, 800, 900, 1000, 1100, 1200], Frequency
        Gosub CalculateIt
        Gosub PrintIt
        Pause 100
      Next
    END
     
    CalculateIt:
      ' There's 90 "steps" for a complete sine-cycle. If we want 1Hz output frequency
      ' we need an interrupt frequency of 90Hz, 1/90=0.01111111111111s.
      ' At 40MHz each instruction cycle (and timertick when prescaler is 1:1) is 100nS
      ' so 0.0111111111111/100E-9 = 111111 but because we want one decimal place on the
      ' frequency variable (123 = 12.3Hz) we multiply that by 10 so 1111111.
     
      ' Load 1111111 into first 24bit math variable.
      Dummy1[2] = $10
      Dummy1[1] = $F4
      Dummy1[0] = $47
     
      'Load frequency variable into second math variable
      Dummy2[2] = 0
      Dummy2[1] = Frequency.HighByte
      Dummy2[0] = Frequency.LowByte
     
      'Perform the division.
    @ MATH_DIV _Dummy1, _Dummy2, _Result
     
      'Move the result to the Reload variable
    @ MOVE?PW  _Result, _Reload          ; Truncate Result into a WORD var
     
      'Negate the value to get the actual reload value.
    Reload = -Reload
     
    RETURN
    End
     
    PrintIt:
      HSEROUT ["Frequency: ", #Frequency/10, ".", #Frequency // 10, "Hz", "   Reload: ", #Reload, 13]
    Return
    1111111 is closer to the real deal than 1120000, upto around Freq=1100 the error is less than 0.01% while at Freq=1200 it "jumps" to 0.1% - pretty good.

    Remember that you can not allow the Frequency variable to be less than 17 or you'll end up with a negative reload value which means the frequency will be WAY off. Ie you can't allow Frequency to be 10 for 1Hz output.
    Thanks, maybe I will later modify my program with this.

  26. #26
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Sometimes it's just there, staring you in the face all along and you still don't see it.... I guess this is one of those of times. It's pretty obvious now that you found it, which I'm glad you did!

    Now that it works properly with DIV32 I see no reason to change to N-Bit math.

  27. #27


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Quote Originally Posted by HenrikOlsson View Post
    Sometimes it's just there, staring you in the face all along and you still don't see it.... I guess this is one of those of times. It's pretty obvious now that you found it, which I'm glad you did!

    Now that it works properly with DIV32 I see no reason to change to N-Bit math.
    Maybe your new routine with n-bit maths is more accurate?

    Anyway, I think that I will open an another thread soon for this 3-phase VFD, with a YouTube video, the source code, schematics, etc. Because it works fine on my 250W 3-phase motor (in theory my IGBT module is capable of 2,2kW of output power). It will be cool.
    Last edited by pxidr84; - 15th May 2011 at 14:21.

  28. #28
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Hi,
    I tried both methods for both accuarcy and speed, here are the results:
    Code:
    N-BIT:  Frequency: 1.8Hz   Reload: 3808    Cycles: 4497
    DIV32:  Frequency: 1.8Hz   Reload: 3809    Cycles: 333
    N-BIT:  Frequency: 2.0Hz   Reload: 9981    Cycles: 4593
    DIV32:  Frequency: 2.0Hz   Reload: 9981    Cycles: 345
    N-BIT:  Frequency: 2.2Hz   Reload: 15031    Cycles: 4579
    DIV32:  Frequency: 2.2Hz   Reload: 15032    Cycles: 349
    N-BIT:  Frequency: 2.5Hz   Reload: 21092    Cycles: 4743
    DIV32:  Frequency: 2.5Hz   Reload: 21092    Cycles: 337
    N-BIT:  Frequency: 3.0Hz   Reload: 28499    Cycles: 4583
    DIV32:  Frequency: 3.0Hz   Reload: 28500    Cycles: 349
    N-BIT:  Frequency: 4.0Hz   Reload: 37759    Cycles: 4282
    DIV32:  Frequency: 4.0Hz   Reload: 37759    Cycles: 349
    N-BIT:  Frequency: 5.0Hz   Reload: 43314    Cycles: 4528
    DIV32:  Frequency: 5.0Hz   Reload: 43314    Cycles: 337
    N-BIT:  Frequency: 6.0Hz   Reload: 47018    Cycles: 4272
    DIV32:  Frequency: 6.0Hz   Reload: 47018    Cycles: 349
    N-BIT:  Frequency: 8.0Hz   Reload: 51648    Cycles: 3971
    DIV32:  Frequency: 8.0Hz   Reload: 51648    Cycles: 353
    N-BIT:  Frequency: 10.0Hz   Reload: 54425    Cycles: 4313
    DIV32:  Frequency: 10.0Hz   Reload: 54425    Cycles: 337
    N-BIT:  Frequency: 15.0Hz   Reload: 58129    Cycles: 4270
    DIV32:  Frequency: 15.0Hz   Reload: 58129    Cycles: 333
    N-BIT:  Frequency: 20.0Hz   Reload: 59981    Cycles: 4002
    DIV32:  Frequency: 20.0Hz   Reload: 59981    Cycles: 341
    N-BIT:  Frequency: 30.0Hz   Reload: 61833    Cycles: 3959
    DIV32:  Frequency: 30.0Hz   Reload: 61833    Cycles: 337
    N-BIT:  Frequency: 40.0Hz   Reload: 62759    Cycles: 3705
    DIV32:  Frequency: 40.0Hz   Reload: 62759    Cycles: 345
    N-BIT:  Frequency: 50.0Hz   Reload: 63314    Cycles: 3617
    DIV32:  Frequency: 50.0Hz   Reload: 63314    Cycles: 349
    N-BIT:  Frequency: 70.0Hz   Reload: 63949    Cycles: 3420
    DIV32:  Frequency: 70.0Hz   Reload: 63949    Cycles: 349
    N-BIT:  Frequency: 80.0Hz   Reload: 64148    Cycles: 3412
    DIV32:  Frequency: 80.0Hz   Reload: 64148    Cycles: 349
    N-BIT:  Frequency: 90.0Hz   Reload: 64302    Cycles: 3298
    DIV32:  Frequency: 90.0Hz   Reload: 64302    Cycles: 353
    N-BIT:  Frequency: 100.0Hz   Reload: 64425    Cycles: 3420
    DIV32:  Frequency: 100.0Hz   Reload: 64425    Cycles: 349
    N-BIT:  Frequency: 110.0Hz   Reload: 64526    Cycles: 3333
    DIV32:  Frequency: 110.0Hz   Reload: 64526    Cycles: 345
    N-BIT:  Frequency: 120.0Hz   Reload: 64611    Cycles: 3351
    DIV32:  Frequency: 120.0Hz   Reload: 64611    Cycles: 345
    For N-Bit I used 1111111/frequency and for DIV32 I used 11111*100 DIV32 Frequency. As you can see the results are pretty much spot on, the small difference there is likely due to 11111*100=1111100. What is surprising is that DIV32 is about 10 times faster than N-Bit in this particular case so I wouldn't change if I were you - it's just way more power than you need for this, and it comes a cost.

    Yes, please do post the project.

    /Henrik.

  29. #29
    Join Date
    Feb 2006
    Location
    Gilroy, CA
    Posts
    1,530


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Thanks Henrik! That's good to know! I knew the N-Bit for multiplication would be slow (doesn't utilize hardware multiplier), but did not think that division would be very different.

    Thanks for the info!

    Walter

  30. #30


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Of course I'm keeping DIV32, and I've modified the TMR1 prescaler to 1/2, now I really have 1.0Hz at the min. frequency (and I still keep a good accuracy at high frequencies).

    The project will be posted in one or two weeks.

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts