I am about as green as can be with steppers, stepper drivers, and Arduino. If that admission is not enough to send you away I'll be grateful! I have a Stepperonline Nema 23 stepper motor, one of their CL57Y drivers, an S-350 48v power supply and a uno. I have some code working but observe a behavior I don't understand. My expected result is the stepper should start with 1000 microseconds between pulses and decrement down to 1, and I should observe see the motor smoothly ramping up in rpm to its max rpm or the max the uno can send out pulses. In execution, what I see is the motor starts out as expected, but at around 200 rpm, suddenly it flips to its max rpm. If I uncomment the serial print, the motor will just barely rotate, and no speed increase is seen. It also happens if I add a delay (500) and the end of the code. Any suggestion will be appreciated.
//Declare variables
float speedC=0; // current speed
//Setting parameters
uint16_t maxSpeed=0; //min time between pulses
uint16_t minSpeed=1000; //max time between pulses
float accel=1; //acceleration of the motor
bool leftDir=0; //direction value for left direction
bool rightDir=1; //direction value for right direction
void setup() {
//pins as input
//pins as output
pinMode(pulPin,OUTPUT); // set Pin9 as PUL
pinMode(dirPin,OUTPUT); // set Pin8 as DIR
Serial.begin(9600); //initialize the serial transmition at 9600 bauds
digitalWrite(dirPin,leftDir);
speedC=1000;
}
void loop() {
digitalWrite(pulPin,HIGH); // Output high
delayMicroseconds(speedC); // set rotate speed by delay
digitalWrite(pulPin,LOW); // Output low
delayMicroseconds(speedC); // set rotate speed by delay
speedC-=1;
if(speedC<1) speedC=1; // clumsey method to run motor as fast as Arduino can pump out pulses.
// Serial.print("speedC="); Serial.println(speedC);
// Serial.print(" speedM="); Serial.println(speedM);
}
Thanks for the suggestion. The behavior remains mostly the same. The motor's top speed is higher. Now I can overdrive (1 microsecond will cause an alarm 5 will not and generate over 3,000rpm) the stepper driver causing it to alarm, so clearly, int v float is an improvement—however, the rapid ramping remains.
Ps. I'm not planning on using the stepper at 3000 rpm. The anticipated speed range is more in the realm of 60 to 1000 rpm.
According to the data sheet of this stepper motor driver...
Oops! The maximum step rate is 200kHz.
I think driver is PANIC when pulse rate from Arduino when exceeds it.
Does 200 kHz convert to 5 microseconds? So if I understand that, that would be the min delay between pulses to the stepper driver to not exceed 200kHz?
For your amusement, a stepper online stepper running at 3,200+ rpm. I do get the practical side as steppers as I understand as rpm increases lose torque and a fraction of the range for my application is useful. Here's a ten-second video of my stepper https://photos.app.goo.gl/cyec6StEjGcAUH6eA
I tried adding a inelegant and sloppy (I have only been writing in the IDE for a few days so I am very confused and deficit in the language) counter (to only decrement speedC n iterations) to slow down the ramp. Didn't work so its commented out. Also I added a delay (500) as the only change and the motor doesn't run at all. Comment the delay out and all goes back to the original behavior.
void loop() {
digitalWrite(pulPin,HIGH); // Output high
delayMicroseconds(speedC); // set rotate speed by delay
digitalWrite(pulPin,LOW); // Output low
delayMicroseconds(speedC); // set rotate speed by delay
//pulse+=1;
//if (pulse=500000);{
speedC-=1;
if(speedC<30) speedC=30; // clumsy method run limit motor speed.
//pulse=0;}
delay (500);
//Serial.print("speedC="); Serial.println(speedC);
// Serial.print(" speedM="); Serial.println(speedM);
}
By the way, it's a fundamental story.
This driver is a closed loop stepper driver.
Looks like to be used in open loop, does it work correctly without an encoder signal?
So I have learned a few things. I decided to create some hardcoded examples of speed in relationship to delays. Surprisingly (to me), it was non-linear and went off the rails at the 100-microsecond delay, then sort of comes to be predictable again by 60-microseconds delay. I have no idea if that kind of behavior is normal or not in steppers. This is the latest iteration of the and code, and the problems persist.
//Pins definitions
#define pulPin 9 // step pin
#define dirPin 8 // direction
#define buttonLPin 6 // left push button
#define buttonRPin 7 // right push button
//Declare variables
int speedC=0;
int speedM=0;
int pulse=0;
int stepC=0;
//Setting parameters
uint16_t mindelay=100; // the minium delay between pulses
uint16_t maxdelay=1000; // the maxium delay between pulses
int delaystep=1; // acceleration of the motor
bool leftDir=0; // direction value for left direction
bool rightDir=1; // direction value for right direction
int delayG=500; // read somewhere that Delay can be sick and by declaring a global variable will cure.
int stepM=10; // number of steps per intial/one-time momentary press of button
void setup() {
//pins as input
pinMode(buttonLPin,INPUT_PULLUP); // set as input with pullup
pinMode(buttonRPin,INPUT_PULLUP); // set as input with pullup
//pins as output
pinMode(pulPin,OUTPUT); // set Pin9 as stepper driver PULSE
pinMode(dirPin,OUTPUT); // set Pin8 as stepper driver DIRECTION
//Serial.begin(38400); // initialize the serial transmition at 9600 bauds
speedC=maxdelay ; // not needed
}
void loop() {
if(digitalRead(buttonLPin)==LOW){ // if left button has been pressed
speedC=maxdelay;
speedM=speedC/2;
stepC=stepM;
while (stepC > 0) {
digitalWrite(dirPin,leftDir); // set direction
digitalWrite(pulPin,HIGH); // Initial step to give adequate time to release button befre continious operation.
delayMicroseconds(mindelay);
digitalWrite(pulPin,LOW);
delayMicroseconds(mindelay); // this should be 1 tenth/second in total delay. The motor doesn't pay attention to this block of code.
stepC=stepC-1;
}
delay (delayG); // this delaty give time to release button before continious operaitons commences. Used for preeise alignment.
while(digitalRead(buttonLPin)==LOW){ // Left button has been depressed
digitalWrite(pulPin,HIGH); // Output high
delayMicroseconds(speedM); // delay interval
digitalWrite(pulPin,LOW); // Output low
delayMicroseconds(speedM); // delay interval
speedC-=delaystep;
speedM=speedC/2;
if(speedC<mindelay) speedC=mindelay; // clumsey method to limit speed
//Serial.print("speedC="); Serial.print(speedC);
//Serial.print(" speedM="); Serial.println(speedM);
//Serial.print(" delaystep="); Serial.println(delaystep);
}
}
if(digitalRead(buttonRPin)==LOW){ // if right button has been pressed
speedC=maxdelay;
speedM=speedC/2;
stepC=stepM;
while (stepC > 0) {
digitalWrite(dirPin,rightDir);
digitalWrite(pulPin,HIGH);
delayMicroseconds(1000);
digitalWrite(pulPin,LOW);
delayMicroseconds(1000);
stepC=stepC-1;
}
delay (delayG);
while(digitalRead(buttonRPin)==LOW){
speedM=speedC/2;
digitalWrite(pulPin,HIGH);
delayMicroseconds(speedM);
digitalWrite(pulPin,LOW);
delayMicroseconds(speedM);
speedC-=delaystep;
if(speedC<mindelay) speedC=mindelay;
}
}
}
I do wonder if creating an array with known values to rpm range and then walk through the array could be the solution I'm searching for. I don't know yet how to deal with an array in Arduino, but that is solvable.
In addition, I have found the verb delay (integer) does not seem to work. If I use a constant, it did not work. If I use a variable it does.