School Project
WiFi CSI Fall Detection
A fall detection system built with Sam Desai and Kristine McLaughlin at the University of Michigan. We extended a published WiFi Channel State Information (CSI) approach to fall detection to run entirely on a Raspberry Pi, turning WiFi signal disturbances into spectrograms and classifying them with a lightweight CNN. We build this as part of an assignment for EECS 598: ML for Computational Sensors on Mobile, Wearable, and IoT Devices, taught by Professor Ke Sun.
Capturing CSI on a Raspberry Pi
Most fall detection systems either rely on wearables people forget to put on, or cameras that raise privacy concerns and only see what's in frame. WiFi CSI sidesteps both problems: it reads the way a person's body disturbs the WiFi signal already passing through a room, with no device worn and no camera required. Prior work by Nakamura et al. paired this technique with a full-sized laptop and a 21-million-parameter ResNet34. We wanted to know whether the same idea could survive being squeezed onto a Raspberry Pi 4B.
The Raspberry Pi's Broadcom WiFi chipset has only one antenna, far less than the 4-antenna setup used in the original paper, so we expected a noisier signal from the start. To collect CSI data we used Nexmon-CSI, a firmware patch that exposes CSI readings for traffic on a chosen WiFi channel and MAC address. A laptop pinged a router at 1KHz while the RPi listened in; a fall happening between the two showed up as a disturbance in the captured CSI data. Not every router cooperated: some rate-limited pings below 1KHz, others operated on channels the Nexmon firmware couldn't read, and we eventually settled on an Xfinity WiFi Gateway that avoided both issues.
From CSI to Predictions
Dropped and delayed packets meant the raw CSI stream first had to be interpolated back to a steady 1KHz. From there we ran Principal Component Analysis to isolate the highest-variance data, since that's where a fall's disturbance shows up most clearly, and used a Short-Time Fourier Transform (512ms windows, 128ms overlap) to turn it into a spectrogram, blending multiple components by how much variance each one explained.
For classification, we swapped the original paper's ResNet34 for MobileNetV2, a ~3-million-parameter model built for exactly this kind of compute-constrained deployment. We fine-tuned it in two phases: first training only the final layer for 16 epochs on 200 samples, then unfreezing the whole network and training all layers for 32 epochs with a cyclical learning rate. Freezing early kept the pretrained features intact while the small fine-tuning dataset was still finding its footing. The full pipeline, Raspberry Pi capture through spectrogram through CNN, also runs live: it streams a rolling 10-second window of CSI data and outputs a prediction in real time.
Results and Limitations
We built a dataset of 100 falls and 150 non-falls (walking, sitting, picking things up, jumping, and similar everyday motions) performed by the three of us, then tested the model two ways: on a held-out set from the same room it trained in, and on a second, previously unseen room to check whether it generalized. In the training room it reached 74% accuracy with 70% recall, a lower accuracy than the original paper's 92% with its larger model, but favoring recall over precision was the right tradeoff, since missing a real fall is a far worse failure mode than a false alarm. End-to-end inference took under 7 seconds, fast enough for real-time use.
Moving to the unseen room told a different story: accuracy dropped to 43%. We think the single-antenna chipset and its automatic gain control made the signal more sensitive to room-specific noise, such as furniture and other people's movement, than a multi-antenna setup would be. That gap between same-room and cross-room performance was the clearest limitation of the single-antenna, single-environment approach, and the most obvious next step is training on data from more rooms.
Read the Full Report
The write-up below covers everything in more depth: the full evaluation setup, confusion matrices for both environments, and the limitations and future work we didn't get to. If it doesn't load, you can also open it directly.
Want to dig into the details?
The full source, dataset, and setup docs are on GitHub, or browse the rest of what I've built.