I'm using a Mega, A4988 driver and a bipolar NEMA17.
I found a tutorial on how to control the speed of the stepper by using a 10k potentiometer from the Mechatronics website. After assembly, I noticed a small "band" where the stepper motor would be rather twitchy instead of rotating at a constant rate. Would this be a problem with the potentiometer I have or would it just be quirkiness with Arduino?
const int stepPin = 3;
const int dirPin = 4;
int customDelay,customDelayMapped; // Defines variables
void setup() {
// Sets the two pins as Outputs
pinMode(stepPin,OUTPUT);
pinMode(dirPin,OUTPUT);
digitalWrite(dirPin,HIGH); //Enables the motor to move in a particular direction
}
void loop() {
customDelayMapped = speedUp(); // Gets custom delay values from the custom speedUp function
// Makes pules with custom delay, depending on the Potentiometer, from which the speed of the motor depends
digitalWrite(stepPin, HIGH);
delayMicroseconds(customDelayMapped);
digitalWrite(stepPin, LOW);
delayMicroseconds(customDelayMapped);
}
// Function for reading the Potentiometer
int speedUp() {
int customDelay = analogRead(A0); // Reads the potentiometer
int newCustom = map(customDelay, 0, 1023, 300,4000); // Convrests the read values of the potentiometer from 0 to 1023 into desireded delay values (300 to 4000)
return newCustom;
}
Additionally, I added the serial.begin and serial.println to monitor the "customDelay" to see where on the band the problems were occurring and it seemed to be around the 580-680 range. I also noted that the motor was spinning slower while I had the serial stuff on. Was the decrease in speed due to the extra work load on the Arduino?
Did you check the pot with a meter?
Would this be a problem with the potentiometer I have or would it just be quirkiness with Arduino?
Nether, it is the mechanical resonance of the stepping motor and load ( if any).
Normally micro stepping can help reduce this.
Show the code with rhe Serial print included.
In the stepping You have 2 delays in the range of 300 - 4000.microseconds and the time used for A/D read. It is a fast spinning loop. Using some time for executing Serial print would slow down the loop a little, maybe enough to be noticed in my opinion.
Added in setup and right after the analog read.
const int stepPin = 3;
const int dirPin = 4;
int customDelay,customDelayMapped; // Defines variables
void setup() {
// Sets the two pins as Outputs
serial.begin(9600);
pinMode(stepPin,OUTPUT);
pinMode(dirPin,OUTPUT);
digitalWrite(dirPin,HIGH); //Enables the motor to move in a particular direction
}
void loop() {
customDelayMapped = speedUp(); // Gets custom delay values from the custom speedUp function
// Makes pules with custom delay, depending on the Potentiometer, from which the speed of the motor depends
digitalWrite(stepPin, HIGH);
delayMicroseconds(customDelayMapped);
digitalWrite(stepPin, LOW);
delayMicroseconds(customDelayMapped);
}
// Function for reading the Potentiometer
int speedUp() {
int customDelay = analogRead(A0); // Reads the potentiometer
serial.println(customDelay);
int newCustom = map(customDelay, 0, 1023, 300,4000); // Convrests the read values of the potentiometer from 0 to 1023 into desireded delay values (300 to 4000)
return newCustom;
}
I'm not an expert regarding execution time for Serial print. You could try to measure it. Collect millis(), then perform a Serial print and collect millis() again. Print the difference between second and first stamp. Eventually You write a "test Serial print execution time" sketch.
This could explain an overall slow down in speed.
The nonlinearity shouldn't have much or anything to do with this.
Eventually You write a "test Serial print execution time" sketch.
It is a lot more complex that that.
When you Serial.print the characters are put in a buffer. Then an interrupt service routine takes bytes out of the buffer and puts them in the UART’s buffer.
All well and good, but if the buffer is full then the Serial.print has to wait until the buffer has space to finish the transfer. Therefore a print statement can take a variable length of time depending on the state of the buffer.
However this has sod all to do with the OPs problem which is due to mechanical resonance.
Doing some math and asuming the baudrate of Serial is 9600 the buffer will get filled up and speed will drop.
If I am right the baydrate need to be higher than 50 000 for the highest speed achieved att 300 uS delay to awoid fulling the UART buffer.
Grumpy_Mike:
It is a lot more complex that that.
When you Serial.print the characters are put in a buffer. Then an interrupt service routine takes bytes out of the buffer and puts them in the UART’s buffer.
All well and good, but if the buffer is full then the Serial.print has to wait until the buffer has space to finish the transfer. Therefore a print statement can take a variable length of time depending on the state of the buffer.
However this has sod all to do with the OPs problem which is due to mechanical resonance.
This is definitely true. Although the speed of the motor is decreased while the serial.print is in place, it still has that goofy stutter at the slower speed range. I'll have to figure out how to implement the microstepping in order for my program to drive the motor as intended.
Is there a better way to utilize the serial.print without reducing the speed of the motor?
Is there a better way to utilize the serial.print without reducing the speed of the motor?
I don’t think so, it takes time to do everything and filling the buffer, while not being too time intensive does slow down other things. I suppose the trick is to have the timing generated independently with a hardware timer so the time between steps is not compromised. Having a more powerful processor helps, or relegating the pulse timing to another system.
Microstepping is a function of the stepping motor driver so if your driver doesn’t do it then you can’t implement it.
Grumpy_Mike:
I don’t think so, it takes time to do everything and filling the buffer, while not being too time intensive does slow down other things. I suppose the trick is to have the timing generated independently with a hardware timer so the time between steps is not compromised. Having a more powerful processor helps, or relegating the pulse timing to another system.
Microstepping is a function of the stepping motor driver so if your driver doesn’t do it then you can’t implement it.
Another system could be a separate Arduino I suppose. Something I'll have to consider if the serial print is even worth it. Do you think I would see the same delay if I "printed" to a 20x4 LCD screen?
I'm using the 4998A stepper driver (per Robin's recommendation) which does support the microstepping wonderfully. I just need to figure out how to program it to accomplish this properly. I'll get there.
Do you think I would see the same delay if I "printed" to a 20x4 LCD screen?
I would have thought that would have taken much longer than just transferring a byte from one place to another.
I just need to figure out how to program it to accomplish this properly
You just set one or more of the inputs MS1, MS2 & MS3 on the driver board high. As described here Pololu - A4988 Stepper Motor Driver Carrier
Grumpy_Mike:
I would have thought that would have taken much longer than just transferring a byte from one place to another.
I'm not sure what you mean. The delay would be worse sending the info to an LCD vs serial.print?
Grumpy_Mike:
Yes.
I guess I finally have an excuse to use a 2nd Arduino in a project 
Thank you for your input. Much appreciated!
Try this:
Every timy You do a Serial print you set a time for the next printout like millis()+100. Before printig You compare if millis() is greater than Your time stamp.
Your loop spins fast so You make more than 1000 printouts ever second. How many of them do You manage to read?
if (mills() > time_to_print
{
Serial.print….
time_to_print = millis +100;// gives 10 printouts per second. +200 gives 5....
}