Hello,
I'm have created a small sketch, that allows a single button to have more than one function, based on the duration of the button press. The sketch works (almost) normally. The problem is that if I press the button rapidly, like 5-6 times a second, it registers it and lits up led1, but if I try to press it longer right after that, aiming to lit up led2 or led3, when:
Serial.begin and Serial.println are used in the sketch, it lits up led2 or led3, i.e. works normally.
Serial.begin and Serial.println are NOT used, it lits up led1 again, or led3, if it has to be led2, or any other random behaviour.
So bottomline is that with Serial active it works and without Serial it does not. It is not so much an issue, if it would be used on Arduino Uno. But the goal is ATTiny85, which has 4 times less memory and ram.
Do you have any idea what would've cause this behaviour?
Thank you.
I see only one code line that prints anything to serial.
At 9600 baud, which is very slow, printing to serial may be acting like a short delay, when the serial output buffer gets full. Each character will take about 1ms to send, I think.
Try these:
Increase baud to 115200.
Replace the Serial.println() with delay(10) or something similar.
The results might confirm my theory (or not!).
But my main comment would be: that the fact that removing Serial causes you code to stop working correctly simply indicates that your code is faulty and not well written. Normally removing Serial should not cause any change in the behaviour of code other than maybe to speed it up a little.
I have already tried that and lots of other possible fixxes, without success. If you can reproduce the circuit and upload the sketch without Serial.begin and Serial.writeln, you would observe it yourself. I agree that removing Serial should not impact the performance, but yet it is. I have tried it on ATTiny as well - it behaves the same, with only difference, that I have not tried with Software serial. But even if It did, it is against the "rule" of less memory and ram usage. The goal is to make it work, but avoid use of the Serial entirely.
My suggestions were not intended to fix the problem. They were only intended to confirm or otherwise my theory about Serial.println() acting like a delay. So what, specifically, did you see when you tried each of my 2 suggestions?
In fact, I said that it might/could affect the performance. I also said that it should not affect the function/operation of the code, provided the code is correctly written. The fact that removing Serial affects the function/operation tells me there is a problem, a bug, in the code. If there was no bug, only the performance should/might be affected by removing Serial.
I haven't yet spotted what that bug might be. But one thing I did notice is that your code is supposedly attempting to time how long the button is held down for, yet it is not detecting the change of state of the button and capturing the time of that state change. I would expect that to be a feature of your code, but I don't see it.
Have you studied the "state change" code from the examples menu in the IDE?
Oddly, the delay(5) seems to fix the bug at ATTiny85 (with Uno not yet confiremed), but I dislike use of the delay(). I preffer millis(). I will try to add an execution filter based on millis() and duplicate the delay() function.
Yes and it is not the same that I need. Not to mention the fact that rapid pushing wears out the button more than continous pushing. The button will never be used in such conditions (rapid clicking), as described in the "bug" but I have just observed it and tried to understand and eventually get rid of it.
Just confirmed. Delay() does not always help. Is it possible that cpu accumulates some kind of error with the multiple clicks and therefor multiple equalizations ot prevMillis and currentMillis?
I tossed your code into Wokwi, unaltered, and wired up per the expectations in the code.
With no 'button bounce', the code works as described, but with button bounce enabled, it does not. Perhaps that's a hint?
Here's the project:
I think it is more likely a logic error than than somehow the low-level CPUMAG register is accumulating clicks.
The ledXflags look like they are all supposed to be mutually exclusive. Maybe using a ledNum state variable would simplify the logic. As could calculating something like uint32_t elapsed = currentMillis - prevMillis; at the top of the loop.
Surely, you know that a button's contacts bounce many times when you press on the button. This fact leads to endless errors in software written by new users.
In Wokwi, with the code not running, if you click on the button, a toolbar appears on which you can select bounce or no bounce as options; when the software is then run, the simulator will obligingly provide a single transition, or a random series, depending upon your selection.
Many beginners look at the "state change" example code and conclude that the principle it demonstrates isn't applicable to their problem or use case. But the example code demonstrates a much more important principle than they think it does. It demonstrates the important difference between:
reading an input to see if it is HIGH or LOW at that moment;
reading an input to see if it has changed from HIGH to LOW or LOW to HIGH since the previous reading.
As I said before, my suggestion of adding delay() was to prove or disprove a theory, not to become a permanent part of your code. This is how the process of debugging code is often done: changes are made to the code not so much in the hope that they will actually fix it, but simply to see how the change affects the operation of the code because something new might be learned that will help to reveal the ultimate fix.
That said, I can tell that my attempts to help here are not appreciated, because I have not handed you the solution on a plate. So I will wish you good luck.
If you exclude the Serial function, this code behaves with same bug. Till the moment using a delay(5) somewhere in the loop is the only fix, but now I'm looking for a way to avoid using delay function.
I didn’t try to eliminate the bug. I was trying to understand the code and the issue.
Use the state change detection example but instead of the delay it uses, rate-limit the state changes to no faster than whatever rate you need to eliminate the bouncing.