OBEX update: PWM_32_v2
Beau Schwabe
Posts: 6,576
A new object has been added to the OBEX that allows independent PWM control on up to 32 I/O Channels.
This object requires 1 COG and has a pulse resolution of 8.15us
Features include:
- Phase Sync between multiple PWM pins
- 0% to 100% Duty control
- Hobby Servo control
- PWM control
http://obex.parallax.com/objects/467/
DEMO code example
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 8/7/2009 3:30:28 AM GMT
This object requires 1 COG and has a pulse resolution of 8.15us
Features include:
- Phase Sync between multiple PWM pins
- 0% to 100% Duty control
- Hobby Servo control
- PWM control
http://obex.parallax.com/objects/467/
DEMO code example
PUB DEMO_Example | DutyCycle
''-------- This Block Starts the PWM Object ----------
PWM.Start '' Initialize PWM cog
''-------- This Block sets a Standard servo on Pin 0 to it's center Position ----------
PWM.Servo(0,1500) '' Define Pin0 with a standard center position
'' servo signal
''-------- This Block creates a 3-Phase 60Hz square wave on Pins 1,2, and 3 -----------
PWM.Duty(1,50,16665) ''Create a 60Hz 50% duty cycle on Pin1
PWM.Duty(2,50,16665) ''Create a 60Hz 50% duty cycle on Pin2
PWM.Duty(3,50,16665) ''Create a 60Hz 50% duty cycle on Pin3
PWM.PhaseSync(1,2,5555) ''Phase Sync Pin2 to Pin1 with a Phase leading by 120 Deg
PWM.PhaseSync(2,3,5555) ''Phase Sync Pin3 to Pin2 with a Phase leading by 120 Deg
''-------- This Block creates a PWM pulse on pin 4 with a duty ratio of 1:10 -----------
PWM.PWM(4,1,10) '' Creates a pulse with 1 On-Time unit and 10 Off-Time
'' units on Pin 4
''-------- This Block creates a speed up/down Motor test on Pin7 -----------
repeat
repeat DutyCycle from 0 to 100
PWM.Duty(7,DutyCycle,5000) '' Ramp Duty cycle up from 0 to 100
repeat 10000
repeat 1000000 '' Hold at 100% for a little bit
repeat DutyCycle from 100 to 0
PWM.Duty(7,DutyCycle,5000) '' Ramp Duty cycle down from 100 to 0
repeat 10000
repeat 1000000 '' Hold at 0% for a little bit
'-------- Extra Stuff -----------
'' PWM.StateMode(Pin,State)
' Used behind the scenes but available to the user, this function allows you to
' Enable/Dissable a pin... If State = 0 pin is Disabled, if State = 1 pin is Enabled
'' DutyMode(Pin,Mode)
' Also used behind the scenes but available to the user, this function allows you to
' Force the output state of a pin to a HIGH or a LOW regardless of what Ton or Toff is
' telling the pin to do . This is especially useful when creating a pulse that needs to
' cover the full duty range of 0% to 100%
'
' If Mode = 1 then the Pin will be forced HIGH ; If Mode = 2 then the Pin will be forced
' LOW ; Any other value for Mode, causes the pin to resume it's default state which will
' follow what Ton and Toff are telling it to do.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 8/7/2009 3:30:28 AM GMT

