Video
                                
                                
# Lab: Button State with Timestamp
## Objective
Learn to track button state changes with precise timestamps using the `millis()` function. This lab builds upon basic button reading to add time-based monitoring and state change detection.
## Learning Outcomes
- Understand state change detection principles
- Master the `millis()` function for timing
- Learn to track button press and release events with timestamps
- Implement efficient state change monitoring without blocking delays
## Required Components

1. **Lonely Binary UNO R3** - Main Arduino board
2. **TinkerBlock UNO R3 Shield** - Expansion shield that plugs onto the UNO R3
3. **TinkerBlock TK04 - Push Button** - Push button module with 4-pin connector
## Theory
### State Change Detection
- **State Change**: Occurs when a button transitions from one state to another (LOW to HIGH or HIGH to LOW)
- **Edge Detection**: Detecting the moment when a signal changes from one level to another
- **Rising Edge**: Transition from LOW to HIGH (button press)
- **Falling Edge**: Transition from HIGH to LOW (button release)
### The `millis()` Function
- **Purpose**: Returns the number of milliseconds since the Arduino board began running the current program
- **Range**: 0 to 4,294,967,295 (approximately 49.7 days)
- **Overflow**: Automatically resets to 0 after reaching maximum value
- **Non-blocking**: Unlike `delay()`, `millis()` doesn't pause program execution
- **Precision**: Provides millisecond-level timing accuracy
### State Tracking Variables
- **`lastButtonState`**: Stores the previous button state for comparison
- **Purpose**: Enables detection of state changes by comparing current vs. previous state
- **Initialization**: Should be set to the initial button state (usually LOW)
### Key Functions Used
- `digitalRead(pin)`: Reads the state of a digital pin (HIGH or LOW)
- `millis()`: Returns milliseconds since program start
- `Serial.begin(baud)`: Initializes serial communication
- `Serial.print()` and `Serial.println()`: Outputs data to Serial Monitor
## Circuit Diagram

## Connection Instructions
1. **Assemble the Hardware:**
   - Place the TinkerBlock UNO R3 Shield onto the Lonely Binary UNO R3
   - Ensure all pins are properly aligned and seated
   - The shield should fit snugly on top of the Arduino board
2. **Connect the Push Button Module:**
   - Take the TinkerBlock TK04 - Push Button module
   - Align the 4-pin connector with any available 4-pin slot on the shield
   - Gently push the module into the slot until it clicks into place
   - The module will automatically connect:
     - **GND** pin to ground
     - **VCC** pin to 5V power
     - **NC** pin remains unconnected
     - **Signal** pin to digital pin D5
3. **Important Notes:**
   - No breadboard or jumper wires required
   - The TK04 push button has a built-in 10kΩ pull-down resistor
   - The button's built-in LED will light when pressed
