Video
# Lab: Hand Wave LED Toggle with TK57 Reflective Optical Sensor
## **Objective**
Create a hand wave detection system using the TK57 reflective optical sensor to toggle the TK01 LED on and off. This lab implements gesture recognition with debouncing and state management for reliable LED control.
## **Required Components**

## **Theory**
### **Hand Wave Detection**
- **Gesture Recognition**: Detecting hand movement patterns
- **Debouncing**: Preventing false triggers from sensor noise
- **State Machine**: Managing LED on/off states
- **Threshold Detection**: Using sensor values below 900 for detection
### **Toggle Function**
- **First Wave**: Turn LED on
- **Second Wave**: Turn LED off
- **Third Wave**: Turn LED on again
- **Pattern Continues**: Alternating on/off states
### **Detection Logic**
- **Sensor Value < 900**: Hand detected (wave detected)
- **Debounce Time**: Minimum time between detections
- **State Tracking**: Remember current LED state
- **Reliable Control**: Prevent rapid toggling
## **Wiring Instructions**
### **TK57 Reflective Optical Sensor Pinout**
- **GND** → Arduino GND
- **VCC** → Arduino 5V
- **NC** → No Connection
- **Signal** → Arduino Analog Pin A3
### **TK01 LED Module Pinout**
- **GND** → Arduino GND
- **VCC** → Arduino 5V
- **NC** → No Connection
- **Signal** → Arduino Digital Pin D3
### **Connection Diagram**

