Add timestamp and remove duplicates to button.pde

I am trying to get the time to display in the serial monitor each time I press a button using the button.pde script (below). I also want to make it so if I hold down the button, it doesn't duplicate, only types it once until released and pressed again.

/*
||
|| @file Button.pde
|| @version 1.1
|| @author Alexander Brevig
|| @contact alexanderbrevig@gmail.com
||
|| @description
|| | Display the intuitive way of using a button when using this Hardware Abstraction class
|| #
||
|| @license
|| | Copyright (c) 2009 Alexander Brevig. All rights reserved.
|| | This code is subject to AlphaLicence.txt
|| | alphabeta.alexanderbrevig.com/AlphaLicense.txt
|| #
||
*/

#include <Button.h>

//create a Button object at pin 12
/*
|| Wiring:
|| GND -----/ ------ pin 12
*/
Button button12 = Button(12,PULLUP);


void setup(){
  Serial.begin(9600);
  pinMode(13,OUTPUT); //debug to led 13 ^show led if button pushed
}

void loop(){
  if(button12.isPressed()){
      digitalWrite(13,HIGH);
        Serial.print("12"); //attempt to print to serial as well
        delay(250); //set delay
  }else{
      digitalWrite(13,LOW);
  }

}

This is the timestamp example I found at Arduino Playground - DateTime I couldn't really figure it out

// DateTime.pde
// example sketch for the DateTime library

#include <DateTime.h>
#include <DateTimeStrings.h>

#define TIME_MSG_LEN  11   // time sync to PC is HEADER followed by unix time_t as ten ascii digits
#define TIME_HEADER  255   // Header tag for serial time sync message

void setup(){
  Serial.begin(19200);
  pinMode(13,OUTPUT); // we flash the LED each second
}

void  loop(){
  unsigned long  prevtime;
  if( getPCtime()) {  // try to get time sync from pc
    Serial.print("Clock synced at: ");
    Serial.println(DateTime.now(),DEC);
  }
  if(DateTime.available()) { // update clocks if time has been synced
    digitalWrite(13,LOW);  // first flash the LED
    prevtime = DateTime.now();
    while( prevtime == DateTime.now() )  // wait for the second to rollover
        ;
    DateTime.available(); //refresh the Date and time properties
    digitalClockDisplay( );   // update digital clock

    // send our time to any app at the other end of the serial port
    Serial.print( TIME_HEADER,BYTE); // this is the header for the current time
    Serial.println(DateTime.now());
    digitalWrite(13,HIGH);
  }
  delay(100); 
}

boolean getPCtime() {
  // if time sync available from serial port, update time and return true
  while(Serial.available() >=  TIME_MSG_LEN ){  // time message consists of a header and ten ascii digits
    if( Serial.read() == TIME_HEADER ) {        
      time_t pctime = 0;
      for(int i=0; i < TIME_MSG_LEN -1; i++){   
        char c= Serial.read();          
        if( c >= '0' && c <= '9'){   
          pctime = (10 * pctime) + (c - '0') ; // convert digits to a number    
        }
      }   
      DateTime.sync(pctime);   // Sync Arduino clock to the time received on the serial port
      return true;   // return true if time message received on the serial port
    }  
  }
  return false;  //if no message return false
}

void digitalClockDisplay(){
  // digital clock display of current date and time
  Serial.print(DateTime.Hour,DEC);
  printDigits(DateTime.Minute);
  printDigits(DateTime.Second);
  Serial.print(" ");
  Serial.print(DateTimeStrings.dayStr(DateTime.DayofWeek));
  Serial.print(" ");
  Serial.print(DateTimeStrings.monthStr(DateTime.Month));
  Serial.print(" ");
  Serial.println(DateTime.Day,DEC); 
}

void printDigits(byte digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits,DEC);
}

So at 2:01 am and 55 seconds if I am in Serial monitor and I press and hold the button connected to pin 12 it will display:

12 - 02:01:55

Hope someone can help, still learning. I am not going to be picky about the timestamp format, it doesn't have to be the real time, just something that counts seconds or milliseconds so I can compare between presses.

12 - 544848
12 - 544950
12 - 545153

Something like above will work to, just something that counts time.

If you don't care what format the time displays at you can simply print
the count of the millisecond timer - millis().

Simple code to do what you want might be this:
You can modify this idea to work with your Button.pde...

int ButtonPinNum = 12;
int AlreadyPrinted = false; // assume we haven't printed anything to start

void setup()
{
   Serial.begin(57600); // change to your preferred baud
   pinMode(ButtonPinNum, INPUT);
   digitalWrite(ButtonPinNum, HIGH); // add pullup
}

