Declan
May 28, 2025, 12:01pm
1
I have 2 stepper motors, 1 NEMA 17 and 1 NEMA 23.
I run these without a library - code examples from Robin2.
I have the following code functions for each stepper motor that runs great individually.
I must now run them simultaneously as different speeds - that is where my problem is - I have attempted numerous examples, but nothing works.
Stepper 17 code:
#define stepper17dirPin 5
#define stepper17clkPin 4
#define stepper17enPin 12
int numberOfStepsCan = 4500;
int betweenStepsCan = 1;
---------------------------------------------
void pedalPressed() {
pedalPinStatus = digitalRead(pedalPin);
Serial.println(pedalPinStatus);
if (interruptPedalFired) {
digitalWrite(stepper17enPin, HIGH); // Enable Stepper 17
digitalWrite(stepper17dirPin, LOW);
for (int n = 0; n < numberOfStepsCan; n++) {
digitalWrite(stepper17clkPin, HIGH);
digitalWrite(stepper17clkPin, LOW);
delay(betweenStepsCan);
}
}
digitalWrite(stepper17enPin, LOW); // Disable Stepper 17
attachInterrupt(digitalPinToInterrupt(pedalPin), INT0_ISR, LOW);
}
Stepper 23 code:
#define stepper23dirPin 10
#define stepper23clkPin 11
#define stepper23enPin 13
----------------------------------------------------
if (loadingLabels == 1) {
Serial.println("Loading");
digitalWrite(stepper23enPin, LOW); // Enable Stepper23
if (irPinStatus == 1) {
do {
irPinStatus = digitalRead(irPin);
digitalWrite(stepper23clkPin, HIGH);
digitalWrite(stepper23clkPin, LOW);
delayMicroseconds(300);
} while (irPinStatus == 1);
}
Drop delay and use libraries. Mobatools is often recommended. Accelstepper provides a lot of functions but also difficulties.
What does that actually mean? Does it only mean they both start and stop at the same time? What is the speed relationship in steps. Two steps for one and one for the other? Or some other ratio? Put some numbers in your requirement.
If you're not going to use libraries, you need a loop that keeps track of when each motor did its last step. Convert your desired speed into delay in microseconds between steps, for each motor. Then go
while(1)
{
if (micros() > last1 + delay1)
{
step1();
last1 = micros();
}
if (micros() > last2 + delay2)
{
step2();
last2 = micros();
}
}
Johan_Ha:
delay1
I am trying to implement the above code into my sketch:
while (1) {
if (micros() > last1 + delay1) {
// step1();
digitalWrite(stepper17clkPin, HIGH); // Run Stepper 17
digitalWrite(stepper17clkPin, LOW);
last1 = micros();
}
if (micros() > last2 + delay2) {
// step2();
digitalWrite(stepper23clkPin, HIGH); // Run Stepper 23
digitalWrite(stepper23clkPin, LOW);
last2 = micros();
}
}
but I cannot get it to work - there is something I am missing or overlooked.
My complete code:
#define stepper23dirPin 10
#define stepper23clkPin 11
#define stepper23enPin 13
int numberOfStepsLabel = 4500;
int betweenStepsLabel = 250;
#define stepper17dirPin 5
#define stepper17clkPin 4
#define stepper17enPin 12
int numberOfStepsCan = 2300;
int betweenStepsCan = 200;
volatile bool interruptPedalFired = false;
#define pedalPin 3
int pedalPinStatus;
unsigned long delay1 = betweenStepsCan;
unsigned long delay2 = betweenStepsLabel;
unsigned long last1;
unsigned long last2;
void INT0_ISR(void) {
interruptPedalFired = true;
detachInterrupt(digitalPinToInterrupt(pedalPin));
pedalPressed();
}
void setup() {
Serial.begin(115200);
pinMode(stepper17enPin, OUTPUT);
digitalWrite(stepper17enPin, LOW); // Disable Stepper 17
pinMode(stepper23enPin, OUTPUT);
digitalWrite(stepper23enPin, HIGH); // Disable Stepper 23
pinMode(pedalPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(pedalPin), INT0_ISR, LOW);
pinMode(stepper17clkPin, OUTPUT);
pinMode(stepper17dirPin, OUTPUT);
pinMode(stepper23clkPin, OUTPUT);
pinMode(stepper23dirPin, OUTPUT);
}
void pedalPressed() {
pedalPinStatus = digitalRead(pedalPin);
Serial.println(pedalPinStatus);
last1 = micros();
last2 = micros();
if (interruptPedalFired) {
digitalWrite(stepper17enPin, HIGH); // Enable Stepper 17
digitalWrite(stepper23enPin, LOW); // Enable Stepper 23
digitalWrite(stepper17dirPin, LOW); // Set Direction for Stepper 17
digitalWrite(stepper23dirPin, LOW); // Set Direction for Stepper 23
for (int n = 0; n < numberOfStepsCan; n++) {
while (1) {
if (micros() > last1 + delay1) {
// step1();
digitalWrite(stepper17clkPin, HIGH); // Run Stepper 17
digitalWrite(stepper17clkPin, LOW);
last1 = micros();
}
if (micros() > last2 + delay2) {
// step2();
digitalWrite(stepper23clkPin, HIGH); // Run Stepper 23
digitalWrite(stepper23clkPin, LOW);
last2 = micros();
}
}
}
}
digitalWrite(stepper17enPin, LOW); // Disable Stepper 17
digitalWrite(stepper23enPin, HIGH); // Disable Stepper 23
attachInterrupt(digitalPinToInterrupt(pedalPin), INT0_ISR, LOW);
}
void loop() {
// Do Nothing
}
Could someone point out where I am going wrong.
How does the code get out of the loop?
Be careful with that code. Assuming the variables are unsigned integers (micros() returns an unsigned long), when (last1 + delay1) overflows you will not get the correct interval.
Better to use
if ((micros() - last1) > delay1) {
jim-p
May 31, 2025, 1:36pm
8
You have done just about everything you are not supposed to do inside an ISR
micros() and Serial.print use interrupts and don't work inside an ISR
Is there a reason why you don't want to use a library?
I am guessing you want something like the following, reading between the lines on your limited description. Note that I changed pin numbers so I could test on a CNC shield.
#define stepper23dirPin 5
#define stepper23clkPin 2
#define stepper23enPin 8
int numberOfStepsLabel = 4500;
int betweenStepsLabel = 250;
#define stepper17dirPin 6
#define stepper17clkPin 3
#define stepper17enPin 8
int numberOfStepsCan = 2300;
int betweenStepsCan = 200;
volatile bool interruptPedalFired = false;
#define pedalPin 12
int pedalPinStatus;
unsigned long delay1 = betweenStepsCan;
unsigned long delay2 = betweenStepsLabel;
unsigned long last1;
unsigned long last2;
void INT0_ISR(void)
{
interruptPedalFired = true;
}
void setup()
{
Serial.begin(115200);
pinMode(stepper17enPin, OUTPUT);
digitalWrite(stepper17enPin, LOW); // Disable Stepper 17
pinMode(stepper23enPin, OUTPUT);
digitalWrite(stepper23enPin, HIGH); // Disable Stepper 23
pinMode(pedalPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(pedalPin), INT0_ISR, LOW);
pinMode(stepper17clkPin, OUTPUT);
pinMode(stepper17dirPin, OUTPUT);
pinMode(stepper23clkPin, OUTPUT);
pinMode(stepper23dirPin, OUTPUT);
}
void pedalPressed()
{
pedalPinStatus = digitalRead(pedalPin);
Serial.println(pedalPinStatus);
last1 = micros();
last2 = micros();
digitalWrite(stepper17enPin, HIGH); // Enable Stepper 17
digitalWrite(stepper23enPin, LOW); // Enable Stepper 23
digitalWrite(stepper17dirPin, LOW); // Set Direction for Stepper 17
digitalWrite(stepper23dirPin, LOW); // Set Direction for Stepper 23
int total_steps = numberOfStepsCan + numberOfStepsLabel;
while (total_steps > 0)
{
if (micros() - last1 > delay1)
{
// step1();
digitalWrite(stepper17clkPin, HIGH); // Run Stepper 17
digitalWrite(stepper17clkPin, LOW);
last1 = micros();
total_steps--;
}
if (micros() - last2 > delay2)
{
// step2();
digitalWrite(stepper23clkPin, HIGH); // Run Stepper 23
digitalWrite(stepper23clkPin, LOW);
last2 = micros();
total_steps--;
}
}
digitalWrite(stepper17enPin, LOW); // Disable Stepper 17
digitalWrite(stepper23enPin, HIGH); // Disable Stepper 23
}
void loop()
{
//
//interruptPedalFired = true;
if (digitalRead (pedalPin) == 0)
{
pedalPressed();
interruptPedalFired = false;
}
}
xfpd
June 1, 2025, 4:10am
10
Is it better to probe pedalPin? I would test interruptPedalFired... is this a bad way to test for an inerrupt?
Yes, if using the interrupt it should test interruptPedalFired but I think the pin I used for the switch on the CNC shield does not support pin change interrupt, it was a bit of a quick hack. Using an interrupt for a button press is not something I would normally do.
Also I realise that the code probably needs separate counters for the two steppers, an exercise left to the reader.
Declan
June 16, 2025, 6:30am
12
I have switched to the Accelstepper library