Hi all, I am 100% new to the Arduino scene. I am a Mechanical engineer and i know some MATLAB, but coding is definitely not my specialty. I am trying to setup a code in which the following happens: A button is pressed, the stepper motor turns a set number of revolutions, and then stops. Then, when the button is pressed again, the motor runs in reverse the same number of steps, and then stops. (I am trying to raise and lower something with the bush of a button. I am currently using a code by Superb to change the direction the motor, but in this code the motor is running continuously. I feel that only slight modification would be needed to make this code do what I want. See the code below:
// Stepper motor run code with a4988 driver
// by Superb
const int stepPin = 3;
int dirPin = 4;
int dirButton = 2;
int state = HIGH;
int reading;
int previous = LOW;
int stepDelay=1000;
// if the input just went from LOW and HIGH and we've waited long enough
// to ignore any noise on the circuit, toggle the output pin and remember
// the time
if (reading == HIGH && previous == LOW && millis() - time > debounce) {
if (state == HIGH)
state = LOW;
else
state = HIGH;
How can the motor ever stop? You are not counting steps, so it will ALWAYS step in whatever direction was last selected. You need to count steps to track position, and STOP stepping when you've taken enough steps to reach your target position. Stepping one direction should increase the the step count, the other direction should decrease the step count. When you reach either maximum or minimum position, stop.
You MAY get away with simply changing direction on the fly like that, IF you are stepping slowly. At higher speeds, doing that will cause the stepper to lose steps, or simply stall. A proper steppers driver should use acceleration and deceleration to gradually change the speed to avoid lost steps or stalling.
gcjr,
Thanks for the help!
So a tried that code (without making any modifications to the code or my circuitry) and this is what happened:
Upon uploading the code, the stepper ran continuously. When the button is pressed, the stepper pauses until the button is released. Then it continue. And then begins slowing down (roughly. not a smooth deceleration) and eventually came to a stop.
In particular use code tags to post your code. (But first, in the IDE use CTRL-T to clean up your indentation).
It is strongly recommended that you don't use reserved words, like "time" as a variable name. If you ever introduce a clock into your project the compiler will complain a lot. Use something more descriptive, like "buttonTime". First this makes the code easier to read and second, there is virtually no chance that "buttonTime" is a reserved word.
Your debounce timing won't work because your variable "time" is uninitialized on the first loop.
Personally, I use a library function called "Bounce2.h" when I want to debounce a button. The Bounce2 library simplifies debouncing and can have two actions if the button is held for a short or long press. For example, press and hold to start the servo or press briefly to stop it.
About how many revolutions is that? And how many steps in a revolution?
I would recommend the AccelStepper library. It will keep track of the stepper's current position and allow you to move to any specific position, like this:
#include <AccelStepper.h>
const int stepPin = 3;
const int dirPin = 4;
AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin);
const int StepsPerRevolution = 200;
const int Revolutions = 30;
const long Top = StepsPerRevolution * Revolutions;
const long Bottom = 0;
const int dirButton = 2;
int state = LOW; // Starting at Bottom
unsigned long debounce = 200;
void setup()
{
pinMode(dirButton, INPUT_PULLUP);
stepper.setMaxSpeed(100);
stepper.setAcceleration(20);
}
void loop()
{
stepper.run();
static int previous = HIGH;
static unsigned long time = 0;
int reading = digitalRead(dirButton);
// if the input just went from LOW and HIGH and we've waited long enough
// to ignore any noise on the circuit, toggle the output pin and remember
// the time
if (reading == HIGH && previous == LOW && millis() - time > debounce)
{
time = millis();
if (state == HIGH)
{
stepper.moveTo(Bottom);
state = LOW;
}
else
{
stepper.moveTo(Top);
state = HIGH;
}
}
previous = reading;
}
that's not what i would expect to happen. when i tested the code, both the LEDs, representing the step and dir pins were on. these are active low so being on indicates the pins were LOW.
when i press the button, one LED begins flashing and then eventually stops, becoming on again.
the code you posted uses delayMicrosecond() and a delay of 1000 (1ms). this means ~msec /step and only 0.2 sec for 100 steps.
i don't understand several things which may (???) be explained if the code is stepping the motor too quickly.
of course, you need to understand what the code is doing. i added serial prints to help debug.
you could slow things down, at least 10 msec per step, verify the function of the button, determine why the motor does not stop. how fast can the motor be stepped?
I am not exactly sure how many revolutions I need yet. This will require testing for the raising and lowering because I am using a "reeling" method. The stepper I am using is a nema17 which has 200 steps per revolution.
Ok. I will try the code again and make sure wiring is correct. As for the issues in the code that I posted, that code is pulled from a tutorial that I watched which performed what I presumed to be a similar operation. Again, I may not quite realize what I need due to my lack of programming knowledge.