## Code
```cpp
// Lab 6: Button State with Timestamp
// Push button connected to digital pin D5
// Tracks button state changes with precise timestamps
// Define the button pin
const int buttonPin = 5;   // Button input pin
// Variable to store the last button state
int lastButtonState = LOW;
void setup() {
  // Configure button pin as input
  pinMode(buttonPin, INPUT);
  
  // Initialize serial communication for debugging
  Serial.begin(9600);
  
  Serial.println("Button State with Timestamp Lab Started");
  Serial.println("Press and release the button to see timestamps");
  Serial.println("----------------------------------------");
}
void loop() {
  // Read the current button state
  int buttonState = digitalRead(buttonPin);
  
  // Check if button state has changed
  if (buttonState != lastButtonState) {
    // Get current time in milliseconds
    unsigned long currentTime = millis();
    
    // Determine the type of state change
    if (buttonState == HIGH) {
      // Button was just pressed (rising edge)
      Serial.print("Button PRESSED at: ");
      Serial.print(currentTime);
      Serial.println(" ms");
    } else {
      // Button was just released (falling edge)
      Serial.print("Button RELEASED at: ");
      Serial.print(currentTime);
      Serial.println(" ms");
    }
    
    // Update the last button state
    lastButtonState = buttonState;
  }
  
  // Small delay to prevent too rapid reading and reduce noise
  delay(10);
}
```
## Code Explanation
### Setup Function
```cpp
void setup() {
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);
  Serial.println("Button State with Timestamp Lab Started");
}
```
- Configures pin D5 as input for button reading
- Initializes serial communication for debugging
- Prints startup messages to Serial Monitor
### Global Variables
```cpp
int lastButtonState = LOW;
```
- **Purpose**: Stores the previous button state for comparison
- **Initial Value**: Set to LOW to match the initial button state (not pressed)
- **Usage**: Compared with current button state to detect changes
### Loop Function
```cpp
void loop() {
  int buttonState = digitalRead(buttonPin);
  
  if (buttonState != lastButtonState) {
    // State change detected - process it
  }
}
```
**State Change Detection:**
- `buttonState != lastButtonState`: Compares current and previous states
- **True**: Button state has changed (either pressed or released)
- **False**: Button state remains the same
**Timestamp Recording:**
- `unsigned long currentTime = millis()`: Captures precise timing
- Records the exact moment when state change occurs
- Provides millisecond-level accuracy
**State Change Processing:**
```cpp
if (buttonState == HIGH) {
  // Button press detected
  Serial.print("Button PRESSED at: ");
  Serial.print(currentTime);
  Serial.println(" ms");
} else {
  // Button release detected
  Serial.print("Button RELEASED at: ");
  Serial.print(currentTime);
  Serial.println(" ms");
}
```
**State Update:**
- `lastButtonState = buttonState`: Updates the stored previous state
- Ensures next comparison will be accurate
- Prevents repeated detection of the same state change
### Timing Considerations
- `delay(10)`: Small delay to prevent excessive reading
- Reduces noise and improves stability
- Allows other processes to run
- 10ms provides good responsiveness while maintaining efficiency
## Testing and Verification
1. **Upload the code to Lonely Binary UNO R3**
2. **Open Serial Monitor** in Arduino IDE (Tools → Serial Monitor)
3. **Observe the behavior:**
   - Initial message: "Button State with Timestamp Lab Started"
   - When button is pressed: Shows "Button PRESSED at: [time] ms"
   - When button is released: Shows "Button RELEASED at: [time] ms"
   - The button's built-in LED should light when pressed
4. **Verify timing accuracy:**
   - Press and hold the button for different durations
   - Note the time difference between press and release events
   - Verify that timestamps increase monotonically
