Table of Contents
- Problem Exploration
- Project Overview
- Why This Tech Stack?
- Hardware Requirements
- Software Requirements
- How it works
- Dataset Collection
- Impulse Design
- Hardware Assembly
- Software Implementation
- User Interface & Experience
- Conclusion
Problem Exploration
You’re practicing table tennis, working on technique improvements. Your forehand feels stronger today, but is it really? Are you hitting with better consistency than last week? Without a coach watching, there’s no way to know if you’re actually improving or just feeling confident. This highlights a core challenge in table tennis training: the lack of real-time, objective feedback.
Image credit: Wally Table Tennis
Current Pain Points:
- Manual stroke counting is error-prone and distracting from technique
- No objective feedback on stroke distribution during practice
- No data tracking for performance improvement over time
What’s Needed:
- Auto-count each stroke type (drives, loops, smashes)
- Filter out noise and movements between strokes
- Instant motivation with real-time feedback after each stroke
- Standalone operation - no phone or PC required
- Feels like a real bat - similar weight and balance

Xinhua News
Project Overview
I built a smart table tennis bat by embedding an Arduino Nano 33 BLE Sense Rev2 in a 3D-printed handle, attached to a real blade and rubber. The bat’s BMI270 + BMM150 IMU captures motion data and feeds it to an AI model trained with Edge Impulse Studio.
Key Features:
- Real-time stroke detection - recognizes 5 stroke types + idle
- Fast response - new detection every 250ms with sliding windows
- Smart filtering - confidence checks + 2g threshold to avoid false positives
- OLED display - shows stroke counts and motivational messages
- Battery powered - just charge and play, no cables
- Real bat feel - careful weight distribution
Why This Tech Stack?
Arduino Nano 33 BLE Sense Rev2
- Built-in IMU (BMI270/BMM150) for 6-axis motion data
- Cortex-M4 core (64 MHz) runs TensorFlow Lite models
- BLE 5.0 for future mobile app features
- Tiny size (45×18mm) fits in bat handle
- Low power for long battery life
- Arduino ecosystem with many available libraries

Arduino Nano 33 BLE Sense Rev2
Edge Impulse Studio
Edge Impulse makes Edge AI simple:- Upload CSV data with automatic labeling
- Built-in signal processing and feature extraction
- AutoML finds the best model architecture
- Deploy as Arduino library
- Handles all the ML complexity in an intuitive UI
- Performance analysis with charts and metrics

