How to store button value by pushing only once - arduino

I am trying to make a program that stores my button digital input so that I don't have to keep holding the button for it to work.
The algorithm I am trying to develop is when the button is pressed, it it executes the servoMomvement() function then increments count by one. If count is even then program runs, but then if the button is pressed again it will not be even and would stop working.
void loop() {
while(true){
int count = 0;
bool isEven = count%2;
bool condition = digitalRead(4);
if(condition == true && isEven == false){
servoMovement();
count++;
}
}
}
It is not working as intended. I still have to hold to push button for it to not stop executing.

You can use timer to incremenet count by one.This timer function check periodically button. And when you press it will work as you want. But first of all you have to know timers ability and capacity.

The problem is that the loop method is executed in a loop (like one could guess by the name of the method...) and therefore it's checked in every loop whether the button is pressed.
Because in your if statement it says condition == true && ... this will only be true if the condition is true (the button is pressed).
If I understood your question correctly you want to have some kind of start-/stop-button. If so you could try like this:
//global variable run
bool run;
void setup() {
run = false;
}
void loop() {
while(true){
bool condition = digitalRead(4);
if (condition) {
run = !run;//switch the state of the run variable
delay(50);//some delay to debounce the button; see https://www.brainy-bits.com/arduino-switch-debounce/ for more information
}
if(run){
servoMovement();
}
}
}

I have a quite simple solution for that.
You can compare the actual buttonstate with the buttonstate the "round" before.
bool Button = false;
bool ButtonBefore = false;
bool help = false;
void loop()
{
Button = digitalRead(ButtonPin);
if(Button > ButtonBefore) help = !help;
if(help) { do stuff; }
ButtonBefore = Button;
}
When you press the button, "Button" becomes true while "ButtonBefore" is still false. So "Button" is bigger than "ButtonBefore" so "help" changes to true. In the next cycle "ButtonBefore" is even to "Button" so "help" won't change its state. When the button is released, "ButtonBefore" is bigger than "Button" so it "help" won't change too. So the state from "help" is changed when the button is pressed.
I hope I could help you with this.

Related

How to limit the number of QCheckboxes checked at the same time?

I'm in the process of creating a QT application which is using multiple (14) qcheckboxes. I need to have a limit (preferably set as a variable that i can change) to the number of checkboxes that can be checked at the same time, is there any way to achieve this cleanly ? Thanks for your time.
There is no simple way of doing this, you have to write your code to do it.
I suppose you have the checkboxes in some parent widget class. So I would create a slot which looks like this.
void SomeParentWidget::onCheckBoxToggled(bool value)
{
// when we unchecked the checkbox,
// we do not need to count the number of checked ones
if (!value)
return;
int total = 0;
int limit = 15; // your "magic" number of maximum checked checkboxes
for (auto chb : allCheckBoxes()) // allCheckBoxes() is some method which returns all the checkboxes in consideration
{
if (chb->isChecked())
{
++total;
if (total > limit)
{
// too many checkboxes checked! uncheck the sender checkbox
// Note: you may want to add some nullptr checks or asserts to the following line for better robustness of your code.
qobject_cast<QCheckBox*>(sender())->setChecked(false);
return;
}
}
}
}
And when creating each of your checkboxes inside some parent widget, connect this slot to their signal:
auto chb = new QCheckBox();
connect(chb, &QCheckBox::toggled, this, &SomeParentWidget::onCheckBoxToggled);
Implementation of allCheckBoxes() is up to you, I do not know how you can retrieve the collection of all your check boxes. Depends on your design.
I found another, even simpler solution. Use this slot.
void SomeParentWidget::onCheckBoxToggled(bool value)
{
static int totalChecked = 0; // static! the value is remembered for next invocation
totalChecked += value ? 1 : -1;
Q_ASSERT(totalChecked >= 0);
int maxChecked = 15; // any number you like
if (value && totalChecked > maxChecked)
{
qobject_cast<QCheckBox*>(sender())->setChecked(false);
}
}
... and connect it to checkboxes' toggled() signal. Note that in order to work correctly, all check boxes must be unchecked at the time when you make the signal-slot connection because this function starts counting from zero (0 is the initial value of the static variable).
You can store all your checkboxes in a map (either in an std::map, an std::unordered_map or an QMap). Your keys will be your checkboxes, and your values will be their states, so something like this:
std::unordered_map<QCheckBox*, bool> m_checkBoxStates;
Here's what your connected to your toggled signal of all your checkboxes look like (keep in mind that all the signals will be connected to the same slot):
void MainWindow::onToggled(bool checked) {
QCheckBox* checkBox = sender(); //the checkbox that has been toggled
m_checkBoxStates[checkBox] = checked;
if (!checked) {
return;
}
const int count = std::count_if(m_checkBoxStates.begin(), m_checkBoxStates.end(),
[](const auto pair) {
return pair.second == true;
});
if (count > maxCount) {
checkBox->setChecked(false);
}
}

Xamarin.Forms UI Test - Tap Button multiple (5) times

