Hi all,
I was wondering if someone could help me troubleshoot my code; I've tried looking around on the forums and can't seem to make any of the solutions I've found work!
What I'm trying to do is simply issue a command to my stepper motor (this is the driver I'm using) to step a set number of times so as to make one full rotation, which I can adjust depending on the microstepping setting I choose on the driver.
What I believe is happening is the singleStep() function is not returning to the stepFunction() to see if it needs to repeat, but rather just skipping back out to the readButtons() function.
Does anyone know how I can make it complete this command before it reads the button status again? I.e. make the "for loop" work properly?
Thank you in advance!
byte directionPin = 44;
byte pulsePin = 46;
byte initiatePin = 50; // inititate one full revolution
boolean initiatePinPressed = false;
const int microStepSetting = 1600; // number of steps per revolution as set on driver
unsigned long curMillis;
unsigned long prevStepMillis = 0;
unsigned long millisBetweenSteps = 10; // milliseconds between steps (default = 25)
// the setup function runs once when you press reset or power up the board.
void setup() {
Serial.begin(9600);
Serial.println("Starting Stepper Demo with millis()");
pinMode(pulsePin, OUTPUT); //initialize digital pin 45 as the pulse pin output.
pinMode(directionPin, OUTPUT); //initialize digital pin44 as the direction pin output.
pinMode(initiatePin, INPUT_PULLUP);
}
void loop() {
curMillis = millis();
readButtons();
actOnButtons();
}
void readButtons() {
initiatePinPressed = false;
if (digitalRead(initiatePin) == LOW) {
initiatePinPressed = true;
Serial.println("Initiate Pin Pressed");
}
if (digitalRead(initiatePin) == HIGH) {
initiatePinPressed = false;
}
}
void actOnButtons() {
if (initiatePinPressed == true) {
stepFunction();
}
}
void stepFunction() {
for (int i=0; i <= microStepSetting; i++){
singleStep();
}
}
void singleStep() {
if (curMillis - prevStepMillis >= millisBetweenSteps) {
prevStepMillis += millisBetweenSteps;
digitalWrite(pulsePin, HIGH); // turn on pulsePin
delayMicroseconds(30); //delay each pulse before pulse turns off
digitalWrite(pulsePin, LOW); // turn off pulsePin
}
}
a) get rid of the print statement line 38
b) you're sending pulses far too quickly, try changing delayMicroseconds(30) to delay(1) and work back
c) you need the low on the pulse to last a non-zero length of time so put another delay(1) after line 62
Looking at it further, your if statement in singleStep() will jump back to stepFunction until time has elapsed which is 10ms, probably plenty of time for your 1000 iterations in stepFunction.
You could change that to while(curMillis - prevStepMillis <= millisBetweenSteps){}; and dispense with the timing changes I mentioned above. singleStep becomes:
void singleStep() {
while(curMillis - prevStepMillis <= millisBetweenSteps) {}; // wait
prevStepMillis += millisBetweenSteps;
digitalWrite(pulsePin, HIGH); // turn on pulsePin
delayMicroseconds(30); //delay each pulse before pulse turns off
digitalWrite(pulsePin, LOW); // turn off pulsePin
}
There are better ways to do this.
I tried both of your suggestions, but neither of them seemed to work; the motor would only advance while I had the button pressed down.
You said there are better ways of doing this? How would you approach it? I would like to continue to control about 8 relays independently while I execute this, so I'd like to avoid using delays if at all possible!
So it works while the button is pushed? That's what your logic tells it to do.
Thanks for the link.
Does my logic not say to execute stepFunction in its entirety if the readButton returns TRUE just once? If so, it should complete the defined number of steps before consulting the readButton function again.. that's my question: why does it only step while the button is pressed, and stop the moment it is released?
I can't find what I'm missing to make this work
I've figured out a way to make it work.. I just commented out the millis() control. I guess that was the issue.
Any idea as to why millis() won't work in this case? I can't find anything.
Thanks
byte directionPin = 44;
byte pulsePin = 46;
byte initiatePin = 50; // inititate one full revolution
boolean initiatePinPressed = false;
const int microStepSetting = 1600; // number of steps per revolution as set on driver
unsigned long curMillis;
unsigned long prevStepMillis = 0;
unsigned long millisBetweenSteps = 25; // milliseconds between steps (default = 25)
// the setup function runs once when you press reset or power up the board.
void setup() {
Serial.begin(9600);
Serial.println("Starting Stepper Demo with millis()");
pinMode(pulsePin, OUTPUT); //initialize digital pin 45 as the pulse pin output.
pinMode(directionPin, OUTPUT); //initialize digital pin44 as the direction pin output.
pinMode(initiatePin, INPUT_PULLUP);
}
void loop() {
curMillis = millis();
readButtons();
actOnButtons();
}
void readButtons() {
initiatePinPressed = false;
if (digitalRead(initiatePin) == HIGH) {
initiatePinPressed = true;
Serial.println("Initiate Pin Pressed");
}
if (digitalRead(initiatePin) == LOW) {
initiatePinPressed = false;
}
}
void actOnButtons() {
if (initiatePinPressed == true) {
stepFunction();
}
}
void stepFunction() {
for (int i=0; i <= microStepSetting; i++){
singleStep();
}
}
void singleStep() {
// if (curMillis - prevStepMillis >= millisBetweenSteps) {
// prevStepMillis += millisBetweenSteps;
digitalWrite(pulsePin, HIGH); // turn on pulsePin
delayMicroseconds(1000); //delay each pulse before pulse turns off
digitalWrite(pulsePin, LOW); // turn off pulsePin
//}
}
You were jumping in and out of singleStep() waiting for 10ms to pass while still incrementing in stepFunction(), consuming your 1000 iterations while doing nothing. When 10ms was up, you reset the 'wait' for another 10ms and issued a single pulse. Not too many (if any) 10ms 'waits' are going to pas before your for loop in stepFunction() increments to 1000 and finishes.