Edge Impulse Studio Project Dashboard
Hardware Requirements
Core Components:
- Arduino Nano 33 BLE Sense Rev2 - Main microcontroller with built-in IMU
- SSD1306 128×32 OLED Display - I2C interface for real-time stats and feedback
- LiPo Battery (400mAh recommended) + JST connector
- Boost converter (steps LiPo output up to 5V for Arduino Vin)
- 3D-printed handle components (STL files provided)
- Table tennis blade (pre-made blade with removed handle or custom order)
- Table tennis rubbers (2.1mm thickness recommended)
Tools & Materials:
- Soldering iron and solder
- PVAC glue
- Table tennis glue/adhesive
- 3D printer (PLA filament)
- Wire strippers
- Small screwdriver set
Software Requirements
Development Environment:
- Arduino IDE 2.0+
- Edge Impulse CLI (optional, for data collection)
- Edge Impulse Studio account (free tier is sufficient)
Arduino Libraries:
How it works
We sample 6-axis motion at 50 Hz and keep a 500 ms rolling window with a 250 ms hop, which balances quick updates with stable predictions. Each window is turned into FFT-32 spectral features on all axes and fed to a compact INT8 neural network (20→10→6) that classifies five stroke types plus idle. Spectral features capture the rhythmic patterns that separate drives, loops and smashes more reliably than raw signals, which is why the model can give consistent feedback while you are still hitting. A lightweight decision layer usesargmax
, confidence above 0.75, an acceleration gate above 2g, and a short cooldown to cut false positives from handling and ball bounces. The OLED updates immediately with counts and messages so you get actionable feedback mid-drill, and the full loop completes in about 250 to 500 ms.
Performance:
On-device inference runs in about 12 ms with the INT8 model. End-to-end response from stroke to display is typically 250 to 500 ms. Battery life is around 2.5 hours per session. Offline evaluation shows 96.4% validation accuracy and 88.7% test accuracy.Dataset Collection
Stroke Categories:
- BHdrive: Backhand drive (equal ratio of spin and hit)
- BHsmash: Backhand smash (flat hit offensive shot)
- FHdrive: Forehand drive (equal ratio of spin and hit)
- FHloop: Forehand loop (spinning offensive shot)
- FHsmash: Forehand smash (flat hit offensive shot)
- zzz: Idle state (no stroke, subtle movement in between shots)
Data Collection Process:
The data collection uses a simple web app on your phone that connects to the Arduino via Bluetooth. Two parts work together:1. Arduino Data Collection Firmware
The Arduino runs specialized firmware (table-tennis-data-collection-bluetooth.ino
) that handles:
Swing Detection Algorithm:
- Keeps the last 500ms of motion data in memory
- When stroke detected, saves full 500ms (100ms before + 400ms after)
- Sends data to phone as CSV via Bluetooth
2. Web App Interface
The web app runs in your phone browser: Bluetooth Connection:3. How to Collect Data:
- Setup: Open web app on phone, upload firmware to Arduino
- Connect: App finds Arduino and connects via Bluetooth
- Pick stroke: Enter type like “FHdrive” or “BHsmash”
- Hit balls: System auto-detects and saves each stroke
- Monitor: See swing count and time in real-time
- Download: Get ZIP with numbered CSV files (
FHdrive0001.csv
, etc.)

Web interface of the data collection app

Download ZIP of CSV files for each stroke type
- Sampling Rate: 50Hz for accelerometer and gyroscope (6 channels total)
- Window Size: 500ms (25 samples per window)
- Detection Method: Combined acceleration (>2g) and angular velocity (>200°/s) thresholds
- Data Format: CSV with headers:
Timestamp,accX,accY,accZ,gyrX,gyrY,gyrZ
- Total Dataset: ~50 seconds per class (100 samples of 500ms windows per stroke type and idle)
- File Organization: Individual CSV per stroke, bundled in labeled ZIP files
Data Collection Tips:
- Record in realistic playing conditions (on table, with ball)
- Include variation in stroke intensity and angle
- Capture edge cases (gentle shots, missed swings)
- Record idle data during normal handling and setup
Upload to Edge Impulse Studio
- Open Edge Impulse Studio and create a new project (or open your existing project).
- Go to Data acquisition → Upload data.
- Drag and drop the ZIP exported by the web app (or multiple CSVs).
- Set Sensor type to Inertial and Sample rate to 50 Hz (if not auto-detected from CSV headers).
- Ensure labels are correct (filenames like
FHdrive0001.csv
will map to theFHdrive
label). Fix any mislabeled files if needed. - Keep the 80/20 train/test split you recorded, or use Studio’s Split function to create it.
- Verify each sample shows 6 axes (accX/accY/accZ, gyrX/gyrY/gyrZ) and that label counts look balanced.

Impulse Design
The impulse design transforms raw 6-axis IMU data into stroke classifications through a two-stage pipeline: spectral analysis for feature extraction, followed by neural network classification. Instead of using raw sensor values, we extract frequency domain features that better capture the distinctive motion signatures of different strokes. This approach proves more effective because table tennis strokes have characteristic frequency patterns—drives have different spectral content than loops or smashes.Edge Impulse Configuration:
1. Time Series Data Setup:
- Input Axes: 6 (accX, accY, accZ, gyrX, gyrY, gyrZ)
- Window Size: 500ms
- Frequency: 50Hz
2. Spectral Analysis:
- Analysis Type: FFT (Fast Fourier Transform)
- FFT Length: 32
- Parameters: Autotune (or basic parameters on free tier)