I'm working on writing an UI-Test for my Xamarin.Forms Application.
Therefore I need to tap a button 5-times. This invokes a dialog and I need the result of the user's input to this dialog.In code I realised this by implementing an GestureRecognizer:
private bool HandleMultipleTouch()
{
if (iLastTap == null || (DateTime.Now - iLastTap.Value).Milliseconds < iToleranceInMs)
{
if (NumberOfTaps == 4)
{
NumberOfTaps = 0;
iLastTap = null;
return true;
}
else
{
NumberOfTaps++;
iLastTap = DateTime.Now;
return false;
}
}
else
{
NumberOfTaps = 0;
iLastTap = null;
return false;
}
}
Do you know any method how to use Xamarin.UITest to get the button taped 5 times in a short time?
I tried used double tap twice and one single tap, but this is not working because of the time needed to execute the taps.
I had a similar issue, where I had to tap a morse code using Xamarin.UITest and concluded that it's impossible to ensure consistent timing between taps. My solution was therefore to abandon the morse code and only check in the app whether the button was hit 5 times.

How to ignore key press events that don't output characters

I'm developing a virtual musical keyboard that allows you to press keys on your keyboard and have it play notes. So in my MainWindow class I have reimplemented keyPressEvent. I would like to ignore events generated by modifiers (Control, Alt, Shift, etc.), as well as events generated by other non-character keys such as Tab, Backspace, and Enter. Something like this would be ideal:
void MainWindow::keyPressEvent(QKeyEvent *event)
{
if (!event->key().isCharacter()))
{
event->ignore();
return;
}
// handle the event
}
Is there a way to do something like that (short of testing every possible non-character key individually)? If not, is there at least a way to easily ignore the event if it is a modifier?
Looks like you want QKeyEvent::text().
The accepted answer is unfortunately incomplete. If you press Ctrl+C, then QKeyEvent::text() will return "\x03" (^C "End of Text").
That is not an empty string.
I decided to look inside the Qt source code, since they need to handle this problem for QLineEdit as well:
In QLineEdit::keyPressEvent:
d->control->processKeyEvent(event);
src/widgets/widgets/qlineedit.cpp:1742
In QWidgetLineControl::processKeyEvent:
if (unknown
&& !isReadOnly()
&& isAcceptableInput(event)) {
insert(event->text());
src/widgets/widgets/qwidgetlinecontrol.cpp:1912
In QInputControl::isAcceptableInput:
bool QInputControl::isAcceptableInput(const QKeyEvent *event) const
{
const QString text = event->text();
if (text.isEmpty())
return false;
const QChar c = text.at(0);
// Formatting characters such as ZWNJ, ZWJ, RLM, etc. This needs to go before the
// next test, since CTRL+SHIFT is sometimes used to input it on Windows.
if (c.category() == QChar::Other_Format)
return true;
// QTBUG-35734: ignore Ctrl/Ctrl+Shift; accept only AltGr (Alt+Ctrl) on German keyboards
if (event->modifiers() == Qt::ControlModifier
|| event->modifiers() == (Qt::ShiftModifier | Qt::ControlModifier)) {
return false;
}
if (c.isPrint())
return true;
if (c.category() == QChar::Other_PrivateUse)
return true;
if (c.isHighSurrogate() && text.size() > 1 && text.at(1).isLowSurrogate())
return true;
if (m_type == TextEdit && c == u'\t')
return true;
return false;
}
src/gui/text/qinputcontrol.cpp:21
This is exactly what you need but you may want to change the check for \t and ignore that as well.

Strange console.log behaviour on keypress

If the keyPressed event is 27 by pressing 'esc' it will print the console.log("ESCY"); as many times as the loopcnt var, all at once
loopcnt = 0;
var fps = 22;
var interval = 1000 / fps;
function draw()
{
setTimeout(function()
{
if (willAnimate)
{
window.requestAnimationFrame(draw);
console.log("Framecnt: "+ loopcnt);
loopcnt++;
}
IndexJSON.each(function(key, value){ IndexOBJECT[key].render(); });
$(window).delegate('body', 'keydown', function(event){
keyPressed = event.which;
if (keyPressed == 27)
{
willAnimate = false;
console.log("ESCY");
}
});
}, interval);
};
willAnimate = true;
draw();
If you ask me, it doesn't make logical sense...
It's as if it's buffering all the console.logs, until the if statement is true..
Any idea why this happens?
(And another question: I tried cancelling the setTimeout function with return, but it won't terminate the function, probably because return will only return from the if statement, but is there a way to externally terminate the function?)
OK, apparently when I move the .delegate outside the setTimeout(); It won't trigger the if statement multiple times.
And, I'm realizing now, that I'm binding the key every time the loop loops, thus when I press the key it will trigger all the bindings..
Pretty obvious now that I think about it...

LinkBar button / label click event transition

I have created a linkbar with two labels. Now, I need to keep a track of the label clicks.
10
100
i.e. If in the beginning "First" is clicked, the details will be displayed. After that, if without submitting the details, "Second" is clicked then an alert message should come to inform the user that "First is still in progress, do you want to cancel and begin Second operation". Vice-versa for Second to First transition. I need to know how to write events to keep track of which button clicked.
maybe....
var inProgress:Boolean = false;
var clickedButton:Button;
private function clickButtonHandler(event:MouseEvent):void{
if(clickedButton != null){
if(clickedButton != event.currentTarget && inProgress){
//handle alert
}
}
else{
clickedButton = event.currentTarget;
}
inProgress = true;
}
private function sumbitDetailsHandler(event:Event):void{
inProgress = false;
clickedButton = null;
}

Resources