PWM 20Khz with Spin
lardom
Posts: 1,659
I just got an LED to go from dim to bright at 20Khz in 20 stages with Spin. Spin is great! The pwm driver is based on an object written by W.G.Marshall. I have no scope so if flaws are found I'll appreciate it.
Top object:
Pwm driver:
Top object:
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
OBJ
CPWGV : "CtrPwmFor 20Khz"
PUB main | p
CPWGV.Start
repeat
repeat p from 0 to 4_000 step 200
CPWGV.Main (p)
waitcnt(clkfreq/20+cnt)
repeat p from 4_000 to 0 step 200
CPWGV.Main (p)
waitcnt(clkfreq/20+cnt)
Pwm driver:
VAR
long tHa, stack[10]
word cog
PUB Start
Stop
cog := cognew(TestPwm, @stack)
PUB Stop
If cog
cogstop(cog~ - 1)
PUB main(j)
tHa := j
PUB TestPwm | tc, t, tInc
ctra[30..26] := %00100 ' Configure Counter A to NCO
ctra[5..0] := 1 ' Set counter output signal to P1
frqa := 1 ' Add 1 to phsa with each clock cycle
dira[1]~~ ' P1 → output
tInc := 200 ' Determine time increment
tC := 4_000 ' Use time increment to set up cycle time
tHa := tInc ' define tHa
t := cnt ' Mark counter time
repeat ' Repeat PWM signal
phsa := -tHa ' Set up the pulse
t += tC ' Calculate next cycle repeat
waitcnt(t) ' Wait for next cycle

Comments
All that just to dim an LED, only one LED?. Plus 20kHz is over the top for this application too and LEDs are quite happy to run at much lower frequencies, at least a couple of hundred Hertz though to reduce flicker. Sorry
I dedicate a cog to PWM too when I need but I get up to 32 8-bit channels at 4.76kHz with it but this does not use the counter at all but rather a tight PASM loop built into Tachyon, and a wave table. With it you can also modify the waveform, at least so that some channels can run at higher frequencies with less resolution, in fact over 122kHz if you only want 16 levels.
I'll combine it with a potentiometer to control DC motors. The LED is my basic testing device. I also recently learned to use a mosfet @ 1Khz for current control so now I want to know if I can get one to work @ 20Khz.
In addition, I am going to have to learn PASM because I want to try building an AM transmitter/receiver pair. I'll take it step by step.
kuroneko, I first commented (+1) because the code still ran so I deleted it. Why do I need it?
Imagine you get no cog (all busy), IOW cog == -1 then you call stop which then kills cog 6 (we pass the if because cog is <> 0 and then stop cog -2 which is the same as 6 because only the least 3 bits are important). So in order to make the if cog work we translate cog IDs 0..7 to 1..8 (-1 would give us 0 == FALSE which is OK) by adding 1 to cognew's result. Another example, you get cog == 4, calling stop then kills cog 3 instead. See the problem here?