Inspiration

A neurologist usually sees a person with Parkinson's for a short visit every few months. Tremor doesn't hold still for that visit. It rises as a dose wears off, drops after the next one, and changes from hour to hour. The doctor gets a snapshot and the patient's memory of the week. We wanted to give them the week itself.

What it does

  • Tracks rest tremor continuously with a Myo armband: how fast the hand shakes (Hz) and how strongly (in g).
  • Logs a dose with a squeeze. Hold a fist for 1.5 seconds and the band buzzes to confirm. No buttons or touchscreen, which matters when your hands shake.
  • Confirms tremor with muscle signals. The band's 8 muscle sensors check that the muscles are firing in the same rhythm as the shaking, so a bumpy car ride doesn't count as tremor.
  • Shows it on a dashboard: live readings, today's timeline with dose markers, a week heatmap, and how much tremor drops after each dose.
  • Writes a doctor-visit summary with Gemini, in plain language for the patient, plus an exact table of numbers for the clinician.
  • Runs on cheap hardware too. The same pipeline works on a Raspberry Pi Zero 2W with a basic Grove accelerometer and a physical button, as a backup and low-cost version.

How we built it

Sensing. We connect to the Myo over the laptop's Bluetooth with dl-myo, reading motion at about 50 samples/s and muscle activity (EMG) at about 200 samples/s.

Finding tremor. Every 1.28 s we analyze the last 2.56 s of motion. We remove gravity and slow drift, take the FFT of each axis, and add the power spectra together. (Taking the FFT of the overall acceleration magnitude instead would double the measured frequency.) We look for the strongest peak between 3 and 12 Hz, the range where tremor lives, and measure its strength as

and the pattern has to hold for 3 consecutive windows. That's what stops picking up a glass from counting as tremor.

Squeeze to log. A short calibration learns each person's relaxed and squeezing muscle levels. A dose is logged when smoothed muscle activity stays above the threshold for 1.5 s and the hand is still, so shaking doesn't count as a squeeze. Tremor checks pause during a squeeze, because a hard fist makes the hand shake too.

Muscle confirmation. We rectify and smooth each EMG channel into an envelope and find its rhythm between 3 and 12 Hz. If it's within 1 Hz of the motion's rhythm, the tremor is marked muscle-confirmed.

Data. Everything goes to Tiger Data (PostgreSQL with TimescaleDB): hypertables for raw samples and tremor features, compression on the raw data, and an hourly continuous aggregate that feeds the dashboard and the report. The ingest script can only insert and the dashboard can only read, using two separate database roles.

The report. Python does all the math (percent change after each dose, strong-tremor hours per day), and Gemini only writes it up, with guardrails: describe patterns, never diagnose, never give medication advice. The clinician table is built in Python, so every number in it is exact.

Tools. Python, Streamlit and Altair for the dashboard. We built it step by step in Cursor (using a Grok model), from a written spec with a "done when" test for every step.

Challenges we ran into

  • Our own gestures fought each other. Squeezing made the hand shake, which looked like tremor. Shaking tensed the forearm, which looked like a squeeze. We fixed it with a stillness check for squeezes and by pausing the tremor check during them.
  • Everyday movement looked like tremor until we required a sharp, sustained rhythm instead of just energy in the 3-12 Hz band.
  • Squeeze detection flickered around the threshold. Smoothing plus hysteresis made it reliable.
  • Hardware pivots. We went from a Raspberry Pi Pico to a Pi Zero 2W with a Grove HAT (whose 6-bit accelerometer is coarse) to the Myo, and kept the Pi as a backup.
  • Small bugs that cost hours: NumPy 2 values breaking database inserts, an API timeout that was in milliseconds rather than seconds, and wearing the band on the bicep instead of the forearm.

Accomplishments that we're proud of

  • A full live loop: armband → analysis → database → dashboard, with doses logged by a squeeze.
  • Two independent sensors (motion and muscle) agreeing before we call something tremor.
  • Without being told, the Gemini report found the late dose and the missed afternoon dose in a week of data.

What we learned

  • How tremor is actually measured: its frequency band, rest vs. action, and why rhythm and persistence matter more than raw strength.
  • The basics of surface EMG, and how much band placement and fit change the signal.
  • Time-series design: raw data, compressed history and rollups in one Postgres database.
  • With LLMs, let code do the numbers and let the model do the words.

What's next

  • Validate against clinician tremor ratings. This is a monitoring prototype, not a medical device.
  • A guided rest vs. posture test, to help tell different tremor types apart.
  • Proactive reminders when tremor stays high and no dose has been logged.
  • A phone app in place of the laptop, and a higher-resolution sensor for the low-cost version.

The week of history in our demo is simulated. Live data comes from the armband.

Built With

Share this project:

Updates

Submission history