void loop()
{
  if(digitalRead(ButtonPinNum) == LOW)  // the button is pressed
  {
    // we want to print ONCE when the pin goes from high to low
    if(AlreadyPrinted == false)
    {
      Serial.print(ButtonPinNum, DEC); // Print the "12"
      Serial.print(" - ");
      Serial.println(millis(), DEC);  // simply print the number of milliseconds since startup
      AlreadyPrinted = true;
        // The button will probably "Bounce" when you press it
        // wait long enough to get past that.
      delay(20); 
    }
  }
  else
  {
      // when the pin goes High again the button is released
      // reset "AlreadyPrinted" so you will print again the
      // next time it goes low.
        // bounce on release isn't usually a problem but  let's allow for it
        // since there is a delay() below we will check to see if we need to
        // change AlreadyPrinted - that way we won't have the delay every
        // time we go through the loop - only when the button is first released
    if(AlreadyPrinted == true) 
    {
          AlreadyPrinted = false;
          delay(20);
    }
  }
}

That works perfect thanks. So the timer will count for days even as long as the unit isn't reset right? Also how can I add a second button, say for digital pin 11 to write 11. I played around with it for the last 20 minutes but couldn't figure it out, I am sure I put a { or } in the wrong place.

Thank you again.

The millisecond timer will roll over every 4 294 967 296 milliseconds.
I'll leave it up to you to get the second button there - you can figure it out.

I also want to make it so if I hold down the button, it doesn't duplicate, only types it once until released and pressed again.

Try the uniquePress(); function. :slight_smile:

Try the uniquePress(); function.

The code above doesn't seem to duplicate holds so that ones solved, just need to figure out out to add a second button. If I figure out how to add a second button I can add a third but with just 1 it's hard for a non programmer to figure out what code I need to copy/paste and what code I can use twice. I tried several options but they all gave me errors :frowning:

It can be done more elegantly in other ways like using a function to check the buttons or using arrays of buttons but for a non-programmer the most straightforward way is to declare a second button, and a second variable to keep track of whether it's status has been printed then copy the code in loop() for the first one paste it below the first one and change the button name and alreadyPrinted name in the copied code to match the second button -- like this:

int ButtonPinNum = 12;
int AlreadyPrinted = false;

int ButtonPinNum2 = 11;                        // add second button
int AlreadyPrinted2 = false;  // add second variable to keep track of second button
void setup()
{
   Serial.begin(57600); 
   pinMode(ButtonPinNum, INPUT);
   digitalWrite(ButtonPinNum, HIGH); 
   
   pinMode(ButtonPinNum2, INPUT);                        // Second button
   digitalWrite(ButtonPinNum2, HIGH);   // second button
}

void loop()
{
  if(digitalRead(ButtonPinNum) == LOW)  // the button is pressed
  {
    // we want to print ONCE when the pin goes from high to low
    if(AlreadyPrinted == false)
    {
      Serial.print(ButtonPinNum, DEC); // Print the "12"
      Serial.print(" - ");
      Serial.println(millis(), DEC);  // simply print the number of milliseconds since startup
      AlreadyPrinted = true;
        // The button will probably "Bounce" when you press it
        // wait long enough to get past that.
      delay(20);
    }
  }
  else
  {
      // when the pin goes High again the button is released
      // reset "AlreadyPrinted" so you will print again the
      // next time it goes low.
        // bounce on release isn't usually a problem but  let's allow for it
        // since there is a delay() below we will check to see if we need to
        // change AlreadyPrinted - that way we won't have the delay every
        // time we go through the loop - only when the button is first released
    if(AlreadyPrinted == true)
    {
          AlreadyPrinted = false;
          delay(20);
    }
  }
  
//}     The closing bracket for loop() WAS here.

  
              // for second button use the same code except substitute ButtonPinNum2
              // and AlreadyPrinted2
  if(digitalRead(ButtonPinNum2) == LOW)  // the button is pressed
  {
    // we want to print ONCE when the pin goes from high to low
    if(AlreadyPrinted2 == false)
    {
      Serial.print(ButtonPinNum2, DEC); // Print the "11"
      Serial.print(" - ");
      Serial.println(millis(), DEC);  // simply print the number of milliseconds since startup
      AlreadyPrinted2 = true;
        // The button will probably "Bounce" when you press it
        // wait long enough to get past that.
      delay(20);
    }
  }
  else
  {
      // when the pin goes High again the button is released
      // reset "AlreadyPrinted2" so you will print again the
      // next time it goes low.
        // bounce on release isn't usually a problem but  let's allow for it
        // since there is a delay() below we will check to see if we need to
        // change AlreadyPrinted2 - that way we won't have the delay every
        // time we go through the loop - only when the button is first released
    if(AlreadyPrinted2 == true)
    {
          AlreadyPrinted2 = false;
          delay(20);
    }
  }
  
}

Thank you so much, forgot to add the second variable. Did it like this:

int ButtonPinNum = 12;
int ButtonPinNum2 = 11;
int AlreadyPrinted = false;

Still learning. :slight_smile: