Hello,
I have followed this tutorial Using BIG Stepper Motors with Arduino | DroneBot Workshop
Using this sketch
/* Stepper Motor Test
stepper-test01.ino
Uses MA860H or similar Stepper Driver Unit
Has speed control & reverse switch
DroneBot Workshop 2019
https://dronebotworkshop.com
*/
// Defin pins
int reverseSwitch = 2; // Push button for reverse
int driverPUL = 7; // PUL- pin
int driverDIR = 6; // DIR- pin
int spd = A0; // Potentiometer
// Variables
int pd = 500; // Pulse Delay period
boolean setdir = LOW; // Set Direction
// Interrupt Handler
void revmotor (){
setdir = !setdir;
}
void setup() {
pinMode (driverPUL, OUTPUT);
pinMode (driverDIR, OUTPUT);
attachInterrupt(digitalPinToInterrupt(reverseSwitch), revmotor, FALLING);
}
void loop() {
pd = map((analogRead(spd)),0,1023,2000,50);
digitalWrite(driverDIR,setdir);
digitalWrite(driverPUL,HIGH);
delayMicroseconds(pd);
digitalWrite(driverPUL,LOW);
delayMicroseconds(pd);
}
I now have a bouncing problem with the reverse switch. I have tried splicing a Debouncing sketch into the code to try to resolve the switch issue to no avail after many attempts.
I am new to Arduino and programming and if someone could help me with the sketch to include Debouncing I'm sure it would break my learning impasse.
Thanks Chris
@azslab If Bill didn't need to debounce, why do you think you need to? The code appears to be the same.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
@zander Hi Ron,
I think the problem is with the switch I am using. I believe the little pushbutton microswitches used in the tutorial hookup are less prone to bouncing. I would like to use a limit switch to reverse the stepper motor. At the moment the stepper only changes direction if I have a lucky press.
I followed a debouncing experiment tutorial that switches the LED light on and off on pin 13 and it worked flawlessly. This used <Bounce2.h> from the library. If I could somehow incorporate this into the stepper motor control sketch I'd be verry happy.
Thanks Chris
@azslab Where exactly do you plan on using debounce code? If you look at the debounce example, you need to read the pin. In Bill's sketch that does not happen, it's just an interrupt. There is no place to do a debounce.
I have to admit I never thought of this before so am not positive.
The other thing to check is the pot. Toss a print in there to show you what pd is set to, it may be too short (that is effectively your debounce)
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
@azslab FYI, the type of switch is pretty much irrelevant, all mechanical switches exhibit more or less bounce.
BTRW, if your intention is to ONLY use a limit switch, you need to provide a second method in case you miss the switch. It's a stepper, so keeping track of position os fairly normal and then the limit switch is the backup. Just make sure that the linit is NOT at the absolute end, allow something like 10% error. If the step count is out by more than 10% AND the limit switch fails all is lost. A second limit switch? That is typical in the industrial applications I am familiar with.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
@zander Hi Ron,
I built a CNC gantry style mill/router machine. I use software limits as the primary and hardwired limit switches beyond the permitted travel of each axis. If this fails I have a big red stop button.
I've just finished building a rotary axis that I will add to my machine. Before I install it I like to play with it to make sure it runs OK and this is why I'm using the Arduino and Bill's sketch.
I know enough about CNC machines but I am a novice when it comes to Arduino and programming.
Thanks Chris
Since you're using an interrupt, the normal method of debouncing is less appropriate. I think instead of looking at the switch and deciding if it has been down long enough to count (as the normal debounce goes) you really want to check there has been a long enough time lapse since the last click occurred.
I have modified the sketch you posted and added two new variables lastPushed (which records the time that the Botton was pushed) and minPause (which is the minimum time you want to elapse before the NEXT click is recognized.
In the interrupt, it first checks if enough time has elapsed for the click to 'count'. If not, it just ignores the click. If true, it negates setdir and resets the time to 'now' ready for the next time check.
This example is to help you understand what needs to be done to solve this problem. You can adjust the value of minPause to get the best effect on your project.
/* Stepper Motor Test stepper-test01.ino Uses MA860H or similar Stepper Driver Unit Has speed control & reverse switch DroneBot Workshop 2019 https://dronebotworkshop.com */ // Defin pins int reverseSwitch = 2; // Push button for reverse int driverPUL = 7; // PUL- pin int driverDIR = 6; // DIR- pin int spd = A0; // Potentiometer unsigned long lastPushed=0; // Time of last accepted press unsigned long minPause= 25; // Minimum time between presses // Variables int pd = 500; // Pulse Delay period boolean setdir = LOW; // Set Direction // Interrupt Handler void revmotor() { if ( (lastPushed-millis())>minPause ) { setdir = !setdir; lastPushed = millis(); } } void setup() { pinMode(driverPUL, OUTPUT); pinMode(driverDIR, OUTPUT); attachInterrupt(digitalPinToInterrupt(reverseSwitch), revmotor, FALLING); } void loop() { pd = map((analogRead(spd)), 0, 1023, 2000, 50); digitalWrite(driverDIR, setdir); digitalWrite(driverPUL, HIGH); delayMicroseconds(pd); digitalWrite(driverPUL, LOW); delayMicroseconds(pd); }
Anything seems possible when you don't know what you're talking about.
@will @azslab The question remains, why did Bill not need that?
Did you notice the following?
Note
Inside the attached function,delay()
won’t work and the value returned bymillis()
will not increment. Serial data received while in the function may be lost. You should declare asvolatile
any variables that you modify within the attached function. See the section on ISRs below for more information.
from https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
In this case, it actually does not make sense to use an interrupt, just do a standard debounced read of the pin. Lots of debounce samples, the one you already have debounce.h is fine.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
@azslab Understood. As a one-time elevator designer/mechanic, a common approach is two limit switches in series. This way any one of the two will stop the motor. It is crucial that these be motor grade switches (lot's of amps and arcing, use appropriate spark suppression components). In the case of your gantry for instance one switch is placed on each side, not sure where they would be placed on your 'rotary axis' but I am sure it is doable.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
Thanks, I forgot to switch setdir to volatile. As I said the code was an example and would work for the original case. I agree that it is the wrong approach for a limit switch as you had said earlier.
I think that an in-line test of the limit switch in the main loop right before the stepper is pulsed would be the proper place for it although that will slow the carriage speed somewhat.
Anything seems possible when you don't know what you're talking about.
@will Also, millis() will NOT update inside an ISR.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
@will Also, millis() will NOT update inside an ISR.
I don't think that matters, does it ? The internal test is only to see if the minimum lapse has occurred, so any change in time WILL ALREADY HAVE HAPPENED between ISR calls and we never need to have the time update inside the ISR.
Anything seems possible when you don't know what you're talking about.
@will So the millis() call isn't needed?
I am still distubed by two things.
1. Why did Bill not encounter this.
2. Did the OP use the pot to change the delay (which effectively is the debounce time)
Maybe after the race I will wire up a stepper etc and try it myself, I hate to see more than the setting of 1 boolean in an ISR, but then I am a speed freak.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
1) Bill has faster fingers ? 🙂 Bill's switch always bounces an odd number of times ? @azslab's switch always bounces an even number of times?
2) the pot adjusts the time between stepper pulses, so it shouldn't affect switch timing at all. If the stepper is running slowly, then the chance of a 'bounce' in the switch is decreased. That is, the switch keeps bouncing during the slow step and has settled by the time it's finished and ready to pulse the direction pin.
Since the pot adjusts the stepper pulse time from 50 ms to 2 sec, the entire time for step ranges from 100 ms to 4 sec. Since the switch is driven by an interrupt it can see clicks and resulting bounces at any time, depending on the type of switch (and possibly build quality). But, it can only change direction AFTER the current step is completed. So pressing the switch while the stepper is taking 4 seconds to make a step means you won' see the effect for up to 4 seconds.Perhaps Bill never ran his version at full speed.
Reading the switch directly in the loop guarantees that a minimum of 100 ms has passed (since the last step) and would suggest that, with a good switch, no debouncing would ever be needed.
Anything seems possible when you don't know what you're talking about.
@will @azslab Here is Mr. Gammon's approach.
const byte LED = 13; const byte BUTTON = 2; // Interrupt Service Routine (ISR) void switchPressed () { if (digitalRead (BUTTON) == HIGH) digitalWrite (LED, HIGH); else digitalWrite (LED, LOW); } // end of switchPressed void setup () { pinMode (LED, OUTPUT); // so we can update the LED digitalWrite (BUTTON, HIGH); // internal pull-up resistor attachInterrupt (digitalPinToInterrupt (BUTTON), switchPressed, CHANGE); // attach interrupt handler } // end of setup void loop () { // loop doing nothing }
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.