Shop OBEX P1 Docs P2 Docs Learn Events
PWM motor control — Parallax Forums

PWM motor control

woody363woody363 Posts: 7
edited 2011-04-30 12:23 in Propeller 1
I think I am misunderstanding some features of the timers and getting some outputs that I am struggling to explain...

I am trying to control a 4 phase stepper motor with variable speed and voltage, sending a PWM signal alternately to the four outputs. Im testing the outputs using LEDs for now and havent been able to control the output signal to alternating pins as I am looking for. when pressing the button: very occasionally it gives the pwm pulses to alternating pins as desired, but more often does nothing or gives short flashes and sometimes gets 'stuck' on one pin and needs resetting.

can anyone tell me what Ive missed? All the other posts seem to talk about cogging, but I cant see how it would help here.

thanks guys,
Woody


the code im using is as follows... (sorry it probably has some unnecessary lines since I have been modifying the examples)
CON

  _clkmode        = xtal1 + pll16x           ' Feedback and PLL multiplier
  _xinfreq        = 5_000_000                ' External oscillator = 5 MHz

  LEDs_START      = 0                        ' Start of I/O pin group for on/off signals
  LEDs_END        = 15                       ' End of I/O pin group for on/off signals
  PUSHBUTTON      = 18

VAR
   long speed

PUB Motor                         ' Main method

  '' Sends on/off (3.3 V / 0 V) signals at approximately 2 Hz. 
  dira[LEDs_START..LEDs_END]~~               ' Set entire pin group to output
   speed := 8
  repeat                                     ' Endless loop

    if ina[16] == 1
      speed := speed + 10
      !outa[4]
      
     
    if ina[17] == 1
     speed :=  speed - 10             ' Change the state of pin group
    
    if ina[19] == 1                          ' If pushbutton pressed
      
        PWM(8,clkfreq/speed + cnt)
        PWM(9,clkfreq/speed + cnt)
        PWM(10,clkfreq/speed + cnt)
        PWM(11,clkfreq/speed + cnt)
    else                                     ' If pushbutton not pressed
      waitcnt(clkfreq / 20 + cnt)            ' Wait 1/20 second -> 10 Hz

      
PUB PWM(PIN, Delay)| tc, tHa, t

  ctra[30..26] := %00100                     ' Configure Counter A to NCO
  ctra[5..0] := PIN
  frqa := 1
  dira[4]~~

  tC := clkfreq/10000                              ' Set up cycle and high times
  tHa := clkfreq/10000
  t := cnt                                   ' Mark counter time
  
  repeat Delay/cnt                               ' Repeat PWM signal
    phsa := -tHa                             ' Set up the pulse
    t += tC                                  ' Calculate next cycle repeat
    waitcnt(t)                               ' Wait for next cycle  
  'ctra[5..0] := 5                            'change output to different pin since i havent found off command yet
  'outa[PIN]:=0
  waitcnt(Delay)
  return  

Comments

  • MagIO2MagIO2 Posts: 2,243
    edited 2011-04-28 15:32
    I think you should not try to build all functionality in one try. Think in modules, build them, test them separately and then put them together.

    1. Your button-handling.
    A button handling routine has to take care of bouncing, otherwise you get strange behaviour.
    And it has to wait for a release of the button before it accepts the next button input - or an automatic repeat rate.

    2. Try to run the stepper without PWM.
    The stepper does not need PWM. Switching the outputs in the right sequence is the trick. This way you operate the stepper in so called full-step mode. Start slow. When you want speed you have to add ramping up and ramping down.

    What's the purpose of the PWM? You want to control the voltage but keep the motors running in full step mode (to increase torque when running on higher speed)? Or is the PWM for microstepping?

    Did you search for stepper in the forum? Recently we had threads dealing with stepper mototrs.
  • woody363woody363 Posts: 7
    edited 2011-04-29 14:58
    The PWM is purely for voltage control. I had a program for non pwm stepping and another for PWM of leds, this was my first attempt at combining the two which came with alot of garbage... I went through and removed and rewrote it and it now works as desired... Im also having some problems with "bouncing" as you mentioned which I will try and program in now, thanks for the post, here is the working code for reference...
    ''This code example is from Propeller Education Kit Labs: Fundamentals, v1.1.
    ''A .pdf copy of the book is available from www.parallax.com, and also through
    ''the Propeller Tool software's Help menu (v1.2.6 or newer).
    ''
    ''File: PushbuttonLedTest.spin
    ''Test program for the Propeller Education Lab "PE Platform Setup"
    
    CON     
    
      _clkmode        = xtal1 + pll16x           ' Feedback and PLL multiplier
      _xinfreq        = 5_000_000                ' External oscillator = 5 MHz
    
    VAR
       long speed
    
    PUB Motor                         ' Main method
    
      '' Sends on/off (3.3 V / 0 V) signals at approximately 2 Hz. 
      dira[LEDs_START..LEDs_END]~~               ' Set entire pin group to output
       speed := 1
      repeat                                     ' Endless loop
    
        if ina[16] == 1
          speed := speed + 10
          '!outa[4]
          
         
        if ina[17] == 1
         speed :=  speed - 10             
        
        if ina[19] == 1                          ' If pushbutton pressed
                            
            PWM(3,clkfreq/speed)            
            PWM(4,clkfreq/speed)           
            PWM(5,clkfreq/speed)           
            PWM(6,clkfreq/speed)                   
        else                                     ' If pushbutton not pressed
          waitcnt(clkfreq / 20 + cnt)            ' Wait 1/20 second -> 10 Hz
    
          
    PUB PWM(PIN, Delay)| tc, tHa, t
    
      ctra[30..26] := %00100                     ' Configure Counter A to NCO
      ctra[5..0] := PIN
      frqa := 1
      dira[4]~~
    
      tC := clkfreq/5000                              ' Set up cycle and high times
      tHa := clkfreq/10000
      t := cnt                                   ' Mark counter time
      
      repeat Delay/tC                               ' Repeat PWM signal
        phsa := -tHa                             ' Set up the pulse
        t += tC                                  ' Calculate next cycle repeat
        waitcnt(t)  
      return                   
    
    
  • MagIO2MagIO2 Posts: 2,243
    edited 2011-04-30 12:23
    An often seen pattern in propeller programs is that one COG is used as glue. It steers the other COGs, for example depending on user-input.

    In your case it could continuously check the input-buttons, only accepting an input in case the button has been released before .... only triggering the PWM if the previous cycle is done ...

    Another COG is waiting for a signal to run the series of PWM-calls. As a signal you can use a global variable, where the glue-COG sets a specific value and the PWM-COG clears that value after the job is done. This way the glue-COG can sync with it, if needed.

    For example you can start a COG which has a repeat loop around your 4 PWM-calls. Before the PWM-calls you only wait for the signal and after the PWM-calls you set the signal back to 0.
    Keep in mind that in this case you need to shift the DIRA definitions of the PINs that should be used by PWM-COG in front of the loop.

    And thank you for sharing your working code! It's always helpfull to not only show the problem but show the sollution as well.
Sign In or Register to comment.