November 22, 2024, 02:56:59 PM

News:

You can now use Vixen to program your Prop-1 and Prop-2 controllers!  Get started quickly and easily, without having to learn PBASIC.  Details in the Library forum.


Stepper control program request

Started by brand, November 16, 2007, 08:03:49 AM

Previous topic - Next topic

brand

November 16, 2007, 08:03:49 AM Last Edit: November 16, 2007, 08:07:17 AM by brand
Jon,
I finally have my prop 1 and am starting to work. Any help appreciated.
Proposed outline of task:

-2 photosensors input to P6 and P7
-pushbutton input P5
-stepper motor 12v, 7.5 deg,  approx 200 mA/phase. Outputs 0, 1, 2, 3  and Commons to V+.
-High power LED, constantly ON. (3Vdc  .35A)

The two photosensors actuate the stepper, 1 in fast speed continuous, the other for slow speed continous until sensor no longer sees objects. The pushbutton will operate the stepper for a 1-time-per-push to turn the stepper at slow speed for 30 degrees of rotation. At cycle end, everything just sits until one of the photosensors goes again active. The LED is an indicator so stays on constantly. I plan to use 13.5 V power supply to allow for the drop thru the Darlington to give stepper full 12 V to minimize current. Is there any way to source Vdd so I don't have to drop V+ from 13V down to 3 V for the LED and pull this current thru the 2803 as well as stepper current? An outline of a program to do all this would really help.
Thank you!

JonnyMac

November 16, 2007, 11:24:58 AM #1 Last Edit: November 16, 2007, 12:22:16 PM by JonnyMac
Questions:

1) What is the output of the photo-sensor?  I'm betting open-collector, but I need to know for sure.
2) How many degrees per step? Or, how many steps per revolution?

On your LED: Use V+ with an appropriate resistor to drop the voltage, that way you can control the LED and stepper with the power switch.  The resistor would be about 30 ohms, 5watts.  This will drop ~10 volts across the resistor and limit the current to ~330 mA.

Jon McPhalen
EFX-TEK Hollywood Office

brand

Jon,
  Sensors are NPN , 5-24Vdc, open collector. (EE-SX770-A  and EE-SX870-A)
The stepper is 7.5 deg/rot = 48 steps/rev so 12 steps per 30 deg.
Thanks.

JonnyMac

Here you go -- I think this should get you started.

When the sensors on P7 and P6 are active the motor will move fast; when P7 clears and P6 is still active the motor will go slow; when both sensors clear the motor will stop and you can manually advance the motor.

Note: At the moment I don't have a convenient way to test this, so please proceed carefully.


' =========================================================================
'
'   File...... Stepper_Control.BS1
'   Purpose...
'   Author.... Jon Williams, EFX-TEK
'              Copyright (c) 2007 EFX-TEK
'   E-mail.... jwilliams@efx-tek.com
'   Started...
'   Updated...
'
'   {$STAMP BS1}
'   {$PBASIC 1.0}
'
' =========================================================================


' -----[ Program Description ]---------------------------------------------


' -----[ Revision History ]------------------------------------------------


' -----[ I/O Definitions ]-------------------------------------------------

SYMBOL  Photo1          = PIN7                  ' SETUP = UP
SYMBOL  Photo2          = PIN6                  ' SETUP = UP
SYMBOL  Manual          = PIN5                  ' N.O. between P5.W/P5.R

SYMBOL  Coil4           = PIN3
SYMBOL  Coil3           = PIN2
SYMBOL  Coil2           = PIN1
SYMBOL  Coil1           = PIN0


' -----[ Constants ]-------------------------------------------------------

SYMBOL  Detect          = 0                     ' activ-low photo sensor
SYMBOL  NoDetect        = 1

SYMBOL  Pressed         = 1                     ' for manual trigger
SYMBOL  NotPressed      = 0


' -----[ Variables ]-------------------------------------------------------

SYMBOL  sensors         = B2                    ' photo sensor inputs
SYMBOL  idx             = B3                    ' loop counter
SYMBOL  phase           = B4                    ' new phase data
SYMBOL  stpIdx          = B5                    ' step pointer


' -----[ Initialization ]--------------------------------------------------

Reset:
  PINS = %00000011                              ' set to first step
  DIRS = %00001111                              ' make coils outputs


' -----[ Program Code ]----------------------------------------------------

Main:
  sensors = PINS ^ %11111111 / 64               ' isolate sensors
  BRANCH sensors, (M_Stop, M_Slow, Main, M_Fast)

