Shop OBEX P1 Docs P2 Docs Learn Events
PWM 20Khz with Spin — Parallax Forums

PWM 20Khz with Spin

lardomlardom Posts: 1,659
edited 2014-05-26 19:23 in Propeller 1
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:
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

  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2014-05-26 16:54
    lardom wrote: »
    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:
      repeat                         ' Repeat PWM signal
        phsa := -tHa              ' Set up the pulse
        t += tC                     ' Calculate next cycle repeat
        waitcnt(t)                  ' Wait for next cycle
    

    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 :) (think Crocodile Dundee)

    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.
  • kuronekokuroneko Posts: 3,623
    edited 2014-05-26 18:38
    lardom wrote: »
    Pwm driver:
    PUB Start
    
        Stop
        cog := cognew(TestPwm, @stack) 
    
    PUB Stop                                                   
    
        If cog 
          cogstop(cog~ - 1)
    
    These two methods don't match. You want cog := cognew(TestPwm, @stack) +1
  • lardomlardom Posts: 1,659
    edited 2014-05-26 18:46
    Peter, I've seen some of the amazing stuff you've done so saying 20Khz is "overkill" is a compliment. You played a major part in helping me to complete my first big project. Thanks.
    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?
  • kuronekokuroneko Posts: 3,623
    edited 2014-05-26 19:00
    lardom wrote: »
    kuroneko, I first commented (+1) because the code still ran so I deleted it. Why do I need it?
    The stop method is written that way (it's not important for running).

    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?
  • lardomlardom Posts: 1,659
    edited 2014-05-26 19:23
    kuroneko, I get it now. Thanks.
Sign In or Register to comment.