/* * Fab Academy 2026 — Week 17 Wildcard * Rock / Paper / Scissors gesture recognition * Board: Seeed Studio XIAO ESP32S3 Sense (OV2640 camera + IMU) * * Workflow: train 3-class image model in Edge Impulse, export Arduino library, * then run inference on live camera frames. * * Before use: * 1. Create Edge Impulse project with labels: rock, paper, scissors * 2. Collect ~50+ images per class (hand in frame, consistent lighting) * 3. Train Impulse (Image classification, 96x96 RGB) * 4. Deployment → Arduino library → copy into Arduino/libraries/ * 5. Uncomment #include and run classify pipeline below */ #include // #include // Edge Impulse export #define EI_CAMERA_RAW_FRAME_BUFFER_COLS 320 #define EI_CAMERA_RAW_FRAME_BUFFER_ROWS 240 static bool debug_nn = false; // Last stable prediction (debounced) String lastGesture = "none"; unsigned long lastDetectMs = 0; const unsigned long DEBOUNCE_MS = 800; void setup() { Serial.begin(115200); delay(1000); Serial.println("Week 17 — Rock Paper Scissors (XIAO ESP32S3 Sense)"); Serial.println("Hold your hand in front of the camera..."); // ei_camera_init(); // from Edge Impulse camera driver } void loop() { // Snapshot + classify (Edge Impulse generated functions) // if (!ei_camera_capture()) return; // ei_impulse_result_t result = { 0 }; // EI_IMPULSE_ERROR err = run_classifier(&result, debug_nn); // if (err != EI_IMPULSE_OK) return; // float rock = result.classification[0].value; // label order from EI // float paper = result.classification[1].value; // float scissors = result.classification[2].value; // Demo serial output when model is linked — replace with real inference values float rock = 0.05, paper = 0.12, scissors = 0.83; String gesture = "unknown"; float threshold = 0.70; if (scissors > threshold && scissors > rock && scissors > paper) gesture = "scissors"; else if (rock > threshold && rock > paper && rock > scissors) gesture = "rock"; else if (paper > threshold && paper > rock && paper > scissors) gesture = "paper"; if (gesture != "unknown" && gesture != lastGesture && millis() - lastDetectMs > DEBOUNCE_MS) { lastGesture = gesture; lastDetectMs = millis(); Serial.print("Detected: "); Serial.println(gesture); // Optional: play tone or drive NeoPixel by gesture } delay(200); }