M_Stop:
  IF Manual = NotPressed THEN Main
  FOR idx = 1 TO 12
    GOSUB Step_Fwd
    PAUSE 20                                    ' adjust for speed
  NEXT

M_Slow:
  GOSUB Step_Fwd
  PAUSE 20                                      ' adjust for slow speed
  GOTO Main

M_Fast:
  GOSUB Step_Fwd
  PAUSE 5                                       ' ajust for fast speed
  GOTO Main


' -----[ Subroutines ]-----------------------------------------------------

' Turn stepper clockwise one full step

Step_Fwd:
  stpIdx = stpIdx + 1 // 4                      ' point to next step
  GOTO Do_Step

' -------------------------------------------------------------------------

' Turn stepper counter-clockwise one full step

Step_Rev:
  stpIdx = stpIdx + 3 // 4                      ' point to previous step
  GOTO Do_Step

' -------------------------------------------------------------------------

' Read new step data and output to pins while preserving
' the state of other I/Os

Do_Step:
  READ stpIdx, phase                            ' read new phase data
  PINS = PINS & %11110000 | phase               ' update stepper pins
  RETURN

' -------------------------------------------------------------------------


' -----[ User Data ]-------------------------------------------------------

Full_Steps:
  EEPROM (%0011, %0110, %1100, %1001)           ' step table


Jon McPhalen
EFX-TEK Hollywood Office

brand

Jon,  Thank you very much. I need to read up on some things to understand a few nuances in your code. I'll likely do half steps but I can figure that out, and the sensors are independent of each other for fast versus slow  but agian that should not be beyond me.
brand

JonnyMac

Here's a quick update that should get you close.

' =========================================================================
'
'   File...... Stepper_Control.BS1
'   Purpose...
'   Author.... Jon Williams, EFX-TEK
'              Copyright (c) 2007 EFX-TEK
'   E-mail.... jwilliams@efx-tek.com
'   Started...
'   Updated...
'
'   {$STAMP BS1}
'   {$PBASIC 1.0}
'
' =========================================================================


' -----[ Program Description ]---------------------------------------------


' -----[ Revision History ]------------------------------------------------


' -----[ I/O Definitions ]-------------------------------------------------

SYMBOL  PhotoFast       = PIN7                  ' SETUP = UP
SYMBOL  PhotoSlow       = PIN6                  ' SETUP = UP
SYMBOL  Manual          = PIN5                  ' N.O. between P5.W/P5.R

SYMBOL  Coil4           = PIN3
SYMBOL  Coil3           = PIN2
SYMBOL  Coil2           = PIN1
SYMBOL  Coil1           = PIN0


' -----[ Constants ]-------------------------------------------------------

SYMBOL  Detect          = 0                     ' activ-low photo sensor
SYMBOL  NoDetect        = 1

SYMBOL  Pressed         = 1                     ' for manual trigger
SYMBOL  NotPressed      = 0

SYMBOL  FullTable       = 0
SYMBOL  HalfTable       = 4


' -----[ Variables ]-------------------------------------------------------

SYMBOL  sensors         = B2                    ' photo sensor inputs
SYMBOL  idx             = B3                    ' loop counter
SYMBOL  phase           = B4                    ' new phase data
SYMBOL  stpIdx          = B5                    ' step pointer
SYMBOL  pntr            = B6                    ' table pointer


' -----[ Initialization ]--------------------------------------------------

Reset:
  PINS = %00000011                              ' set to first step
  DIRS = %00001111                              ' make coils outputs


' -----[ Program Code ]----------------------------------------------------

Main:
  IF PhotoFast = Detect THEN M_Fast
  IF PhotoSlow = Detect THEN M_Slow

M_Stop:
  IF Manual = NotPressed THEN Main
  FOR idx = 1 TO 24
    GOSUB Half_Step_Fwd
    PAUSE 15                                    ' adjust for speed
  NEXT

M_Slow:
  GOSUB Step_Fwd
  PAUSE 15                                      ' adjust for slow speed
  GOTO Main

M_Fast:
  GOSUB Step_Fwd
  PAUSE 5                                       ' ajust for fast speed
  GOTO Main


' -----[ Subroutines ]-----------------------------------------------------

' Turn stepper clockwise one full step

Step_Fwd:
  stpIdx = stpIdx + 1 // 4                      ' point to next step
  pntr = FullTable
  GOTO Do_Step

' -------------------------------------------------------------------------

' Turn stepper counter-clockwise one full step

Step_Rev:
  stpIdx = stpIdx + 3 // 4                      ' point to previous step
  pntr = FullTable
  GOTO Do_Step

' -------------------------------------------------------------------------

