odd PWMPAL behavior
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.
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
' {$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 Savage
Parallax Engineering
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Chris Savage
Parallax Engineering
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
' {$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 ENDSetPwm: 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 ] RETURNThe PWMPAL seems to want the starting phases of the four channels to be set explicitly, hence the "SP" command.
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
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.
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
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 Savage
Parallax Engineering
' 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
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 ????
>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]
(all devices off) elst the dreaded short between rails