Go Down

Topic: How to require a key-up event before continuing (Read 1 time) previous topic - next topic

Jul 08, 2011, 09:47 pm Last Edit: Jul 08, 2011, 09:49 pm by roggesound Reason: 1
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: [Select]
void loop() {
  if (digitalRead(10) == HIGH) {
    delay(10);
  } else {
    Keyboard.print(" "); // print a space (GO)
    delay(1000);
  }



flyboy

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: [Select]
              if((go == LOW) && (last_go == LOW))
                  {
                     go_button_pressed = 1;
                  }

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

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. 

robtillaart


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

Code: [Select]

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
}

 
Rob Tillaart

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

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: [Select]
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
  }
}

robtillaart

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: [Select]

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


Rob Tillaart

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

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: [Select]
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
  }
}

cyclegadget


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

Code: [Select]
int spacesAllowed = 1;
Good links: Eagle tutorial= http://www.youtube.com/playlist?list=PLDE1858BD83D19C70
General Arduion tutorials = http://tronixstuff.wordpress.com
http://www.gammon.com.au/forum/bbshowpost.php?bbtopic_id=123

robtillaart

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: [Select]

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
 }
}
Rob Tillaart

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

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?

robtillaart


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: [Select]

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

}

Rob Tillaart

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

liudr

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/

Go Up