Shop OBEX P1 Docs P2 Docs Learn Events
odd PWMPAL behavior — Parallax Forums

odd PWMPAL behavior

TWRackersTWRackers Posts: 33
edited 2009-05-08 02:31 in BASIC Stamp
I've noticed an odd behavior with the PWMPAL sitting under my BS2sx. In my application I have each of the four PWMPAL output channels driving the gate of a MOSFET to turn on a high-power LED. I do have a 220 ohm resistor in between each PWMPAL output and its MOSFET gate. In my software I turn on or off all four channels together by setting (in a small loop) each channel to the same on/off times, specifically 50 msec on and 450 msec off. So all four channels should be pulsing at 2 Hz with 10% on-time, with perhaps a very slight skew between channels, since I have to set them one at a time. The BS2sx is talking to the PWMPAL's serial I/O pin at 38400 baud.

What I actually see sometimes (about half the time I power up the system) is that one of the four channels, I don't know which one, runs at a different rate than the other three. Sometimes the difference is barely noticeable until a couple of minutes pass, and sometimes it's obvious very soon. It's like either (a) one channel's clock is running at a different rate than the others' clocks, or (b) that channel's on-time and off-time registers got loaded with a different value.

I doubt (a) is the cause, assuming all four channels share a clock; I don't know if that's the case. Cause (b) could occur if bit errors occur on the serial input when loading the registers, so that the channels don't end up with the same on and off times.

Does anybody have any experience with odd PWMPAL behavior? I can think of only two possible remedies: (1) drop the serial baud rate to 19200 or 9600 to reduce the possibility of serial errors; (2) swap out the PWMPAL with a spare.

