On-device ML: a padel racket that thinks in real time
Most machine learning runs somewhere comfortable: a server, a GPU, all the memory it wants. I wanted to put a classifier somewhere uncomfortable, on a microcontroller strapped to a padel racket, and have it decide what shot you just hit before the ball reaches the other side. No cloud, no round trip, no excuses.
The whole loop fits on the racket
The hardware is an Arduino Nano 33 BLE Sense, chosen for its onboard IMU: an accelerometer and gyroscope that capture how the racket moves through a swing. The pipeline is deliberately end to end:
- Capture. A custom Arduino sketch records raw IMU data per stroke, building a labelled dataset of forehands, backhands, smashes and bandejas, plus a noise class for everything that is not a real shot.
- Train. The model is trained in TensorFlow on those sensor traces.
- Shrink. It is converted to TensorFlow Lite and exported as a C header,
model.h, that compiles straight into the firmware. - Infer on-device. The board runs inference in real time from the live IMU stream. Classification happens on the racket itself.
- Show. A SwiftUI iOS app connects over Bluetooth Low Energy and displays stats across a dashboard, statistics and history view.
What the constraints teach you
A GPU lets you be sloppy. A microcontroller does not. When the whole model has to fit in a header file and run between two swings, you feel every decision: how to window the sensor signal, how much precision you can drop in quantization before the classifier starts confusing a smash for a bandeja, how little compute a real-time budget actually leaves you. Those pressures teach you things about a model that unlimited hardware never will.
This is the same instinct I bring to everything: strip the system to parts, understand each one, and put it back so it runs where it has no business running. The code is on my GitHub if you want to take it apart yourself.
ML on-device: una raqueta de pádel que piensa en tiempo real
La mayor parte del machine learning corre en algún sitio cómodo: un servidor, una GPU, toda la memoria que quiera. Yo quería poner un clasificador en un sitio incómodo, en un microcontrolador atado a una raqueta de pádel, y que decidiera qué golpe acabas de dar antes de que la bola llegue al otro lado. Sin nube, sin viaje de ida y vuelta, sin excusas.
El bucle entero cabe en la raqueta
El hardware es un Arduino Nano 33 BLE Sense, elegido por su IMU integrada: un acelerómetro y un giroscopio que capturan cómo se mueve la raqueta durante el golpe. El pipeline es deliberadamente de principio a fin:
- Captura. Un sketch propio de Arduino graba los datos crudos de la IMU por golpe, construyendo un dataset etiquetado de drives, revés, smashes y bandejas, más una clase de ruido para todo lo que no es un golpe real.
- Entrenamiento. El modelo se entrena en TensorFlow sobre esas trazas de sensor.
- Compresión. Se convierte a TensorFlow Lite y se exporta como una cabecera C,
model.h, que compila directa dentro del firmware. - Inferencia on-device. La placa hace la inferencia en tiempo real a partir del flujo en vivo de la IMU. La clasificación ocurre en la propia raqueta.
- Visualización. Una app iOS en SwiftUI se conecta por Bluetooth Low Energy y muestra estadísticas en una vista de dashboard, estadísticas e historial.
Lo que te enseñan las restricciones
Una GPU te deja ser descuidado. Un microcontrolador no. Cuando el modelo entero tiene que caber en una cabecera y correr entre dos golpes, sientes cada decisión: cómo ventanear la señal del sensor, cuánta precisión puedes soltar en la cuantización antes de que el clasificador empiece a confundir un smash con una bandeja, qué poco cómputo te deja de verdad un presupuesto en tiempo real. Esas presiones te enseñan cosas sobre un modelo que el hardware ilimitado nunca te enseñará.
Es el mismo instinto que llevo a todo: reducir el sistema a piezas, entender cada una, y volver a montarlo para que corra donde no tiene ningún derecho a correr. El código está en mi GitHub por si quieres desmontarlo tú mismo.