sinusoidal PWM


Closed Thread
Results 1 to 40 of 84

Thread: sinusoidal PWM

Hybrid View

  1. #1
    Join Date
    Feb 2011
    Posts
    37


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    hi,
    i've managed to get the sinusoidal output sine wave although i'm getting frequency of 202Hz instead of 50Hz and peak voltage of 4.58v instead of 4.5v.Also the waveform is not smooth.Simulation results.docWhat should i do to acheave this parameters?
    code:
    Code:
    define OSC 4
    ;*****************VARIABLE DECLARATION******************************************
    wsave   VAR BYTE    $70     SYSTEM      ' alternate save location for W 
    wsave1  VAR BYTE    $A0     SYSTEM      ' location for W if in bank1
    wsave2  VAR BYTE    $120    SYSTEM      ' location for W if in bank2
    wsave3  VAR BYTE    $1A0    SYSTEM      ' location for W if in bank3 
    ADCON0 = %00000000
    ADCON1 = %00000000
    trisb = %11111111
    trisc = %11111011
    trisa = %11111111
    TMR2 = 16
    PR2 = 15      ;set for 16Khz HPWM        
    CCP1CON.3 = 1        ' set to pwm mode
    CCP1CON.2 = 1
    T2CON.2=1
    T2CON.0=1
    STEPCOUNT var byte
    stepcount = 32
    ; Set sine "table" in an array
    sineval var byte[32]
    sineval[1] = 128
    sineval[2] = 148
    sineval[3] = 167
    sineval[4] = 185
    sineval[5] = 200
    sineval[6] = 213
    sineval[7] = 222
    sineval[8] = 228
    sineval[9] = 230
    sineval[10] = 228
    sineval[11] = 222
    sineval[12] = 213
    sineval[13] = 200
    sineval[14] = 185
    sineval[15] = 167
    sineval[16] = 148
    sineval[17] = 128
    sineval[18] = 108
    sineval[19] = 89
    sineval[20] = 71
    sineval[21] = 56
    sineval[22] = 43
    sineval[23] = 34
    sineval[24] = 28
    sineval[25] = 26
    sineval[26] = 28
    sineval[27] = 34
    sineval[28] = 43
    sineval[29] = 56
    sineval[30] = 71
    sineval[31] = 89
    sineval[32] = 108
     
     
    timerone var word 
     
    INCLUDE "DT_INTS-14.bas"     ; Base Interrupt System
    ;include "ReEnterPBP-18.bas"  ;not needed for ASM type interrupt service routines
     
    ASM
     
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler   TMR1_INT,   _sine,   ASM,  yes
        endm
        INT_CREATE               ; Creates the interrupt processor
    ENDASM
     
    T1CON = $31                 ; Prescaler = 8, TMR1ON
    TMR1L = 255
    TMR1H = 254
    @   INT_ENABLE  TMR1_INT     ; Enable Timer 1 Interrupts  
    timerone = 65504               ;gives about 50 htz sine 
    Main:
            pause 5
            'timerone = timerone - 1      'uncomment to vary 60hz sine
            if timerone = $F9FF then timerone = $FF00
     
    GOTO Main
     
    '---[TMR1_INT - interrupt handler]------------------------------------------
     
    sine:
        TMR1L = timerone.byte0
        TMR1H = timerone.byte1     
        CCPR1L = sineval[STEPCOUNT]>>1 
        stepcount = stepcount -1
        if stepcount = 0 then stepcount = 32
     
    @    INT_RETURN

  2. #2
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,623


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    Hi,
    You're still off on the array.
    Code:
    Sinval VAR BYTE[32]
    This creates an array of 32 elements numbered 0-31 but you assign values to it starting at 1 and ending at 32 - not very good. There is no SineVal[32], when you read/write to that variable you're actually accessing the "next" RAM location, something I'm sure you don't want to do here.

    You can adjust the peak value by "scaling" the value in your sine-table but really, you're not even 2% off target.

    Are you using a 4MHz x-tal like the code says or are you using something else?

    If I'm not mistaken a reload value of 65505 with a prescaler of 1:8 running at 4Mhz gives an interrupt frequency of 4032Hz, you have 32 "steps" to your cycle so you "should" get around 126Hz....

    For accuracy it's usually better to stop the timer and then ADD the preload value to the timers current value since this will take into account the interrupt latency etc. Stop it, copy it to a WORD, add the reload value, copy it back and restart the timer.

    Any specific reason you're using a TMR1 prescaler of 8? Using a lower prescaler ratio will give you better "resolution" on the interrupt frequency.

    /Henrik.

  3. #3
    Join Date
    Feb 2011
    Posts
    37


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    hellow Henrik,
    thanx for the tips, i've re-worked my sine table,also i've include the code for accuracy although i'm not sure if i've place it in a right place!
    For a 4MHz xtal and TMR1 prescaler of 1 i reload the T1 with the value 64980 to get 50Hz and it's what m getting on the scope.
    Also TMR2 with prescaler of 4 is loaded with 117 for the interrupt to be generated every 556us(256-(556/(4*0.25*4))
    But the problem is that the waveform i'm getting on the scope is not smooth at all....Simulation results..pdf

    code:
    Code:
    define OSC 4
     
    ;*****************VARIABLE DECLARATION******************************************
    wsave   VAR BYTE    $70     SYSTEM      ' alternate save location for W 
    wsave1  VAR BYTE    $A0     SYSTEM      ' location for W if in bank1
    wsave2  VAR BYTE    $120    SYSTEM      ' location for W if in bank2
    wsave3  VAR BYTE    $1A0    SYSTEM      ' location for W if in bank3
    STEPCOUNT var byte                      'Define stepcount as byte type variable
    stepcount = 36
     
    ;**************SETTING THE REGISTERS WITH APPROPIATE BIT DEFINITION************* 
    ADCON0 = %00000000
    ADCON1 = %00000000  ;all anolog output
    trisb = %11111111   ;define porta as input
    trisc = %11111011   ;make ccp1/portc.2 an output pin
    trisa = %11111111   ;define porta as input
    TMR2 = 117
    PR2 = 13          ;set for 18Khz HPWM(=36 steps*10 times*50hz)        
    CCP1CON = %000001100       ;set to pwm mode
    T2CON=%00000110           ;enable timer2 and set timer2 prescaler value of 1:4
     
    ;****************A sine lookup table in an array********************************
    sineval var byte[36]
    sineval[0] = 128
    sineval[1] = 148
    sineval[2] = 167
    sineval[3] = 185
    sineval[4] = 201
    sineval[5] = 215
    sineval[6] = 227
    sineval[7] = 235
    sineval[8] = 240
    sineval[9] = 242
    sineval[10] = 240
    sineval[11] = 235
    sineval[12] = 227
    sineval[13] = 215
    sineval[14] = 201
    sineval[15] = 185
    sineval[16] = 167
    sineval[17] = 148
    sineval[18] = 128
    sineval[19] = 108
    sineval[20] = 89
    sineval[21] = 71
    sineval[22] = 55
    sineval[23] = 41
    sineval[24] = 29
    sineval[25] = 21
    sineval[26] = 16
    sineval[27] = 14
    sineval[28] = 16
    sineval[29] = 21
    sineval[30] = 29
    sineval[31] = 41
    sineval[32] = 55
    sineval[33] = 71
    sineval[34] = 89
    sineval[35] = 108
     
    timerone var word 
     
    INCLUDE "DT_INTS-14.bas"     ; Base Interrupt System
     
    ;********Define INT_Handler as ISR********************************************** 
    ASM
     
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler   TMR1_INT,   _sine,   ASM,  yes
        endm
        INT_CREATE               ; Creates the interrupt processor
    ENDASM
     
    T1CON = %000001    ; Prescaler = 1, TMR1ON          
    TMR1L = 255    
    TMR1H = 254
    @   INT_ENABLE  TMR1_INT     ; Enable Timer 1 Interrupts  
    timerone = 64980           ;gives about 50 hz sine 
    Main:
            pause 5
     
    GOTO Main
     
    '---[TMR1_INT - interrupt handler]------------------------------------------
     
    'accuracy thing
    TimerShadow VAR WORD
    T1CON.0 = 0  'Stop TMR1
    TimerShadow.HighByte = TMR1H
    TimerShadow.LowByte = TMR1L
    TimerShadow = TimerShadow + Timerone
    TMR1H = TimerShadow.HighByte
    TMR1L = TimerShadow.LowByte
    T1CON.0 = 1  'Restart TMR1
    sine:
        TMR1L = timerone.byte0
        TMR1H = timerone.byte1     
        CCPR1L = sineval[STEPCOUNT]>>1 
        stepcount = stepcount -1
        if stepcount = 0 then stepcount = 36
    @    INT_RETURN
    where i'm wrong in the code? are the calculations above correct?
    Last edited by Ioannis; - 8th May 2011 at 16:38.

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


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    What are you using for a filter? You should have at least half of the below example to smooth out the signal. Also, it will never look too good on simulation. Might look better on actual hardware. Might be some issues with running it at 4 mhz. Is there a reason you don't want 20 mhz? Even AN655 's example showed 20 mhz.

    Code:
    ;   Filter Diagram
    ;        
    ;               2.7k            2.7k    
    ;    RC2  ___/\  /\  /\______/\  /\  /\________ Analog Output
    ;              \/  \/    |     \/  \/     |  
    ;                        |                |
    ;                      ----- 0.1uF      ----- 0.1uF
    ;                      -----            -----
    ;                        |                |
    ;                       GND              GND
    ;
    ;

  5. #5
    Join Date
    Feb 2011
    Posts
    37


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    the 877 pic on the board i'm using have 4Mhz clock, and i'm using the same filter as above.are the calculations above correct?
    Last edited by Ioannis; - 8th May 2011 at 16:38.

  6. #6
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,623


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    Hi,
    Several things.....
    TMR2 is the timer used for the PWM generation. The fact that you initially load it with 117 doesn't matter for either the PWM frequency or your interrupt frequency since you're using TMR1 to generate the interrupts.

    You have the prescaler for TMR2 set to 1:4 and PR2 set to 13 which indeed gives you ~18kHz PWM frequency but it'll only give you a give you 56 discrete dutycycles. Ie. the maximum value you can put in the dutycycle register is 56. The highest value in your sine table is 242 which you then shift right one time bofore putting in the CCP1L, so you're trying to put 121 in there when 56 is max.

    Changing the prescaler to 1:1 and putting 55 in PR2 gives you the same PWM frequency but allows dutycycle values of 0-222.

    TMR1 is now setup with a prescaler of 1:1 and you reload it with 64980 making it interrupt every 65536-64980=556us or at a frequency of 1798Hz, there's now 36 steps to your "cycle" so 1798/36=49.96Hz so it seems to be correct. I don't think you should expect to be able to run much faster than that at 4Mhz, the DT-ints takes quite afew cycles to save and restore all the system variables on each interrupt so you won't have much time left.

    The "accuracy thing" needs to be performed on each reload or it won't have much effect. It should be in your ISR instead of the reload code you have there now.

    /Henrik.

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


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    Hi Henrik! As always, great post!
    I've done some work with DT_INTS, and in ASM mode, they are fairly fast, as they only copy a few registers, vs the PBP type, which copies then restores about 70 registers with each interrupt. So I don't understand your warning about going above 4 Mhz? I've run it at 40 Mhz on a different chip and it worked pretty well using ASM type DT_INTS.

  8. #8
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,623


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    Hi,
    I missed the fact that the interrupt was declared as ASM. In that case, as you say, there's not that much overhead but it's also risky business since the actual handler IS written in PBP - if you don't know what you're doing here you're likely to run into trouble.

    And, with the above in mind, perhaps adding the "extra" reload code for accuracy isn't a good idea (and not needed since there's much less overhead) since it might use some PBP system variables and then the whole thing is a mess.

    I wasn't trying to say that it couldn't run at a higher oscillator speed than 4Mhz. I was trying to say that I don't think it'll be able to interrupt much faster when running AT 4Mhz, in fact that IS what I said ;-) But that was before you enlightned me of the fact that he has the ISR declared as ASM.

    bwaxing,
    You do realise the difference of declaring the interrupt as type ASM as oppesed to type PBP and what impact it might have on your code if you declare it as ASM but write the handler in PBP?

    /Henrik.

  9. #9
    Join Date
    Feb 2011
    Posts
    37


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    Quote Originally Posted by HenrikOlsson View Post
    Hi,
    Several things.....
    TMR2 is the timer used for the PWM generation. The fact that you initially load it with 117 doesn't matter for either the PWM frequency or your interrupt frequency since you're using TMR1 to generate the interrupts.

    You have the prescaler for TMR2 set to 1:4 and PR2 set to 13 which indeed gives you ~18kHz PWM frequency but it'll only give you a give you 56 discrete dutycycles. Ie. the maximum value you can put in the dutycycle register is 56. The highest value in your sine table is 242 which you then shift right one time bofore putting in the CCP1L, so you're trying to put 121 in there when 56 is max.

    Changing the prescaler to 1:1 and putting 55 in PR2 gives you the same PWM frequency but allows dutycycle values of 0-222.

    TMR1 is now setup with a prescaler of 1:1 and you reload it with 64980 making it interrupt every 65536-64980=556us or at a frequency of 1798Hz, there's now 36 steps to your "cycle" so 1798/36=49.96Hz so it seems to be correct. I don't think you should expect to be able to run much faster than that at 4Mhz, the DT-ints takes quite afew cycles to save and restore all the system variables on each interrupt so you won't have much time left.

    The "accuracy thing" needs to be performed on each reload or it won't have much effect. It should be in your ISR instead of the reload code you have there now.

    /Henrik.
    i've the changes in the code as you suggested above,but the waveform is still not smooth....Simulation results..pdf

    Code:
    define OSC 4
    
    ;*****************VARIABLE DECLARATION******************************************
    wsave   VAR BYTE    $70     SYSTEM      ' alternate save location for W 
    wsave1  VAR BYTE    $A0     SYSTEM      ' location for W if in bank1
    wsave2  VAR BYTE    $120    SYSTEM      ' location for W if in bank2
    wsave3  VAR BYTE    $1A0    SYSTEM      ' location for W if in bank3
    STEPCOUNT var byte                      'Define stepcount as byte type variable
    stepcount = 36
    
    ;**************SETTING THE REGISTERS WITH APPROPIATE BIT DEFINITION************* 
    ADCON0 = %00000000
    ADCON1 = %00000000  ;all anolog output
    trisb = %11111111   ;define porta as input
    trisc = %11111011   ;make ccp1/portc.2 an output pin
    trisa = %11111111   ;define porta as input
    TMR2 = 117
    PR2 = 55          ;set for 18Khz HPWM(=36 steps*10 times*50hz)        
    CCP1CON = %000001100       ;set to pwm mode
    T2CON=%00000100           ;enable timer2 and set timer2 prescaler value of 1:1
    
    ;****************A sine lookup table in an array********************************
    sineval var byte[36]
    sineval[0] = 128
    sineval[1] = 148
    sineval[2] = 167
    sineval[3] = 185
    sineval[4] = 201
    sineval[5] = 215
    sineval[6] = 227
    sineval[7] = 235
    sineval[8] = 240
    sineval[9] = 242
    sineval[10] = 240
    sineval[11] = 235
    sineval[12] = 227
    sineval[13] = 215
    sineval[14] = 201
    sineval[15] = 185
    sineval[16] = 167
    sineval[17] = 148
    sineval[18] = 128
    sineval[19] = 108
    sineval[20] = 89
    sineval[21] = 71
    sineval[22] = 55
    sineval[23] = 41
    sineval[24] = 29
    sineval[25] = 21
    sineval[26] = 16
    sineval[27] = 14
    sineval[28] = 16
    sineval[29] = 21
    sineval[30] = 29
    sineval[31] = 41
    sineval[32] = 55
    sineval[33] = 71
    sineval[34] = 89
    sineval[35] = 108
     
    timerone var word 
    TimerShadow VAR WORD 
    INCLUDE "DT_INTS-14.bas"     ; Base Interrupt System
    
    ;********Define INT_Handler as ISR********************************************** 
    ASM 
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler   TMR1_INT,   _sine,   ASM,  yes
        endm
        INT_CREATE               ; Creates the interrupt processor
    ENDASM
    
    T1CON = %000001    ; Prescaler = 1, TMR1ON          
    TMR1L = 255    
    TMR1H = 254
    @   INT_ENABLE  TMR1_INT     ; Enable Timer 1 Interrupts  
    timerone = 64980           ;gives about 50 hz sine 
    Main:
            pause 5
            
    GOTO Main
     
    '---[TMR1_INT - interrupt handler]------------------------------------------
    
    
    sine:
    'accuracy thing
    T1CON.0 = 0  'Stop TMR1
    TimerShadow.HighByte = TMR1H
    TimerShadow.LowByte = TMR1L
    TimerShadow = TimerShadow + Timerone
    TMR1H = TimerShadow.HighByte
    TMR1L = TimerShadow.LowByte
    T1CON.0 = 1  'Restart TMR1
    
        TMR1L = timerone.byte0
        TMR1H = timerone.byte1     
        CCPR1L = sineval[STEPCOUNT]>>1 
        stepcount = stepcount -1
        if stepcount = 0 then stepcount = 36
    
    @    INT_RETURN

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


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    One small thing I notice is that your:

    Code:
        TMR1L = timerone.byte0
        TMR1H = timerone.byte1     
        CCPR1L = sineval[STEPCOUNT]>>1 
        stepcount = stepcount -1
        if stepcount = 0 then stepcount = 36
    will read the value of stepcount 36 (doesn't exist), and never get to read stepcount 0.

    I don't think this is the dramatic fix you are looking for, but maybe it's one small step forward.

    Code:
        TMR1L = timerone.byte0
        TMR1H = timerone.byte1     
        CCPR1L = sineval[STEPCOUNT]>>1 
        if stepcount = 0 then stepcount = 36
        stepcount = stepcount -1

  11. #11
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,623


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    Hi,
    You still don't have the reload thing correct. The way you currently have it you are first reloading the timer with the calculated value (for accuracy) then you reload it again with the default value overwriting the "correct", calculated value. However, since the overhead is much less then I initially thought you might not need this "accuracy thing". And because it might also mess up the interrupt system due the ASM/PBP type interrupt I suggest you remove it and go back to the way you had it intitially. It's also not the cause of the distroted waveform.

    Something that's more likely the cause of that is the fact that you load the dutycycle value into the top 8 bits of the dutycycle register when you really should load it to the low 8 bits. CCP1L are the 8 high bits and CCP1CON.5 and CCP1CON.4 are the two least significant bits. You are currently putting the (highest) value 121 into CCP1L which, in reallity, looks as 484 to the PWM module. But with the current PWM frequency the PWM module can't "resolve" to that kind of resolution.

    As a test, scale down you'r sinetable so that the highest value is around 200. Then use this in the interrupt:
    Code:
    Temp = SineVal[StepCount]   'Don't forget to declare Temp as BYTE.
    CCP1CON.4 = Temp.0   'Bit 0
    CCP1CON.5 = Temp.1   'Bit 1
    CCP1L = Temp >> 2     'Bit 2-7
    /Henrik.

    PS. Please don't quote the previous message all the time. There's no need to have a copy of it right after the original. If you're responding to specific questions or comment in the message quote those line only.

  12. #12
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    4,170


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    I have made a little house keeping on the thead and deleted all the un-necessary quotes and left only the necessary. The replies were following the answers so it it was really obvious.

    As Henrik stated quote only when absolute necessary. It makes reading the thread more comfortable and easy to follow. Saves resources too!

    Ioannis

  13. #13
    Join Date
    Jan 2006
    Location
    New Hampshire, USA
    Posts
    107


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    Check into Don Lancaster's Magic Sinewaves here: http://www.tinaja.com/
    I did it with a basic stamp BS1 several years ago when I was a newby, it is quite simple and works great.

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


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    Hi,
    Attached is an Excel spreadsheet showing an examle of a 72 steps/cycle SIN table with an 8bit dutycycle. You can modify it for any number of steps and resolution you see fit or you may want to create one half cycle and then have your code invert it for the second half and so on - it's up to you.

    To get three phases there's no need to have three tables, you use three pointers 120° appart indexing the same table. So, with the table in the attached .xls you start at steps 0, 24 and 48 respectively.

    /Henrik.

    EDIT: Crap, can't attach the .xls here. Send me a PM with your email adress and I'll send it to you.

  15. #15
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    EDIT: Crap, can't attach the .xls here. Send me a PM with your email adress and I'll send it to you.
    Add ".txt" to the extension...
    Dave
    Always wear safety glasses while programming.

  16. #16
    Join Date
    Oct 2011
    Posts
    52


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    Thankx again HenrikOlsson here are some things which I dont understand I ask for the help from any one
    (1) ask for the help again which formula should I use to generate this sine look up table I need some detail on it thankx.

    (2) and how this portion of code work , what is function, and how to get values of TMR1L AND TMR1H
    ASM

    INT_LIST macro ; IntSource, Label, Type, ResetFlag?
    INT_Handler TMR1_INT, _sine, ASM, yes
    endm
    INT_CREATE ; Creates the interrupt processor
    ENDASM

    T1CON = 000001 ; Prescaler = 8, TMR1ON
    TMR1L = 255
    TMR1H = 254
    @ INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts

  17. #17
    Join Date
    Oct 2011
    Posts
    52


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    Hi!

    I manage to compile and modify the example from that link www.picbasic.co.uk/forum/cont...-DT-interrupts, for pic 16877. Because the pic I want to use for three phase spwm signal is (16f777) which has 3 CCP module and I' m waiting for it to come the problem it is not includeded in ISIS simulator that is why I used pic 168777 having 2 CCP module for simulation and is present in ISIS and my college lab. I belive if I manage to generate two phase spwm it became eaasy for 3 phase spmw.

    here is the code and attachement of my output from ISIS and mysinelooktable and
    define OSC 4

    STEPCOUNT var byte
    STEPCOUNT1 var byte
    STEPCOUNT = 0 'pointer for phase one in sinearray
    STEPCOUNT1 = 0 'pointer for phase two in sine array
    ADCON0 = %00000000
    ADCON1 = %00000000

    TRISB = %11111111
    TRISC = %11111001 'PMW output for CCP1 AND CCP2
    TRISA = %11111111
    TMR2 = 117
    PR2 = 55 'set for 18Khz HPWM
    CCP1CON = %00001100 'set CCP1 for PWM OPERATION
    CCP2CON = %00001100 'set CCP2 for PWM OPERATION
    T2CON = %00000100 'TIMER2ON and prescale of 1:1

    sineval var byte[36]
    sineval[0] = 128
    sineval[1] = 150
    sineval[2] = 171
    sineval[3] = 191
    sineval[4] = 209
    sineval[5] = 225
    sineval[6] = 238
    sineval[7] = 247
    sineval[8] = 253
    sineval[9] = 255
    sineval[10] = 253
    sineval[11] = 247
    sineval[12] = 238
    sineval[13] = 225
    sineval[14] = 209
    sineval[15] = 191
    sineval[16] = 171
    sineval[17] = 150
    sineval[18] = 128
    sineval[19] = 105
    sineval[20] = 84
    sineval[21] = 64
    sineval[22] = 46
    sineval[23] = 30
    sineval[24] = 17
    sineval[25] = 8
    sineval[26] = 2
    sineval[27] = 0
    sineval[28] = 2
    sineval[29] = 8
    sineval[30] = 17
    sineval[31] = 30
    sineval[32] = 46
    sineval[33] = 64
    sineval[34] = 84
    sineval[35] = 105

    timerone var word
    Temp var byte
    Temp1 var byte

    INCLUDE "DT_INTS-14.bas" ; Base Interrupt System emp


    ASM

    INT_LIST macro ; IntSource, Label, Type, ResetFlag?
    INT_Handler TMR1_INT, _sine, ASM, yes
    endm
    INT_CREATE ; Creates the interrupt processor
    ENDASM

    T1CON = 000001 ; Prescaler = 1;1, TMR1 ON
    TMR1L = 255
    TMR1H = 254
    @ INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts

    timerone = 64980 ;gives about 50 htz sine
    Main:
    PAUSE 5

    GOTO Main

    '---[TMR1_INT - interrupt handler]------------------------------------------

    sine:
    TMR1L = timerone.byte0
    TMR1H = timerone.byte1

    TeMP = sineval[STEPCOUNT]
    CCP1CON.4 = Temp.0 ' bit 0
    CCP1CON.5 = Temp.1 ' bit 1
    CCPR1L = Temp >>2 'Bit 2-7

    TeMP1 = sineval[STEPCOUNT1]
    CCP2CON.4 = Temp.0 ' bit 0
    CCP2CON.5 = Temp.1 ' bit 1
    CCPR2L = Temp >>2 'Bit 2-7
    if stepcount = 36 then stepcount =0
    if stepcount1 = 24 then stepcount1 =0
    stepcount = stepcount +1
    stepcount = stepcount1 +1

    @ INT_RETURN



    any one can help me
    Attached Files Attached Files

  18. #18
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,623


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    Hi,

    First of all, please don't post the same question in several threads. It makes it really hard for people to help you then when someone answers in one thread and someone else in the other. It gets impossible to get the whole picture then.

    Second, when posting code put it in between code-tags so it shows up in a scrollable window instead of just cut and paste it.

    Right, your code then...
    1)
    Code:
    TMR1L = 255
    TMR1H = 254
    This doesn't make much sense, all it does is cause an interrupt after a single cycle. The timer reloading is done in the ISR so just remove those two lines.

    2) It's best to stop the timer before reloading it as it can otherwise overflow between writing to the low and high byte. Even better is to stop it and then ADD the calculated reload value to the timer register as this will account for the otherwsie lost time that occurs when entering the ISR.

    3) You have two index variables pointing into the the array (StepCount and StepCount1). To get the phase shift you need to start at different places in the SIN-table, if you don't the phases will be "in sync".

    4)
    Code:
    if stepcount = 36 then stepcount =0
    if stepcount1 = 24 then stepcount1 =0
    stepcount = stepcount +1
    stepcount = stepcount1 +1
    Here you have three problems.
    4.1) There are 36 entries the table, numbered 0-35. Because you are incrementing your pointers AFTER you check if it's 36 you're actually trying to ACCESS sinval[36] which isn't that good since it doesn't exist. Swap that around so that you increment the pointer FIRST then check if its beyond the boundry of the array.

    4.2) You reset stepcount1 to 0 when it reach 24 so you won't get a full cycle out of it. It needs to get to 36 and then be reset but again, you need to "start" it at 12 instead of 0.

    4.3) If you look at the last two lines of your code above you never actually increment StepCount1.

    Start by fixing that and see what happens. May I also suggest you toggle an output or something in the ISR to verify that you've got the correct interrupt frequency.

    /Henrik.
    Last edited by HenrikOlsson; - 12th February 2012 at 14:08.

  19. #19
    Join Date
    Oct 2011
    Posts
    52


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    Hi HenrikOlsson
    thankx for your coments and Idea you gave me on the code I posted last time which make my output to be some how clear. But is not quiet clear. here are some challenges I faced again

    (1) The ouput does not apper smoth. I tttach the output as seen from ISIS and code.

    Code:
    STEPCOUNT var byte
    STEPCOUNT1 var byte
    
    STEPCOUNT = 0   'pointer for phase one in sinearray
    STEPCOUNT1 = 12 'pointer for phase two  in sine array
    ADCON0 = %00000000
    ADCON1 = %00000000
    
    TRISB = %11111001
    TRISC = %11111001  'PMW output for CCP1 AND CCP2
    TRISA = %11111111
    TMR2 = 117
    PR2 = 55   'set for 18Khz HPWM
    CCP1CON = %00001100 'set CCP1 for PWM OPERATION
    CCP2CON = %00001100 'set CCP2 for PWM OPERATION
    T2CON = %00000100  'TIMER2ON and prescale of 1:1 
    
    sineval var byte[36]
    sineval[0] = 128   
    sineval[1] = 150   
    sineval[2] = 171
    sineval[3] = 191
    sineval[4] = 209
    sineval[5] = 225
    sineval[6] = 238
    sineval[7] = 247
    sineval[8] = 253
    sineval[9] = 255  
    sineval[10] = 253
    sineval[11] = 247
    sineval[12] = 238   
    sineval[13] = 225
    sineval[14] = 209
    sineval[15] = 191
    sineval[16] = 171
    sineval[17] = 150
    sineval[18] = 128   
    sineval[19] = 105
    sineval[20] = 84
    sineval[21] = 64
    sineval[22] = 46
    sineval[23] = 30
    sineval[24] = 17
    sineval[25] = 8
    sineval[26] = 2
    sineval[27] = 0
    sineval[28] = 2
    sineval[29] = 8
    sineval[30] = 17
    sineval[31] = 30
    sineval[32] = 46
    sineval[33] = 64
    sineval[34] = 84
    sineval[35] = 105
     
     timerone var word 
    Temp var byte
    Temp1 var byte
    INCLUDE "DT_INTS-14.bas"     ; Base Interrupt System          emp
     
     
    ASM
     
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler   TMR1_INT,   _sine,   ASM,  yes
        endm
        INT_CREATE               ; Creates the interrupt processor
    ENDASM
     
    T1CON = 000001                 ; Prescaler = 1;1, TMR1 ON
    @   INT_ENABLE  TMR1_INT     ; Enable Timer 1 Interrupts 
    
     
    timerone = 64980   ;gives about 50 htz sine 
    Main:  
    
    PAUSE 5
     GOTO Main
     
    '---[TMR1_INT - interrupt handler]------------------------------------------
    
    sine:
         T1CON = 000000 'stop the timer
    
        TMR1L = timerone.byte0 'reload the timer
        TMR1H = timerone.byte1
        
        
        T1CON = 000001         'start the timer
         
        TeMP = sineval[STEPCOUNT]
        CCP1CON.4 = Temp.0 ' bit 0
        CCP1CON.5 = Temp.1 ' bit 1       
        CCPR1L = Temp >>2  'Bit 2-7 
        
        TeMP1 = sineval[STEPCOUNT1]
        CCP2CON.4 = Temp.0 ' bit 0
        CCP2CON.5 = Temp.1 ' bit 1       
        CCPR2L = Temp >>2  'Bit 2-7 
        stepcount =  stepcount +1
        stepcount1 =  stepcount1 +1    
        if stepcount = 36 then stepcount =0
        if stepcount1 = 36 then stepcount1 =12   
     
    @    INT_RETURN
    (2) I try to write a code so that I can measure if the interrupt frequence is 1800hz.
    When I start learning timer in the previous days I passed I cross the link http://www.microcontrollerboard.com/...-tutorial.html there is formural for calcalating a numeric value(count) to be placed to obtain the desired output frequency.
    count=fclk/(4*prescale*(65536-TMR1)*fout

    where for me
    fout=1800hz, prescale 1, TMRI=64980 and fclk=4MHz

    gives count = 1 ohh! here I'm confusing how should I proceed since is very small count I cant use it.

    can you help which count should I use so I can measure my interrupt frequecy
    thankx
    Attached Files Attached Files

  20. #20
    Join Date
    Oct 2011
    Posts
    52


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    Hi to all

    I am here again I am still working on the code I posted last 2 days. It try to work on the code but I still get the same output, as I Attach on the two days ago, when I try to put LED on the interrupt service routine and to see if the frequency is clear this became another problem to me. The problem arising are

    (1) The ouput does not apper smoth and which condition should I put to show I get the desired frequency . I atttach again the output as seen from ISIS and the code use to generate that output.

    Code:
    DEFINE OSC 4
    
    STEPCOUNT var byte
    STEPCOUNT1 var byte
    
    STEPCOUNT = 0   'pointer for phase one in sinearray
    STEPCOUNT1 = 12 'pointer for phase two  in sine array
    ADCON0 = %00000000
    ADCON1 = %00000000
    
    TRISB = %11111001
    TRISC = %11111001  'PMW output for CCP1 AND CCP2
    TRISA = %11111111
    TMR2 = 117
    PR2 = 55   'set for 18Khz HPWM
    CCP1CON = %00001100 'set CCP1 for PWM OPERATION
    CCP2CON = %00001100 'set CCP2 for PWM OPERATION
    T2CON = %00000100  'TIMER2ON and prescale of 1:1 
    
    sineval var byte[36]
    sineval[0] = 128   
    sineval[1] = 150   
    sineval[2] = 171
    sineval[3] = 191
    sineval[4] = 209
    sineval[5] = 225
    sineval[6] = 238
    sineval[7] = 247
    sineval[8] = 253
    sineval[9] = 255  
    sineval[10] = 253
    sineval[11] = 247
    sineval[12] = 238   
    sineval[13] = 225
    sineval[14] = 209
    sineval[15] = 191
    sineval[16] = 171
    sineval[17] = 150
    sineval[18] = 128   
    sineval[19] = 105
    sineval[20] = 84
    sineval[21] = 64
    sineval[22] = 46
    sineval[23] = 30
    sineval[24] = 17
    sineval[25] = 8
    sineval[26] = 2
    sineval[27] = 0
    sineval[28] = 2
    sineval[29] = 8
    sineval[30] = 17
    sineval[31] = 30
    sineval[32] = 46
    sineval[33] = 64
    sineval[34] = 84
    sineval[35] = 105
     
     timerone var word 
    Temp var byte
    Temp1 var byte
    INCLUDE "DT_INTS-14.bas"     ; Base Interrupt System          emp
     
     
    ASM
     
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler   TMR1_INT,   _sine,   ASM,  yes
        endm
        INT_CREATE               ; Creates the interrupt processor
    ENDASM
     
    T1CON = 000001                 ; Prescaler = 1;1, TMR1 ON
    @   INT_ENABLE  TMR1_INT     ; Enable Timer 1 Interrupts 
    
     
    timerone = 64980   ; vakue loaded to TMR1 to gives about 50 htz sine 
    Main:  
    
    PAUSE 5
     GOTO Main
     
    '---[TMR1_INT - interrupt handler]------------------------------------------
    
    sine:
         T1CON = 000000 'stop the timer
    
        TMR1L = timerone.byte0 'reload the timer
        TMR1H = timerone.byte1
        
        
        T1CON = 000001         'start the timer
         
        TeMP = sineval[STEPCOUNT]
        CCP1CON.4 = Temp.0 ' bit 0
        CCP1CON.5 = Temp.1 ' bit 1       
        CCPR1L = Temp >>2  'Bit 2-7 
        
        TeMP1 = sineval[STEPCOUNT1]
        CCP2CON.4 = Temp.0 ' bit 0
        CCP2CON.5 = Temp.1 ' bit 1       
        CCPR2L = Temp >>2  'Bit 2-7 
        stepcount =  stepcount +1
        stepcount1 =  stepcount1 +1    
        if stepcount = 36 then stepcount =0
        if stepcount1 = 36 then stepcount1 =12   
     
    @    INT_RETURN
    When I start learning timer in the days ago I passed across the link http://www.microcontrollerboard.com/...-tutorial.html there is formural for calcalating a numeric value(count) to be placed to obtain the desired output frequency.

    count=fclk/(4*prescale*(65536-TMR1)*fout this formular gives me a small count which I can not use to test the frequency condition.

    thanks
    Attached Files Attached Files

  21. #21
    Join Date
    Oct 2011
    Posts
    52


    Did you find this post helpful? Yes | No

    Default Re: sinusoidal PWM

    Hi to all
    can any one help me how to write 10 bit resolution to PWM MODULE because I read pic datasheets and Ds33023 refference manual I see 10bit resolution is applicable for low frequencies.
    thankx.

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