' Turn stepper clockwise one half step

Half_Step_Fwd:
  stpIdx = stpIdx + 1 // 8                      ' point to next step
  pntr = HalfTable
  GOTO Do_Step

' -------------------------------------------------------------------------

' Turn stepper counter-clockwise one half step

Half_Step_Rev:
  stpIdx = stpIdx + 7 // 8                      ' point to previous step
  pntr = HalfTable
  GOTO Do_Step

' -------------------------------------------------------------------------

' Read new step data and output to pins while preserving
' the state of other I/Os

Do_Step:
  pntr = pntr + stpIdx                          ' point into correct table
  READ pntr, phase                              ' read new phase data
  PINS = PINS & %11110000 | phase               ' update stepper pins
  RETURN

' -------------------------------------------------------------------------


' -----[ User Data ]-------------------------------------------------------

Full_Steps:
  EEPROM 0, (%0011, %0110, %1100, %1001)        ' full step table

Half_Steps:
  EEPROM 4, (%0011, %0010, %0110, %0100)        ' half step table
  EEPROM 8, (%1100, %1000, %1001, %0001)
Jon McPhalen
EFX-TEK Hollywood Office

brand

Jon,
I got the sensors hooked up and running fine and skimmed over the book about ^ XOR but never figured out the logic in your first program. I like/understand the nested IF's in the second take. I am only needing CW rotation, and all 'steps' can be in the 30 degree increments so I sliced and diced to get the code below working: (questions below code)

'-------------- I/O Definitions --------------------------
SYMBOL PhotoFast     = PIN7       'pin 7.W      jumper UP
SYMBOL PhotoSlow    = PIN6       'pin 6.W      jumper UP
SYMBOL PButton       = PIN5        'N-O Push Button  pin 5 <W-R>
'
SYMBOL coil4        = PIN3       'stepper coils
SYMBOL coil3        = PIN2
SYMBOL coil2        = PIN1
SYMBOL coil1        = PIN0
'
'------------- Constants ----------------------------------
'
SYMBOL Detect              = 1      'active HI sensors
SYMBOL NotDetect         = 0
SYMBOL Pressed             = 1      'for Push Button
SYMBOL goFast              = 10     'fast stepper speed
SYMBOL goSlow             = 50     'slow stepper speed
'
'-------------- Vars -------------------------------------
'
SYMBOL sensors  = B2        'photosensor inputs
SYMBOL idx        = B3        'loop counter
SYMBOL phase    = B4        'new phase data
SYMBOL stpIdx   = B5        'step pointer
SYMBOL speed    = B6        'stepper speed
'
'--------------Initialize -------------------------------
'
Reset:
  PINS = %00000011         'set to first step
  DIRS = %00001111         'make coils outputs
'
'------------- Program Code ----------------------------
'
Main:
  DEBUG %PINS
  IF PhotoFast = Detect THEN M_fast
  IF PhotoSlow = Detect THEN M_slow
  IF PButton = Detect THEN M_slow
  PAUSE 5
  GOTO Main

M_slow:
  speed = goSlow
  GOSUB Step_Fwd
  GOTO Main

M_fast:
  speed = goFast
  GOSUB Step_Fwd
  GOTO Main
'
'------------- Subroutines ----------------------------
'....... turn stepper CW  for 30 degrees
Step_Fwd:
  FOR idx = 1 TO 8
  stpIdx = stpIdx + 1 // 8          'point to next step
  READ stpIdx, phase                'read new phase data
  PINS = PINS & %11110000 | phase   'update stepper pins
  PAUSE speed
  NEXT
  RETURN
'-------------- User Data -----------------------------
'
Half_steps:   
EEPROM 0,(%0011, %0010, %0110, %0100)
EEPROM 4, (%1100, %1000, %1001, %0001)


Questions.......
1) what happens to stpIdx ? Seems like it would incement forever, taking up bigger chunks of memory. Assume this program will cycle a lot of a lot, should this counter ever get 'reset'? Or does the // keep it decremented ?

2) for whatever reason, in Subroutine Step_Fwd, I had to   // 8   instead of the calculated  //24. Not sure why that is so, but rotation increments appear to be 30 degrees with that change (12 slices per rev). I copied the way you broke EEPROM into two chunks, and perhaps I made a coding error that caused this  other issue?

3) does the half step cycle give better torque in this program than the full steps? That was motivation for going half steps. Motor got pretty hot after 10 minutes constant fast speed. Activating more coils with half steps likely generates more heat than full steps would. (?)

