SPWM_INT - Multiple Software PWM Question


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

    Default SPWM_INT - Multiple Software PWM Question

    (I'm starting a new thread as none of the ones I searched which referenced 'SPWM_INT' seemed appropriate)

    I've implemented Darrel's excellent SPWM_INT include file together with ADCIN (reading a trim pot) to adjust the duty cycle for one pin (see my thread here). The problem is that (a) using 8-bit resolution (0-255) makes the LED brightness adjustment a little coarse, and (b) there's a delay in changing the duty cycle no matter how low I adjust the ADC_SAMPLEUS value. I'm willing to live with (b) but I'd like to move to 10-bit resolution to address (a).

    Is it just a matter of changing
    Code:
    DEFINE SPWM_RES 256
    to
    Code:
    DEFINE SPWM_RES 1024
    and then altering
    Code:
    DEFINE ADC_BITS 8
    to
    Code:
    DEFINE ADC_BITS 10
    and
    Code:
    ADCON1.7 = 1
    for right-justified values? Will that give me the finer control of LED brightness that I'm after?

    BTW, I'm using a PIC16F1825 with 16Mhz internal oscillator setting.

    Darrel's page (below) doesn't have the frequency range definitions like his earlier Multi-SPWM page, but I think this won't work with DC motors as the frequency needs to be greater than 16,000 Hz. Is that right?

    DT_INTS-14 (SPWM_INT - Multiple Software PWM)
    http://www.darreltaylor.com/DT_INTS-14/SPWM.html
    Last edited by RossWaddell; - 15th January 2013 at 20:14.

  2. #2


    Did you find this post helpful? Yes | No

    Default Re: SPWM_INT - Multiple Software PWM Question

    (I guess I really have 2 issues here: finer LED brightness control and doing PWM for a motor (since I also want to 'fade in/out' the motor RPM by changing the duty cycle). If this should be a separate thread, please let me know)..

    For the motor application, I think I can configure the registers for the duty cycle (CCP1CON.4 & .5, CCPR1L) but I can't wrap my head around the frequency calculation (with 10-bit resolution at FOSC 32Mhz, I think I need PR2 = 255 with a timer prescale of 1 to get 31.25kHz judging from Table 24-5 in the PIC16F1825 datasheet). But what if I want to aim for 16-20kHz?

  3. #3
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    SPWM_INT has a maximum resolution of 8-bits (0-255), as detailed on the page you linked to.

    For using PWM with the CCP module, mister-e's PicMultiCalc is very useful for figuring out what frequencies and dutycycles you can get.
    http://www.picbasic.co.uk/forum/cont....-PICMultiCalc
    DT

  4. #4


    Did you find this post helpful? Yes | No

    Default Re: SPWM_INT - Multiple Software PWM Question

    Thank Darrel. I mis-read "PWM resolution is no longer limited to 8-bit (256)" on your web page to mean higher resolutions were possible - I guess you mean lower resolutions are now possible.

    I just grabbed Mr E's MultiCalc, but it doesn't seem to output results for a 1:1 prescaler (which I think would give me 10-bit resolution for 32Mhz & 16kHz). Also, when you say it will give me available duty cycles does that mean I can't just use 0-1023 (10-bit) or 0-255 (8-bit) when incrementing the CCPRIL & CCP1CON.4 & 5 registers?
    Last edited by RossWaddell; - 15th January 2013 at 23:53.

  5. #5
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default Re: SPWM_INT - Multiple Software PWM Question

    No, it's not very often that you get a full 0-1023 resolution with hardware PWM.

    And you can't get 16Khz from Timer2 with a 1:1 prescaler, which is why PicMultiCalc didn't show it.
    With a 32Mhz OSC, the number of timer ticks required is ...

    32,000,000 / 4 / 16,000 = 500

    But Timer2 is only an 8-bit counter, so the max is 256 ticks till it overflows.
    The next available prescaler is 1:4. So divide 500 / 4 = 125
    Timer2 overflows at PR2 + 1, so subtract 1 to make it 124. This is the PR2 value for 16Khz.

    The maximum dutycycle value is (PR2 + 1) * 4 because of the CCPxCON.4,5 bits.
    (124 + 1) * 4 = 500
    So 500 is the "Always On" point (100%), and anything above that is 100% too.

    If your control value is 0-1023, it must be scaled to 0-500.

    500 is slightly less than a 9-bit value, which is 1-bit better than the 8-bit resolution of SPWM_INT.

    At 32kHz, you can get 0-1000 dutycycle, because a 1:1 Timer2 prescaler will give 32Khz when PR2 = 249.
    DT

  6. #6


    Did you find this post helpful? Yes | No

    Default Re: SPWM_INT - Multiple Software PWM Question

    If I switch to 16Mhz OSC I can get 10-bit resolution at 16kHz:

    Name:  Mr_E_PWM_Calc.PNG
Views: 1200
Size:  15.2 KB

    So here's the thing: if I set up my ADCIN to use 10-bit then presumably I can get 0-1023 values from my trim pot but since 1000 is the max duty cycle anything above that changes nothing. Will it cause a problem if I pass that in to the duty cycle registers (e.g. 1012) or do I need to set a programmatic limit at 1000? Same applies to 8-bit - max duty cycle is 250 but 8-bit resolution on ADCIN would give me 0-255, so anything greater than 250 does nothing.

  7. #7
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,604


    Did you find this post helpful? Yes | No

    Default Re: SPWM_INT - Multiple Software PWM Question

    As Darrel wrote earlier, anything above the highest value (1000 in this case) will cause 100% dutycycle - all that's happening is that you get a flat spot at the very top of the otherwise linear curve. Only you know if that will be an actual problem for you.
    If you want to scale your 0-1023 ADC input value to 0-1000 dutycycle value you could do something like DutyCycle=ADCValue**64063 or, for 8bit resolution, DutyCycle=ADCValue**64251.

    /Henrik.

  8. #8


    Did you find this post helpful? Yes | No

    Default Re: SPWM_INT - Multiple Software PWM Question

    Got it - thanks Henrik (and Darrel). I've been playing around with Mr E's multi-calc with various OSC & freq values - I never know there were upper limits to duty cycles before and that they depended on the prescaler as well. All of this is hidden if using pbp's PWM or HPWM, but I want to get into the down-and-dirty of PWM registers to really understand this stuff (besides, it's fun). For the motor spinning up aspect, I had read that it's not good to do something like this:

    Code:
    For dutyval = 0 to 255
        HPWM 1, dutyval, 16000
    Next dutyval
    because the HPWM command changes more than just the duty cycle register values. Plus, on my PIC16F1824 I want to use CCP3 & CCP4 which you can't do with pbp's HPWM.

  9. #9
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,604


    Did you find this post helpful? Yes | No

    Default Re: SPWM_INT - Multiple Software PWM Question

    Hi,
    Basically the PWM generator consists of a counter, a dutycycle register and a comparator.
    The PWM period (therefor frequency) is the time it takes for the counter to count from 0 to whatever value makes it roll over back to 0.

    * When the PWM period starts (counter=0) the output is set.
    * When the counter value equals that of the dutycycle register (that's the comparators job) the output is reset.
    * The counter continues counting up, rolls over and the cycle repeats.

    Now, to make it easy, concider the counter rolling over at 99 making it a 100 "step" counter. If you set the dutycycle value to 50 the output will turn on and stay on untill the counter hits 50 then turn off. The counter continues counting up to 99, rolls over and the cycle repeats. The output is on for 50 "ticks" and off for 50 "ticks" - you have 50% dutycycle.

    If the counter is "ticking" at 1MHz the PWM period would be 100us (f=10kHz). Now, if you want to change the PWM frequency you can do one of two things.
    A) Change the frequency at which the counter "ticks".
    B) Change at which value the counter rolls over (this is the PR2 value as described earlier).

    Changing the "counter roll-over value" so that the counter rolls over at 49 instead of 99 will cause the PWM frequency to double but it'll also cause your resolution to be cut in half since there's now only 50 "steps". So when you previously set the dutycycle value to 50 to get 50% you'd now have to set it to 25.

    What makes it a little bit tricky to understand in the PIC is how you can have PR2 set to 200 and still be able to set your dutycycle value to 600 (for example). This is because of those additional two bits of the counter (and the dutycycle register and comparator) so when you set PR2 to 200 the counter actually counts from 0 to 800 (rolling when hitting 801).

    As for your HPWM example (and I'm not sure about this) I think that the HPWM command sets everything up every time so to speak. Even if all you're actually doing is changing the dutycycle it most likely does some other stuff behind the scenes (you MAY wanted to change the frequency or the PWM MAY not have been running) so there may be glitches in the output when trying to change the dutycyle by rapidly "calling" HPWM like that.

    Well, enough rambling, time to hit the sack for me.

    /Henrik.

  10. #10


    Did you find this post helpful? Yes | No

    Default Re: SPWM_INT - Multiple Software PWM Question

    Any idea why I get this ASM warning when compiling my code? I've included the snippet of code which I think is applicable, and the full code too.

    Name:  ASM_Warning.png
Views: 810
Size:  16.7 KB

    Code:
    ' ***************************************************************
    ' Set up registers for PWM on CCP3 & 4
    ' ***************************************************************
    
    ; Use Mister E's MultiCalc to calculate PR2 value & hence Prescaler setting
    ; for T2CON:
    
    ; http://www.picbasic.co.uk/forum/content.php?r=159-New-PIC-Utility.-PICMultiCalc
    
    ; Can also use this web-based site:
    ; http://www.micro-examples.com/public/microex-navig/doc/097-pwm-calculator.html
    
    CCP3CON = %00001100         ; Use CCP3 in PWM mode
    CCP4CON = %00001100         ; Use CCP4 in PWM mode
    
    ;CCPTMRS = %00000000         ; Use Timer2 for all CCPs in PWM mode
                                 ; (The default appears to be Timer2, so no need
                                 ; to set it explicitly)
                                 
    T2CON   = %00000100         ; Timer2 on with 1:1 prescaler
    PR2     = 249               ; For 16Mhz OSC the desired output of 16,000Hz is
                                ; achieved with this PR2 value (10-bit resolution
                                ; with 1:1 prescaler)
    
    MinDuty CON 50              ; Lowest possible duty cycle at which motor spins
    MaxDuty CON 1000            ; Maximum duty cycle available with PR2 = 249 and
                                ; 1:1 prescaler (According to Darrel:
                                ;      MaxDuty = (PR2 + 1) * 4
    
    DutyVar3 VAR WORD
    DutyVar4 VAR WORD
    
    ' Spin up motors to saved value of _MotorRPM
    ' (Below a cycle of MinDuty, the motors don't move at all)
    FOR I = (MinDuty - 10) to MotorRPM
        DutyVar3  = I
        CCP3CON.4 = DutyVar3.0
        CCP3CON.5 = DutyVar3.1
        CCPR3L    = DutyVar3 >> 2
    
        IF PortEngDir = 0 THEN
            DutyVar4  = I
            CCP4CON.4 = DutyVar4.0
            CCP4CON.5 = DutyVar4.1
            CCPR4L    = DutyVar4 >> 2    
        ELSE
            DutyVar4  = (MaxDuty - I)
            CCP4CON.4 = DutyVar4.0
            CCP4CON.5 = DutyVar4.1
            CCPR4L    = DutyVar4 >> 2        
        ENDIF
    
        pause 33
    NEXT I
    Full PIC code:
    PIC16F1825_Code.txt
    Last edited by RossWaddell; - 20th January 2013 at 22:54.

  11. #11
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default Re: SPWM_INT - Multiple Software PWM Question

    Those warnings aren't coming from the section you posted.

    You are trying to use a value of 500 with byte sized EEPROM locations.

    But I'm pretty sure you really want WORD sized EEPROM locations.
    Change this ...
    Code:
    ' ***************************************************************
    ' EEPROM Variables
    ' ***************************************************************
    
    MotorRPM_Default   CON  500 ; half speed if max is 1000
    EE_MotorRPM        DATA MotorRPM_Default
    MotorRPM           VAR  BYTE
    READ EE_MotorRPM, MotorRPM
    
    PortEngDir_Default CON  0
    EE_PortEngDir      DATA PortEngDir_Default
    PortEngDir         VAR  BYTE
    READ EE_PortEngDir, PortEngDir
    ... to this ...
    Code:
    ' ***************************************************************
    ' EEPROM Variables
    ' ***************************************************************
    
    MotorRPM_Default   CON  500 ; half speed if max is 1000
    EE_MotorRPM        DATA WORD MotorRPM_Default
    MotorRPM           VAR  WORD
    READ EE_MotorRPM, WORD MotorRPM
    
    PortEngDir_Default CON  0
    EE_PortEngDir      DATA WORD PortEngDir_Default
    PortEngDir         VAR  WORD
    READ EE_PortEngDir, WORD PortEngDir
    There are a few other WRITE statements in your program that need to be changed too.
    DT

  12. #12


    Did you find this post helpful? Yes | No

    Default Re: SPWM_INT - Multiple Software PWM Question

    You're a life saver, Darrel - thanks. Updated the corresponding WRITE statements and all compiles fine (I didn't change the 'PortEngDir' stuff as that has only 2 values: 0 & 1)

    Was there anything in the warning message which told you where to look?'
    Last edited by RossWaddell; - 21st January 2013 at 01:24.

  13. #13
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default Re: SPWM_INT - Multiple Software PWM Question

    Woops, I changed too much.

    When I can't tell were an error is comming from, I go to the .LST file and search for the error or warning.
    Ususally, the first error found in that file is the most important one.

    It helps being able to read assembly language though.
    DT

  14. #14


    Did you find this post helpful? Yes | No

    Default Re: SPWM_INT - Multiple Software PWM Question

    Being able to read assembly language would be helpful - I'm going to have to add that to the list of 'to-dos'.

  15. #15


    Did you find this post helpful? Yes | No

    Default Re: SPWM_INT - Multiple Software PWM Question

    Quote Originally Posted by Darrel Taylor View Post
    The maximum dutycycle value is (PR2 + 1) * 4 because of the CCPxCON.4,5 bits.
    (124 + 1) * 4 = 500
    So 500 is the "Always On" point (100%), and anything above that is 100% too.
    Is that calculation dependent somehow on the prescaler? I'd like to programmatically determine the max duty cycle available to me with PR2=249 and prescaler of 1:1 (16Mhz OSC, 16,000Hz freq). With Mister E's MultiCalc it shows me '1000' is the max duty cycle for these paramters, which also works with (PR2 + 1)*4 where PR2 = 249 but is that always the rule?

  16. #16
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    The prescaler has already been factored in when calculating the PR2 value.

    The (PR2+1)*4 formula holds true in all cases for the maximum dutycycle.
    DT

  17. #17


    Did you find this post helpful? Yes | No

    Default Re: SPWM_INT - Multiple Software PWM Question

    Thanks Darrel - I'll add that formula into the next round of changes once I get the basic PWM via registers sorted out.

    Part of this thread was how to set PWM frequency/duty cycle via registers so I can use CCP3 & CCP4 on the PIC16F1825 (CCP1 & CCP2 are ECCP's). I have code to control DC motors via a SN754410 motor driver and while it works OK with pbp's HPWM I have to use CCP1 & CCP2 and changing the duty cycle in a loop (the motors have to spin up to the desired speed slowly) means that the HPWM command is changing more than just the duty cycle. So, wanting to learn how to do this via registers I came up with this simple test code:

    Code:
    DEFINE OSC 16               ; Set oscillator 16Mhz
    
    ' ***************************************************************
    ' Device Fuses
    ' ***************************************************************
    #CONFIG
       __config _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF
       __config _CONFIG2, _PLLEN_OFF & _STVREN_ON & _BORV_LO & _LVP_OFF
    #ENDCONFIG
    
    OSCCON   = %01111000        ' 16MHz internal osc
    
    pause 100                   ' As advised by Darrel Taylor for EEPROM issue
    
    ANSELA   = 0                ; Digital only for all PortA pins
    ANSELC   = 0                ; Diginal only for all PortC pins
    
    TRISA = 0
    TRISC = 0
    
    MOTOR_1_DIR    VAR PORTC.0   ' Alias PORTC.0 as "MOTOR_1_DIR"
    MOTOR_1_PWM    VAR PORTA.2   ' Alias PORTA.2 as "MOTOR_1_PWM"
    
    ' ***************************************************************
    ' Set up registers for PWM on CCP3 & 4
    ' ***************************************************************
    
    CCP3CON = %00001100         ; Use CCP3 in PWM mode                             
    T2CON   = %00000101         ; Timer2 on with 1:4 prescaler
    PR2     = 62                ; For 16Mhz OSC the desired output of 15,873Hz is
                                ; achieved with this PR2 value (8-bit resolution
                                ; with 1:4 prescaler)
    
    i        VAR BYTE
    
    DutyVar3 VAR BYTE
     
    ;LOW MOTOR_1_DIR
    ;DutyVar3 = 0
    
    HIGH MOTOR_1_DIR
    DutyVar3 = 250
     
    FOR i = 0 to 250
    ;    DutyVar3 = DutyVar3 + 1
        DutyVar3 = DutyVar3 - 1
    
        CCP3CON.4 = DutyVar3.0
        CCP3CON.5 = DutyVar3.1
        CCPR3L = DutyVar3 >> 2
        
        pause 33
    NEXT i
                                
    Main:
    
        GOTO Main
    For clockwise rotation of the DC motor, I use:

    Code:
    LOW MOTOR_1_DIR
    DutyVar3 = 0
    and inside the loop:

    Code:
    DutyVar3 = DutyVar3 + 1
    This works! The motor spins CW slowly up to 250 (max duty cycle with prescaler of 1:4, according to Mister E's MultiCalc).

    The problem is when I want to spin the motor CCW. For that, I use:

    Code:
    HIGH MOTOR_1_DIR
    DutyVar3 = 250
    and inside the loop:

    Code:
    DutyVar3 = DutyVar3 - 1
    This almost works: the motor spins CCW slowly up to max speed but then when the loop is over (and presumably the motor is spinning its fastest) it just stops. Am I using the wrong register settings when I want to count backwards from the maximum (with the SN754110, if the motor direction pin is HIGH then the motor speed starts at the opposite end of the duty cycle range).

  18. #18
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    172


    Did you find this post helpful? Yes | No

    Default Re: SPWM_INT - Multiple Software PWM Question

    You may need to limit the decrement counter so that it never goes below 0
    Code:
    If DutyVar3 > 0 then
        DutyVar3 = DutyVar3 -1
    else
        DutyVar3 = 0
    endif
    Cheers
    Barry
    VK2XBP

  19. #19


    Did you find this post helpful? Yes | No

    Default Re: SPWM_INT - Multiple Software PWM Question

    Quote Originally Posted by Aussie Barry View Post
    You may need to limit the decrement counter so that it never goes below 0
    Code:
    If DutyVar3 > 0 then
        DutyVar3 = DutyVar3 -1
    else
        DutyVar3 = 0
    endif
    Cheers
    Barry
    VK2XBP
    Ah! You think DutyVar3 is ending with -1? I can hook up my serial LCD and see for sure, but that looks to be what's happening. Thanks Barry!

  20. #20


    Did you find this post helpful? Yes | No

    Default Re: SPWM_INT - Multiple Software PWM Question

    That was it. I should have learned by now to go over my loop code in more detail.

    Any ideas on combining SPWM and blinking LEDs?

Similar Threads

  1. Darrel's Multiple Software PWM
    By passion1 in forum mel PIC BASIC Pro
    Replies: 10
    Last Post: - 15th October 2013, 15:21
  2. Replies: 1
    Last Post: - 4th March 2013, 21:57
  3. DT Multiple Software PWM and 18F2321 issue
    By microuser in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 20th December 2012, 08:23
  4. General Question About Multiple Interrupts
    By grzeh666 in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 31st August 2008, 17:09
  5. Multiple HPWM question
    By Johan in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 17th October 2007, 13:00

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