Stepper motor wont hold position (solved)

Hello,

I'm controlling a steppermotor via stepperdriver A4988 and a Nano.
I have two buttons, one that runs the motor and the other one changes direction. (and two leds)
Also there is a potentiometer that controls the motor speed.

Evereythings works just fine except that motor will not hold position when "run" button is released.

I think the problem is that the code below is sending a "High" command to the enable pin when button is released.

How can i get the steppermotor to stay enabled? For me the total opposite would be fine ==> motor Enabled as soon as power is on. I have tried to change code from LOW to HIGH and vice versa without success i this section:
"ButtonValue = digitalRead(Button);
if(ButtonValue == 0){
digitalWrite(Enable, HIGH);
}
else{
digitalWrite(Enable, LOW);
} "

I found below code and i'm sorry to say that i don't remember were :flushed:

int ButtonValue = 0;

const int stepPin = 3;
int Button = 5;
int Button1 = 6;
int ledPin = 9;
int ledPin1 = 10;
int dirPin = 4;
int Enable = 7;
int brightness = 0;

// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

int customDelay,customDelayMapped; // Defines variables
 
void setup() {
  pinMode(Button, INPUT);
  pinMode(Button1, INPUT);
  pinMode(Enable, OUTPUT);
  pinMode(stepPin,OUTPUT);
  pinMode(dirPin,OUTPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(ledPin1, OUTPUT);
  Serial.begin(9600);
  
}
void loop() {

  brightness = digitalRead(Button);  // read input value
  if (brightness == HIGH) {         // check if the input is HIGH (button released)
    digitalWrite(ledPin, HIGH);  // turn LED OFF
  } else {
    digitalWrite(ledPin, LOW);  // turn LED ON
  }

  brightness = digitalRead(Button1);  // read input value
  if (brightness == HIGH) {         // check if the input is HIGH (button released)
    digitalWrite(ledPin1, HIGH);// turn LED OFF
  } else {
    digitalWrite(ledPin1, LOW);  // turn LED ON
  }

  ButtonValue = digitalRead(Button);

  if(ButtonValue == 0){
    digitalWrite(Enable, HIGH);
  }

  else{
    digitalWrite(Enable, LOW);
  }

  buttonState = digitalRead(Button1);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button went from off to on:
      buttonPushCounter++;
      Serial.println("on");
      Serial.print("number of button pushes: ");
      Serial.println(buttonPushCounter);
    } else {
      // if the current state is LOW then the button went from on to off:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(100);
  }
  // save the current state as the last state, for next time through the loop
  lastButtonState = buttonState;

  if (buttonPushCounter % 2 == 0) {
    digitalWrite(dirPin, LOW);
  } else {
    digitalWrite(dirPin, HIGH);
  }

  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, 600,12000); // Convrests the read values of the potentiometer from 0 to 1023 into desireded delay values (500 (highest speed) to 12000 (lowest speed), just try)
  return newCustom;  
}

Hope soemone now a fix

br /Hans

If you want the motor permanently enabled, don't connect it's Enable pin to an Arduino pin. Just connect it to 5V ground.

Thanks for the quick reply.
If i do like this will the buttons still work the same?

Why not try it?

I will. Just wondered

Leave ENABLE disconnected (module has 100K pulldown, Pololu modules at least) or set to LOW (ground) to enable the motor.

From the A4988 data sheet.

Enable Input ( ̄E ̄ ̄N ̄ ̄A ̄ ̄B ̄ ̄L ̄ ̄E ̄). This input turns on or off all of the
FET outputs. When set to a logic high, the outputs are disabled.
When set to a logic low, the internal control enables the outputs
as required.

Thanks, I should have checked that. Corrected my post.

Now i have tested to connect enable pin to 5v.. still not holding the motor. (hadn't read above comment when doing this :grinning: )
After that i connected enable pin to ground, that enabled the motor.
However motor is now constantly spinning.
My intention is ==> push button and motor spins ==> release button and motor stops and holds the position(enabled). I will use this to control a router up and down so constantly running or not enabled is not working for me.

Anything i can do in the code?

A stepper motor cannot move on it's own, so look at your program to see why you are telling it to move and why you are doing it.

The motor should start spinning (enabled) when i push the button and stop when i release button. I think it has to do with following part of Code:


  // 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, 600,12000); // Convrests the read values of the potentiometer from 0 to 1023 into desireded delay values (500 (highest speed) to 12000 (lowest speed), just try)
  return newCustom;  
}

