am a complete beginner at coding with Arduino, although I have used them for a few years by copying other peoples code. I only understand a tiny fraction of the layout of a sketch and would really appreciate some help to solve, what I believe, is a simple problem.
I have a sketch to control the speed and direction of a stepper motor:-
/*
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(LED_BUILTIN, OUTPUT);
pinMode (driverPUL, OUTPUT);
pinMode (driverDIR, OUTPUT);
attachInterrupt(digitalPinToInterrupt(reverseSwitch), revmotor, FALLING);
}
void loop() {
pd = map((analogRead(spd)),0,1023,1000,150);
digitalWrite(driverDIR,setdir);
digitalWrite(driverPUL,HIGH);
digitalWrite(LED_BUILTIN, HIGH);
delayMicroseconds(pd);
digitalWrite(driverPUL,LOW);
delayMicroseconds(pd);
}
This works perfectly with my stepper driver and stepper motor with good speed control. However, the author did warn that debounce might be a problem and this has proved to be the case. I understand the principal of debounce and I have studied a number of debounce sketches and can also understand the method of reduction using a few milliseconds delay. I believe that the following code is as simple as it can get but I have no idea how to incorporate this in the above sketch.
bool debounce() {
static uint16_t state = 0;
state = (state<<1) | digitalRead(btn) | 0xfe00;
return (state == 0xff00);
}
(The author appears to have split the code into two parts (I think)
#define btn 2 //assuming we use D2 on Arduino
void setup() {
pinMode(btn, INPUT_PULLUP);
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
if (debounce()) {
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
}
Can anyone look at these sketches and advise me if a) they are compatible and b) how do incorporate the debounce code into the working sketch?
Thanks in advance from a complete coding numptee (Scottish expression!)
2 Answers 2
You can try replacing the function revmotor() with this code. That is instead of using the separate debounce code that you have found. It works by locking out presses of the switch for 100ms following the last press.
void revmotor (){
static uint32_t lastSwitchAtMs = 0 ;
if ( millis() - lastSwitchAtMs > 100UL ) { // debounce 100ms
setdir = !setdir;
}
lastSwitchAtMs = millis() ;
}
Note that the variable setdir
should really be declared so volatile boolean setdir = LOW; // Set Direction
EDIT:
Incidentally, found the article that you followed here: https://dronebotworkshop.com/big-stepper-motors/ which includes the code and a schematic diagram.
-
This has worked perfectly. Thank you. I have tweaked the debounce delay up to 400 millis which works best with the switch that I am using. Thanks again.Solmod– Solmod2024年10月04日 13:21:24 +00:00Commented Oct 4, 2024 at 13:21
-
1@Solmod 400ms ? That must be some rough old switch but, anyway, I am happy that you have something which you can use. The code I supplied is a special case because it is not so usual to use an interrupt service routine to read a switch/button (overkill or sledgehammer to crack a nut) but there are cases where it is valid for example when the loop contains some blocking code.6v6gt– 6v6gt2024年10月04日 17:43:24 +00:00Commented Oct 4, 2024 at 17:43
-
The "switch" is actually the bare end of two wires at the moment until I could get everything working. Now that it works, I will be building up the physical circuit in a control box with a good quality press button switch - I may be able to reduce the period after that ;-). Anyway, thank you for you assistance - it has helped me a lot.Solmod– Solmod2024年10月04日 18:11:02 +00:00Commented Oct 4, 2024 at 18:11
I believe that the debounce() function and example was from me that I described in my blog post The simplest button debounce solution, in fact I was not the one who first write it, I adapted it from Jack Gansslle's A Guide to Debouncing - Part 2 that was first published way back to 2004.
In your case, all you need to do is when revmotor()
event is triggered, called the debounce function and alter the state of setdir
only if debounce
return true.
int reverseSwitch = 2; // Push button for reverse
void revmotor (){
if (debounce())
setdir = !setdir;
}
bool debounce() {
static uint16_t state = 0;
state = (state<<1) | digitalRead(reverseSwitch) | 0xfe00;
return (state == 0xff00);
}
void setup() {
// your pin setup code here
pinMode(reverseSwitch, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(reverseSwitch), revmotor, FALLING);
}
I must say that I did not test this particular code before post this answer, but I've been using it in similar use case in the past many times.
-
Thank you for getting involved - it is much appreciated. I have tried to follow your suggestions and I have altered my code accordingly, however, I get an error message saying "debounced" not declared in this scope. I'm not sure if I am reading this correctly but I see that the if (debounced) statement comes before the Bool debounce statement - does this have an impact on the program?Solmod– Solmod2024年10月04日 12:50:35 +00:00Commented Oct 4, 2024 at 12:50
-
My code now looks like this: void revmotor (){ if (debounced()) setdir = !setdir; } bool debounce() { static uint16_t state = 0; state = (state<<1) | digitalRead(reverseSwitch) | 0xfe00; return (state == 0xff00); } void setup() { pinMode (driverPUL, OUTPUT); pinMode (driverDIR, OUTPUT); attachInterrupt(digitalPinToInterrupt(reverseSwitch), revmotor, FALLING); }Solmod– Solmod2024年10月04日 12:53:59 +00:00Commented Oct 4, 2024 at 12:53
-
OK - problem solved - tiny spelling error debounce / debounced. code is running now although the debounce action is still a little erratic. I'll keep experimenting. Thank you.Solmod– Solmod2024年10月04日 12:58:48 +00:00Commented Oct 4, 2024 at 12:58
-
You could change the
0xfe00
to0x8000
and0xff00
to0xc000
to have longer debouncing period.hcheung– hcheung2024年10月05日 04:26:33 +00:00Commented Oct 5, 2024 at 4:26 -
Thank you again for your input. For me to understand what this change will do, could you explain what the changes mean please.Solmod– Solmod2024年10月06日 12:30:13 +00:00Commented Oct 6, 2024 at 12:30
digitalWrite(LED_BUILTIN, HIGH);
in the first code? ... it makes no sense to execute it repeatedlyThe author appears to have split the code into two parts
... the author used a function ... it is grouping code into sections that are more easily managed