4) Any ideas on how best to install a limit switch that deactivates the stepper while another task is being done, and upon it's completion let the program run? I thought perhaps putting the new limit swtich in series with the stepper commons to V+,
but would prefer it in code perhaps using P4. Then add line at start of Main to loop to Main until LS detected. Comments?

Thank you V-E-R-Y much for the great product and support. Hard to believe this works and I can barely spell electron.

JonnyMac

I'm glad you were able to take the code I gave you and massage it into a solution that works just right for you -- that's really my ultimate goal for everyone.

Quote1) what happens to stpIdx ? Seems like it would incement forever, taking up bigger chunks of memory. Assume this program will cycle a lot of a lot, should this counter ever get 'reset'? Or does the // keep it decremented ?

Actually, the // (modulus) operator causes stpIdx to wrap-around on itself.  This operator returns the remainder of a division, so in this program stpIdx will go 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, ...  Here's the key: the modulus operator always returns a value between zero and the divisor minus 1, so anything // 8 will fall between 0 and 7.

Quote2) for whatever reason, in Subroutine Step_Fwd, I had to   // 8   instead of the calculated  //24. Not sure why that is so, but rotation increments appear to be 30 degrees with that change (12 slices per rev). I copied the way you broke EEPROM into two chunks, and perhaps I made a coding error that caused this  other issue?

You have to use // 8 because you have eight steps; using // 24 would give you 0 to 23 and cause the pointer for READ to be outside the table.

Quote3) does the half step cycle give better torque in this program than the full steps? That was motivation for going half steps. Motor got pretty hot after 10 minutes constant fast speed. Activating more coils with half steps likely generates more heat than full steps would. (?)

No, half-cycling gives reduced torque.  Steppers always get hot, this is nothing to be worried about (so long as the motor is moving correctly).  If you decide to change to full steps then you need to change the stpIdx modifier to // 4.

Quote4)Any ideas on how best to install a limit switch that deactivates the stepper while another task is being done, and upon it's completion let the program run? I thought perhaps putting the new limit switch in series with the stepper commons to V+, but would prefer it in code perhaps using P4. Then add line at start of Main to loop to Main until LS detected. Comments?

The problem with a limit switch that breaks current is that it's open loop; the controller doesn't know about it.  You could put it into your step loop:

Step_Fwd:
  FOR idx = 1 TO 8
    IF LimitSw = Yes THEN Limit_Error
    stpIdx = stpIdx + 1 // 8
    READ stpIdx, phase
    PINS = PINS & %11110000 | phase
    PAUSE speed
  NEXT
  RETURN

Limit_Error:
  ' do something
  RETURN


By placing the limit switch check at the top of the movement loop you can catch the switch, stop the motor, and take any other action that you want -- when you break the voltage to the motor it gets stopped, but the controller doesn't know about it; this is not always a good thing for a control system.  Note that this code now has two RETURNs for the subroutine; this is very important: you must hit a RETURN after issuing a GOSUB.

You can use P4, just us an active-high input.  Connect the N.O. switch between P4.R and R4.W -- the ULN acts like a soft pull-down.

QuoteThank you V-E-R-Y much for the great product and support. Hard to believe this works and I can barely spell electron.

You're very welcome!  We enjoy helping our customers solve their technical "problems" using our products.
Jon McPhalen
EFX-TEK Hollywood Office

brand

On the limit switch, LS, connected to P4, I see what you did putting it in subroutine Step_Fwd. What ramifications do you see between that approach or this:

Main:
IF  LS = yes THEN CheckSensors
PAUSE 20
GOTO Main

Then the old 'Main' that tests the sensors becomes the sub CheckSensors. I don't know that it matters either way.

On the stepper motor temperature issue I had a thought. I really don't need a holding torque while in wait time between cycles. How and where could I add something like   PINS = %00000000   and   PINS = %00000011   statements so that the stepper coils are not activated unless executing motion. Heat  is a definite concern on my project. In looking at it again I would need to leave the upper 4 PINS as they are so would need some sort of logic to set value of PINS with only the stepper ouputs P0 - P3 set to '0'. Is this worth exploring at all?
Thanks again.

JonnyMac

Your logic vis-a-vis check the limit switch seems reasonable. 

And so long as you don't have a load on the stepper that would cause it to turn [out of position] when it's not powered you could shut it down by clearing the output pins.  The next time you do a move it should pick up where it left off.  Note that you may notice a tiny stutter when you restart it if there is any rotational drift.

Jon McPhalen
EFX-TEK Hollywood Office

brand

Thanks Jon. It'll be a few days before my schedule clears to get back to this and I'll give it a shot. I appreciate the help.