Video
# Lab: Multiply-Click Detection - Advanced Button Patterns
## Objective
Learn to detect different button click patterns (single, double, and triple clicks) using the TinkerBlock TK04 Push Button module. The button's built-in LED will light when pressed, and we'll use Serial communication to monitor and analyze click patterns within a time window.
## Learning Outcomes
- Understand timing-based button pattern detection
- Learn about click counting and time windows
- Master advanced button state management
- Create responsive multi-click detection systems
- Use timing functions for pattern recognition
- Use Serial communication for pattern analysis and debugging
## 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
### Click Pattern Detection
- **Single Click**: One button press and release
- **Double Click**: Two button presses within a time window (e.g., 500ms)
- **Triple Click**: Three button presses within a time window
- **Time Window**: Maximum time allowed between clicks to be considered a pattern
### Timing Concepts
- **millis()**: Returns milliseconds since Arduino started (non-blocking)
- **Time Windows**: Critical for distinguishing between intentional patterns and accidental clicks
- **Click Counting**: Tracking number of clicks within the time window
- **State Management**: Managing different phases of click detection
### Pattern Recognition Logic
1. **Detection Phase**: Monitor for button presses
2. **Timing Phase**: Wait for additional clicks within time window
3. **Action Phase**: Execute appropriate response based on click count
4. **Reset Phase**: Prepare for next pattern detection
### Key Functions Used
- `pinMode(pin, mode)`: Configures a pin as input or output
- `digitalRead(pin)`: Reads the state of a digital pin (HIGH or LOW)
- `millis()`: Returns milliseconds since Arduino started (non-blocking)
- `Serial.begin(baud)`: Initializes serial communication
- `Serial.print()` and `Serial.println()`: Outputs data to Serial Monitor
- `delay(milliseconds)`: Pauses the program for a specified time
## 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
- Multiple 4-pin slots are available on the shield for expansion
## Code
```cpp
// Lab: Double-Click Detection
// Push button connected to digital pin D5
// Define the button pin
const int buttonPin = 5; // Button input pin
// Timing constants
const unsigned long CLICK_WINDOW = 500; // Time window for multi-click detection (ms)
const unsigned long DEBOUNCE_TIME = 50; // Debounce delay (ms)
// Variables for click detection
int lastButtonState = LOW; // Previous button state
unsigned long lastClickTime = 0; // Time of last button press
int clickCount = 0; // Number of clicks in current window
bool waitingForMoreClicks = false; // Whether we're waiting for more clicks
void setup() {
// Configure button pin as input
pinMode(buttonPin, INPUT);
// Initialize serial communication for debugging
Serial.begin(9600);
Serial.println("Double-Click Detection Lab Started");
Serial.println("Click patterns:");
Serial.println(" Single click: Pattern detected");
Serial.println(" Double click: Pattern detected");
Serial.println(" Triple click: Pattern detected");
Serial.println(" Press the button to see click patterns!");
}
void loop() {
// Read the current button state
int buttonState = digitalRead(buttonPin);
// Detect button press (transition from LOW to HIGH)
if (buttonState == HIGH && lastButtonState == LOW) {
unsigned long currentTime = millis();
// Check if this is the first click or within the time window
if (currentTime - lastClickTime > CLICK_WINDOW) {
// New click sequence started
clickCount = 1;
waitingForMoreClicks = true;
Serial.println("First click detected");
} else {
// Additional click within time window
clickCount++;
Serial.print("Click ");
Serial.print(clickCount);
Serial.println(" detected");
}
lastClickTime = currentTime;
delay(DEBOUNCE_TIME); // Debounce delay
}
// Check if time window has expired and we have clicks to process
if (waitingForMoreClicks && (millis() - lastClickTime > CLICK_WINDOW)) {
// Time window expired, process the click pattern
processClickPattern(clickCount);
// Reset for next pattern
clickCount = 0;
waitingForMoreClicks = false;
}
// Update last button state
lastButtonState = buttonState;
// Small delay to prevent too rapid reading
delay(10);
}
void processClickPattern(int clicks) {
Serial.print("Processing ");
Serial.print(clicks);
Serial.print(" click(s): ");
switch(clicks) {
case 1:
// Single click
Serial.println("SINGLE CLICK detected!");
break;
case 2:
// Double click
Serial.println("DOUBLE CLICK detected!");
break;
case 3:
// Triple click
Serial.println("TRIPLE CLICK detected!");
break;
default:
// More than 3 clicks - special pattern
Serial.print("SPECIAL PATTERN detected: ");
Serial.print(clicks);
Serial.println(" clicks!");
break;
}
}
```
## Code Explanation
### Setup Function
```cpp
void setup() {
pinMode(buttonPin, INPUT);
Serial.begin(9600);
}
```
- Configures pin D5 as input for button reading
- Initializes serial communication for debugging
### Main Loop Logic
```cpp
void loop() {
int buttonState = digitalRead(buttonPin);
if (buttonState == HIGH && lastButtonState == LOW) {
// Button press detected
// Check timing and update click count
}
if (waitingForMoreClicks && (millis() - lastClickTime > CLICK_WINDOW)) {
// Time window expired, process pattern
processClickPattern(clickCount);
}
}
```
**Click Detection:**
- Detects button press transitions (edge detection)
- Tracks timing between clicks using `millis()`
- Counts clicks within the time window
- Waits for time window to expire before processing
**Timing Management:**
- `CLICK_WINDOW = 500`: 500ms window for multi-click detection
- `lastClickTime`: Records when each click occurred
- `millis() - lastClickTime > CLICK_WINDOW`: Checks if time window expired
### Pattern Processing Function
```cpp
void processClickPattern(int clicks) {
switch(clicks) {
case 1: Serial.println("SINGLE CLICK detected!"); break;
case 2: Serial.println("DOUBLE CLICK detected!"); break;
case 3: Serial.println("TRIPLE CLICK detected!"); break;
default: Serial.println("SPECIAL PATTERN detected!"); break;
}
}
```
**Pattern Responses:**
- **1 Click**: "SINGLE CLICK detected!"
- **2 Clicks**: "DOUBLE CLICK detected!"
- **3 Clicks**: "TRIPLE CLICK detected!"
- **4+ Clicks**: "SPECIAL PATTERN detected: X clicks!"
### Key Variables
- **clickCount**: Number of clicks in current window
- **lastClickTime**: Timestamp of last button press
- **waitingForMoreClicks**: Flag indicating active detection
- **CLICK_WINDOW**: Time window for pattern detection
## Testing and Verification
1. **Upload the code to Lonely Binary UNO R3**
2. **Open Serial Monitor** in Arduino IDE (Tools → Serial Monitor)
3. **Test different click patterns:**
- **Single click**: Serial shows "1 click(s): SINGLE CLICK detected!"
- **Double click** (within 500ms): Serial shows "2 click(s): DOUBLE CLICK detected!"
- **Triple click** (within 500ms): Serial shows "3 click(s): TRIPLE CLICK detected!"
- **4+ clicks**: Serial shows "X click(s): SPECIAL PATTERN detected: X clicks!"
4. **Verify timing:**
- Clicks must be within 500ms to be counted as a pattern
- Wait more than 500ms between patterns
5. **Verify connections:**
- Ensure the TK04 module is firmly connected to the shield
- Check that the shield is properly seated on the Arduino
- Confirm the button's built-in LED is visible and working
## Troubleshooting
### Button doesn't detect clicks properly:
- 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 code uploaded successfully to the Lonely Binary UNO R3
- Open Serial Monitor to see if button presses are being detected
### Click patterns not recognized:
- Check Serial Monitor output to see click detection messages
- Verify timing between clicks is less than 500ms
- Try adjusting the `CLICK_WINDOW` value if needed
- Ensure button debouncing is working properly
### 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
### Multiple clicks detected for single press:
- This indicates button bounce - increase `DEBOUNCE_TIME` to 100ms
- Check if the button module is properly seated
- Try cleaning the module connector pins if necessary
### Serial Monitor shows no output:
- Ensure Serial Monitor is set to 9600 baud rate
- Check that Serial.begin(9600) is in setup()
- Verify the correct COM port is selected in Arduino IDE
## Experiment Variations
### 1. Adjustable Click Window
Make the click window configurable:
```cpp
const unsigned long CLICK_WINDOW = 300; // Faster response
// or
const unsigned long CLICK_WINDOW = 1000; // Slower response
```
### 2. Different Pattern Responses
Create more complex pattern responses:
```cpp
void processClickPattern(int clicks) {
switch(clicks) {
case 1:
Serial.println("SINGLE CLICK - Quick response");
break;
case 2:
Serial.println("DOUBLE CLICK - Medium response");
break;
case 3:
Serial.println("TRIPLE CLICK - Complex response");
Serial.println(" Analyzing pattern...");
delay(500);
Serial.println(" Pattern confirmed!");
break;
case 4:
Serial.println("QUADRUPLE CLICK - Special sequence");
Serial.println(" Sequence 1: Complete");
delay(300);
Serial.println(" Sequence 2: Complete");
delay(300);
Serial.println(" All sequences: DONE");
break;
}
}
```
### 3. Click Counter with Reset
Add a reset function for long press:
```cpp
unsigned long pressStartTime = 0;
bool buttonWasPressed = false;
void loop() {
int buttonState = digitalRead(buttonPin);
if (buttonState == HIGH && lastButtonState == LOW) {
pressStartTime = millis();
buttonWasPressed = true;
// ... existing click detection code
} else if (buttonState == LOW && buttonWasPressed) {
unsigned long holdTime = millis() - pressStartTime;
if (holdTime > 2000) {
// Long press - reset click counter
clickCount = 0;
waitingForMoreClicks = false;
Serial.println("Long press - Click counter reset");
}
buttonWasPressed = false;
}
// ... rest of existing code
}
```
## Questions for Understanding
1. What is the purpose of the `CLICK_WINDOW` constant?
2. How does the code distinguish between single and double clicks?
3. Why do we use `millis()` instead of `delay()` for timing?
4. What happens if you click the button 4 times within the time window?
5. How could you modify the code to detect a quadruple click?
6. What is the difference between `waitingForMoreClicks` and `clickCount`?
7. How would you change the timing to make the system more or less sensitive?
## Next Steps
- Try connecting multiple TK04 push buttons to different 4-pin slots
- Experiment with different click patterns and timing windows
- Learn about interrupt-based button handling for more responsive detection
- Explore other TinkerBlock input modules (sensors, switches)
- Try creating more complex gesture recognition systems
- Implement click patterns for different button combinations
## 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 resistors in the modules prevent component damage
- Keep the Lonely Binary UNO R3 and shield in a stable position during operation
---
**Lab Completion Checklist:**
- [ ] TinkerBlock shield properly seated on Lonely Binary UNO R3
- [ ] TK04 Push Button module connected to shield (D5)
- [ ] Code uploaded successfully to Lonely Binary UNO R3
- [ ] Single click detected correctly
- [ ] Double click detected correctly
- [ ] Triple click detected correctly
- [ ] Serial Monitor shows correct click detection patterns
- [ ] Button's built-in LED lights when pressed
- [ ] Troubleshooting completed (if needed)
- [ ] Experiment variations tried
- [ ] Questions answered