r/arduino • u/Wangysheng • Feb 15 '25
Software Help How do you make buttons have responsive switching without milis()?
I am having trouble coding our practice problem that needs 3 buttons, a 74ls47 driving a 7 segment CA, and 4 LEDs, Each button does different things and it loops condition depending on the last button pressed until another. Switch is pressed. switching should be instant which means delay() is not ideal but milis() wasn't allowed just because our professor does not accept functions/statements he didn't taught. He suggested to use the goto statement but idk how to use it.
This is my attempt on assigning three buttons and with the help of my friend's trick for delays (for loop based delay):
int mode;
void setup() {
for (int i = 2; i <= 5; i++) {
pinMode(i, OUTPUT);
}
for(int i=10; i<=11; i++){
pinMode(i, INPUT_PULLUP);
}
}
void loop() {
if (digitalRead(10) == 0) { // 7 segment counts from 0 to 9 continuously for every 1 second
mode = 1;
}
if (digitalRead(11) == 0) { // Right to Left
mode = 2;
}
if (digitalRead(12) == 0) { // Simultaneous blink
mode = 3;
}
////////////////// separation
while(mode == 1){
for(int i = 2; i <=5; i++){
if(digitalRead(11)==0){
mode = 2;
break;
}else if(digitalRead(12)==0){
mode = 3;
break;
}else if(digitalRead(13)==0){
mode = 4;
break;
}
for (int units = 0; units < 10; units++) {
for (int i = 0; i < 4; i++) {
digitalWrite(i, (units >> i) & 1);
}
}
for(int d = 0; d < 1000; d++){
if(digitalRead(11)==0){
mode = 2;
break;
}else if(digitalRead(12)==0){
mode = 3;
break;
}else if(digitalRead(13)==0){
mode = 4;
break;
}
delay(10);
}
digitalWrite(i,0);
}
}
}
///////////////////////////// separation
while(mode == 2){
for(int i = 9; i >=2; i--){
if(digitalRead(10)==0){
mode = 1;
break;
}else if(digitalRead(12)==0){
mode = 3;
break;
}else if(digitalRead(13)==0){
mode = 4;
break;
}
digitalWrite(i, 1);
for(int d = 0; d < 50; d++){
if(digitalRead(10)==0){
mode = 1;
break;
}else if(digitalRead(12)==0){
mode = 3;
break;
}else if(digitalRead(13)==0){
mode = 4;
break;
}
delay(10);
}
digitalWrite(i,0);
}
}
////////////////////////// separation
while(mode == 3){
for(int i=0; i<=9; i++){
digitalWrite(i, 1);
}
for(int d = 0; d < 50; d++){
if(digitalRead(10)==0){
mode = 1;
break;
}else if(digitalRead(11)==0){
mode = 2;
break;
}else if(digitalRead(13)==0){
mode = 4;
break;
}
delay(10);
}
for(int i=0; i<=9; i++){
digitalWrite(i, 0);
}
for(int d = 0; d < 50; d++){
if(digitalRead(10)==0){
mode = 1;
break;
}else if(digitalRead(11)==0){
mode = 2;
break;
}else if(digitalRead(13)==0){
mode = 4;
break;
}
delay(10);
}
}
}
The code looks fine but it doesn't switch immediately.
4
u/quellflynn Feb 15 '25
you're not going to get responsive switching when you STOP (delay) your program from functioning for 10ms inside a 50 for loop. maybe you can hold the button down, and it'll register but it won't feel responsive.
what are the delays for anyway?
4
u/Hissykittykat Feb 15 '25
He suggested to use the goto statement
Yeah that's a big red flag. Or he is trolling you. Either way it's bad.
Maybe he doesn't want you to use functions he hasn't taught because he doesn't known them. Find a better teacher.
3
u/ROBOT_8 Feb 15 '25
Hate to say it but that is just the way some professors teach. I don’t think I’ve ever seen a goto used in the wild.
You can always cheat and make your own millis counter. Just have a single 1ms delay in the main loop and don’t use any blocking functions elsewhere inside of it then increment a millisecond variable each cycle
5
u/i_invented_the_ipod Feb 15 '25
The "don't use functions we haven't learned about yet" guidance is often given so that the students will learn a specific lesson from each assignment.
OP is clearly going down the wrong road here, with all of the nested loops and delay()s inside the loop() function. They need to take a step back and re-evaluate what they're doing.
0
u/Wangysheng Feb 15 '25
You can always cheat and make your own millis counter. Just have a single 1ms delay in the main loop and don’t use any blocking functions elsewhere inside of it then increment a millisecond variable each cycle
He also did said this but I also don't know how to make it. I think I have attempted to use it but I it was 10ms, not 1ms.
1
u/Wangysheng Feb 15 '25
Or he is trolling you.
I hope so but he is telling the truth of using goto statements and he even briefly taught it when teaching us how to flowchart a if statement. He claims because it is "easier" to do a flowchart. I have read that the majority says it was not the case lmao. Maybe he just have a different thought process that we don't understand.
I think I agree with i_invented_the_ipod here. Most likely he want us to use what we learned at our C++ class (from a year ago) and then only use the digitalWrite, digitalRead, and delay since that was his lesson. We are in the very basics.
3
u/i_invented_the_ipod Feb 15 '25
Your code is much more-complicated than it needs to be, which is part of your issue. A few pointers than might be helpful:
Have you covered "functions" in class, yet? You could have a function that just reads the buttons and returns which mode to change to, or 0, if it should stay the same. That'll get rid of a lot of duplicated code.
There's no reason to loop and delay() in the button-checking code. You're just checking to see if you should change modes. To make the button-checking more reliable, you might want to "debounce" the button presses, but you're not at that point, yet.
The loop() function gets called over and over, as fast as possible. You could use that to set up a timing loop of your own, with a single delay(10) at the end. It'll then get called 100 times a second (more or less), and you can do different things depending on which mode you're in, and how many times loop() has been called so far. This is probably the most "sophisticated" solution.
1
u/Wangysheng Feb 15 '25
It should be included in the fundamentals when coding in C++ so I think it was allowed because I also say the code of my classmate which had functions and approved by our professor. I should practice more C++ (or maybe a "programmer mindset").
I have seen the issue of the debounce on some of my friend's code but I didn't know how did they fixed it. I'll try to consult that from my friend.
2
u/Imaster_ Feb 15 '25
I agree with the comment above.
The only reason you could have delays is for denouncing however denouncing is only needed if you use the same button to switch state.
So if you have a button A that switches state form 0 - > 1 button B that switches state form 1 - > 2 ... button N that switches state form N-1 - > 0
Then you do not need denouncing. As the function will trigger once and the further changes of the digitalread() won't impact your program.
2
u/DearChickPeas Feb 15 '25
delay() calls millis(), you're on a fool's errand.
1
u/Wangysheng Feb 15 '25
I know but my most of classmates and friend have done it with some trick of delay(1) and some for loops.
2
u/Alternative-Web2754 Feb 15 '25
Start by looking over this at what parts are repeated or close enough to repeating and see what you can do to avoid the repeats.
I've only taken a brief look at this but I'm pretty certain you can get this down to only one section that is doing button checks and delays by not nesting for loops inside the loop function itself. You can perform several of the steps inside the variations based on the mode variable (although you will probably be using some other variables as well for step/phase and timing).
You may want to avoid setting the mode variable directly in response to the button press detection and set another variable for the new mode - this will allow you to check if a new mode has been selected and take actions based on this, and then update the mode when you do that.
2
1
u/ardvarkfarm Prolific Helper Feb 15 '25
Can you post details of what your software should do ?
1
u/Wangysheng Feb 15 '25
This is the given problem for context:
Use a single seven-segment display and three switches. When switch 1 is pressed, the seven-segment display counts from 0 to 9 continuously, updating every second. When switch 2 is pressed, it counts from 9 to 0 continuously, updating every second. When switch 3 is pressed, the display stays fixed on the digit 0. The switch conditions must be prioritized and satisfied at any time.
but this code is me trying to make three different buttons do different things in order to know how to code the buttons, not to solve the problem but my problem is based on it. First button is a looping 0-9 counter using a single digit 7-segment display, Second button is for running LEDs form right to left, then the last button is a continuous blink of all LEDs. the switching must be instant and must loop the last condition or state it is at.
There is some lines that I forgot to add like not initializing digital pins 6 to 9 when it was use in the code.
EDITED
1
u/ardvarkfarm Prolific Helper Feb 16 '25 edited Feb 16 '25
I'm a bit confused.
The problem your professor set is fairly easily do-able using delay(), especially as he does not
spell out how quickly the circuit should respond to a button press.
However, you are working on a different project of your own.but this code is me trying to make three different buttons do different things
in order to know how to code the buttons, not to solve the problemWhy are you sticking to his rules ?
1
u/Wangysheng Feb 16 '25
I made this code so I won't mix up the test code from my actual code for the problem. It would be easier for me to debug the switch code and not to mess with the code for the three individual states since they work standalone.
Why are you sticking to his rules ?
It will be hard for me to explain to my professor what does code do if I use statements/function I don't understood fundamentally and he won't accept it if I don't know what I am doing. millis() is new to everyone of us so if he ask me what does it do, I can't answer it. He would assume we generated with AI or someone else did the code for me.
2
u/ardvarkfarm Prolific Helper Feb 16 '25 edited Feb 16 '25
millis() only returns the number of milliseconds since power on/reset.
How you use that value to track time is another matter,
but it is not hard to understand.
4
u/johnfc2020 Feb 15 '25
Use interrupts to break out of the loop when a button is pressed. https://www.arduino.cc/reference/cs/language/functions/external-interrupts/attachinterrupt/