HELP with Stepper Code

Hi, looking for Arduino coding help for a stepper motor operating system. I’m a complete newbie (Old Mech engineer) to the world of Arduino and ‘C’ programming so please bear with me.

System- NEMA17 /100:1 ratio stepper connected to a Leonardo board via an Easy Driver shield. It’s controlled via 2 pushbutton momentary switches (FWD & REV) and 2 limit switches on the stepper motor/gear box assy (REV & STOP/PARK). The REV switches are connected in parallel, one for automated operation, the other for Manual intervention/override.

Operation- Push the FWD(GO) button and the stepper motor runs CW until it hits the REV limit switch (or the manual REV button is pushed) and then returns CCW to the STOP/PARK limit switch and stops - total movement 20deg. Additionally, the FWD/CW (GO) movement is speed variable via a 10K pot (Slowly rotate at a manually set / adjusted speed). While the REV/CCW movement runs at single high speed only. (Returns quickly to start position and stops). It also has R/G/B LED indicators for each action/mode.

My difficulties – I found during Adruino research Brian Schmalz excellent EasyDriver examples, one of which I’ve used and modified (butchered??). Sadly it doesn’t work so I’m probably doing a huge number of incorrect things within the code??? I’ve read complex stepper codes talking of push button ‘Debounce’ etc, but struggle to understand what I require?

//Based on Example5 code for Brian Schmalz's Easy Driver Example page
// http://www.schmalzhaus.com/EasyDriver/EasyDriverExamples.html
 

#include <AccelStepper.h>


// Define the stepper and the pins it will use
AccelStepper stepper1(1, 9, 8);

// Define our three input button pins
#define  GO_PIN     4
#define  STOP_PIN   3
#define  RETURN_PIN 2
#define  ENABLE     6
#define  RELAY1     7 
#define  LED_BLUE   11
#define  LED_GREEN  12                       
#define  LED_RED    10  
#define  SPEED_PIN  0  
#define  MAX_SPEED  5500
#define  MIN_SPEED  1

      

void setup() {
  // The only AccelStepper value we have to set here is the max speeed, which is higher than we'll ever go 
  stepper1.setMaxSpeed(10000.0);
  
  // Set up the three button inputs, with pullups
  pinMode(GO_PIN, INPUT_PULLUP);
  pinMode(STOP_PIN, INPUT_PULLUP);
  pinMode(RETURN_PIN, INPUT_PULLUP);
  pinMode(RELAY1, OUTPUT);        
  pinMode(LED_BLUE, OUTPUT); 
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_RED, OUTPUT);
  pinMode(ENABLE,OUTPUT);

}

