​ ​ ​ ​ Using PWMDIV options with the PICAXE-28X2 and 40X2
Results 1 to 8 of 8

Thread: Using PWMDIV options with the PICAXE-28X2 and 40X2

  1. #1
    Technical Support
    Join Date
    Jan 1970
    Location
    UK
    Posts
    22,008

    Default Using PWMDIV options with the PICAXE-28X2 and 40X2

    Introduction

    On PICAXE-28X2 and 40X2 parts any new 'pwmout' command will reset 'pwmdiv' divider settings used in previous 'pwmout' commands.

    This issue only applies if:
    1. You are using a 28X2 or 40X2 part,
    2. You are using multiple 'pwmout' commands on different pins,
    3. You are using 'pwmdiv' dividers within these 'pwmout' commands.
    The issue is that a 'pwmdiv' divider is only applied to the last 'pwmout' command used.

    Any 'pwmdiv' divider previously used on any other pin is reset to the default (1) via the latest 'pwmout' command.

    This issue can be worked around by manually resetting the 'pwmdiv' settings on the other pins using 'pokesfr' commands.

    Detailed Description

    On the 28X2 and 40X2 any change to the 'pwmdiv' settings of a particular 'pwmout' channel affects the 'pwmdiv' settings of other 'pwmout' channels. When using multiple 'pwmout' channels and 'pwmdiv' settings the outcome may not always be as anticipated.

    This is an issue which only affects the PICAXE-28X2 and 40X2 parts, only when using multiple 'pwmout' channels. Whether there may be an unexpected outcome or not depends on which 'pwmout' channels are used, the 'pwmdiv' settings required and the order any changes to 'pwmdiv' settings are applied.

    On 28X2 and 40X2 devices the following pins can be used for 'pwmout' -
    • B.0
    • B.5
    • C.1 - Shares timer with C.2
    • C.2 - Shares timer with C.1
    The 28X2 and 40X2 have two independent 'pwmout' channels on B.0 and B.5 which are each controlled by separate timers. They also have two additional 'pwmout' channels on C.1 and C.2 controlled by a single, shared timer. The 'pwmdiv' setting is applied to the timer which drives the 'pwmout' channel.

    Due to the way the firmware interacts with the internal chip control registers to provide 'pwmout' only the last 'pwmdiv' applied takes affect and other 'pwmout' channels are reset to what is effectively 'pwmdiv1'.

    To give a clarifying example -

    Code:
    pwmout pwmdiv4, B.0, period, duty
    pwmout pwmdiv4, B.5, period, duty
    B.0 is initialised with the desired 'pwmdiv4' but after B.5 is initialised B.0 is reset to 'pwmdiv1'; so the outcome is as if the code executed were -

    Code:
    pwmout          B.0, period, duty
    pwmout pwmdiv4, B.5, period, duty
    If 'pwmout' channels C.1 or C.2 are active they too will be reset to 'pwmdiv1'.

    When using C.1 and C.2 for 'pwmout', because these use the same timer, a change to one will always affect the other, so for -

    Code:
    pwmout pwmdiv4, C.1, period, duty
    pwmout pwmdiv4, C.2, period, duty
    The outcome is as would be expected; C.1 was using 'pwmdiv4', and setting C.2 to 'pwmdiv4' sets C.1 to the same, which is what it was already set to.

    In addition though, a change to C.1 or C.2 will reset B.0 and B.5 to 'pwmdiv1'.

    When using multiple 'pwmout' channels and altering 'pwmdiv', the final outcome will depend upon which 'pwmout' channels are being used, which 'pwmdiv' settings are applied, and the order in which 'pwmdiv' settings are applied.

    Unfortunately it is not possible to track what 'pwmdiv' settings have been used within the firmware, nor can the compiler determine where 'pwmdiv' settings for timers would need to be adjusted automatically.

    There is however a solution and that is to manually reset the timers for 'pwmout' channels to the desired 'pwmdiv' value when necessary. This can be achieved using the 'peeksfr' and 'pokesfr' commands to access the internal registers which hold the 'pwmdiv' settings for the timer which drives the 'pwmout' channel. The code required to do this for each 'pwmout' channel is detailed later.

    For example, to achieve setting both B.0 and B.5 to 'pwmdiv4', where the setting of B.5 will have reset B.0 to 'pwmdiv1', force the 'pwmdiv' setting for B.0 after setting B.5 -

    Code:
    pwmout pwmdiv4, B.0, period, duty
    pwmout pwmdiv4, B.5, period, duty
    peeksfr $4A, b0
    bit0 = 1
    bit1 = 0
    pokesfr $4A, b0
    The code required to force each 'pwmout' channel to a specific 'pwmdiv' setting is detailed below -

    To force B.0 to 'pwmdiv4'

    peeksfr $4A, b0
    bit0 = 1
    bit1 = 0
    pokesfr $4A, b0

    To force B.0 to 'pwmdiv16'

    peeksfr $4A, b0
    bit1 = 1
    pokesfr $4A, b0

    To force B.5 to 'pwmdiv4'

    peeksfr $51, b0
    bit0 = 1
    bit1 = 0
    pokesfr $51, b0

    To force B.5 to 'pwmdiv16'

    peeksfr $51, b0
    bit1 = 1
    pokesfr $51, b0

    To force C.1 and C.2 to 'pwmdiv4'

    peeksfr $BA, b0
    bit0 = 1
    bit1 = 0
    pokesfr $BA, b0

    To force C.1 and C.2 to 'pwmdiv16'

    peeksfr $BA, b0
    bit1 = 1
    pokesfr $BA, b0
    Last edited by hippy; 10-04-2014 at 11:55. Reason: See post 4 below

  2. #2
    Senior Member
    Join Date
    Sep 2013
    Location
    Sweden
    Posts
    131

    Default

    For some reason reality seem to differ slightly from above, running on 28X2 vB.3, using PE6.0.6.4:
    Copied and completed the code from last section above, and finished it for running:
    Code:
    #picaxe 28X2
    #no_table
    pinsB=0 ;for sanity of logic analyser
    dirsB=$FF ;tie all unused pins low.
    pwmout pwmdiv4, B.0, 254, 100
    pwmout pwmdiv4, B.5, 254, 50
    peeksfr $51, b0
    bit0 = 1
    bit1 = 0
    pokesfr $51, b0
    do
    loop
    I see on the scope B.0 oscillates 4 times faster than B.5
    But if i exchange B.0 and B.5 both have the slow frequency.

    Is the workaround different between revisions?
    Have not tested other things, post above seem to need correction.

  3. #3
    Technical Support
    Join Date
    Jan 1970
    Location
    UK
    Posts
    22,008

    Default

    I must admit that I cannot recall all the details from almost two years ago and would have to investigate further and verify what you are seeing.

  4. #4
    Technical Support
    Join Date
    Jan 1970
    Location
    UK
    Posts
    22,008

    Default

    It appears the SFR addresses which relate to B.0 and B.5 PWMOUT channels were inadvertently switched in the original post; the correct SFR should be $4A for B.0, $51 for B.5. I have updated the original post accordingly.

    Many thanks for spotting this mistake which we and everyone else seem to have missed and please accept our apologies for it.

    In the original version; setting B.0 as PWMDIV4, then setting B.5 as PWMDIV4 would reset B.0 to PWMDIV1, and the POKESFR was setting B.5 to PWMDIV4 rather than B.0. Thus B.0 was left at PWMDIV1 so runs four times faster than expected.

    Swapping the order of the PWMOUT so B.5 first then B.0; sets B.5 as PWMDIV4, then setting B.0 as PWMDIV4 would reset B.5 to PWMDIV1, the POKESFR sets B.5 to PWMDIV4 rather than B.0 so both become the same, PWMDIV4.

    With the SFR addresses now corrected everything should work as expected.

  5. #5
    Senior Member
    Join Date
    Sep 2013
    Location
    Sweden
    Posts
    131

    Default

    That was quick, thanks
    Could have been even quicker if we had a list of which function use which resource
    Nag, nag...

    I the current code i just save/restore the configuration:
    Code:
    pwmout pwmdiv16, B.5 , 254 , 50
    #define T4CON $51
    peeksfr T4CON, b0 ; pwmdiv command resets dividers on earlier channels...
    pwmout pwmdiv16, B.0 , 254 , 50
    pokesfr T4CON, b0 ; ... so restore it!
    I believe there should not be any problem with that?

  6. #6
    Technical Support
    Join Date
    Jan 1970
    Location
    UK
    Posts
    22,008

    Default

    Quote Originally Posted by Morganl View Post
    I believe there should not be any problem with that?
    I don't know. Doing it that way could overwrite any alterations the firmware makes in executing the PWMOUT command. We recommend the method described in the original post which alters only the bits which need to be changed after PWMOUT execution completes.

  7. #7
    Senior Member
    Join Date
    Sep 2013
    Location
    Sweden
    Posts
    131

    Default

    I think you need to revisit the method for C.1 and C.2
    Using the following program, they are not frequency divided:
    Code:
    pwmout pwmdiv16, C.1 , 254 , 10
    pwmout pwmdiv16, C.2 , 254 , 300
    pwmout pwmdiv16, B.5 , 254 , 700
    pwmout pwmdiv16, B.0 , 254 , 1000
    ;__Set pwmdiv16 on B.5
    #define T4CON $51
    peeksfr T4CON, b0 : bit1 = 1 : pokesfr T4CON, b0
    ;__Set pwmdiv16 on C.1 & C.2
    #define T2CON $BA
    peeksfr T2CON, b0 : bit1 = 1 : pokesfr T2CON, b0
    do:loop

  8. #8
    Technical Support
    Join Date
    Jan 1970
    Location
    UK
    Posts
    22,008

    Default

    Quote Originally Posted by Morganl View Post
    I think you need to revisit the method for C.1 and C.2
    This will require further investigation.

Tags for this Thread

Bookmarks

Posting Permissions

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