I am new to the forum and hope I am posting my question on the right thread. I am working on a fixture and I require some help. I need a way to determine the 'homing' (center) position of my stepper motor. I am thinking of using limit switches but I also did some research on rotary encoders and would like to know if it is possible to do it with rotary encoder. I am fairly new to Arduino and would like to know how to go about with this.
Below I have listed how I want to program the motor to run.
The motor is connected to a gear assembly and a shaft attached to the center of a beam. On either end of the beam are two limit switches. ( Like a see-saw)
Determining the centre position of the motor will help to determine if the beam is equally balanced.
To determine this center position the motor is to turn clockwise until the first limit switch is triggered. Then the motor would stop and turn anticlockwise and count the steps until the other limit switch is triggered. Then the program is to take the total number of steps and find the center (midpoint of the steps) and so the motor will turn back clockwise and stop at the center ( by going half the number of steps). This should therefore keep the beam equally balanced.
I am working on a code for this at the moment but would like some thoughts on if there is an easier approach to take by using a rotary encoder.
Your proposal seems quite normal, doesn't need alternatives. Please post the code you have written, paying attention to the forum guidelines about how to post code.
As stated, your topic might also go under "project Guidance" but most people who read there also read here, so it's not a big issue.
If you have specific doubts or questions about your own approach, please voice them so they can be addressed specifically.
I have one bit of advice - you can calibrate the number of steps and record that somewhere, you don't need to recalculate it every time.
I don't know why you need the encoder. If you have limit switches at both extremes, it seems to me, that that is all you need unless your stepper is prone to missing steps. If that is the case I would fix the problem with the stepper, not use an encoder as a band-aid. The way that you describe finding center is perfectly reasonable, I use the same 2 switch method on one of my 2D plotters to find a center of one axis.
Thank you for your response. I do require some help with the coding as well. I have just been doing simple coding for stepper motor controls by looking at the tutorials available.
Ok thank you for the clarification. Is it possible to see how you did the coding (if its allowed on the forum). Of course it will probably be different to what I am trying to do but will help me understand what approach to take.
You provided a better than average solution description. Yet, you haven't really explained what you exact difficulty is, in coding it. Also no details of your hardware.
Have you at least made the stepper move and, for example, stop and wait at one limit switch? You should. You don't need advice on that here, it's easy to find examples in the stepper libraries and in many different similar projects all over the net.
Then we could help you with your own specific, definite code if you can't grasp the next steps.
The only difference between what you posted and what was suggested, you would count stepper pulses not encoder pulses... or issue a count to the stepper library and let it execute them.
By the way, I see information in post #11 that should have been in post #1. Be aware that the number of posts you are allowed as a new member is limited in the first 24 hours...
What is strange about that, as I said, you actually described the problem better than most people do. It's puzzling that you say you can't extrapolate from that. For example, the number of steps to reach the middle, is half the total number of steps. Right?
If you are asking how to count steps, it's a library function question, so posting the example sketch you are working with will help a great deal.
Its because I haven't done coding before and its my first time learning Arduino to do this project. So I know the basis of what needs to be done, i.e. how I need everything to run and work but trying to code it is what I don't know. But thank you for the tips. I'll get a code made and if I have any more doubts I'll post here.
The code I am using is from online, I haven't made any changes to it or anything. Should I still post it here?
I should probably keep this quiet, but there are people on here that will write code for you. But even they can't help without some code and details to start with.
If it's already public and open source, sure. People who read the forum on phones need posted code in code tags to make it readable.
Here, it was as simple as some mouse clicks:
/*
* Created by ArduinoGetStarted.com
*
* This example code is in the public domain
*
* Tutorial page: https://arduinogetstarted.com/tutorials/arduino-stepper-motor-and-limit-switch
*/
#include <ezButton.h>
#include <AccelStepper.h>
#define MAX_POSITION 0x7FFFFFFF // maximum of position we can set (long type)
ezButton limitSwitch(A0); // create ezButton object that attach to pin A0;
AccelStepper stepper(AccelStepper::FULL4WIRE, 7, 6, 5, 4);
bool isStopped = false;
void setup() {
Serial.begin(9600);
limitSwitch.setDebounceTime(50); // set debounce time to 50 milliseconds
stepper.setMaxSpeed(500.0); // set the maximum speed
stepper.setAcceleration(50.0); // set acceleration
stepper.setSpeed(100); // set initial speed
stepper.setCurrentPosition(0); // set position
stepper.moveTo(MAX_POSITION);
}
void loop() {
limitSwitch.loop(); // MUST call the loop() function first
if (limitSwitch.isPressed()) {
Serial.println(F("The limit switch: TOUCHED"));
isStopped = true;
}
if (isStopped == false) {
// without this part, the move will stop after reaching maximum position
if (stepper.distanceToGo() == 0) { // if motor moved to the maximum position
stepper.setCurrentPosition(0); // reset position to 0
stepper.moveTo(MAX_POSITION); // move the motor to maximum position again
}
stepper.run(); // MUST be called in loop() function
} else {
// without calling stepper.run() function, motor stops immediately
// NOTE: stepper.stop() function does NOT stops motor immediately
Serial.println(F("The stepper motor is STOPPED"));
}
}
Have you consulted the stepper library documentation and examples?
Have you set up the hardware and run this example?
The code used here makes the motor continuously rotate and change direction whenever the a limit switch is triggered. I am trying to incorporate this code but do it so that it wont keep looping continuously and stop at its center after both limit switches are pressed only once.
#include <ezButton.h>
#include <AccelStepper.h>
#define DIRECTION_CCW -1
#define DIRECTION_CW 1
#define STATE_CHANGE_DIR 1
#define STATE_MOVE 2
#define STATE_MOVING 3
#define MAX_POSITION 0x7FFFFFFF // maximum of position we can set (long type)
ezButton limitSwitch_1(A0); // create ezButton object that attach to pin A0;
ezButton limitSwitch_2(A1); // create ezButton object that attach to pin A1;
AccelStepper stepper(AccelStepper::FULL4WIRE, 7, 6, 5, 4);
int stepperState = STATE_MOVE;
int direction = DIRECTION_CW;
long targetPos = 0;
void setup() {
Serial.begin(9600);
limitSwitch_1.setDebounceTime(50); // set debounce time to 50 milliseconds
limitSwitch_2.setDebounceTime(50); // set debounce time to 50 milliseconds
stepper.setMaxSpeed(500.0); // set the maximum speed
stepper.setAcceleration(50.0); // set acceleration
stepper.setSpeed(100); // set initial speed
stepper.setCurrentPosition(0); // set position
}
void loop() {
limitSwitch_1.loop(); // MUST call the loop() function first
limitSwitch_2.loop(); // MUST call the loop() function first
if (limitSwitch_1.isPressed()) {
stepperState = STATE_CHANGE_DIR;
Serial.println(F("The limit switch 1: TOUCHED"));
}
if (limitSwitch_2.isPressed()) {
stepperState = STATE_CHANGE_DIR;
Serial.println(F("The limit switch 2: TOUCHED"));
}
switch (stepperState) {
case STATE_CHANGE_DIR:
direction *= -1; // change direction
Serial.print(F("The direction -> "));
if (direction == DIRECTION_CW)
Serial.println(F("CLOCKWISE"));
else
Serial.println(F("ANTI-CLOCKWISE"));
stepperState = STATE_MOVE; // after changing direction, go to the next state to move the motor
break;
case STATE_MOVE:
targetPos = direction * MAX_POSITION;
stepper.setCurrentPosition(0); // set position
stepper.moveTo(targetPos);
stepperState = STATE_MOVING; // after moving, go to the next state to keep the motor moving infinity
break;
case STATE_MOVING: // without this state, the move will stop after reaching maximum position
if (stepper.distanceToGo() == 0) { // if motor moved to the maximum position
stepper.setCurrentPosition(0); // reset position to 0
stepper.moveTo(targetPos); // move the motor to maximum position again
}
break;
}
stepper.run(); // MUST be called in loop() function
}