03 - Lab Hand Wave LED Toggle

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** ![](https://cdn.shopify.com/s/files/1/0331/9994/7908/files/Pasted_image_20250723112055.png?v=1753857055) ## **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** ![](https://cdn.shopify.com/s/files/1/0331/9994/7908/files/Pasted_image_20250723112036.png?v=1753857060) ## **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