Comments
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
My Prop Info&Apps: ·http://www.rayslogic.com/propeller/propeller.htm
Completely different... The Servo32 object provides better resolution, so if you are mainly using Servo's I would use that. The PWM offers more features that would be applicable to motor speed control, Power switching applications, etc.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
{{ ''******************************************* ''* Fire Fly Object V1.0 * ''* Author: Beau Schwabe * ''* Copyright (c) 2009 Parallax, Inc. * ''* See end of file for terms of use. * ''******************************************* Schematic for Each LED (aka FireFly): 330 I/O ──── GND LED LED = Yellow or Green }} CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 Number_of_Flies = 32 OBJ PWM : "PWM_32_v1.spin" VAR byte fly,i[noparse][[/noparse]Number_of_Flies],s[noparse][[/noparse]Number_of_Flies] long random,w[noparse][[/noparse]Number_of_Flies] PUB MainLoop|t1 LightTest random := $1234_5678 ''-------- This Block Starts the PWM Object ---------- PWM.Start '' Initialize PWM cog repeat fly from 0 to Number_of_Flies-1 s[noparse][[/noparse]fly]++ i[noparse][[/noparse]fly] := fly * 3 repeat repeat fly from 0 to Number_of_Flies-1 if w[noparse][[/noparse]fly] <> 0 w[noparse][[/noparse]fly] -= 1 else i[noparse][[/noparse]fly] += s[noparse][[/noparse]fly] if i[noparse][[/noparse]fly] == 100 s[noparse][[/noparse]fly] := -1 if i[noparse][[/noparse]fly] == 0 s[noparse][[/noparse]fly] := +1 if i[noparse][[/noparse]fly] == 0 w[noparse][[/noparse]fly] := 200+((?random & $FF)*3000)/$FF PWM.Duty(fly,i[noparse][[/noparse]fly],10000) waitcnt(clkfreq/600+cnt) PUB LightTest|_i '' Light test ALL blink repeat 3 repeat _i from 0 to Number_of_Flies-1 dira[noparse][[/noparse]_i]~~ outa[noparse][[/noparse]_i]~~ waitcnt(clkfreq/15+cnt) repeat _i from 0 to Number_of_Flies-1 dira[noparse][[/noparse]_i]~ outa[noparse][[/noparse]_i]~ waitcnt(clkfreq/15+cnt) CON {{ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ TERMS OF USE: MIT License │ ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │ │files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │ │modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│ │is furnished to do so, subject to the following conditions: │ │ │ │The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│ │ │ │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │ │WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │ │COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │ │ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ }}▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 6/15/2009 7:12:17 PM GMT
First - thank you for the object.
I am using the object, specifically the PWM function. During my testing I wonder if I found a bug. Can you check me here?
My code is a simple call to the PWM method. This is just test code at the moment, so nothing else fancy happening. A byte variable will replace the temporary t0. The thought is 0 is off and 255 is full intensity of the LED.
I think this will work based on the following of the PWM object:
PUB PWM(Pin,OnTime,OffTime) '' Pin = 0 to 31 If OnTime == 0 '' An OnTime value of 0 forces a 0% Duty Cycle DutyMode(Pin,1) '' An OffTime value of 0 forces a 100% Duty Cycle If OffTime == 0 '' If OnTime & OffTime are both 0 then the pin is DutyMode(Pin,2) '' disabled. If OnTime ==0 and OffTime == 0 StateMode(Pin,0)The bug, I think, is that when t0 is 0 in my code, the LED is on/100% duty cycle and I think it should be off. Similarly, when t0 is 255 the LED is off, 0% duty cycle and it should be on.
Based on the comments in the below function, I think the "1" and "2" are swapped in the PUB PWM above for the zero testing of the on/off time.
PUB DutyMode(Pin,Mode) '' Pin = 0 to 31 ARG0 := Pin '' If Duty = 0 then the pin is in it's default state ARG1 := Mode '' If Duty = 1 then the pin is forced HIGH ; 100% command := DutyOverRide '' If Duty = 2 then the pin is forced LOW ; 0% repeat until command == 0Bug, miswritten comments, problem with my understanding?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, 3.0" LCD Composite video display, eProto for SunSPOT
www.tdswieter.com
Post Edited (Timothy D. Swieter) : 8/2/2009 7:18:04 AM GMT
First, after my previous post I noticed that the Duty method "1" and "2" of the Duty method set as I suspect they should be, which is opposite the PWM method which makes me think the PWM method is wrong int he PWM_32_v1 object.
Ok - the other potential bug. I created a simple program to use the object, the code is as follows:
con _clkmode = xtal1 + pll16x 'Use the PLL to multiple the external clock by 16 _xinfreq = 5_000_000 'An external clock of 5MHz. is used (80MHz. operation) obj PWM : "PWM_32_v1.spin" pub main | t0 PWM.Start repeat repeat t0 from 0 to 255 PWM.PWM(20, t0, (255 - t0)) PauseMSec(10) repeat t0 from 255 to 0 PWM.PWM(20, t0, (255 - t0)) PauseMSec(10) PRI PauseMSec(Duration) waitcnt(((clkfreq / 1_000 * Duration - 3932) #> 381) + cnt) returnWhen the above code executes, the LEDs is stuck on or off (depending on what way the PWM method is setup). I expected this routine to be cycling the LED to full brightness and then back down to off, repeating indefinitely. It appears that perhaps the duty on/off times are set by the first pass of the repeat loop, when t0 = 0, but then no duty on/off times are set after that. Maybe the PWM is a set it and forget it function, but keeps that same on/off times?
I can get the Duty method working with the ramp up/down:
repeat repeat t0 from 0 to 100 PWM.Duty(20, t0, 5000) PauseMSec(20) repeat t0 from 100 to 0 PWM.Duty(20, t0, 5000) PauseMSec(10)With the Duty method as it currently written it is 0 to 100%. I am working with bytes, not percentages, so I would like to be able to set the range of values or perhaps use the PWM as I described in the other post, but my ideas are not working yet. What do you think regarding the two potential bugs/pitfalls? Should I use duty and covert bytes to a percentage?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, 3.0" LCD Composite video display, eProto for SunSPOT
www.tdswieter.com
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, 3.0" LCD Composite video display, eProto for SunSPOT
www.tdswieter.com
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, 3.0" LCD Composite video display, eProto for SunSPOT
www.tdswieter.com
Good Job for finding the errors! I have updated the OBEX and the errors you were observing should be fixed now.
Revision History:
Version 1.0 - (05/01/2009) initial release
Version 2.0 - (08/06/2009) bug/error fix:
1)Time on/off mode swapped in PWM function
2)locked I/O states when returning from 0% or 100% Duty Cycle modes
to 'normal' 1% to 99% Duty Cycle modes.
BTW) I would have video of the fireflies, but my camera doesn't do it justice in the dark ... you can run the FireFly Program on the Propeller Demo Board and get an idea (after a small initialization routine) of what it does.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, 3.0" LCD Composite video display, eProto for SunSPOT
www.tdswieter.com