I am trying to create a simple code using two buttons.
When you click one button, it should rotate by 90 degrees clockwise for a set acceleration and speed
When you click on another button it should rotate by 90 degrees anticlockwise for a set acceleration and speed i.e., to go back to the original position
Right now, the issue is that I need to click on the buttons a couple of times to activate. Its probably because of the state of the button but I am unable to debug that. I want to avoid using the state of the button and just take a click sensor to activate the rotation of the motor.
I also want to add a physical limitation in case someone accidentally moves the object by a couple of degrees, I want to reset to the previous position reached by the motor - I have not yet figured out how to do this or whether I need to add any controlling element.
I am including a link to Wokwi simulation as well 2 button test
I am not an expert in programming and this is a DIY project so I am learning things as I try different ideas and learn tricks.
Thank you!
#include <AccelStepper.h>
#define dirPin 8
#define stepPin 9
// Define button pins
#define buttonPinCW 2
#define buttonPinCCW 3
AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin);
void setup() {
// put your setup code here, to run once:
stepper.setMaxSpeed(20); // Set maximum speed value for the stepper
stepper.setAcceleration(1); // Set acceleration value for the stepper
stepper.setCurrentPosition(0); // Set the current position to 0 steps
}
void loop() {
boolean CWActive = digitalRead(buttonPinCW);
boolean CCWActive = digitalRead(buttonPinCCW);
if(CWActive == true) {
//Serial.println("Going Clockwise");
//stepper.setCurrentPosition(0)
stepper.moveTo(50);
stepper.run();
}
else if (CCWActive == true) {
//Serial.println("Going Counter Clockwise");
//stepper.setCurrentPosition(0);
stepper.moveTo(-50);
stepper.run();
}
}
Non sense! I see no attempts in the code you posted. There is always serial.Print() showing the results of some instruction. And there are LEDs you can add to show the results of something.
So your switches are wired to ground when closed. And you never set the pins to INPUT_PULLUP. You might want to think about what digitalRead will return when the switches are open, and the input pins aren't connected to anything.
Furthermore, your code looks at the state of the pin, not the event of being pressed. Something else to think about.
In particular, read the "How to Wire and Program a Button" stuff. Your inputs are floating, and if you use INPUT_PULLUP, they will be in the HIGH state and odd things will happed with your ==true logic.
The original position is 0, and there is nothing in the code to moveTo(0).
Consider also the MobaTools Stepper Example 3 -- it has a couple jog buttons and uses a nice state machine to do interesting logic handling:
As you're not setting the input/output mode of the two buttons pins you're using the default mode of the mcu, that is OD INPUT. you'll have to set the pinmode to INPUT_PULLUP, or set an external pullup or pulldown depending on your preferences.
You also need to debounce the button to ensure a clear and unique signal start and keep it stable, simply add a library to take care of that. In the simulation I see you added the toggle library, but never used it in your code.
Start there, then come back with the results to go further.
The toughest thing about your project to "learn" (not just "do") is reading a button press. You need to "wire" it, hold it steady when not active, know when it goes from "not pressed" to "pressed, disregard "noise" ("bounce"), know when the button goes from "pressed" to "not pressed" and register the button "was pressed" (as opposed to "is pressed."
Write your code while on the shoulders of giants who have written libraries that do all that thinking. These libraries and examples are linked in the other comments.
I looked at the code and did not immindiantly see a need for any button handling, on the assumption that the run() method blocks.
It does not. It's not just non-blocking, it actually needs to be called repeatedly in order for the motor to take the necessary steps (one at a time) to the targa position. From the documentation:
Note that each call to run() will make at most one step, and then only when a step is due, based on the current speed and the time since the last step.
Which would suit many of us just fine. @vimit might do better with an interrupt-driven stepper library that has more a launch and forget style of control for which now, yes, proper button handling will be necessary.
Thank you everyone for all your great input and guidance!! I learned new things along the way! I was able to simplify using a toggle switch and added a LnED as well.
The next challenge for me is to figure out how to use closed loop control in case the user (in this case myself) accidentally rotates the object by a couple of degrees. Object in this case is a counter table so a slim glass (more like a turn table). I'll reach out here again for questions. Any guidance would be helpful!
#include <AccelStepper.h>
#define dirPin 8
#define stepPin 9
#define switchPin 6
AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin);
void setup() {
pinMode(switchPin, INPUT_PULLUP);
pinMode(LED_BUILTIN, OUTPUT);
stepper.setMaxSpeed(20); // Set maximum speed value for the stepper
stepper.setAcceleration(1); // Set acceleration value for the stepper
stepper.setCurrentPosition(0); // Set the current position to 0 steps
}
void loop() {
if(digitalRead(switchPin) == HIGH) {
digitalWrite(LED_BUILTIN, digitalRead((6)));
stepper.moveTo(50);
stepper.runToPosition();
}
else if (digitalRead(switchPin) == LOW) {
digitalWrite(LED_BUILTIN, digitalRead((6)));
stepper.moveTo(0);
stepper.runToPosition();
}
}
Hi @vimit,
I'll add something to the situation noted by @alto777:
The change in the slide switch in the middle of a sweep will be ignored until the quarter turn ends... and then it'll be read, so you'll have your rotation backwards started even if you changed your mind of reversing, but forgot to set the slide switch back.
I mean... it's ok if you decide to label your switch with something like oº position, 90º position and it's what you really want, but if it's not, you're justa adjusting your whole project due to lack of debouncing procedure.
Once again, you can always use a debouncing library or a switch building library and keep the reigns of your project!