Hello,
Doing this code for a school project, and for it I am using a stepper motor. I have spent hours using multiple versions of the T Flip Flop, but no matter which one I use, the motor will only stay on for about a second or two before turning off. How can I make the motor stay on when toggled on?
Literally just did some edits as well as value checking. I've fixed the error of it turning off, however now it stays on. According to the serial monitor, enable is immediately being set to 'true' after being toggled off.
Edit: I did remove the delay(100), however with or without the delay I still get the same problem.
Here is a code that demonstrates how to write a function that creates a toogle-switch functionality with a momentary push-button.
This code is well organised in functions where each function does one thing
The code itself has additional explanations how it works
/* explanation of the most important details:
realising a functionality where using a momentary push-button
acts as a toogle-switch
push => activated push again => DE-activated
push again => activated push again => DE-activated
etc. etc. ...
This needs quite some code. This code is well organised in MULTIPLE functions
where each function is a senseful SUB-program
This is the reason why function loop looks super-short:
void loop () {
activationMode = GetToggleSwitchState(); // must be executed all the time
execute_if_Active(activationMode); // function that does what its name says
}
Huh that's all? No. Of course there is more (below function loop)
If you just want to APPLY the functionality to your own code
replace the code inside function void my_Action()
with your own code that shall only be executed if you activated execution
with the momentary push-button
I recommend to RENAME the function my_Action() to a SELF-explaining name
This will cause a compiler-error which shows you where you have to rename
the function-call of this function too (this is inside function execute_if_Active
If you want to understand how it works read and analyse the rest of the functions.
*/
/*
overview:
function setup() is that function that is always executed only ONCE
the function loop() start doing what its nam says: LOOPING around and around infinetely
inside function
loop()
- GetToggleSwitchState()
- execute_if_Active()
- my_Action()
loop() calls-->execute_if_Active() calls--->my_Action()
inside function myAction the onBoard-LED is made blinking
*/
#define ProjectName "Toggle Button demonstration"
// define IO-states for inputs with pull-up-resistors
// pull-up-resistors invert the logig
#define unPressed HIGH
#define pressed LOW
const byte ToggleButtonPin = A0;
bool activationMode = false;
unsigned long myCounter = 0;
unsigned long MyBlinkTimer = 0;
void setup() {
Serial.begin(115200); // adjust baudrate in the serial monitor to match the number
Serial.println( F("Setup-Start") );
printFileNameDateTime();
pinMode (LED_BUILTIN, OUTPUT); // used for indicating logging active or not
digitalWrite(LED_BUILTIN, LOW);
// wire button between IO-pin and GND
// Pull-up-resistor inverts the logic
// unpressed: IO-pin detects HIGH
// pressed: IO-Pin detects LOW
pinMode(ToggleButtonPin, INPUT_PULLUP);
MyBlinkTimer = millis();
}
// this is the function that is called
// inside function execute_if_Active()
void my_Action() {
if ( TimePeriodIsOver(MyBlinkTimer, 250) ) {
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN) ); // read state of LED-output and set to invertetd state
}
}
void loop () {
activationMode = GetToggleSwitchState(); // must be executed all the time
execute_if_Active(activationMode); // function that does what its name says
}
bool GetToggleSwitchState() {
// "static" makes variables persistant over function calls
static bool toggleState = false;
static bool lastToggleState = false;
static byte buttonStateOld = unPressed;
static unsigned long buttonScanStarted = 0;
unsigned long buttonDebounceTime = 50;
static unsigned long buttonDebounceTimer;
byte buttonStateNew;
if ( TimePeriodIsOver(buttonDebounceTimer, buttonDebounceTime) ) {
// if more time than buttonDebounceTime has passed by
// this means let pass by some time until
// bouncing of the button is over
buttonStateNew = digitalRead(ToggleButtonPin);
if (buttonStateNew != buttonStateOld) {
// if button-state has changed
buttonStateOld = buttonStateNew;
if (buttonStateNew == unPressed) {
// if button is released
toggleState = !toggleState; // toggle state-variable
} // the attention-mark is the NOT operator
} // which simply inverts the boolean state
} // !true = false NOT true is false
// !false = true NOT false is true
return toggleState;
}
void execute_if_Active(bool p_IsActivated) {
printActionState(p_IsActivated); // for demonstration purposes only
if (p_IsActivated) {
my_Action(); // <<<<== inside this function you do what shall be executed only if mode isActivated is true
}
}
void printFileNameDateTime() {
Serial.print( F("File : ") );
Serial.println( F(__FILE__) );
Serial.print( F("Date : ") );
Serial.println( F(__DATE__) );
Serial.print( F("Project: ") );
Serial.println( F(ProjectName) );
}
// ignore at first
// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
void printActionState(boolean p_IsActivated) {
static boolean lastIsActivated;
if ( p_IsActivated != lastIsActivated) {
// only if state of parameter p_logIsActivated has changed
if (p_IsActivated) {
Serial.println();
Serial.println("start executing");
Serial.println();
digitalWrite(LED_BUILTIN, HIGH);
}
else { // not activated
Serial.println();
Serial.println("stopp executing");
Serial.println();
digitalWrite(LED_BUILTIN, LOW);
}
lastIsActivated = p_IsActivated; // update variable lastSDlogActive
}
}
@itsfoxy87 let's get your crude but simple program to function.
Here's your idea, only instead of starting and stopping a motor, we turn on and off an attached LED.
Note: I wired the switch in a conventional manner, between the input pin and ground, and used INPUT_PULLUP mode for it.
Therefore, the switch reads LOW when presst.
Note: I greatly increased the delay as I have fat fingers and have trouble getting on and off the buton fast enough.
bool enable = false;
void setup() {
//...
pinMode(7, INPUT_PULLUP);
pinMode(6, OUTPUT);
Serial.begin(9600);
}
void loop() {
// wire your switch between the pin and ground. then when pressed it will read LOW
if (digitalRead(7) == LOW) {
//...
delay(300);
enable = !enable;
}
Serial.println(enable);
if (enable == true) {
digitalWrite(6, HIGH);
}
else {
digitalWrite(6, LOW);
}
}
Once you have that working, please check the documentation on the Stepper so that you can confidently make the motor run where the code now lights the LED, and stop where the code now extinguishes the LED.
Once that functions to your satisifaction, you may want to ask about real switch handling to replace the "poor man's" method which though effective is crude and will not serve you very well in anything larger than this small sketch.
The switch I'm using is weird, it's a limit switch module from Adeept, it only functions if it is powered by both VCC and Ground, which the input then goes into 7. I don't have any LEDs or really any other Arduino component at the moment, I'll have to get one from home tomorrow before school.
Edit: The Arduino is unplugged in this photo, hence the light being off.
the onboard LED of the arduino-board itself.
usually the onboard-LED is wired to IO-pin 13
For the demo-code I have posted you would simply add
stepper.step(1); // do a SINGLE step
inside the function myAction
What do you think:
Will you be able to copy and paste the code-version below into the arduino-IDE
compile and flash the code for a test?
The code below uses IO-pin 7 as start/stop button and uses the stepper-library to drive your stepper-motor.
The button on IO-pin 7 must be connected to IO-pin and ground.
It uses the input-mode INPUT_PULLUP which is different from your mode "INPUT"
#include <Stepper.h>
#define STEPS 100
Stepper stepper(STEPS, 8, 9, 10, 11);
#define ProjectName "Toggle Button stepper on/off"
// define IO-states for inputs with pull-up-resistors
// pull-up-resistors invert the logig
#define unPressed HIGH
#define pressed LOW
const byte ToggleButtonPin = 7;
bool activationMode = false;
unsigned long myCounter = 0;
unsigned long MyBlinkTimer = 0;
void setup() {
Serial.begin(115200); // adjust baudrate in the serial monitor to match the number
Serial.println( F("Setup-Start") );
printFileNameDateTime();
pinMode (LED_BUILTIN, OUTPUT); // used for indicating logging active or not
digitalWrite(LED_BUILTIN, LOW);
// wire button between IO-pin and GND
// Pull-up-resistor inverts the logic
// unpressed: IO-pin detects HIGH
// pressed: IO-Pin detects LOW
pinMode(ToggleButtonPin, INPUT_PULLUP);
MyBlinkTimer = millis();
}
// this is the function that is called
// inside function execute_if_Active()
void my_Action() {
stepper.step(1); // do a SINGLE step
if ( TimePeriodIsOver(MyBlinkTimer, 250) ) {
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN) ); // read state of LED-output and set to invertetd state
}
}
void loop () {
activationMode = GetToggleSwitchState(); // must be executed all the time
execute_if_Active(activationMode); // function that does what its name says
}
bool GetToggleSwitchState() {
// "static" makes variables persistant over function calls
static bool toggleState = false;
static bool lastToggleState = false;
static byte buttonStateOld = unPressed;
static unsigned long buttonScanStarted = 0;
unsigned long buttonDebounceTime = 50;
static unsigned long buttonDebounceTimer;
byte buttonStateNew;
if ( TimePeriodIsOver(buttonDebounceTimer, buttonDebounceTime) ) {
// if more time than buttonDebounceTime has passed by
// this means let pass by some time until
// bouncing of the button is over
buttonStateNew = digitalRead(ToggleButtonPin);
if (buttonStateNew != buttonStateOld) {
// if button-state has changed
buttonStateOld = buttonStateNew;
if (buttonStateNew == unPressed) {
// if button is released
toggleState = !toggleState; // toggle state-variable
} // the attention-mark is the NOT operator
} // which simply inverts the boolean state
} // !true = false NOT true is false
// !false = true NOT false is true
return toggleState;
}
void execute_if_Active(bool p_IsActivated) {
printActionState(p_IsActivated); // for demonstration purposes only
if (p_IsActivated) {
my_Action(); // <<<<== inside this function you do what shall be executed only if mode isActivated is true
}
}
void printFileNameDateTime() {
Serial.print( F("File : ") );
Serial.println( F(__FILE__) );
Serial.print( F("Date : ") );
Serial.println( F(__DATE__) );
Serial.print( F("Project: ") );
Serial.println( F(ProjectName) );
}
// ignore at first
// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
void printActionState(boolean p_IsActivated) {
static boolean lastIsActivated;
if ( p_IsActivated != lastIsActivated) {
// only if state of parameter p_logIsActivated has changed
if (p_IsActivated) {
Serial.println();
Serial.println("start executing");
Serial.println();
digitalWrite(LED_BUILTIN, HIGH);
}
else { // not activated
Serial.println();
Serial.println("stopp executing");
Serial.println();
digitalWrite(LED_BUILTIN, LOW);
}
lastIsActivated = p_IsActivated; // update variable lastSDlogActive
}
}
If you are not comfortable with using a jumper or even a short length of plain wire between the I/O pin and ground, see if you can get a LED to simply echo the condition coming from your weird switch.
void loop() {
int theSwitch = digitalRead(7);
if (digitalWrite(6, theSwitch);
}
Then if you cannot change the sense of the switch as I did, just change the logic of the if statement in your poor man's switch handler, viz:
You can use the build-in LED on your Arduino board. On the UNO this is at digital output 13. Usually it is also on a named pin LED_BUILTIN, like
// in setup()
pinMode(LED_BUILTIN, OUTPUT);
// and then anywhere
digitalWrite(LED_BUILTIN, HIGH);
which I hope is obvious by now.
There also appear to be LEDs on the weird switch board. I saw similar modules but did not find your exact version, so cannot advise with actual code.
Do you have a part number or link to where it was purchased, or a pointer to a product of whichit is a part?
It will be good for you to develop an inquisitive nature and a willingness to experiment. It is also a good idea to break even such a simple sketch as you are working on into the tiniest of pieces.
You could also do a huge amount of the work by using a simulator. Try
the best of them at the moment. I'd like to say it is mostly intuitive, dare to pretend that you know what you are doing and see if you can rig a pushbutton and LED to perform the code in my #7 above.
The simulator will let you add a stepper motor to this sketch. I am usually able to do nearly 100 percent of the software for a small project without needing to touch any hardware except my keyboard and mouse.
It makes taking a sketch into the real world, where there will inevitably be issues cropping of of a different nature much easier. If you know the software works, and you have problems, it is very more likely to be hardware which cuts way back on the areas where you must focus.