Hi, I have a question (again)..
After I got the push button working, I tried making it count, and run a different block of code depending on the number of times it's been pressed..
I have gotten it to run once, if it counts and gets to 1, it will run, if it counts to 2 (I think it does), it does not run anything at all.
If I however place the count++ in setup it doesn't seem to do anything..
So can anyone tell me if maybe I'm doing something wrong here?
I cannot for the life of me get it to work, I have tried many things but they either only seem to count to 1, or not do anything at all..
I wish I was better at this stuff
This is what I took from the statechangedetection example, does anyone know what I'm doing wrong?
mmm... Just some random ideas.
Your problem is that you don't know how long the button is pressed (nor do you care, really), so you have to wait until the button is released.
So some draft code (untested) of how I'd approach this. Note: code is blocking and won't allow you to do anything else. If the button is supposed to interrupt something, use interrupts instead.
for (int i = 0, i<2, i++) {
// Wait for button to be pressed.
while (digitalRead(pin), HIGH) delay(1);
// Wait for button to be released.
while (digitalRead(pin), LOW) delay(1);
}
// Pressed two times now; do your stuff.
Another approach would be to use pulseIn(pin, LOW) where you wait for a pulse to come in - i.e. button to be pressed.
@Delta_G Well no in this case I changed it here and there just because I was trying things and messing around at some point, since when I copied the first part of the example I couldn't get it to run either, I must've messed up somewhere, I don't know where however, I basically copied the whole thing, took out the serial and led parts, and changed % 4 == 0 in the example to pushButtonCounter == 1, I don't know what I did wrong
@TomGeorge I just figured that like in the example that every time it goes to a low state the counter gets increased by 1, and then when it goes back to a high state it will check if it goes to a low state again, if it does, and the counter equals 1, then that would be the second push, and the counter would increase again.
My own way of doing it only went to 1 though, it would not count the second, so I might be thinking about it wrong here
@wvmarle Thanks, I will give it a try, I'm not using an external resistor though, I use INPUT PULLUP, so would that mean in your example I'd have to reverse high and low?
It doesn't compile, it says expected initializer before <, what does that mean?
@TomGeorge I just figured that like in the example that every time it goes to a low state the counter gets increased by 1, and then when it goes back to a high state it will check if it goes to a low state again, if it does, and the counter equals 1, then that would be the second push, and the counter would increase again.
How long do you wait after the button has gone back to a high state after the first press to decide that only one press has been signaled, or wait to see if the button is pressed for the second time?
@TomGeorge, I tried 50ms like in the example first, then I tried 200ms, 1000ms and 2000ms, as I thought maybe it was too fast..
@larryd That error went away now, but now it gives me an error at " if(i == 1){"
It says: exit status 1
name lookup of 'i' changed for ISO 'for' scoping [-fpermissive]
As I now have this
#include <KEY.h>
const int pin = 2;
void setup() {
pinMode(pin, INPUT_PULLUP);
}
void loop() {
for (int i = 0; i<2; i++) {
// Wait for button to be pressed.
while (digitalRead(pin), HIGH) delay(1);
// Wait for button to be released.
while (digitalRead(pin), LOW) delay(1);
}
// Pressed two times now; do your stuff.
if(i == 1){
KEY.delay(300);
KEY.Stroke(r, GUI);
KEY.delay(1500);
KEY.print("cmd");
KEY.delay(300);
KEY.Stroke(ENTER);
KEY.delay(3000);
KEY.print("mkdir C:\Once")
KEY.Stroke(ENTER);
KEY.delay(1500);
KEY.print("exit");
KEY.Stroke(ENTER);
}
if(i == 2){
KEY.delay(300);
KEY.Stroke(r, GUI);
KEY.delay(1500);
KEY.print("cmd");
KEY.delay(300);
KEY.Stroke(ENTER);
KEY.delay(3000);
KEY.print("mkdir C:\Twice")
KEY.Stroke(ENTER);
KEY.delay(1500);
KEY.print("exit");
KEY.Stroke(ENTER);
}
exit(0);
}
I tried using the example itself now, and ditched my own sketch, just to see, but the example worked when trying the remainder like %4 == 0, when I tried buttonPushCounter == 1 for instance it either didn't work, or constantly ran..
Now with this it will immediately constantly run the first option when plugged in (without pressing the button), as if the counter starts at 1, doesn't make a difference if I change it to high or low.
Edit: High now runs constantly, low does not run anything at all even when pressing the button.
It has the same effect if I change == 1 to %4 ==1
#include <KEY.h>
const int pin = 2;
/*
State change detection (edge detection)
Often, you don't need to know the state of a digital input all the time,
but you just need to know when the input changes from one state to another.
For example, you want to know when a button goes from OFF to ON. This is called
state change detection, or edge detection.
This example shows how to detect when a button or button changes from off to on
and on to off.
The circuit:
* pushbutton attached to pin 2 from +5V
* 10K resistor attached to pin 2 from ground
* LED attached from pin 13 to ground (or use the built-in LED on
most Arduino boards)
created 27 Sep 2005
modified 30 Aug 2011
by Tom Igoe
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/ButtonStateChange
*/
// this constant won't change:
const int buttonPin = 2; // the pin that the pushbutton is attached to
const int ledPin = 13; // the pin that the LED is attached to
// Variables will change:
int buttonPushCounter = 0; // counter for the number of button presses
int buttonState = 0; // current state of the button
int lastButtonState = 0; // previous state of the button
void setup() {
// initialize the button pin as a input:
pinMode(buttonPin, INPUT_PULLUP);
// initialize the LED as an output:
// initialize serial communication:
Serial.begin(9600);
}
void loop() {
// read the pushbutton input pin:
buttonState = digitalRead(buttonPin);
// compare the buttonState to its previous state
if (buttonState != lastButtonState) {
// if the state has changed, increment the counter
if (buttonState == HIGH) {
// if the current state is HIGH then the button
// wend from off to on:
buttonPushCounter++;
Serial.println("on");
Serial.print("number of button pushes: ");
Serial.println(buttonPushCounter);
} else {
// if the current state is LOW then the button
// wend from on to off:
Serial.println("off");
}
// Delay a little bit to avoid bouncing
delay(50);
}
// save the current state as the last state,
//for next time through the loop
lastButtonState = buttonState;
delay(2000);
// turns on the LED every four button pushes by
// checking the modulo of the button push counter.
// the modulo function gives you the remainder of
// the division of two numbers:
if (buttonPushCounter == 1) {
KEY.Stroke(d, GUI);
KEY.delay(1000);
KEY.Stroke(r, GUI);
KEY.print("one");
KEY.Stroke(SPACE);
}
if (buttonPushCounter == 2){
KEY.Stroke(d, GUI);
KEY.delay(1000);
KEY.Stroke(r, GUI);
KEY.print("two");
KEY.Stroke(SPACE);
}
}
Lastofthetukkers: @wvmarle Thanks, I will give it a try, I'm not using an external resistor though, I use INPUT PULLUP, so would that mean in your example I'd have to reverse high and low?
Ah, yes of course, you're using inverted logic. Missed that part. Indeed, just reverse HIGH and LOW in that example.
In case you're planning on using interrupts, have it look for a falling edge, not a change in status or you'd get an interrupt upon both press and release.
wvmarle:
Ah, yes of course, you're using inverted logic. Missed that part. Indeed, just reverse HIGH and LOW in that example.
In case you're planning on using interrupts, have it look for a falling edge, not a change in status or you'd get an interrupt upon both press and release.
As a newbie I'm afraid this is the point my brain refuses to cooperate..
Interrupts as in every time the signal gets interrupted by pressing the button?
Basically it connects to a pin (not all pins are available for interrupts on some boards - check carefully for your specific board) and when the event happens your normal program code is interrupted and the event is handled. This may or may not be overkill for your button, depending on the exact use case.
Lastofthetukkers: @TomGeorge, I tried 50ms like in the example first, then I tried 200ms, 1000ms and 2000ms, as I thought maybe it was too fast..
@larryd That error went away now, but now it gives me an error at " if(i == 1){"
It says: exit status 1
name lookup of 'i' changed for ISO 'for' scoping [-fpermissive]
As I now have this
#include <KEY.h>
const int pin = 2;
void setup() {
pinMode(pin, INPUT_PULLUP);
}
void loop() {
for (int i = 0; i<2; i++) {
// Wait for button to be pressed.
while (digitalRead(pin), HIGH) delay(1);
// Wait for button to be released.
while (digitalRead(pin), LOW) delay(1);
}
// Pressed two times now; do your stuff.
@larryd like this?
This gives me the message "expected unqualified-id before 'for'"
#include <KEY.h>
const int pin = 2;
for (int i = 0; i<2; i++) {
// Wait for button to be pressed.
while (digitalRead(pin), HIGH) delay(1);
// Wait for button to be released.
while (digitalRead(pin), LOW) delay(1);
}
// Pressed two times now; do your stuff.
void setup() {
pinMode(pin, INPUT_PULLUP);
}
void loop() {
if(i == 1){
KEY.delay(300);
KEY.Stroke(r, GUI);
KEY.delay(1500);
KEY.print("cmd");
KEY.delay(300);
KEY.Stroke(ENTER);
KEY.delay(3000);
KEY.print("mkdir C:\Once")
KEY.Stroke(ENTER);
KEY.delay(1500);
KEY.print("exit");
KEY.Stroke(ENTER);
}
if(i == 2){
KEY.delay(300);
KEY.Stroke(r, GUI);
KEY.delay(1500);
KEY.print("cmd");
KEY.delay(300);
KEY.Stroke(ENTER);
KEY.delay(3000);
KEY.print("mkdir C:\Twice")
KEY.Stroke(ENTER);
KEY.delay(1500);
KEY.print("exit");
KEY.Stroke(ENTER);
}
}
@wvmarle I'm using an attiny85, I read that for interrupts it should use pin 5? I'm afraid my skills don't go that far yet though, I when I try the statechangedetection example itself however I can get it to execute the first option if I do 1 press for example, if I want it to do something at 2 presses though it doesn't do jack..
I feel like I'm wasting people's time here by being inexperienced and maybe not so smart, so sorry about that, I really cannot seem to get things working though, and if it does it's only half
I still couldn't get that working, it still gave me a compiling error, however I managed to get the statechangedetection working like this:
#include <KEY.h>
const int pin = 2;
int count = 0;
int state = 0;
int last = 0;
int skip = 0;
void setup(){
pinMode(pin, INPUT_PULLUP);
}
void loop(){
state = digitalRead(pin);
if (state != last){
if (state == LOW){
count++;
}
delay(50);
}
last = state;
if (count == 1 && skip < 1) {
KEY.delay(500);
KEY.Stroke(r, GUI);
KEY.delay(1500);
KEY.print("cmd");
KEY.delay(300);
KEY.Stroke(ENTER);
KEY.delay(3000);
KEY.print("mkdir C:\\Once");
KEY.Stroke(ENTER);
KEY.delay(1500);
KEY.print("exit");
KEY.Stroke(ENTER);
skip++;
delay(500);
}
if (count == 2 && skip < 2) {
KEY.delay(500);
KEY.Stroke(r, GUI);
KEY.delay(1500);
KEY.print("cmd");
KEY.delay(300);
KEY.Stroke(ENTER);
KEY.delay(3000);
KEY.print("mkdir C:\\Twice");
KEY.Stroke(ENTER);
KEY.delay(1500);
KEY.print("exit");
KEY.Stroke(ENTER);
skip++;
delay(500);
}
if (count == 3 && skip < 3) {
KEY.delay(500);
KEY.Stroke(r, GUI);
KEY.delay(1500);
KEY.print("cmd");
KEY.delay(300);
KEY.Stroke(ENTER);
KEY.delay(3000);
KEY.print("mkdir C:\\Thrice");
KEY.Stroke(ENTER);
KEY.delay(1500);
KEY.print("exit");
KEY.Stroke(ENTER);
skip++;
delay(500);
}
}
Now it works, and if I press once it will do the first, if I press again it will skip the first and do the second, etc etc..
There is still one issue though, I think it would be better if somehow I could delay the action and check if I pressed the button twice in a row in succession, so it will skip the first action entirely..
As right now, in this manner, I will have to wait until it's finished with the first action after pressing the button once, and then I can press it again making the counter 2 and performing the second action.
If I now press the button twice or 3 times in quick succession then it seems to get all scrambled