Shop OBEX P1 Docs P2 Docs Learn Events
stepper motor time a bit off — Parallax Forums

stepper motor time a bit off

BitsBits Posts: 414
edited 2012-07-18 19:15 in Propeller 1
Below is the code that runs a stepper motor. When I compare the RPMs with a meter I am off slightly. What can I do to improve the time?

RPMs is calculated as
60_000 = msec to minute conversion
20 steps = 1 revolution whole stepping
40 steps = 1 revolution half stepping

60_000 / 40 = 1.5K 'half stepping here
For better resolution I take 1.5K * 100 but then make adjustment in motor object.
= 150_000 / rpms

main object calling the motor object
mot.Control(150_000 / StirSpeed,power) 

The Motor object
Pub Running(_time, _activate) 

  Dira[pin1..pin4]~~
  Time := _Time     
  activate := _activate 


  Repeat  
      IF Activate 
          outa[pin1..pin4] := halfSteps[coil := ++coil // 8]        
          waitcnt((clkfreq / 100_000) * Time + cnt)               
      Else
          outa[pin1..pin4] := $0000 

I think that the IF and Else statements are creating the lag in time. Is there a way to cancel this out?

Comments

  • JonnyMacJonnyMac Posts: 9,194
    edited 2012-07-18 15:08
    What you want to learn to do is create a synchronized delay loop. You do this by grabbing the time at the top of the loop and then offsetting from it; this allows you to control the loop timing. By getting cnt in the loop as you do you're not accounting for loop overhead.

    You may ultimately find yourself with something like this:
    pri run_stepper(delaypntr, flagpntr) | t, coil
    
      dira[M1..M4] := %1111                                 ' set coils to output state
      coil := 0                                             ' reset index
    
      t := cnt                                              ' sync timer
      repeat
        outa[M1..M4] := Half_Steps[coil]                    ' output step pattern
        coil := ++coil & %0111                              ' update step index
    
        if (long[flagpntr] == true)                         ' still running?
          waitcnt(t += long[delaypntr])                     ' yes, do the delay
        else
          quit                                              ' no, quit the cog 
    
      outa[M1..M4] := %0000                                 ' clear pins
      dira[M1..M4] := %0000
      
      cogstop(cogid)                                        ' unload the cog
    


    I would tend to want to pass a pointer to the timing value (calculated outside) and a pointer to a flag that allows the cog to unload itself. Of course, you have to start this with cognew.
    cognew(run_stepper(@delayustix, @runflag), @stack)
    
  • BitsBits Posts: 414
    edited 2012-07-18 15:22
    Thanks Johnny

    I used this appnote to solve the problem. Once I found out how many clock cycles it took I recalculated the constant with this


    mot.Control(145_325 / StirSpeed,power)
    Looking over your code I cant help but ask why you and others clear variables when they are cleared to began with.

    You called
    pri run_stepper(delaypntr, flagpntr) | t, coil
    
    
      dira[M1..M4] := %1111                                 ' set coils to output state
      coil := 0 
    

    Why clear "coil" when this will always be %0 on a new boot. Is it not a local variable?
    Thanks none the less for the help
  • msrobotsmsrobots Posts: 3,709
    edited 2012-07-18 15:40
    Bits,

    you are wrong there. The only 'local' variable initialised is RESULT.

    all other local variables are NOT initialised by spin but contain whatever is at that stack location from earlier use of that adress.

    Enjoy!

    Mike
  • photomankcphotomankc Posts: 943
    edited 2012-07-18 19:15
    Yep, I thought the same thing early on till I spent hours figureing out why a condition kept randomly being 'ignored'. Assuming that the variable was 0 when I entered the function was the reason.
Sign In or Register to comment.