Arduino Processor

I am trying to program a stepper motor in micro-step mode to turn at 128000 pulse/sec. I know the motor can handle this number, but when I attempt to run my acceleration s-curve program, it jumps to max velocity. I was wondering if the max velocity is too large a number for the arduino uno to handle? Can the board support 12 and 16 bit numbers? My code is attached to the post.

Stepper_Motor_Acceleration_Version1.ino (1.8 KB)

Please post your code.
Use code tags

(This is.not an installation question)

// Parameters
long ta = 3e5;     // acceleration time (microsec)
long td = 3e5;     // deceleration time (microsec)
long Vm = 128000;    // steady state velocity (pulse/sec)
//long Pt = 3200;    // total number of pulses for move (3200 steps per rev)

// Other variables
long dly;           // stepper pulse delay (microsec)
long t = td/9;      // current time (microsec)
long t12 = 1e6-ta-td;           // time during constant velocity (microsec)

int count = 0;      // count the number of pulses

const float loopdelay = 1000; //delay between each move (milliseconds)

// Arduino pins
#define dirPin 13   //define direction output pin number
#define stepPin 3   //define step output pin number

void setup() {

 //set both pins as outputs
 pinMode(dirPin, OUTPUT);
 pinMode(stepPin, OUTPUT);

}


void loop()
{
 digitalWrite(dirPin, LOW);  // set the stepper direction (LOW=counterclockwise, HIGH=clockwise)

 // decide which part of the velocity curve your at
 if (t<ta) {                                       // acceleration
   dly = (ta)/(2*(Vm/1e6)*t);
 } 
 else if (t>=ta && t<(ta+t12)){                    // constant velocity
   dly = 1/(2*(Vm/1e6));
 }
 else if (t>=(ta+t12) && t<(ta+t12+td)){           // deceleration
   dly = 1/(2*((Vm/1e6)-(Vm/(1e6*td))*(t-ta-t12)));
 }
 
 t = t+2*dly; // update the current time
 
 // move stepper one pulse using delay just calculated - delay depends on current position in s-curve
 digitalWrite(stepPin, HIGH);
 delayMicroseconds(dly);
 digitalWrite(stepPin, LOW);
 delayMicroseconds(dly);
 count ++;
   
 // condition that checks if the move is completed
 if (t>(ta+t12+td)){
   
   count=0;  //reset both time and the pulse count before starting the next move
   t=td/9;
   
   delay (loopdelay);  //delay variable that is the time between moves
 }
 
}

Also I apologize I posted my question under the wrong section. Any help or suggestions would be much appreciated.

You are using a lot of integer divisions. I'm not sure that they will all give you the result you're expecting.

Dividing by 1e6 will be treated as floating-point, which makes the rest of the calculation use floating-point, which will be slow. (Note that a floating point division, while slow, is actually faster than a long int division on the 8-bit Arduinos.)

Then you're using delayMicroseconds() when your calculations above are actually taking many milliseconds to complete, due to the extensive use of division and float. To drive steppers at that speed, you need to really concentrate on getting as much mathemathics as possible outside of the stepping loop.

EM501:
I am trying to program a stepper motor in micro-step mode to turn at 128000 pulse/sec

That means a pulse every 7.8 microsecs if my maths is corrrect. That will be a challenge for a 16 MHz microprocessor unless you are content to program one of the hardware timers to do it and then leave it to get on with it.

...R

Thank you guys for the responses. The equations were found online and any time I try to modify the eqns, the program stops working completely. Robin is probably right in saying that the processor is not adequate for such complex operations at such high speed.

As for the delayMicroseconds(), this function is required between digitalWrite(dirPin,HIGH) and digitalWrite(dirPin,LOW). The amount of delay determines the frequency of the pulses and therefore the speed of the motor. This is also part of the reason the equations were needed. We want a pulse/sec input to result in a certain sec output.

