Pages: [1]   Go Down
Author Topic: How to require a key-up event before continuing  (Read 958 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So I've made a box with a "Go" button on it to fire a show control program on my computer.  Unfortunately, if the button is held down, the signal is repeated after the delay.  What I'd like to do is fire the signal once and have the program wait until it sees the button go open before allowing another signal to fire.  

Here's my current code.  The board is a Teensy 2.0.  Any help you can give will be much appreciated.  Thank you.

Code:
void loop() {
  if (digitalRead(10) == HIGH) {
    delay(10);
  } else {
    Keyboard.print(" "); // print a space (GO)
    delay(1000);
  }

« Last Edit: July 08, 2011, 02:49:47 pm by roggesound » Logged

Central Indiana, USA
Offline Offline
Full Member
***
Karma: 0
Posts: 203
So many projects, so little time...and money!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You could use something like this to determine if the go button is not released.  Once the button is released, it changes the value of go_button_pressed.  When the value goes from 1 to 0, the program starts on your PC.

Code:
              if((go == LOW) && (last_go == LOW))
                  {
                     go_button_pressed = 1;
                  }

              if((go == HIGH) && (last_go == LOW))
                  {
                     go_button_pressed = 0;
                  }
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I should probably have mentioned that I'm also relatively an idiot when it comes to programming.  I understand what my simple code does, but when it gets more complicated than that, i don't know what's going on...  And the code must ultimately print a space, but not print a space again until after the button comes up. 
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 216
Posts: 13663
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Give the variables a meaningfull name makes the program more "English" readable. That makes programming easier.

Code:
int spacesAllowed = 1;

if (digitalRead(10) == LOW && spacesAllowed > 0)
{
  Keyboard.print(" ");
  spacesAllowed = 0;  // no  spaces allowed anymore
}

if (digitalRead(10) == HIGH)
{
  spacesAllowed = 1;  // butto is up again
}
 
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you.  That's much easier for me to understand.  I even understand why it should work and the logic of the program...  but it doesn't work somehow.  I added a 1 second delay, which slows it down a bit, but when that's not in there, it just prints spaces very quickly when the button is held down.  With the delay, it prints one space per second.

Code:
void setup() {
  Serial.begin(9600);
  pinMode(10, INPUT_PULLUP);
  delay(4000);
}

void loop() {
  int spacesAllowed = 1;
  if (digitalRead(10) == LOW && spacesAllowed > 0)
  {
    Keyboard.print(" ");
    spacesAllowed = 0;  // no  spaces allowed anymore
    delay(1000);
  }
  if (digitalRead(10) == HIGH)
  {
    spacesAllowed = 1;  // button is up again
  }
}
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 216
Posts: 13663
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There is something called a bouncing switch, then the switch does on/off a few times when pressed. The code without delay will see HIGH/LOW/HIGH/LOW/HIGH/LOW for 1 to 20 milliseconds. => a delay(50) should be enough to capture that.

I am not familiar with INPUT_PULLUP; it is not in my IDE22 edition? I use:

Code:
void setup()
{
  Serial.begin(9600);
  pinMode(10, INPUT);
  digitalWrite(10, HIGH);  // pullup
}

Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes.  The 1 second delay is kind of a debounce, but one specifically for your finger, to keep the operator from hitting the button twice in quick succession.  I have added a couple of 50ms delays after the if lines, but still do not get the result of being able to hold down the button and have only one space print.  It currently waits a bit and prints another space, on and on forever while the button is held down.

I don't really know about input_pullup.  That came from a post on a blog somewhere about diy photobooth buttons.  I'm expanding on that code for this purpose.

Code:
void setup() {
  Serial.begin(9600);
  pinMode(10, INPUT_PULLUP);
  delay(4000);
}

void loop() {
  int spacesAllowed = 1;
  if (digitalRead(10) == LOW && spacesAllowed > 0){
    delay(50);
    Keyboard.print(" ");
    spacesAllowed = 0;  // no  spaces allowed anymore
    delay(1000);
  }
  if (digitalRead(10) == HIGH){
    delay(50);
    spacesAllowed = 1;  // button is up again
  }
}
Logged

Greenville, IL
Offline Offline
Edison Member
*
Karma: 15
Posts: 1330
Warning Novice on board! 0 to 1 chance of errors!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


 I could be wrong but, I think the first instance of this needs moved up to the setup area.

Code:
int spacesAllowed = 1;
Logged


Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 216
Posts: 13663
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There is a bug in the program I posted, sSorry;
the initialization of spacesAllowed should not be in loop() as it gots initialized every loop, overruling the value we want it to have.

Here is the new version; ==> switch between GND and pin 10.

Give it a try.
Code:
int spacesAllowed = 1;

void setup() {
  Serial.begin(9600);
  pinMode(10, INPUT);
  digitalWrite(10, HIGH);  // pullup
}

void loop() {
  if (digitalRead(10) == LOW && spacesAllowed > 0){
    delay(50);
    Keyboard.print(" ");
    spacesAllowed = 0;  // no  spaces allowed anymore
  }
  if (digitalRead(10) == HIGH){
    delay(50);
    spacesAllowed = 1;  // button is up again
  }
}
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That works perfectly.  It's exactly what I wanted to do.  Thank you so much.  I just have one other question...

Where is the proper place to put my delay(1000);?  Right now I have it after spacesAllowed = (0);
Is that right?  It works there, but should it be after the button up?  I guess maybe it doesn't matter?
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 216
Posts: 13663
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


you should ask yourself
- what is the purpose of the delay(1000)?
- do you want the delay at all?
- if yes how big should it be (1 second seems short but it might be to long - usability argument
- if yes where ?

OK assuming you want at max 1 space per second than it could be just after the keyboard.print(" ");

But better is it to have a flag that holds timing of last space set (similar to blink without delay)
The advantage is that you don't block the CPU so you can do other things ...
Can be used to handle the bouncing delays too, see modded code below
Code:
int spacesAllowed = 1;
unsigned long lastDown = 0;
unsigned long lastUp = 0;

#define DOWN_THRESHOLD 1000    // minimum # milliseconds between two spaces;   min. 50 for bouncing
#define UP_THRESHOLD 50     // min 50 for bouncing

void setup()
{
  Serial.begin(9600);
  pinMode(10, INPUT);
  digitalWrite(10, HIGH);  // pullup
}

void loop() {
  // HANDLE KEYDOWN
  if (digitalRead(10) == LOW  && (millis() - lastDown ) > DOWN_THRESHOLD && spacesAllowed > 0){
    lastDown = millis();
    Keyboard.print(" ");
    spacesAllowed = 0;  // no  spaces allowed anymore
  }
  // HANDLE KEYUP
  if (digitalRead(10) == HIGH && (millis() - lastUp ) > UP_THRESHOLD){
    lastUp = millis();
    spacesAllowed = 1;  // button is up again
  }

  // do other things here

}
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Central MN, USA
Online Online
Tesla Member
***
Karma: 73
Posts: 7186
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Another way to achieve "button_released" is to use library that does the logic for you and you can expand to more buttons as well.

In my phi_buttons class, to sense button_released, you can do

while(button1.sense()!=phi_buttons_released)
{
//do nothing
}
//do_your_stuff_when_button_released

In case you're interested here it is:

http://liudr.wordpress.com/libraries/phi_buttons/
Logged


Pages: [1]   Go Up
Jump to: