motor knob modification

I finally have an Uno and have set up the motor knob stepper control as in the example. I would like to speed the motor up as much as possible, but I seem to hit trouble over 150rpm. Anything higher and the motor does not behave properly. At or below 150rpm and it works beautifully. My question is this: is the processor fast enough to operate the motor into thousands of rpm? I cannot seem to find any other limitation but as I'm new with this type of thing I just don't know.

Once I have the project running as I'd like, the object will then be to use an RC receiver to position the motor for steering a truck.

Any advice would be greatly appreciated.

Stepper motors aren't usually very good at high speeds (where "high speed" is much more than 100 RPM). The Arduino can generate pulses at 8 MHz which could be used with a step-and-direction driver to run 8 million steps per second (40,000 RPS or 2,400,000 RPM with a 200-step-per-revolution stepper) but I doubt the driver and stepper can get close to that.

There is a software limitation in the Stepper library. It delays between steps in milliseconds.

  this->step_delay = 60L * 1000L / this->number_of_steps / whatSpeed;

That means once you go beyond 1000 steps per second you jump to "Ludicrous Speed" (no delay between steps). With a 200-step motor that's 5 RPS (300 RPM). Are you using a 400 step motor? That would cause a failure at 150 RPM.

For higher speeds you can copy the Stepper.c and Stepper.h files from your installation an create your own library that uses delayMicroseconds() for delays below about 100 milliseconds. This would give smooth control up to 150,000 RPM (probably more than the stepper can handle).

That 150rpm sounds quite plausible for a unipolar at 5V. For high speed stepping you need a high voltage to overcome the back-EMF and a special PWM controller to limit the current to what the motor can take. You also need the winding inductance to be low to allow fast changes in current in the windings - this means high-current low-voltage windings.

What are the winding specs for your motor? The higher the resistance and inductance of the windings, the slower the maximum speed will be. Unipolar wired motors will be 50% worse than bipolar's anyway since half the copper is idle at any one time.. A modern high-speed stepper will be bipolar, have windings with resistance around an ohm or less, and be designed to run at 1000's of rpm if driven from 50V PWM driver circuit.

I hate to say it, but you're going over my head with some of this. The project is a small part of a much larger system, and I did not intend to spend so much time trying to get the motor to move as I need.

As for the motor itself, the specs state DC phase resistance as 10 ohms and it operates on 3.5V. It is unipolar.

I do have a stepper controller board that is based upon an L298 which can handle more current and heat than the H-bridge I am now using. However, as of yet I cannot get the motor to move when going through the controller board. The connections are clear enough for me, but it just doesn't move.

I need more study, and I appreciate the help.

Well you could try running it at 12V with a 22 ohm 3W resistor in series with the supply positive rail, in a unipolar configuration.

If you're going to configure it as bipolar then the number of wires to the motor affects what is possible. How fast do you want it to go? Do you have full specs/datasheet for the motor?

Well, I have learned that the stepper controller board I tried to use is for a bipolar motor, and my motor is unipolar. I will get my hands on another motor and try again with the board.

I have used the L298 chip on a custom PCB before to drive a solenoid valves, but I'm not sure about the board you are talking about. For the L298 to drive your inductive load properly:
make sure that Vss is connected to a 5 volts and attach a decoupling capacitor of 100nF between Vss and Ground, and GND is grounded
make sure that senseA and senseB are being pulled low.
if you want to sink current for output1 (low side driver), then follow this

digitalWrite(input1, LOW); // set output1 to sink current
digitalWrite(input2, HIGH); // set output2 to high impedance
digitalWrite(enableA, HIGH); // set enableA to actuate output1

Hope that will help, and be a ware that I might be generalizing here a bit as I'm talking about the solenoid valves.

Ok, scratch that last reply. The motor is bipolar.

johnwasser:
Stepper motors aren't usually very good at high speeds (where "high speed" is much more than 100 RPM). The Arduino can generate pulses at 8 MHz which could be used with a step-and-direction driver to run 8 million steps per second (40,000 RPS or 2,400,000 RPM with a 200-step-per-revolution stepper) but I doubt the driver and stepper can get close to that.

There is a software limitation in the Stepper library. It delays between steps in milliseconds.

  this->step_delay = 60L * 1000L / this->number_of_steps / whatSpeed;

That means once you go beyond 1000 steps per second you jump to "Ludicrous Speed" (no delay between steps). With a 200-step motor that's 5 RPS (300 RPM). Are you using a 400 step motor? That would cause a failure at 150 RPM.

For higher speeds you can copy the Stepper.c and Stepper.h files from your installation an create your own library that uses delayMicroseconds() for delays below about 100 milliseconds. This would give smooth control up to 150,000 RPM (probably more than the stepper can handle).