Comments

  • TWRackersTWRackers Posts: 33
    edited 2009-04-07 23:27
    Here's the snippet of code which sets the PWMPAL channels.
    ' {$STAMP BS2sx}
    ' {$PBASIC 2.5}
    
    ' -----[noparse][[/noparse] Constants ]-------------------------------------------------------
    
    #SELECT $stamp
        #CASE BS2, BS2E, BS2PE
            T1SEC       CON     1000
            T9600       CON     84
            T19K2       CON     32
            T38K4       CON     6
        #CASE BS2SX, BS2P
            T1SEC       CON     2500
            T9600       CON     240
            T19K2       CON     110
            T38K4       CON     45
        #CASE BS2PX
            T1SEC       CON     2500
            T9600       CON     396
            T19K2       CON     188
            T38K4       CON     84
    #ENDSELECT
    
    ' -----[noparse][[/noparse] I/O Pin Assignments ]-------------------------------------------------
    
    PwmPal          PIN 0       ' PWMPAL serial I/O
    Pwm1            PIN 12      ' PWMPAL PWM 1 output
    Pwm2            PIN 13      ' PWMPAL PWM 2 output
    Pwm3            PIN 14      ' PWMPAL PWM 3 output
    Pwm4            PIN 15      ' PWMPAL PWM 4 output
    
    ' -----[noparse][[/noparse] Constants: PWMPAL ]-----------------------------------------
    
    PwmBaud         CON T38K4       ' 38400 baud
    AllSwCtrl       CON %00000000   ' all PWM channels set to software control
    AllHwCtrl       CON %00001111   ' all PWM channels set to hardware control
    AllDisabled     CON %00000000   ' all PWM channels disabled
    AllEnabled      CON %11110000   ' all PWM channels enabled
    PwmInit         CON AllSwCtrl | AllDisabled
    AllCtrs         CON %00001111   ' all counter inputs enabled
    ...
        ' Disable all PWM channels.
        SEROUT PwmPal, PwmBaud, [noparse][[/noparse] "!PWMM0" ]
        ' Set all PWM channels to s/w control, disabled.
        SEROUT PwmPal, PwmBaud, [noparse][[/noparse] "!PWMSS", PwmInit ]
        ' Set on-time to 50 msec, off-time to 450 msec (2 Hz, 10% duty cycle).
        tOn = 40 * 50
        tOff = 40 * 450
        GOSUB SetPwm
    ...
    SetPwm:
        FOR chan = 1 TO 4
            SEROUT PwmPal, PwmBaud, [noparse][[/noparse] "!PWMM", "0" + chan,
                tOn.LOWBYTE, tOn.HIGHBYTE, tOff.LOWBYTE, tOff.HIGHBYTE ]
        NEXT
        SEROUT PwmPal, PwmBaud, [noparse][[/noparse] "!PWMSS", AllSwCtrl | AllEnabled ]
        RETURN
    ...
    
    
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2009-04-08 17:44
    Try using 9600 to see if that changes anything. At the very least it will rule out one possibility. When new commands are sent to the PWMPAL there is a brief interruption of the PWM output...not sure this is what you're seeing though.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Engineering
  • TWRackersTWRackers Posts: 33
    edited 2009-04-09 03:09
    Okay, I've tried both 9600 and 19200 baud instead of 38400, and the behavior is the same, namely one channel (channel 1 I believe) will drift out of phase with the other three, and the rate of drift will change from one startup to the next. I don't see any evidence without scoping the signals that the oddball channel's rate changes once it's started, only that it seems to start up at a slightly different rate from the others and stays there. The only thing left to try (tomorrow) is to swap out the PWMPAL chip with my spare one.
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2009-04-09 22:05
    Are you running all four channels at the same 2 Hz frequency with a 10% duty cycle? If so it may just be that you’re trying to use a frequency for which that duty cycle isn’t stable. You won’t get the full 0-100% duty cycle control through the entire frequency range of the PWMPAL as per the documentation. You didn’t post your full code so I didn’t bother trying to determine what was happening, but I suspect this is the case. Once Tech Support has your code set up I will have a look at it. Take care.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Engineering
  • TWRackersTWRackers Posts: 33
    edited 2009-04-09 23:12
    I did post the entire portion of the code which pertains to the PWMPAL. And there's no other code that's accidentally talking to the PWMPAL's serial input or the I/O pins it uses. I will post the entire code this evening before 5 PM PDT (before tech support goes home).

    What do you mean by "unstable"? I know there will be some frequencies and duty cycles that can't be precisely achieved, but any that can be should be stable (i.e. not changing with time). There's nothing that I can see in the PWMPAL documentation that implies that there are "unstable" frequencies or duty cycles.

    Okay, if you look at the code snippet above, you see I load the on-time registers with 40 * 50 or 2000. 2000 * 25 usec = 50000 usec = 50 msec. Exactly. The off-time is 40 * 450 or 18000. 18000 * 25 usec = 450000 usec = 450 msec. Exactly. Total period is 500 msec -> 2 Hz. Duty cycle is 50 msec / ( 50 + 450 ) msec = 0.1 = 10%. Exactly.

    So what's so unstable (or unreachable) about 2 Hz at 10% duty cycle? And why does it affect only one channel? The other three are in precise (to the eye) lock step.

    Post Edited (TWRackers) : 4/9/2009 11:49:41 PM GMT
  • TWRackersTWRackers Posts: 33
    edited 2009-04-09 23:49
    Okay, here's the full code.

    ' {$STAMP BS2sx}
    ' {$PBASIC 2.5}
    
    ' -----[noparse][[/noparse] Constants ]-------------------------------------------------------
    
    #SELECT $stamp
        #CASE BS2, BS2E, BS2PE
            T1SEC       CON     1000
            T9600       CON     84
            T19K2       CON     32
            T38K4       CON     6
        #CASE BS2SX, BS2P
            T1SEC       CON     2500
            T9600       CON     240
            T19K2       CON     110
            T38K4       CON     45
        #CASE BS2PX
            T1SEC       CON     2500
            T9600       CON     396
            T19K2       CON     188
            T38K4       CON     84
    #ENDSELECT
    
    #DEFINE TRACE
    
    ' -----[noparse][[/noparse] I/O Pin Assignments ]-------------------------------------------------
    
    PwmPal          PIN 0       ' PWMPAL serial I/O
    Alt2M           PIN 8       ' PWMPAL counter 1 input (alt 2 main)
    Alt2A           PIN 9       ' PWMPAL counter 2 input (alt 2 apogee)
    Alt1M           PIN 10      ' PWMPAL counter 3 input (alt 1 main)
    Alt1A           PIN 11      ' PWMPAL counter 4 input (alt 1 apogee)
    Pwm1            PIN 12      ' PWMPAL PWM 1 output
    Pwm2            PIN 13      ' PWMPAL PWM 2 output
    Pwm3            PIN 14      ' PWMPAL PWM 3 output
    Pwm4            PIN 15      ' PWMPAL PWM 4 output
    
    ' -----[noparse][[/noparse] Constants: PWMPAL ]-----------------------------------------
    
    'PwmBaud         CON T38K4       ' 38400 baud
    PwmBaud         CON T19K2       ' 19200 baud
    'PwmBaud         CON T9600       ' 9600 baud
    AllSwCtrl       CON %00000000   ' all PWM channels set to software control
    AllHwCtrl       CON %00001111   ' all PWM channels set to hardware control
    AllDisabled     CON %00000000   ' all PWM channels disabled
    AllEnabled      CON %11110000   ' all PWM channels enabled
    PwmInit         CON AllSwCtrl | AllDisabled
    AllCtrs         CON %00001111   ' all counter inputs enabled
    PwmTO           CON T1SEC * 1   ' 1 second timeout
    
    ' -----[noparse][[/noparse] Variables ]-------------------------------------------------------
    
    chan            VAR Nib     ' strobe channel
    tOn             VAR Word    ' on time, 25 usec per unit
    tOff            VAR Word    ' off time, 25 usec per unit
    errCd           VAR Nib     ' error code
    charIn          VAR Byte
    onState         VAR Bit
    
    ' -----[noparse][[/noparse] Initialization ]-------------------------------------------------
    
    Start:
        ' Splash text.
        #IF TRACE #THEN
        DEBUG "PWMPAL / Strobe Ground Test Software, v3.0", CR
        DEBUG "Written Apr 2009 by Thomas W. Rackers, Ph.D.", CR
        #ENDIF
    
        ' Set on-state to 0.
        onState = 0
        GOSUB StrobeOff
    
        ' Disable all PWM channels.
        SEROUT PwmPal, PwmBaud, [noparse][[/noparse] "!PWMM0" ]
        ' Set all PWM channels to s/w control, disabled.
        SEROUT PwmPal, PwmBaud, [noparse][[/noparse] "!PWMSS", PwmInit ]
        ' Read back status byte to verify PWMPAL is working.
        SEROUT PwmPal, PwmBaud, [noparse][[/noparse] "!PWMGS" ]
        SERIN PwmPal, PwmBaud, PwmTO, NoResp, [noparse][[/noparse] charin ]
        IF charIn <> PwmInit THEN GOTO BadResp
    
        #IF TRACE #THEN
        DEBUG "Running.", CR
        #ENDIF
    
    ' -----[noparse][[/noparse] Main Code ]----------------------------------------------------
    
    Main:
    
        GOSUB StrobeOn
        #IF TRACE #THEN
        DEBUG "Strobe ON.", CR
        #ENDIF
        STOP
    
    StrobeOff:
        onState = 0
        SEROUT PwmPal, PwmBaud, [noparse][[/noparse] "!PWMM0" ]
        RETURN
    
    StrobeOn:
        onState = 1
        tOn = 40 * 50
        tOff = 40 * 450
        GOSUB SetPwm
        RETURN
    
    SetPwm:
        FOR chan = 1 TO 4
            SEROUT PwmPal, PwmBaud, [noparse][[/noparse] "!PWMM", "0" + chan,
                tOn.LOWBYTE, tOn.HIGHBYTE, tOff.LOWBYTE, tOff.HIGHBYTE ]
        NEXT
        PAUSE 1000
        SEROUT PwmPal, PwmBaud, [noparse][[/noparse] "!PWMSS", AllSwCtrl | AllEnabled ]
        RETURN
    
    NoResp:
        #IF TRACE #THEN
        DEBUG "PWMPAL not responding, stopping.", CR
        #ENDIF
        STOP
    
    BadResp:
        #IF TRACE #THEN
        DEBUG "PWMPAL bad response, stopping.", CR
        #ENDIF
        STOP
    
        END
    
    
  • TWRackersTWRackers Posts: 33
    edited 2009-04-10 00:17
    It looks like I have found a fix to this problem. I'm running the system now to see if the four channels remain in sync for at least 15 minutes. I've revised the "SetPwm" subroutine as follows:

    SetPwm:
        FOR chan = 1 TO 4
            SEROUT PwmPal, PwmBaud, [noparse][[/noparse] "!PWMM", "0" + chan,
                tOn.LOWBYTE, tOn.HIGHBYTE, tOff.LOWBYTE, tOff.HIGHBYTE ]
            PAUSE 100    ' non-critical addition
        NEXT
        PAUSE 1000
        ' BEGIN critical addition to code
        SEROUT PwmPal, PwmBaud, [noparse][[/noparse] "!PWMSP", %11110000 ]    ' %00000000 works just as well
        PAUSE 100
        ' END critical addition to code
        SEROUT PwmPal, PwmBaud, [noparse][[/noparse] "!PWMSS", AllSwCtrl | AllEnabled ]
        RETURN
    
    



    The PWMPAL seems to want the starting phases of the four channels to be set explicitly, hence the "SP" command.
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2009-04-10 16:55
    Hello,

    Regardless of how exact your calculations are there are only so many clock cycles available to process each channel. Any number of factors can affect the timing for that channel including settings for other channels, which is partly why all duty cycle ranges are not available for all frequencies. When serial commands are sent the signal is also briefly interrupted. The reason I asked for complete code is that I cannot put what you posted into the editor and run it. So in that sense it is incomplete. With the code I would have been able to evaluate what the code wanted versus the results. It seems you have found your answer though so I will consider this issue solved. Take care.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Engineering
  • TWRackersTWRackers Posts: 33
    edited 2009-05-04 17:40
    Okay, the other day I was testing out my BS2sx/PWMPAL system, and I noticed something else odd going on. My test program displays a prompt on the Debug console, waits for the user to enter a single key choice, sets the four output channels of the PWMPAL to the same on/off times (recall each channel is driving a high-power LED through a MOSFET), then redisplays the prompt, and the cycle repeats until you power down.

    What I saw that surprised me was that the LEDs flickered during the fraction of a second that the Stamp was redisplaying the prompt. I thought the outputs of the PWMPAL were supposed to operate independently of whatever the Stamp was doing, as long as the Stamp wasn't talking to the PWMPAL or changing any of the pins the two devices share.

    I'm attaching the code which I was running.
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2009-05-04 17:54
    Hello,

    You can optimize your code considerably…for example, for each case you print:

    DEBUG CLREOL, " selected... "

    This occurs for every line…instead you should print it immediately following the DEBUGIN statement so you can remove so many instances of it. As for your flicker problem….I can’t see where the menu gets re-displayed…it seems like the cursor just moves back to the original position. If this is the case, then the outputs would have only been affected by having just set them, unless I am not understanding what you mean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Engineering
  • TWRackersTWRackers Posts: 33
    edited 2009-05-04 18:10
    Chris Savage (Parallax) said...
    Hello,

    You can optimize your code considerably…for example, for each case you print:

    DEBUG CLREOL, " selected... "

    This occurs for every line…instead you should print it immediately following the DEBUGIN statement so you can remove so many instances of it. As for your flicker problem….I can’t see where the menu gets re-displayed…it seems like the cursor just moves back to the original position. If this is the case, then the outputs would have only been affected by having just set them, unless I am not understanding what you mean.
    The optimization isn't critical because (1) this was a test program to be used only a few times, and (2) the CASE ELSE section does not have the source line above.

    You are correct, most of the text is not re-displayed upon each pass. I wrote that test code weeks ago, so I hadn't looked closely at it since then. Now that I do look at it, what I may be seeing is flickering caused by the channels being reconfigured while they're still running. What I will do is turn off the outputs before I reconfigure them, then turn them back on.
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2009-05-05 18:44
    The reason I offered up the optimization while trying to help you with your original problem is that sometimes a small problem can be easily overlooked in a program with a lot of duplicated code. You start looking at each line and after the first 10 it all starts to look the same. Optimizing (condensing) can often make it easier to spot errors. But I think you plan is the appropriate one. It seems you’re modifying the values while they’re active, so you can either have the flicker, or you can briefly disable the outputs. Take care.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Engineering
  • hitswarehitsware Posts: 156
    edited 2009-05-05 20:56
    ' I don't know if this is the same glitch, but if you listen to
    ' the output certain notes stutter (double) AT TIMES but not always.
    ' At an octave higher the problem is gone.
    ' {$STAMP BS2}
    SEROUT 0,6,[noparse][[/noparse]"!PWMSS",240]
    x VAR Nib:y VAR Nib:c VAR Byte:n VAR Nib:z VAR Byte
    dt VAR Word:d1 VAR Byte:d2 VAR Byte
    play
    FOR x=0 TO 3:FOR y=0 TO 3
    LOOKUP x,[noparse][[/noparse]20,24,18,27],c:LOOKUP y,[noparse][[/noparse]2,4,3,4],n
    dt=14544/(c*n):d1=dt//256:d2=dt/256 ' change 14544 to 7272 to raise octave
    SEROUT 0,6,[noparse][[/noparse]"!PWMM1",d1,d2,d1,d2] ' play note listen to PWMPAL channel 1
    PAUSE 300
    NEXT:NEXT:GOTO play
  • TWRackersTWRackers Posts: 33
    edited 2009-05-05 21:02
    I suspect it is the same effect, both of us are changing the on/off registers while the output is running.
  • hitswarehitsware Posts: 156
    edited 2009-05-05 21:12
    But that shouldn't happen.
    That's the whole point of the device.
    AND for some reason at higher frequencies it doesn't.
    I'm only using squarewaves, so it's not the unusable freq/dutycycle.
    At one time I thought I had it fixed by proper settings on the 'status bytes',
    but ????
  • TWRackersTWRackers Posts: 33
    edited 2009-05-05 21:37
    I believe the PWMPAL is a dedicated microprocessor which is generating the output signals directly, rather than loading values into oscillator circuits. So any comms to the device, including changing the timing registers, would momentarily disrupt the outputs. And how they're disrupted is probably hard to predict. I think the only way to prevent it is to turn off the outputs, then change the timing registers, then turn the outputs back on. I haven't had a chance to try it, but it makes sense.
  • hitswarehitsware Posts: 156
    edited 2009-05-05 21:41
    >So any comms to the device, including changing the timing registers,
    >would momentarily disrupt the outputs.

    Then you'd be blowing mosfets like a bad dog trying to do
    something like a H bridge [noparse]:([/noparse]
  • TWRackersTWRackers Posts: 33
    edited 2009-05-05 23:01
    I haven't used an H bridge before but I think I understand the principle (four gates driven in pairs 180 degrees out of phase). If that's a correct interpretation, I'd drive one with a single output, direct and inverted, so the phases would be guaranteed to be the same.
  • hitswarehitsware Posts: 156
    edited 2009-05-08 02:31
    you have to remember the need for 'deadtime'
    (all devices off) elst the dreaded short between rails
Sign In or Register to comment.