A discontinued controller, rebuilt end to end
A 1989 Nintendo Power Glove stripped to its shell and rebuilt as a working Bluetooth input device: original electronics discarded, an nRF52840 and a 6-DoF IMU fitted with five flex sensors, a replacement enclosure designed and 3D printed, the assembly hand-soldered, and firmware written to fuse the sensors through an extended Kalman filter and classify 31 finger gestures into mouse and keyboard events.
Why it earns its keepThat a piece of hardware with no usable documentation and no surviving vendor can be taken apart, understood, and rebuilt across every layer at once — mechanical, electrical, firmware and software. The estimator is the part that transfers: raw flex readings cross a threshold repeatedly on noise alone, so the gesture only becomes stable once the signal is filtered. Every instrumentation project meets that problem, and it is usually mistaken for a bad sensor.
What it is notA university capstone sponsored by Lockheed Martin, delivered by a student team, and not a commercial engagement of this firm. One unit, built to prove the rebuild rather than to be produced: no design-for-manufacture pass, no environmental qualification, no fleet. The filter core is TinyEKF (Simon D. Levy, MIT), adapted here to two different state dimensions and made to run on the microcontroller; the estimator models, the gesture classification and the hardware are the team's own.
- MCU
- nRF52840, Bluetooth LE
- Sensing
- 6-DoF IMU + 5 flex
- Gestures
- 31 finger combinations
- Output
- Bluetooth HID
// Per-finger thresholds: a pinky does not travel as far as a thumb,// so one shared constant would misread both.#define THUMB_THRES 60#define INDEX_THRES 40#define MIDDLE_THRES 50#define RING_THRES 35#define PINKY_THRES 42 static inline Gestures gesture(float thumb, float index, float middle, float ring, float pinky){ // turning it into a bitmap for fast checking int mask = (thumb > THUMB_THRES) << 4 | (index > INDEX_THRES) << 3 | (middle > MIDDLE_THRES) << 2 | (ring > RING_THRES) << 1 | (pinky > PINKY_THRES); switch (mask) { case 0b11111: return TIMRP; // all five: disable mouse case 0b11000: return TI; // thumb + index: drag case 0b10000: return T; // thumb: laser case 0b01000: return I; // index: left click // ... 31 named combinations in total }} // called with filtered values, not raw ones — an unfiltered// flex reading crosses its threshold repeatedly on noise alonecurrentGesture = gesture(thumbFiltered, indexFiltered, middleFiltered, ringFiltered, pinkyFiltered);