I am developing a product using a stepperonlne (https://www.omc-stepperonline.com/servo-motor-nema-23-integrated-easy-servo-motor-180w-3000rpm-0-6nm-84-98oz-in-20-50vdc-brushless-dc-servo-motor-isv57t-180) and I need it to run at its full rated 3000 RPM. Currently I am only getting 2200 RPM using micros() - with a step value of 1.
I am also using Pin 4 on the Mega that theoretically is high frequency - 980 Hz to drive the servo. Does this mean I have hit the Mega frequency wall in that I need a higher frequency board to get the full 3000 RPM? Any suggestions appreciated!
This is a simple test code I wrote to run the servo motor: Output RPM ~ 2200
// Define pin connections
const int dirPin = 8;
const int stepPin = 4;
const int stepDelay = 1;
// define variables
unsigned long startMicros;
unsigned long currentMicros;
unsigned long motorOnTime;
void setup()
{
// Declare pins as Outputs
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
}
void loop()
{
motorOnTime = 10000;
startMicros = micros(); //initial start time;
currentMicros = micros(); //get the current micro
digitalWrite(dirPin, HIGH); // Set motor direction clockwise
while ((currentMicros - startMicros) <= motorOnTime){ //test whether the period has elapsed
digitalWrite(stepPin, HIGH);
delayMicroseconds(stepDelay);
digitalWrite(stepPin, LOW);
delayMicroseconds(stepDelay);
currentMicros = micros();
}
}
Look closer into the datasheet to find out how to achieve 3000 RPM. Maybe even shorter delays than 1 microsecond can be used. Know that the surrounding code lines cause some delay.
You post in the English forum but links to a German site.
How are the DIP switches S1, S2, S3 set?
The step is initiated on the rising edge of STEP pulse, so this delay just wastes time. 10 us delay is usually more than enough.
For highest speed, a relatively high voltage stepper power supply is required, the higher the better within the driver limits, and the current limit has to be set correctly.
Finally, you need to start from a much lower step speed, and accelerate to the desired maximum.
Thanks for the suggestions - the DIP switched are set to only S1-on that gives the minimum steps/rev. I tried varying the switches - all other settings were slower.
There is a big difference in speed between 1 and 10 us delay... I am using a 50V power supply that provides up to 6A... also the 50V power supply that stepperonline sell for that servo produces the same result. For sure, torques are less at lower voltage though I did not see any variation in speed (one of my power supplier is variable so I can dial up the voltage 0-70V.)
@jremington.... Should I try running with no delay - is that what you are suggesting?
Obey the step pulse width specifications for your motor driver. The details should be in the data sheet.
Thanks @Railroader - I tried commenting out the delay completely - still no improvement in top speed.
Some math:
You want to reach 3000RPM. That is 3000/60 = 50 rev/sec.
You need 1600 steps per rev. With 50rev/sec you need 80000 steps/sec. That means you have only 12.5µs per step.
Your while loop can never run that fast on a Mega.
digitalWrite needs about 5µs on an AVR with 16MHz. So the two digitalWrite consume nearly all the time you have for your speed.
The call to micro() also takes time, and the comparison in the while loop is also fairly slow (comparing 32 bit values on an 8-bit processor).
You could try to create the steppulses by direct manipulation of IO-registers. This is much faster than digitalWrite.
Or use a faster processor.
Are you only interested in RPM, or do you need position control as well? Providing a fast step rate is easier than generating a precise number of steps.
Another crucial question is what else do you need the Mega to do? If it is dedicated to generating pulses it is relatively easy, but if you need do other things it gets harder the more you need to do.
It appears the servo controller handles acceleration, so I think you don't have to worry about creating a speed profile.
As a data point Marlin firmware achieves about 10kHz step rate (40kHz with quad stepping) on an AVR, but Marlin does a lot of other stuff apart from generating pulses.
If all you need to is generate pulses, the following code generates pulses at about 80Khz (3000RPM @1600 steps/rev)
#define _delayNanoseconds(__ns) __builtin_avr_delay_cycles( (double)(F_CPU)*((double)__ns)/1.0e9 + 0.5 )
void loop()
{
// put your main code here, to run repeatedly:
#define DELAY 6000
while (1)
{
PORTD |= (1 << 4);
_delayNanoseconds (DELAY);
PORTD &= ~(1 << 4);
_delayNanoseconds (DELAY);
}
}
However, if you need to do other activities, then an interrupt or hardware timer would be a better option.
Ah yes that's interesting thanks @MicroBahner - I believe you are correct in saying the Mega is max'd out. Maybe the Due? hard to swap because I have a lot of peripheral devices needing 5v. Possibly I could use a slave processor (like a Due) communicating with the Mega via UART to drive the servo?
This also is very interesting thanks @bobcousins . I don't need positioning, I need torque, speed control and low noise. It is for an appliance prototype. It does everything I need so far, just need to get the speed up to a suitable level - this motor can max out to 4K RPM though if I can get to 3K will be OK. Thanks also for the code - I will test it - seems like you have come across this issue before?
The Mega is also running a TMC2209 with a NEMA 17 stepper, IR sensors, a slave nano that reads a load cell, temp sensors all talking to a Nextion display. Quite a bit going on.
I only know a bit about Marlin controllers for 3D printing/CNC?? I didn't know they were capable of such high frequencies!
Oh yeah, I spent some time writing software for 3d printers, also my day job involves software for motor controllers.
I ran the sketch you provided and it generates a pulse rate of about 84kHz, which should be 3150 RPM. I am using an Uno not a Mega, but it should be the same I think. I wonder if there is some other issue at play here. How are you measuring the RPM?
Oh, OK - that makes sense! That's great you tested my code - I really appreciate it! I am measuring the speed with a laser tachometer on the output shaft. I also have the DIP switches set for 1600 steps per rev. I saw in a youTube vid that you can also set the steps per revolution in the nearly-impossible-to-understand app available on the stepperonline website. I haven't been able to get that to work on my new Win 11 computer and I heard it is only Win 10 compatible so I will blow the dust off my old laptop to see if I can connect. I will also test my code on a separate Uno and see if there is any difference...
Have a look at this bit of your code:
motorOnTime = 10000;
startMicros = micros(); //initial start time;
currentMicros = micros(); //get the current micro
digitalWrite(dirPin, HIGH); // Set motor direction clockwise
while ((currentMicros - startMicros) <= motorOnTime){ //test whether the period has elapsed
Having ' currentMicros = micros();' immediately after 'startMicros = micros(); ' means that the while condition is always true.
Having ' digitalWrite(dirPin, HIGH); ' where it is means you are slowing loop() down as you are wasting valuable time setting dirPin high every time you go round loop.
I tested it as well, and came up with a different result - See oscilloscope trace below:
The frequency is 61.1kHz - giving a speed of (61100*60/1600)rpm, or 2291rpm - which agrees with the speed that you mentioned in post #2.
It appears that the Mega is slightly slower than an Uno, which is apparently due to the increased memory size, certain instructions taking slightly longer. I never realized that. I have a Mega somewhere, I will try on that.
ETA: just tested same code on a clone Mega and I get about 60kHz. Quite a big difference.
I just tested it on a Uno - 85kHz, similar to your result bobcousins.
So a Mega is slower than a Uno.

