Press VS. Hold (Button Help)

I am starting to write the code for my binary clock, and I am stuck...

You know how on a normal clock, you can press the buttons and the time goes up by 1, and if you hold the button down, it just keeps going up? I want to do this, but I'm not sure how to... How can I tell between a single press and a hold?

How can I tell between a single press and a hold?

Well, one lasts a short time, and the other a long time. I'll leave it to you to figure out which is which.

@AWOL: Well, you got me there... ;D Let me re-phrase that... How can the Arduino tell the difference?

Hint, use the millis() function ( http://arduino.cc/en/Reference/Millis ) to keep track of elapsed time.

Lefty

Another hint... you're not as interested in the buttonpress event as you are the buttonrelease event.

I still don't know how... I'm not being lazy, I'm just a 12 year old kid who doesn't understand how to make it work... I'll keep trying, but I'm not sure...

You need to recognise two events: one when the switch is pressed, and one when the switch is released. Start a timer when the first event happens, and if the current time each time through loop is "n" milliseconds after the first event, start counting up, until you get a release event.

[edit]No, your solution won't work, because you need to detect the change of state (from low to high), not the state itself ("==HIGH), otherwise you'll just keep resetting "time" to the current value of "millis()"[/edit]

I think I got it... I can't test it right now, so please let me know if it should work...

int buttonPin = 13;

unsigned long time;

void setup()
{
 pinMode(buttonPin, INPUT); 
  
 Serial.begin(9600);
}

void loop()
{
 if(buttonPin == HIGH){
  time = millis();
 } 
 else if(buttonPin == LOW){
  time = 0;
 }  
 Serial.print("Time: ");
 Serial.println(time);
}

Edit: I had to add one little line to the code... It is the time = 0 line.

See my edited comments, and don't forget "loop" runs many thousands of times a second.

Also, if something read by "digitalRead" isn't HIGH, it must be LOW, so there's no need to test it again. Also buttonPin has a value of 13, so is never LOW. [edit]Come to that, it's never HIGH either! ;D[/edit]

Erm... I'm stuck... Help? How do I detect the actual state change? Wait, I think that there is an example, let me check.

How do I detect the actual state change?

You have to remember what it looked like last time you looked.

Do I have reason to be happy? :slight_smile:

int buttonPin = 13;

int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin
unsigned long time;

void setup()
{
 pinMode(buttonPin, INPUT); 
  
 Serial.begin(9600);
}

void loop()
{
 buttonState = digitalRead(buttonPin); 
  
 if (buttonState != lastButtonState){
  if (buttonState == HIGH) {
   time = millis();
  }
  
  else{
   time = 0;
  }
 
  lastButtonState = buttonState;
 }
 Serial.print("Time: ");
 Serial.println(time);
}

You have a reason to start being vaguely comfortable. A little way off happiness, but on the right road.

As far as? Well, will I know that this isn’t completely for the press / hold… This just shows how long it’s being pressed… Then I would need two “if” statements, like if time <= 500, and if time >= 500…

Would this code work just to show how long the button has been pressed?

Well, I put the circut together real quick… When I tested it, my results weren’t what I had hoped…

What I got was then I pressed the button, the time would display, but it would be the time since the program started running… Also, the time wouldn’t update until I let the button go and and then pressed it again…

My current code:

int buttonPin = 12;

int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin
unsigned long time;

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

void loop()
{
 buttonState = digitalRead(buttonPin); 
  
 if (buttonState != lastButtonState){
  if (buttonState == LOW) {
   time = millis();
  }
  
  else{
   time = 0;
  }
 
  lastButtonState = buttonState;
 }
 Serial.print("Time: ");
 Serial.println(time);
}

it would be the time since the program started running

Would that be because of this:

else{
   time = 0;

?

Slow down, think it through. You're interested in the time between events (relative aka difference), not absolute time.

@AWOL: You came back for me! LOL! But I’m not sure…

Edit: Do I need to subtract the rest of the time when the button’s not pressed?

Don't forget to debounce the button presses (i.e. consider digitalRead of a button to be unreliable the first 20ms or so after detecting a state change). The Serial.printing for every round of loop may take care of the debouncing for now.

I got it... Kevin Darrah helped me figure it out (Thanks Kevin!).

int buttonPin = 12;

int firsttime = 1;
unsigned long startTime;
unsigned long pressTime;

void setup()
{
pinMode(buttonPin, INPUT);
digitalWrite(buttonPin, HIGH);
}

void loop()
{
 if(digitalRead(buttonPin) == LOW){
  if(firsttime == 1){
   startTime = millis();
   firsttime=0;
  }
  pressTime = millis()- startTime;
  }
 }
 if(firsttime == 0){ 
  firsttime = 1;
 }
}

And here is a modded version to serial print the output. Also, when you let go, it prints 0's. When you press it again, it will only print if pressTime is 1 or more.

Again, props to Kevin Darrah for the help and pushing me to finish this when I wanted to give up on it!

int ledPin = 13;
int buttonPin = 12;

int firsttime = 1;
unsigned long startTime;
unsigned long pressTime;

void setup()
{
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
digitalWrite(buttonPin, HIGH);

Serial.begin(9600);
}

void loop()
{
 if(digitalRead(buttonPin) == LOW){
  if(firsttime == 1){
   startTime = millis();
   firsttime=0;
  }
  pressTime = millis()- startTime;
  if(pressTime >= 1){
   Serial.print("Time: ");
   Serial.print(pressTime);
   Serial.print(" milliseconds ");
   Serial.print(int(pressTime/1000));
   Serial.println(" seconds");
  }
  if(pressTime>3000){
   digitalWrite(ledPin, HIGH); 
  }
 }
 else if(firsttime == 0){
  firsttime = 1;
  Serial.println("Time: 0 milleseconds; 0 seconds");
  digitalWrite(ledPin, LOW);
 }
}