3. Classifier Configuration:
- Type: Neural Network Classifier
- Output Features: 6 (BHdrive, BHsmash, FHdrive, FHloop, FHsmash, zzz)
4. Neural Network Architecture:
Note: Edge Impulse automatically configured this default architecture when selecting the “Classifier” model, which proved effective for our stroke classification task.*
5. Training Configuration:
- Training Cycles: 500 epochs
- Learning Rate: 0.0002
- Loss Function: Categorical crossentropy
- Validation Split: 20%
6. Model Optimization:
- EON Tuner: Automated architecture search for optimal size/performance
- Quantization Options: Both Float32 and INT8 models available
- Memory Usage:
- Float32: 1.8KB RAM, 21.5KB Flash
- INT8: 1.5KB RAM, 16.8KB Flash

Training parameters and performance metrics for validation set

Model performance on testing dataset
Model Performance:
Model Type | Validation Accuracy | Test Accuracy | Inference Time | RAM Usage | Flash Usage |
---|---|---|---|---|---|
Float32 | 96.4% | 88.0% | 13ms | 1.8KB | 21.5KB |
INT8 | 96.4% | 88.7% | 12ms | 1.5KB | 16.8KB |

Summary
This design achieves excellent performance through smart feature engineering. The spectral analysis extracts meaningful frequency patterns from raw motion data, while the compact neural network efficiently processes these features for real-time classification. The INT8 quantization delivers the final optimization—maintaining high accuracy while fitting comfortably within Arduino memory constraints for 12ms inference speed.Hardware Assembly
I custom ordered a table tennis blade without a handle so the build would feel like a real racket. I then designed a two part handle in Fusion 360 with hollow interiors and printed both halves. The internal cavities and simple mounts hold the Arduino Nano 33 BLE Sense Rev2, the SSD1306 OLED, a boost converter, the LiPo battery, and a small power switch. The layout keeps the weight balanced, routes the wiring inside, and leaves both the power switch and the USB port accessible for charging and firmware updates.Step 1: Prepare the 3D-Printed Handle
- Print handle components using provided STL files
- Test-fit Arduino Nano and OLED display
- Sand/file mounting points if needed

Fusion360 CAD model
Step 2: Electronics Assembly
- Solder connections:
- OLED VCC → 3.3V
- OLED GND → GND
- OLED SDA → A4 (SDA)
- OLED SCL → A5 (SCL)
- Battery → boost converter
- Boost converter → Arduino Vin/GND

- Component placement:
- Arduino positioned for USB access during development
- OLED display visible through handle opening
- Battery and boost converter positioned on the other half of the handle

Step 3: Handle Integration
- Secure Arduino and OLED in printed housing
- Route battery, boost converter, and power switch through handle
- Seal electronics compartment
- Test all connections before final assembly

Assembly Tips:
- Keep IMU orientation consistent with training data
- Ensure OLED is easily readable during play
- Test electronics before permanent assembly
- Consider weight distribution for natural bat feel
Software Implementation
This sketch samples IMU data, builds overlapping windows, runs the Edge Impulse classifier, gates detections, and drives the OLED via a small state machine.Setup and model integration
Timing, windowing and thresholds
Buffering and sampling
Classification
State machine and OLED updates
User Interface & Experience
The UI is built for glanceability: a small state machine switches between an opening animation, live counters, a brief centered confirmation after each detection, and a subtle idle animation when you pause. The main screen shows only BH/FH drives, smashes, loop, and a total in a consistent layout you can read while playing. Updates arrive in about 250 to 500 ms, messages are short and positive, and there is nothing to configure mid‑drill, just power on, swing, and get feedback. Text UI mockups (128x32 OLED):