However i cant figure out what to do.

Here is an example that, I think, does what you want. Speed is adjusted by the pot. One switch to toggle the direction and the motor runs only when another switch is closed. Note that the code is separated into functions making the code easier to follow and debug.

#define CW 1
#define CCW 0

// make sure the pins are set right
const byte stepPin = 2;
const byte dirPin = 5;
const byte enablePin = 8;
const byte dirButtonPin = 9;
const byte runButtonPin = 11;
const byte dirLedPin = 10;
const byte speedPotPin = A0;

unsigned long microsBetweenSteps = 10000; // initial value.  Set by pot runtime

// adjust the following for your stepper and microstepping
unsigned long minSpeedMicros = 4000;
unsigned long maxSpeedMicros = 500;

bool dir = CW;

void setup()
{
   Serial.begin(115200);
   Serial.println("starting");
   pinMode(stepPin, OUTPUT);
   pinMode(dirPin, OUTPUT);
   pinMode(enablePin, OUTPUT);
   digitalWrite(enablePin, LOW);
   pinMode(dirLedPin, OUTPUT);
   pinMode(dirButtonPin, INPUT_PULLUP);
   pinMode(runButtonPin, INPUT_PULLUP);
}

void loop()
{
   readSpeedPot();
   checkDirButton();
   if (digitalRead(runButtonPin) == LOW)
   {
      singleStep();
   }
}

void readSpeedPot()
{
   int speed = analogRead(speedPotPin);
   microsBetweenSteps = map(speed, 0, 1023, maxSpeedMicros, minSpeedMicros);
}

void singleStep()
{
   static unsigned long timer = 0;
   if (micros() - timer >= microsBetweenSteps)
   {
      timer = micros();
      digitalWrite(stepPin, HIGH);
      digitalWrite(stepPin, LOW);
   }
}

void checkDirButton()
{
   static bool lastButtonState = HIGH;
   bool buttonState = digitalRead(dirButtonPin);
   if (buttonState != lastButtonState)
   {
      if (buttonState == LOW)
      {
         dir = !dir;
         digitalWrite(dirPin, dir);
         digitalWrite(dirLedPin, dir);
      }
      lastButtonState = buttonState;
   }
}

Ohh, thank you. I will try later today when back from work.

Now i have tested the code. (First i changed the pins)

I noticed that motor was constantly running until pushing and holding the button, when released the button motor started again. The direction button worked as expected. Potentiometer showed some erratic behaviour, when turning to max speed motor stopped. (i will try to change "SpeedMicros" values to see if this helps?)

To solve the motor always running maybe i should change to a toggle switch instead of a button to stop motor?

The switches are wired one side to ground and the other side to the input. Both are momentary push buttons.

Put a 0.1uF cap from the wiper of the pot to ground to help with the noise.

I tested the code before I posted it and know it to work as stated.

I changed some values (SpeedMicros) for the pot to 600, and 12000 and now it seems to work correctly.

Regarding the buttons, i think i have it wired up correctly. (there is one led not in usenow but i suppose that should not effect the behaviour?)

I noticed now that my switches are wired to the input and 5v :flushed:

You need to arrange that no step pulses are generated unless the button is pushed.

However I'd strongly suggest trying out the AccelStepper library or other stepper library that supports speed-ramping as this is necessary for all but the smallest steppers to prevent miss-stepping - motors have to follow the laws of physics and inparticular cannot jump from stationary to a speed instantly due to inertia.

When changed switches to input and ground nothing works.
As you may have noticed i'm a total noob regarding this.. but i' try to learn.

I think i will revert back to buttons wired to input and 5v and try a toggle switch fooling the arduino that button is pressed. That should work right?

I expected that the numbers would not be right for you. Since the simple code for stepping the motor does not use acceleration, the maximum speed is limited. Also I am running x4 microstepping to avoid resonance effects like skipping steps.

Your switches are not wired right. Here is how to wire the switches. Note that on the switches with 4 terminals, wire to diagonal terminals to avoid a short.

Like I said, the code is tested on real hardware so if wired right it will work.

First of all i'm really greatful you are helping out. When i said i have wired correctly was according to sketch i found. Apperantly that sketch wrong.

I will try according to your sketch above.. (so i don't need any resistors for the switches?)