Stepper motor code help

I've got a stepper motor which says the "angular move distance" is 60 degrees, the "step angle" is 1.8 degrees, and the "suggested motor speed" is 40 rpm. It also says I should "set the default microstepping value to 16" (I am using this board and have flipped switches 1, 2, and 3 to do this).

I am attempting to use the AccelStepper library, but what I'm not sure about is how to compute the values to pass to both the "setMaxSpeed" and "setMinPulseWidth" functions when I set up the stepper?

Thanks

Also, while I'm at it, would you mind verifying my circuit is correct? The documentation with my motor states that it is "wired as bipolar series, 4 lead-wire connection"

KL-4030 | where it goes
-----------------------------
VCC+    | +24V bench psu
GND     | - bench psu

A+      |  motor coil A start (red)
A-      |  motor coil A end (blue)
B+      |  motor coil B start (green)
B-      |  motor coil B end (black)

EN-     |  not connected
EN+     |  not connected
DIR-    |  arduino pin 6 (the pin I pass to AccelStepper for "direction")
DIR+    |  +5v
PUL-    |  arduino pin 5 (the pin I pass to AccelStepper for "step")
PUL+    |  +5v

Edit: Ok, I've been doing some thinking, is this right....?

360° in a circle / 1.8° per step = 200 steps per revolution
@40rpm (suggested motor speed) = 8000 steps per minute (spm)
8000 spm / 60 seconds in 1 minute = 133 1/3 steps per second (sps)
133 1/3 sps * 16 microsteps in 1 step = 2133 1/3 microsteps per second

So, I should call setMaxSpeed(2133.333) ? That seems... way too high?

Still not sure what to pass setMinPulseWidth, though.