At 128K pulses/second, it is pointless to even DO micro-stepping.... Above a few thousand steps/second, you should be doing full steps - micro-stepping buys you nothing. Many commercial stepper drivers "morph" from micro-steps to full steps when the step rate exceeds a few kHz.

Regards,
Ray L.

128K pulses/sec is required for the degree of precision that will be needed later on. This is only a "test" for lack of a better word. This program needs to work before I can modify it to make use of the microstepping at high velocity.

The motor is capable of doing 128K pulses/sec because it jumps to this velocity. The problem lies in getting a smooth acceleration while ramping up to this velocity.

Thanks again

Maybe change the title of your thread? "Arduino Processor" isn't gonna attract the attention of many motor-heads.

Follow the code manually through a few moves. You may find that it's dependent on a number being greater than one. In integer math, all fractions are zero.

The resolution is determined by the clock speed. The basic Arduinos are clocked at 16MHz. This means only 125 clock cycles between steps at your 128kHz highest step speed. It also means the resolution is less than 1kHz at this speed - if you have 126 clocks as your next-slowest speed, this gives 126.984Hz or a 1.015kHz gap. This is probably good enough resolution for most purposes.

But that also means that you're really going to have to use a hardware timer to produce the pulses. You can't do much computation in 125 clock cycles. Certainly not any delayMicroseconds(). If all you're doing is just loading the next interval into the timer from a pre-calculated table, then that's do-able.

Moving to a faster Arduino like a Teensy will give you more clock cycles to do more computation. A Teensy 3.2 runs natively at 72MHz, so you'll get about 500 clock cycles to do computations. A Teensy 3.6 is 180MHz, so you get over 1000 clock cycles, which is enough to think about calling functions and doing some calculation in between each step.

What kind of stepper is this anyway? That's an exceptionally high step speed.

Thank you guys for your responses. Morgan, I am slightly confused at what you are trying to explain. Are you saying that the motor or processor are not capable of the high frequencies? The motor is a standard NEMA 14 pancake stepper motor. The motor is then geared down 30:1 using a custom gearbox.

It's unusual to see a motor stepping at those speeds. As Ray said, microsteps are not relevant at that speed. It's better to use full steps and a slower step rate. Have you tested that you can actually accelerate the motor to that speed (with AccelStepper or a simpler system) and it works?

My last stepper project went up to 8kHz and it took a lot of effort to get the motors to reliably accelerate to that speed.

I can get the motor up to that speed but the acceleration curve is not smooth. My acceleration curve program works at smaller frequencies (less than 8192 pulse/sec) but the higher frequencies do not cooperate. That was the initial problem that I came to this forum with. How did you get the moor to accelerate up to 8kHz?

CORRECTION: It APPEARS to be getting up to speed. I am unfamiliar with what a high frequency such as 128kHz would look like, therefore I can only assume.

If the stepper misses steps it makes a bad noise. If you are sure that you are actually sending the right frequency (you original code cannot) then either the motor runs smoothly or it obviously runs badly.

Just write the simplest possible code that sends the right frequency. You can use big jumps to accelerate up to speed in only one or two jumps.

Then work on the programmable acceleration.

The stepper may be skipping steps, but I am not sure what indication the motor would give if this were true.

Noise. The sound of skipping is different to normal running.

There is nothing out of the ordinary besides the large jump in speed. Is there a way to incorporate Serial.print into the code to see the velocity curve?

UPDATE: The problem is most likely in the equations. Do you guys see anything?

Do we see anything in the new code you didn't post? No.

Your original code is doing way too much calculation. Those calculations take time. Microseconds at least, possibly milliseconds. So you need to tune your delayMicroseconds() to take that time into account. You will end up with something like a Blink-Without-Delay, which is very close to how the main stepper libraries like AccelStepper work.

Calculate your s-curve first. Put all the numbers that you need for stepping into an array. The bit that actually drives your motor should not do any calculation, it should just pull pre-calculated numbers out of that array.

I'd suggest that the numbers in your array ought to simply be the microsecond delay at each step, held as a two-byte value (you won't need longer delays than that).