void loop() {
  static float current_speed = 0.0;         // Holds current motor speed in steps/second
  static int analog_read_counter = 3000;    // Counts down to 0 to fire analog read
  static char sign = 0;                     // Holds -1, 1 or 0 to turn the motor on/off and control direction
  static int analog_value = 0;              // Holds raw analog value.

if (digitalRead(GO_PIN) == 0) {    
    sign = -1;
    digitalWrite(RELAY1,LOW);
    digitalWrite(LED_BLUE,LOW);
    digitalWrite(LED_GREEN,LOW); 
    digitalWrite(LED_RED,HIGH); 

if(analog_read_counter > 0) 
    analog_read_counter--;
    analog_read_counter = 3000;
    analog_value = analogRead(SPEED_PIN);
    stepper1.runSpeed();
    current_speed = sign * ((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED;
    stepper1.setSpeed(current_speed);
    stepper1.runSpeed();

}

  else if (digitalRead(RETURN_PIN) == 0) {
    sign = 1;
    digitalWrite(RELAY1,HIGH); 
    digitalWrite(LED_BLUE,LOW);  
    digitalWrite(LED_GREEN,HIGH); 
    digitalWrite(LED_RED,LOW); 
    stepper1.setSpeed(MAX_SPEED);
    stepper1.runSpeed();
  }
  
     
  else if (digitalRead(STOP_PIN) == 0) {
    sign = 0;
    digitalWrite(RELAY1,LOW); 
    digitalWrite(LED_BLUE,HIGH);
    digitalWrite(LED_GREEN,LOW); 
    digitalWrite(LED_RED,LOW); 
    digitalWrite(ENABLE, HIGH);  
 
  }
  }

Any help coding this thing to work would be HIGHLY appreciated.
Wiring Diagram attached.

Hi,
Welcome to the forum.
Thanks for reading the how to use the forum message.

Have you written this code all at once or in stages?
That is.

  • Connected the control box and written code to read and output to your LEDS and got that worrking.
  • Started a completely new code to control the EasyDriver and the Stepper, and got that working.
  • Added the limits and got them working.
  • Combined the codes and got them working,

What is not working?

Tom..... :slight_smile:

Image from Original Post so we don't have to download it. See Image Guide

...R

In addition to what @TomGeorge has said ...

Have you been able to control the stepper motor properly with simple code and simple connections. Or, put another way, have you the correct combination of stepper motor, stepper driver and power supply.

If you have not got that working correctly there is no point worrying about anything more complex.

Post a link to the datasheet for your motor and give details (volts and amps) of your power supply.

Have you tested to make sure the motor has sufficient torque to do whatever it is required to do (you don't seem to have told us)?

Use the AutoFormat tool to lay out your code so it is easier to read. Then you should see that your second IF is missing its {}

Have a look at Planning and Implementing a Program. It will be much easier to develop and debug a program if you organize the code into separate short functions - for example to read the buttons and to implement the different motor movements.

...R

Hi Tom & Robin2, thanks for your prompt replies and useful advice. I’ve read through the recos and followed your advice by going back to basics.

In answer to your questions.

Yes, the stepper has been running but I’ve lost my way as the code and wiring have evolved and now it doesn’t run at all nor do the LEDs alight....Alas until today.

The power supply is a 12VDC 1A – 240VAC Input

The motor torque is very low. The stepper is simply driving a multi circuit potentiometer on a machine system that controls a variable air flow valve.

So, as I say I’ve gone back to basics and worked up from the original Easy Driver example and it now runs the motor variably via the pot and alights the LEDS appropriately…..Yeah!

// Example5 code for Brian Schmalz's Easy Driver Example page
// http://www.schmalzhaus.com/EasyDriver/EasyDriverExamples.html

#include <AccelStepper.h>

// Define the stepper and the pins it will use
AccelStepper stepper1(1, 9, 8);

// Define our three input button pins
#define  RETURN_PIN  4
#define  STOP_PIN  3
#define  GO_PIN 2
#define  RELAY_PIN 7
#define  LED_RED   10
#define  LED_BLUE  11
#define  LED_GREEN 12



// Define our analog pot input pin
#define  SPEED_PIN 0

// Define our maximum and minimum speed in steps per second (scale pot to these)
#define  MAX_SPEED 5500
#define  MIN_SPEED 1

void setup() {
  // The only AccelStepper value we have to set here is the max speeed, which is higher than we'll ever go
  stepper1.setMaxSpeed(10000.0);

  // Set up the three button inputs, with pullups
  pinMode(RETURN_PIN, INPUT_PULLUP);
  pinMode(STOP_PIN, INPUT_PULLUP);
  pinMode(GO_PIN, INPUT_PULLUP);
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(LED_BLUE, OUTPUT);
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_RED, OUTPUT);
}

void loop() {
  static float current_speed = 0.0;         // Holds current motor speed in steps/second
  static int analog_read_counter = 1000;    // Counts down to 0 to fire analog read
  static char sign = 0;                     // Holds -1, 1 or 0 to turn the motor on/off and control direction
  static int analog_value = 0;              // Holds raw analog value.

  // If a switch is pushed down (low), set the sign value appropriately
  if (digitalRead(GO_PIN) == 0) {
    sign = -1;
    digitalWrite(LED_BLUE, LOW);
    digitalWrite(LED_GREEN, HIGH);
    digitalWrite(LED_RED, LOW);
    digitalWrite(RELAY_PIN, HIGH);
  }
  else if (digitalRead(RETURN_PIN) == 0) {
    sign = 1;
    digitalWrite(LED_BLUE, LOW);
    digitalWrite(LED_GREEN, LOW);
    digitalWrite(LED_RED, HIGH);
    digitalWrite(RELAY_PIN, LOW);
  }
  else if (digitalRead(STOP_PIN) == 0) {
    sign = 0;
    digitalWrite(LED_BLUE, HIGH);
    digitalWrite(LED_GREEN, LOW);
    digitalWrite(LED_RED, LOW);
    digitalWrite(RELAY_PIN, LOW);
  }

  // We only want to read the pot every so often (because it takes a long time we don't
  // want to do it every time through the main loop).
  if (analog_read_counter > 0) {
    analog_read_counter--;
  }
  else {
    analog_read_counter = 3000;
    // Now read the pot (from 0 to 1023)
    analog_value = analogRead(SPEED_PIN);
    // Give the stepper a chance to step if it needs to
    stepper1.runSpeed();
    //  And scale the pot's value from min to max speeds
    current_speed = sign * ((analog_value / 1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED;
    // Update the stepper to run at this new speed
    stepper1.setSpeed(current_speed);
  }

  // This will run the stepper at a constant speed
  stepper1.runSpeed();
}

However, I still have some problems to address.

1/ NO DIECTION CHANGE- The 3 sequences in the loop are FWD/REV/STOP. However, pushing the REV Button or hitting the REV Limit switch runs the stepper in the same CW direction as the FWD cycle. I’m not sure why it’s doing this so I’ll change the board and driver and try again, maybe a dead DIR pin?

2/ NO SPEED SEPARATION - My original code (as last posted) attempted to separate the FWD & REV stepper speeds. However, my attempts didn’t work so this newer version has the same variable speed in both directions. However, the system requires the FWD speed to be variable via a pot (Slow) while the REV action (triggered by the limit switch or manual REV push button) needs to be fast (MAX SPEED) to return the controller to the start position ready for the next cycle. This is the part I really need help on. I have no idea how to code separate speeds for the FWD (variably Slow) & REV (Fixed Fast) parts of the loop.

So any help on writing this part of the code would be greatly appreciated.

I assume you want the RETURN_PIN to cause the higher speed for the return process. However the way the code is structred now the speed is always set by the potentiometer because that is the last code immeediately before stepper.runSpeed().

Incidentally, you should only have stepper.runSpeed() in one place - line 90

You should break up the code into functions. For example one function should read all the digital inputs and save the values. Another can read the analog inputs

Another function will set the LEDs

And another one will update the settings for the motor. For example the fact that the RETURN_PIN has been triggered should take precedence over other stuff.

What you have is going to evolve into spaghetti code that is impossible to debug and maintain.

Have a look at Planning and Implementing a Program

...R

I can only underline what Robin said:

Break down your code into functions, depending on the button which was pressed.
E.g.:

if (digitalRead(GO_PIN) == 0) {
  forward();
  }
  else
  if (digitalRead(RETURN_PIN) == 0) {
  backward();
  }
  else
  if (digitalRead(STOP_PIN) == 0) {
  stop();
  }

The functions:

  • void forward()
  • void backward()
  • void stop()

Within the functions you set the adequate parameters and/or actions for the:

  • LED's
  • relay
  • speed of motor
  • direction of motor
  • stop command if applicable

rpt007:
I can only underline what Robin said:
...SNIP....

The functions:

  • void forward()
  • void backward()
  • void stop()

I would also read all the I/O pins in a function and save their values into variables. My loop() would be something like this

void loop() {
readSwitchPins();
readPotentiometer();
updateLEDs();
moveMotor();
}

The moveMotor() function could call the functions forward(), backward() etc

...R

Hi Guys, thanks again for your help and suggestions.

I've now read through 'Planning & implementing a programme' multiple times and while its very comprehensive and begins very clearly it quickly loses me, leaving me glassy eyed and further bewildered.

I spent many hrs today working step by step through a new code from the example in the tutorial but it too fails to compile (familiarly) – and that’s only the first of many errors I’m sure! I’ve tried to follow your collective advice and structure it into 3 defined functions Forward/Backward/Stop but it looks quite complex to me? (New code below)

I'm particularly confused with writing the SPEEDS (2), DIRECTION and RUN STEPPER and the initial definitions??

#include <AccelStepper.h>

//======for the stepper==========
#include <AccelStepper.h>

AccelStepper stepper1(1, 9, 8);
#define  MAX_SPEED = 5500
#define  MIN_SPEED = 1

//======for the potentiometer===
const byte SPEED_PIN = A0;


//======for the LEDs============
const unsigned long ledOnMillis = 300;
const unsigned long ledGRNbaseInterval = 200;
const unsigned long ledBLUbaseInterval = 200;
const unsigned long ledREDbaseInterval = 200;
unsigned long ledGRNInterval = ledGRNbaseInterval;
unsigned long ledBLUInterval = ledBLUbaseInterval;
unsigned long ledREDInterval = ledREDbaseInterval;
byte ledGRNstate = HIGH;
byte ledBLUstate = HIGH;
byte ledREDstate = HIGH;
unsigned long prevLedGRNMillis;
unsigned long prevLedBLUMillis;
unsigned long prevLedREDMillis;
unsigned long currentMillis;
const byte ledGRN = 12;
const byte ledBLU = 11;
const byte ledRED = 10;
unsigned long ledGRNoffMillis = ledGRNbaseInterval;
unsigned long ledBLUoffMillis = ledBLUbaseInterval;
unsigned long ledREDoffMillis = ledREDbaseInterval;


//======for the switch buttons===
const byte buttonGO = 2;
const byte buttonSTOP = 3;
const byte buttonRETURN = 4;
byte buttonGOstate;
byte buttonSTOPstate;
byte buttonRETURNstate;

//======for direction========
const byte direction_CW = 1;
const byte direction_CCW = -1;

//======for the Relay========
const byte Relay = 7;
byte Relaystate;
//=========================

//===========================VOID SETUP===================
void setup() {

  pinMode(ledGRN, OUTPUT);
  pinMode(ledBLU, OUTPUT);
  pinMode(ledRED, OUTPUT);

  digitalWrite(ledGRN, HIGH);
  digitalWrite(ledBLU, HIGH);
  digitalWrite(ledRED, HIGH);

  pinMode(buttonGO, INPUT_PULLUP);
  pinMode(buttonSTOP, INPUT_PULLUP);
  pinMode(buttonRETURN, INPUT_PULLUP);

  pinMode(Relay, OUTPUT);

  stepper1.setMaxSpeed(10000);

}
//=============================VOID LOOP=====================
void loop() {

  currentMillis = millis(); {


    //=======================FORWARD==========================
    void  forward() {

      if (digitalRead(buttonGO) == 0) {
      }
      ledGRNoffMillis = ledGRNbaseInterval;
    }

    if (currentMillis - prevLedGRNMillis >= ledGRNInterval) {
      prevLedGRNMillis += ledGRNInterval;
      ledGRNstate = ! ledGRNstate;
      if (ledGRNstate == HIGH) {
        ledGRNInterval = ledOnMillis;
      }
      else {
        ledGRNInterval = ledGRNoffMillis;
      }
      digitalWrite(ledGRNpin, ledGRNstate);
    }
    static float current_speed = 0.0;        // Holds current motor speed in steps/second
    static int analog_read_counter = 1000;   // Counts down to 0 to fire analog read
    static char sign = 0;                    // Holds -1, 1 or 0 to turn the motor on/off and control direction
    static int analog_value = 0;             // Holds raw analog value.

    if (analog_read_counter > 0) {
      analog_read_counter--;
    }
    else {
      analog_read_counter = 3000;
      analog_value = analogRead(SPEED_PIN);
      stepper1.runSpeed();
      current_speed = sign * ((analog_value / 1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED;
      stepper1.setSpeed(current_speed);
      stepper1.direction = direction_CW;
      digitalWrite(Relay, HIGH);
    }

    //========================BACKWARD==========================
    void backward() {

      else if (digitalRead(buttonRETURN) == 0) {
        backward();
      }
      ledREDoffMillis = ledREDbaseInterval >> 1;
    }
    if (currentMillis - prevLedREDMillis >= ledREDInterval) {
      prevLedREDMillis += ledREDInterval;
      ledREDstate = ! ledREDstate;
      if (ledREDstate == HIGH) {
        ledREDInterval = ledOnMillis;
      }
      else {
        ledREDInterval = ledREDoffMillis;
      }
      digitalWrite(ledREDpin, ledREDstate);
      stepper1.setSpeed(MAX_SPEED);
      stepper1.direction = direction_CCW;
      digitalWrite(Relay, HIGH);

    }
    //===========================STOP==========================
    void Stop() {

      else if (digitalRead(buttonSTOP) == 0) {
        stop();
      }
      ledBLUoffMillis = ledBLUbaseInterval;
    }
    if (currentMillis - prevLedBLUMillis >= ledBLUInterval) {
      prevLedBLUMillis += ledBLUInterval;
      ledBstate = ! ledBstate;
      if (ledBLUstate == HIGH) {
        ledBLUInterval = ledOnMillis;
      }
      else {
        ledBLUInterval = ledBLUoffMillis;
      }
      digitalWrite(ledBLUpin, ledBLUstate);
      digitalWrite(Relay, LOW);
    }

    stepper1.runSpeed();
  }
}

I'm clearly not wired for writing or understanding computer code?? Is it time to walk away? I’ve been reading tutorials and mucking around with this for months now yet I don’t seem any closer to having a usable device.

Once again any further help gratefully appreciated.

Don't worry, I was in the same position only 9 months ago when I started with Arduino.
And my goal was very very challenging being a newbie as you at that time (still there are a lot of areas I don't have touched yet).
So I also read tutorials, (tried to follow) forum discussions, tried to understand and follow examples, tested and was sometimes very disappointed. The sketch was so clear to me but it didn't do, what I wanted, it did do, what I had programmed (sometimes worlds apart ..)

How do you eat an elephant? -> slice by slice ...

So the most important thing to programming is, to cut your project in eatable chunks.
And, there will be a time when first successes will come and your understanding shoots up, especially if you have understood that the arduino loop is running thousands of times per second over and over your loop commands.

Then you understand, what state machines can do and your style improves - still far away from the pros, but most of them do programming all the time in their business, while you and I are just doing it for ourselves, as a hobby or whatever.

If I have time tonight I will try to load your sketch on my test board and see, what is going on.

The first problem with the code in Reply #8 is that you are creating various functions (such as foward() ) inside the loop() function. You are not allowed to define one function inside another.

Fix that and see if it compiles. In any case, then post your revised program.

...R