(PS if anyone remembers the long thread I had about stepper motor problems a few months ago, the problem ended up being a bad motor. I've solved those problems and have moved on. I was going to update that thread, but I didn't want to bump it all the way to the top when I had just posted this one, but maybe I'll do that later on, just for closure.)

It will be much easier to help if you post your code so we can see what you are talking about in context.

As far as I know the functions setMaxSpeed() etc require integer values (but I have not checked the AccelStepper docs today)

Have you tried your code to see what happens ?

...R
Stepper Motor Basics
Simple Stepper Code

Robin, I haven't written any code yet. The first thing I have to do is initialize the stepper and call setMaxSpeed in setup, only then I can run the motor.

Also, I need to make sure I've got the circuit right first.

I'll probably rip off the "constant speed" or "quck stop" simple examples from this accelstepper docs, to start with.

Let's pretend my code currently looks like this: AccelStepper: ConstantSpeed.pde

sarink:
Robin, I haven't written any code yet.

The FIRST thing to do when faced with any new product or technique is to write a short simple program to learn how to do it.

Do not start by trying to get the entire project figured out.

Start with one of the AccelStepper examples and try modifying it so you understand what the different library functions do and how they are used.

...R

I really just want to know how I calculate the value I should pass to setMaxSpeed! (And also that my circuit is correct, I assume so, because I can turn the motor, but I just want to verify)

But, OK, maybe I need to give a little history and context before anyone wants to answer that, I guess.

Here goes:

I can write code to get the motor turning -- that is not my issue. The real problem is that the motor is attached to a multi-port valve (1 input and 6 output ports) that it turns, and this valve has some sensors to tell you when you are at a port, and when you are not.

Currently, the code looks something like this: while (notAtPort()) { stepMotor(); } ...
but I get very inconsistent results. Sometimes it stops at the port, sometimes it doesn't. Sometimes it stops when it's almost at the port, but isn't quite there yet. Etc.... I assume that this is all happening because I am stepping the motor without any microsteps at all, and the documentation states:
"It is recommended to use an additional '24' microstep adjustment after the 'Home' or 'Port' signals are detected for optimal alignment of the port position. It is also recommended to set the default microstepping value to '16' in the control program"

So, in order to properly microstep my motor, I need to rewrite my stepMotor() function. Everyone says the AccelStepper library is the best, so I figured I would try to use it. And the first part of using it comes in the setup() function, where you have to call setMaxSpeed().

Does that help clear things up a little?

Here's a link to the motor+valve+sensor documentation, if it helps

Thanks for your help, btw, the reference links above were very educational.

From the AccelStepper website for setMaxSpeed()

speed The desired maximum speed in steps per second. Must be > 0. Caution: Speeds that exceed the maximum speed supported by the processor may Result in non-linear accelerations and decelerations.

And I was wrong (again) - speed is a float value, not an int.

As you don't need fast movement maybe you don't need acceleration and maybe you don't need the AccelStepper library. The second example in my simple stepper code may be sufficient.

133 steps per second is 1 step every 7500 microsecs (7.5 millisecs - but there are no decimals for millis() )

Then you just need to figure how many steps you need.

...R

Did you see my original calculation in the first post? It seems as if the answer is 2133, but that just seems really high, much higher than any examples I have seen online. But I think I did the calculation correctly?

If so, it would seem that an arduino processor is not capable of turning this motor at its full speed, I think (and I really want this to be as fast as possible)?

microsteps always means lots of steps!

2133 steps per second would require one every 468 microsecs. That should be doable.

The only possible problem is that the Arduino may not have much time available to do anything else.

However if all you are doing is moving a valve I can't see the need for microsteps.

My read of the document is that microstepping is intended to align the valve orifice properly - to make up for the fact that the motor may not have been installed so its natural full-step positions don't coincide with the valve positions. Careful installation of the motor should deal with that problem. If the movement between valve positions is an integer number of steps then it should not need microstep adjustment.

How much error in valve alignment is acceptable - keeping in mind that there is no such thing as perfect ?

Have you tried x8 or x4 microsteps ? Maybe that would be good enough.

You should also be aware that it is only at full-step positions that a stepper motor holds an accurate position. Microsteps are approximate.

It is also possible to use the Arduino to control the microstep setting so that most of the move could be done with full steps and the final positioning with microsteps. Obviously the code would be a bit more complex.

...R

Robin, I think I understand what you're saying. Although the motor and the valve come attached together as one, so it should be installed "correctly"...

Here's the code I've got so far:

#include <AccelStepper.h>

float calculateMaxSpeed() {
  return 2133.333;
  //float degreesPerStep = 1.8;
  //int rpm = 40;
  //int microstep = 16;
  //return (360/degreesPerStep) * microstep * (rpm/60);
}

int i;
char c;
char cmd[64];
int pulPin = 5;
int dirPin = 6;
int portPin = A1;
float MAX_SPEED = calculateMaxSpeed();
AccelStepper stepper(AccelStepper::FULL2WIRE, pulPin, dirPin);

void setup() {
  // turn on serial
  Serial.begin(9600);
  Serial.write("Power On\n");
  
  // set up pins
  pinMode(pulPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  
  // set up stepper
  stepper.setMaxSpeed(MAX_SPEED);
  stepper.setSpeed(1100); // about half of the max, just for now
}

bool isBetween(float num, float min, float max) {
  return num > min && num < max;
}
bool atPort() {
  return isBetween(readPortPinVoltage(), 0.0, 1.0);
}
bool notAtPort() {
  return isBetween(readPortPinVoltage(), 1.5, 5.0);
}
float readPinVoltage(int pin) {
  return analogRead(pin) * (5.0 / 1023.0);
}
float readPortPinVoltage() {
  return readPinVoltage(portPin);
}

void loop() {
  
  if (Serial.available()) {
    
    // read the character we sent
    c = Serial.read();
  
    // command complete char
    if (c == '\r') {
      
      // did we say 'step_next' ?
      if (strcmp(cmd, "step_next") == 0) {
        
        // echo the command back to us so we know it got here
        Serial.print(cmd);
        
        // we should already be at a port on the valve, so step until we leave it
        while (atPort()) stepper.runSpeed();
        
        // now we're in limbo, keep stepping
        while (notAtPort()) stepper.runSpeed();
        
        // now we should be at the next valve port, stop stepping
        stepper.stop();
      }
      
      // this command is complete, reset and print success
      i = 0;
      memset(&cmd[0], 0, sizeof(cmd));
      Serial.println("...done");
    }
    // else if we didn't hit the command complete char, append the char to our `cmd`
    else {
      cmd[i] = c;
      i++;
    }
    
  }
  
}

This code does step the motor, and always stops at a port, but it doesn't move to the next port. Sometimes it stops almost immediately, sometimes it steps a bunch of ports, sometimes the step_next command echos back but then never gets to "done"... I don't really get it. I'm probably doing something stupid and obvious wrong, but I'm lost :-S

I hope that example is simple enough, I've been stripping things down and this is where I'm at right now.

All I really want to be able to do is send a serial command to step to the next port, if I could do that reliably, I'd be happy!

Thanks for your help!