## Expected Output Example
```
Button State with Timestamp Lab Started
Press and release the button to see timestamps
----------------------------------------
Button PRESSED at: 1250 ms
Button RELEASED at: 1850 ms
Button PRESSED at: 3200 ms
Button RELEASED at: 3450 ms
Button PRESSED at: 5200 ms
Button RELEASED at: 5800 ms
```
## Troubleshooting
### No state change detection:
- Check if the TinkerBlock shield is properly seated on the Arduino
- Ensure the TK04 module is firmly connected to the shield
- Verify the module is connected to a slot that uses D5 pin
- Check if `lastButtonState` is properly initialized to LOW
- Open Serial Monitor to see if any output appears
### Repeated state change messages:
- Check for loose connections between shield and Arduino
- Verify the button module is securely connected
- Try reconnecting the TK04 module to a different 4-pin slot
- Check for electrical noise or interference
### Incorrect timestamps:
- Verify that `millis()` is being called correctly
- Check that Serial Monitor is set to 9600 baud rate
- Ensure no other timing functions are interfering
- Verify the Arduino has been running continuously
### Button's built-in LED doesn't light:
- Check if the TK04 module is properly powered (VCC and GND connections)
- Verify the module is firmly seated in the shield
- Try reconnecting the module to a different 4-pin slot
## Experiment Variations
### 1. Button Hold Duration
Calculate and display how long the button was held:
```cpp
int lastButtonState = LOW;
unsigned long pressTime = 0;
void loop() {
  int buttonState = digitalRead(buttonPin);
  
  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
      // Button pressed - record start time
      pressTime = millis();
      Serial.print("Button PRESSED at: ");
      Serial.println(pressTime);
    } else {
      // Button released - calculate hold duration
      unsigned long holdDuration = millis() - pressTime;
      Serial.print("Button RELEASED at: ");
      Serial.print(millis());
      Serial.print(" ms - Held for: ");
      Serial.print(holdDuration);
      Serial.println(" ms");
    }
    lastButtonState = buttonState;
  }
  delay(10);
}
```
### 2. Multiple Button Press Counter
Count button presses and track timing:
```cpp
int lastButtonState = LOW;
int pressCount = 0;
unsigned long lastPressTime = 0;
void loop() {
  int buttonState = digitalRead(buttonPin);
  
  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
      pressCount++;
      unsigned long currentTime = millis();
      Serial.print("Press #");
      Serial.print(pressCount);
      Serial.print(" at: ");
      Serial.print(currentTime);
      Serial.println(" ms");
      
      if (pressCount > 1) {
        unsigned long timeSinceLastPress = currentTime - lastPressTime;
        Serial.print("Time since last press: ");
        Serial.print(timeSinceLastPress);
        Serial.println(" ms");
      }
      lastPressTime = currentTime;
    }
    lastButtonState = buttonState;
  }
  delay(10);
}
```
### 3. Button Activity Monitor
Track button activity patterns:
```cpp
int lastButtonState = LOW;
unsigned long sessionStartTime = millis();
int totalPresses = 0;
int totalReleases = 0;
void loop() {
  int buttonState = digitalRead(buttonPin);
  
  if (buttonState != lastButtonState) {
    unsigned long currentTime = millis();
    unsigned long sessionTime = currentTime - sessionStartTime;
    
    if (buttonState == HIGH) {
      totalPresses++;
      Serial.print("Press #");
      Serial.print(totalPresses);
      Serial.print(" at ");
      Serial.print(currentTime);
      Serial.print(" ms (Session: ");
      Serial.print(sessionTime);
      Serial.println(" ms)");
    } else {
      totalReleases++;
      Serial.print("Release #");
      Serial.print(totalReleases);
      Serial.print(" at ");
      Serial.print(currentTime);
      Serial.println(" ms");
    }
    lastButtonState = buttonState;
  }
  delay(10);
}
```
## Questions for Understanding
1. What is the difference between `millis()` and `delay()`?
2. Why do we need to store the `lastButtonState`?
3. What is a "state change" in the context of button input?
4. How does the `millis()` function help with timing measurements?
5. What would happen if we didn't update `lastButtonState`?
6. Why do we use `delay(10)` instead of a longer delay?
7. How can you calculate the duration between button press and release?
8. What is the advantage of using timestamps over simple state reporting?
## Next Steps
- Experiment with different timing intervals and patterns
- Try combining timestamp tracking with other sensors
- Learn about interrupt-based button handling for more precise timing
- Explore creating a button activity logger with timestamps
- Try implementing button gesture recognition using timing patterns
- Learn about debouncing techniques for more reliable state detection
## Safety Notes
- Always disconnect power before connecting or disconnecting modules
- Handle the TinkerBlock shield and modules carefully to avoid bending pins
- Ensure proper alignment when connecting modules to prevent damage
- The built-in resistor in the TK04 module prevents component damage
- Keep the Lonely Binary UNO R3 and shield in a stable position during operation
- Monitor Serial output to ensure proper operation and detect any issues
                                
                            
                            

 
	   
	 
	   
	 
	   
	 
	   
	 
	   
	 
	   
	 
	   
	