Okay! After connecting the stepper controller board properly, the motor moves as it did with the H-bridge chip. So, I have it operating again at 150rpm and the motion is smooth.

I would like to try the library modification as you suggest to see if I can speed the motor up to over 1000rpm. Hopefully this does not sound too stupid, but where would I insert the delayMicroseconds() command in order to change the timing? I have the Stepper.cpp file in notepad but hesitate to change things for fear of doing something wrong.

Again, I cannot tell you how much I appreciate the assistance with this project.

In Stepper.cpp there is a function to calculate the delay in millliseconds between steps:

void Stepper::setSpeed(long whatSpeed)
{
  this->step_delay = 60L * 1000L / this->number_of_steps / whatSpeed;
}

I would start by converting that to calculate in microseconds:

void Stepper::setSpeed(long whatSpeed)
{
  this->step_delay = 60L * 1000000L / this->number_of_steps / whatSpeed;
}

Then in the two places where it uses millis():

  // move only if the appropriate delay has passed:
  if (millis() - this->last_step_time >= this->step_delay) {
      // get the timeStamp of when you stepped:
      this->last_step_time = millis();

...change those to micros():

  // move only if the appropriate delay has passed:
  if (micros() - this->last_step_time >= this->step_delay) {
      // get the timeStamp of when you stepped:
      this->last_step_time = micros();

I thought it might be a good idea to include some information about exactly what I am attempting.

The steering system on my truck is actuated by a block on a lead screw. When the screw is turned, the block moves from end to end which pushes and pulls some wire ropes that swing the steering on either end of the vehicle. The lead screw must complete 9 turns to move the steering from lock to lock. Since this system takes a bit of torque to move, there must be a reduction on the drive. How fast I can spin the motor will dictate the reduction, but it will likely need to be at least 3:1. Of course, I do not expect the speed of this to be comparable to a servo, but less than 2 seconds from lock to lock would be ideal.

My first idea was a sail winch servo, but the torque required is quite a bit. Plus, since I have used such unorthodox means (just to make it a challenge) in designing this vehicle, the idea of a computer-controlled stepper just seemed too cool not to try.

Anyway, this is the system. I hope this sheds some light on my project with the Uno.

johnwasser:
In Stepper.cpp there is a function to calculate the delay in millliseconds between steps:

void Stepper::setSpeed(long whatSpeed)

{
  this->step_delay = 60L * 1000L / this->number_of_steps / whatSpeed;
}




I would start by converting that to calculate in microseconds:


void Stepper::setSpeed(long whatSpeed)
{
  this->step_delay = 60L * 1000000L / this->number_of_steps / whatSpeed;
}




Then in the two places where it uses millis(): 


// move only if the appropriate delay has passed:
  if (millis() - this->last_step_time >= this->step_delay) {
      // get the timeStamp of when you stepped:
      this->last_step_time = millis();




...change those to micros():


// move only if the appropriate delay has passed:
  if (micros() - this->last_step_time >= this->step_delay) {
      // get the timeStamp of when you stepped:
      this->last_step_time = micros();

Thank you! This is just what I was hoping for.

You really have helped and I cannot tell you how much I appreciate the effort. I will post my results after working the modifications.

:slight_smile:

I changed the appropriate functions and now I have speed up to ~220rpm before the motor starts to wig out. Below that it is very smooth.

The stepper board is capable of 40kHz, so I don't believe that is the limitation. Do you suppose I am asking too much of the Uno? Is there anything else I can change within Stepper.cpp or Stepper.h?

Sorry for all the questions.

Do you need the positioning accuracy of a stepper motor? Perhaps a stepper motor is not the best choice for your application.

When you start the motor stepping, is it supposed to step a fixed number of times, as would be needed when driving a CNC machine? Or, will it spin until something tells it to stop?

PaulS:
Do you need the positioning accuracy of a stepper motor? Perhaps a stepper motor is not the best choice for your application.

When you start the motor stepping, is it supposed to step a fixed number of times, as would be needed when driving a CNC machine? Or, will it spin until something tells it to stop?

The RC receiver will dictate how far the motor needs to turn, just as the proportional movement of a servo.

The positional accuracy of a servo is typically not all that great. If that is all the accuracy you need, any motor with an encoder that you can read to know where the motor is would be sufficient. You could use a gearmotor to get any speed you need.

I'm not convinced that a stepper motor is right for you.

Would you suggest I use a DC motor instead?

Stepper motors, servo motors, gearmotors, etc. are also DC motors. But, yes, a standard (not stepper) motor would probably be more useful in your case. You'll need to add a rotary encoder to measure position, effectively making a servo out of it (and the Arduino).