Unstable sine PWM output


Closed Thread
Results 1 to 30 of 30

Hybrid View

  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
    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.

  8. #8
    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

  9. #9


    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 : 0

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