## **Basic Hand Wave Detection Code**
```cpp
// Hand Wave LED Toggle with TK57 Reflective Optical Sensor
// Pin definitions
#define SENSOR_PIN A3 // TK57 connected to A3
#define LED_PIN 3 // TK01 connected to D3
// Detection parameters
#define WAVE_THRESHOLD 400 // Threshold for hand detection (below 400)
#define DEBOUNCE_TIME 1000 // Minimum time between detections (ms)
// Variables
int sensorValue = 0; // Raw sensor reading
bool ledState = false; // Current LED state (false = off, true = on)
bool handDetected = false; // Current hand detection state
unsigned long lastDetection = 0; // Time of last detection
unsigned long lastToggle = 0; // Time of last LED toggle
void setup() {
// Initialize serial communication
Serial.begin(9600);
Serial.println("Hand Wave LED Toggle System");
Serial.println("============================");
// Initialize LED pin
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW); // Start with LED off
// Wait for sensor to stabilize
delay(1000);
Serial.println("System ready! Wave your hand near the sensor to toggle LED.");
Serial.println("Threshold: < 900 | Debounce: 1000ms");
Serial.println();
}
void loop() {
// Read sensor value
sensorValue = analogRead(SENSOR_PIN);
// Check for hand detection
bool currentHandDetected = (sensorValue < WAVE_THRESHOLD);
// Handle hand detection changes
if (currentHandDetected && !handDetected) {
// Hand just detected (rising edge)
handleHandWave();
}
// Update detection state
handDetected = currentHandDetected;
// Display status
displayStatus();
// Small delay for stable readings
delay(50);
}
// Function to handle hand wave detection
void handleHandWave() {
unsigned long currentTime = millis();
// Check debounce time
if (currentTime - lastDetection < DEBOUNCE_TIME) {
Serial.println("Debounce: Ignoring rapid detection");
return;
}
// Update last detection time
lastDetection = currentTime;
// Toggle LED state
ledState = !ledState;
digitalWrite(LED_PIN, ledState ? HIGH : LOW);
// Display toggle information
Serial.print("*** HAND WAVE DETECTED! *** LED: ");
Serial.println(ledState ? "ON" : "OFF");
// Show timing information
if (lastToggle > 0) {
unsigned long timeSinceLastToggle = currentTime - lastToggle;
Serial.print("Time since last toggle: ");
Serial.print(timeSinceLastToggle);
Serial.println("ms");
}
lastToggle = currentTime;
Serial.println();
}
// Function to display current status
void displayStatus() {
Serial.print("Raw: ");
Serial.print(sensorValue);
Serial.print(" | Threshold: ");
Serial.print(WAVE_THRESHOLD);
Serial.print(" | Hand: ");
Serial.print(handDetected ? "DETECTED" : "Clear");
Serial.print(" | LED: ");
Serial.print(ledState ? "ON" : "OFF");
// Show countdown for debounce
if (handDetected) {
unsigned long timeSinceDetection = millis() - lastDetection;
if (timeSinceDetection < DEBOUNCE_TIME) {
Serial.print(" | Debounce: ");
Serial.print(DEBOUNCE_TIME - timeSinceDetection);
Serial.print("ms");
}
}
Serial.println();
}
```
## **Advanced Hand Wave Detection with Multiple Gestures**
```cpp
// Advanced Hand Wave Detection with Multiple Gestures
// Pin definitions
#define SENSOR_PIN A3
#define LED_PIN 3
// Detection parameters
#define WAVE_THRESHOLD 900 // Threshold for hand detection
#define DEBOUNCE_TIME 800 // Debounce time (ms)
#define GESTURE_TIME 3000 // Time window for gesture recognition (ms)
#define MIN_WAVES 2 // Minimum waves for gesture recognition
// Variables
int sensorValue = 0;
bool ledState = false;
bool handDetected = false;
unsigned long lastDetection = 0;
unsigned long lastToggle = 0;
unsigned long gestureStartTime = 0;
int waveCount = 0;
bool gestureInProgress = false;
// Gesture types
enum GestureType {
NONE,
SINGLE_WAVE,
DOUBLE_WAVE,
TRIPLE_WAVE
};
void setup() {
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
delay(1000);
Serial.println("Advanced Hand Wave Detection System");
Serial.println("===================================");
Serial.println("Gestures:");
Serial.println("1 Wave: Toggle LED");
Serial.println("2 Waves: LED ON");
Serial.println("3+ Waves: LED OFF");
Serial.println();
}
void loop() {
// Read sensor value
sensorValue = analogRead(SENSOR_PIN);
// Check for hand detection
bool currentHandDetected = (sensorValue < WAVE_THRESHOLD);
// Handle detection changes
if (currentHandDetected && !handDetected) {
handleHandWave();
}
// Update detection state
handDetected = currentHandDetected;
// Check for gesture completion
checkGestureCompletion();
// Display status
displayAdvancedStatus();
delay(50);
}
// Function to handle hand wave detection
void handleHandWave() {
unsigned long currentTime = millis();
// Check debounce
if (currentTime - lastDetection < DEBOUNCE_TIME) {
return;
}
// Start or continue gesture
if (!gestureInProgress) {
gestureStartTime = currentTime;
gestureInProgress = true;
waveCount = 0;
}
// Increment wave count
waveCount++;
lastDetection = currentTime;
Serial.print("Wave #");
Serial.print(waveCount);
Serial.print(" detected! Time: ");
Serial.print(currentTime - gestureStartTime);
Serial.println("ms");
}
// Function to check if gesture is complete
void checkGestureCompletion() {
if (!gestureInProgress) return;
unsigned long currentTime = millis();
// Check if gesture time window has expired
if (currentTime - gestureStartTime > GESTURE_TIME) {
// Process completed gesture
processGesture();
// Reset gesture tracking
gestureInProgress = false;
waveCount = 0;
}
}
// Function to process completed gesture
void processGesture() {
Serial.print("Gesture completed: ");
Serial.print(waveCount);
Serial.print(" wave(s) - ");
switch (waveCount) {
case 1:
// Single wave: toggle LED
ledState = !ledState;
digitalWrite(LED_PIN, ledState ? HIGH : LOW);
Serial.println("LED TOGGLED");
break;
case 2:
// Double wave: turn LED on
ledState = true;
digitalWrite(LED_PIN, HIGH);
Serial.println("LED ON");
break;
default:
// Triple or more waves: turn LED off
ledState = false;
digitalWrite(LED_PIN, LOW);
Serial.print("LED OFF (");
Serial.print(waveCount);
Serial.println(" waves)");
break;
}
Serial.print("LED State: ");
Serial.println(ledState ? "ON" : "OFF");
Serial.println();
}
// Function to display advanced status
void displayAdvancedStatus() {
Serial.print("Raw: ");
Serial.print(sensorValue);
Serial.print(" | Hand: ");
Serial.print(handDetected ? "DETECTED" : "Clear");
Serial.print(" | LED: ");
Serial.print(ledState ? "ON" : "OFF");
if (gestureInProgress) {
unsigned long timeLeft = GESTURE_TIME - (millis() - gestureStartTime);
Serial.print(" | Gesture: ");
Serial.print(waveCount);
Serial.print(" waves (");
Serial.print(timeLeft);
Serial.print("ms left)");
}
Serial.println();
}
```
## **Interactive Hand Wave Detection with Serial Commands**
```cpp
// Interactive Hand Wave Detection with Serial Control
// Pin definitions
#define SENSOR_PIN A3
#define LED_PIN 3
// Configuration
int waveThreshold = 900; // Detection threshold
int debounceTime = 1000; // Debounce time (ms)
bool continuousMode = true; // Continuous output mode
bool ledEnabled = true; // LED control enabled
// Variables
int sensorValue = 0;
bool ledState = false;
bool handDetected = false;
unsigned long lastDetection = 0;
unsigned long lastToggle = 0;
int toggleCount = 0;
void setup() {
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
Serial.println("Interactive Hand Wave Detection System");
Serial.println("======================================");
Serial.println("Commands:");
Serial.println("t: Toggle continuous mode");
Serial.println("l: Toggle LED control");
Serial.println("+: Increase threshold");
Serial.println("-: Decrease threshold");
Serial.println("d: Adjust debounce time");
Serial.println("r: Reset system");
Serial.println("s: Show statistics");
Serial.println("c: Calibrate threshold");
Serial.println();
displaySettings();
}
void loop() {
// Check for serial commands
if (Serial.available()) {
handleCommand(Serial.read());
}
// Read sensor
sensorValue = analogRead(SENSOR_PIN);
// Check for hand detection
bool currentHandDetected = (sensorValue < waveThreshold);
// Handle detection changes
if (currentHandDetected && !handDetected) {
handleHandWave();
}
// Update detection state
handDetected = currentHandDetected;
// Continuous output mode
if (continuousMode) {
displayInteractiveStatus();
}
delay(100);
}
// Function to handle hand wave detection
void handleHandWave() {
unsigned long currentTime = millis();
// Check debounce
if (currentTime - lastDetection < debounceTime) {
Serial.println("Debounce: Ignoring rapid detection");
return;
}
// Update timing
lastDetection = currentTime;
// Toggle LED if enabled
if (ledEnabled) {
ledState = !ledState;
digitalWrite(LED_PIN, ledState ? HIGH : LOW);
toggleCount++;
}
// Display detection information
Serial.println("*** HAND WAVE DETECTED! ***");
Serial.print("LED State: ");
Serial.println(ledState ? "ON" : "OFF");
Serial.print("Toggle Count: ");
Serial.println(toggleCount);
if (lastToggle > 0) {
unsigned long timeSinceLastToggle = currentTime - lastToggle;
Serial.print("Time since last toggle: ");
Serial.print(timeSinceLastToggle);
Serial.println("ms");
}
lastToggle = currentTime;
Serial.println();
}
// Function to handle serial commands
void handleCommand(char command) {
switch (command) {
case 't':
continuousMode = !continuousMode;
Serial.print("Continuous mode: ");
Serial.println(continuousMode ? "ON" : "OFF");
break;
case 'l':
ledEnabled = !ledEnabled;
Serial.print("LED control: ");
Serial.println(ledEnabled ? "ON" : "OFF");
if (!ledEnabled) {
digitalWrite(LED_PIN, LOW);
ledState = false;
}
break;
case '+':
waveThreshold += 50;
Serial.print("Threshold increased to: ");
Serial.println(waveThreshold);
break;
case '-':
waveThreshold -= 50;
if (waveThreshold < 100) waveThreshold = 100;
Serial.print("Threshold decreased to: ");
Serial.println(waveThreshold);
break;
case 'd':
adjustDebounceTime();
break;
case 'r':
resetSystem();
break;
case 's':
showStatistics();
break;
case 'c':
calibrateThreshold();
break;
}
}
// Function to adjust debounce time
void adjustDebounceTime() {
Serial.println("Current debounce time: ");
Serial.print(debounceTime);
Serial.println("ms");
Serial.println("Enter new debounce time (100-5000ms):");
while (!Serial.available()) {
delay(100);
}
int newTime = Serial.parseInt();
if (newTime >= 100 && newTime <= 5000) {
debounceTime = newTime;
Serial.print("Debounce time set to: ");
Serial.print(debounceTime);
Serial.println("ms");
} else {
Serial.println("Invalid time. Keeping current value.");
}
}
// Function to reset system
void resetSystem() {
ledState = false;
digitalWrite(LED_PIN, LOW);
toggleCount = 0;
lastDetection = 0;
lastToggle = 0;
Serial.println("System reset");
}
// Function to show statistics
void showStatistics() {
Serial.println("System Statistics:");
Serial.print(" Total toggles: ");
Serial.println(toggleCount);
Serial.print(" Current LED state: ");
Serial.println(ledState ? "ON" : "OFF");
Serial.print(" Threshold: ");
Serial.println(waveThreshold);
Serial.print(" Debounce time: ");
Serial.print(debounceTime);
Serial.println("ms");
Serial.println();
}
// Function to calibrate threshold
void calibrateThreshold() {
Serial.println("Calibration mode:");
Serial.println("1. Keep hand away from sensor");
Serial.println("2. Press any key when ready");
while (!Serial.available()) {
delay(100);
}
Serial.read();
// Read baseline (no hand)
int baseline = 0;
for (int i = 0; i < 20; i++) {
baseline += analogRead(SENSOR_PIN);
delay(50);
}
baseline /= 20;
Serial.println("3. Place hand near sensor");
Serial.println("4. Press any key when ready");
while (!Serial.available()) {
delay(100);
}
Serial.read();
// Read with hand
int handLevel = 0;
for (int i = 0; i < 20; i++) {
handLevel += analogRead(SENSOR_PIN);
delay(50);
}
handLevel /= 20;
// Calculate threshold
waveThreshold = baseline - ((baseline - handLevel) * 0.7);
Serial.print("Baseline (no hand): ");
Serial.println(baseline);
Serial.print("Hand level: ");
Serial.println(handLevel);
Serial.print("New threshold: ");
Serial.println(waveThreshold);
Serial.println("Calibration complete!");
}
// Function to display interactive status
void displayInteractiveStatus() {
Serial.print("Raw: ");
Serial.print(sensorValue);
Serial.print(" | Threshold: ");
Serial.print(waveThreshold);
Serial.print(" | Hand: ");
Serial.print(handDetected ? "DETECTED" : "Clear");
Serial.print(" | LED: ");
Serial.print(ledState ? "ON" : "OFF");
Serial.print(" | Toggles: ");
Serial.println(toggleCount);
}
// Function to display current settings
void displaySettings() {
Serial.println("Current Settings:");
Serial.print(" Threshold: ");
Serial.println(waveThreshold);
Serial.print(" Debounce time: ");
Serial.print(debounceTime);
Serial.println("ms");
Serial.print(" Continuous mode: ");
Serial.println(continuousMode ? "ON" : "OFF");
Serial.print(" LED control: ");
Serial.println(ledEnabled ? "ON" : "OFF");
Serial.println();
}
```
## **Code Explanation**
### **Detection Logic**
- **Threshold**: Values below 900 indicate hand detection
- **Debouncing**: Prevents rapid toggling (1000ms minimum between detections)
- **State Machine**: Tracks LED on/off state
- **Smoothing**: Reduces sensor noise for reliable detection
### **Toggle Function**
- **First Wave**: LED turns ON
- **Second Wave**: LED turns OFF
- **Third Wave**: LED turns ON again
- **Pattern Continues**: Alternating states
### **Advanced Features**
- **Multiple Gestures**: Single, double, triple wave recognition
- **Gesture Timing**: 3-second window for gesture completion
- **Interactive Control**: Serial commands for system adjustment
- **Statistics Tracking**: Count total toggles and timing
## **Troubleshooting**
### **LED not toggling:**
- Check threshold value (should be below 900)
- Verify sensor wiring (A3 pin)
- Ensure LED wiring (D3 pin)
- Check debounce time setting
### **False detections:**
- Increase debounce time
- Adjust threshold value
- Check for ambient light interference
- Clean sensor surface
### **Rapid toggling:**
- Increase debounce time
- Add more smoothing
- Check sensor positioning
- Verify threshold calibration
### **LED not responding:**
- Check LED pin connection (D3)
- Verify LED module power (5V)
- Test LED with simple digitalWrite test
- Check for pin conflicts
## **Customization Ideas**
### **Add More Gestures:**
- **Hold Hand**: Continuous LED control
- **Wave Pattern**: Different LED patterns
- **Distance Control**: LED brightness based on proximity
- **Timing Patterns**: Different wave speeds
### **Add More Outputs:**
- **Multiple LEDs**: Different colors for different gestures
- **Buzzer**: Audio feedback for detections
- **Display**: Show gesture information
- **Relay**: Control external devices
### **Advanced Features:**
- **Gesture Learning**: Machine learning for custom gestures
- **Multi-Sensor**: Multiple sensors for 3D gesture recognition
- **Pattern Recognition**: Complex gesture sequences
- **Wireless Control**: Remote gesture control
## **Next Steps**
- Experiment with different threshold values
- Test various hand wave patterns
- Combine with other sensors for complex interactions
- Create custom gesture recognition algorithms
## **Resources**
- **TCRT5000 Datasheet**: Available online for detailed specifications
- **Gesture Recognition**: Understanding hand movement patterns
- **State Machine Design**: Managing system states
- **Debouncing Techniques**: Preventing false triggers