Turn Your Phone Into a Toy Seismograph With termux-sensor
Your phone has an accelerometer that measures acceleration on three axes, gravity included. With termux-sensor you can read it from the command line. This project turns those readings into a toy seismograph: a script that logs every reading to CSV, flags sudden shaking with an STA/LTA trigger (the same basic idea real seismic recorders use), and plots the result right in Termux. Expect it to catch footsteps, a slammed door or a knock on the table. Catching an earthquake is possible if it’s strong and close, but don’t count on it.
Warnings
CriticalThis is a hobby toy, not a seismometer or an earthquake warning. A phone accelerometer isn’t built to be a seismic sensor, and the script can’t tell a quake from a passing truck. For real earthquake information use USGS (see Big Island Hazard Pager). If you feel strong shaking near the coast, don’t check your phone: move to high ground (see Tsunami Safety).
What You Need
- Termux from F-Droid, working (see Install Termux).
- The Termux:API app from the same source as Termux (don’t mix F-Droid and Play builds).
- A phone with an accelerometer (almost all have one), and a flat, solid surface to lay it on.
- Basic comfort with pipes and editing a script in
nano.
Install → list → read → script → shake → plot → tune
Step 1: Install the packages
Install the Termux:API app first, then in Termux:
pkg update pkg install termux-api jq pkg install gnuplot # optional, for the ASCII plot in step 7
awk(gawk) is already part of Termux’s base system.Step 2: List your sensors
termux-sensor -l
You’ll get a JSON list of sensor names. They vary by phone, for example something like “LSM6DSO Accelerometer”. You don’t need the exact name:
-saccepts part of a name, ignores case, and if several sensors match it picks the one with the shortest name.Step 3: Read the accelerometer
termux-sensor -s accelerometer -d 500 -n 5
-d 500prints a reading every 500 ms and-n 5stops after five. Each reading is a JSON object keyed by the sensor’s name, with avaluesarray of x, y, z in m/s². Android’s accelerometer includes gravity, so a phone lying flat shows roughly 9.8 on one axis. The very first output may be an empty{}before the sensor reports. If a run is interrupted and the sensor seems stuck, release it withtermux-sensor -c.Step 4: Know the limits before you trust a squiggle
- Sample rate: Termux:API registers the sensor at Android’s
SENSOR_DELAY_UIrate, which Android documents as a suggested 60,000 microseconds (about 16 readings a second).-donly sets how often the latest value is printed, so going much below 60 ms just repeats readings. - Android calls the delay “only a suggested delay”; the system can change it.
- Noise: phone sensors are noisy and the phone picks up every footstep, fan and fridge. It is one sensor in one place, so it can’t locate or size an earthquake.
- Real phone-based earthquake projects, like UC Berkeley’s MyShake, combine data from many phones with careful science. One phone in Termux is a learning toy.
- Sample rate: Termux:API registers the sensor at Android’s
Step 5: Create the shake logger script
mkdir -p ~/bin nano ~/bin/shakelog.sh
Paste this script, then save with Ctrl+O, Enter, Ctrl+X:
#!/data/data/com.termux/files/usr/bin/bash # shakelog.sh - log accelerometer readings from termux-sensor and flag # sudden shaking with a simple STA/LTA trigger. A hobby toy, not a seismometer. # Usage: shakelog.sh [delay_ms] [sta_samples] [lta_samples] [ratio] set -u DELAY="${1:-60}" # ms between readings STA="${2:-8}" # short-term average length (samples) LTA="${3:-600}" # long-term average length (samples) RATIO="${4:-4}" # trigger when STA/LTA rises above this DIR="$HOME/shake" mkdir -p "$DIR" STAMP="$(date +%Y%m%d-%H%M%S)" CSV="$DIR/shake-$STAMP.csv" EVENTS="$DIR/events-$STAMP.log" echo "epoch,time,x,y,z,dev,ratio" > "$CSV" cleanup() { termux-sensor -c > /dev/null 2>&1 termux-wake-unlock printf '\nSaved %s\n' "$CSV" [ -s "$EVENTS" ] && cat "$EVENTS" exit 0 } trap cleanup INT TERM termux-wake-lock echo "Reading every ${DELAY} ms. Lay the phone flat and leave it alone. Ctrl+C to stop." termux-sensor -s accelerometer -d "$DELAY" | jq --unbuffered -r ' (to_entries[0].value.values? // empty) as $v | [now, (now | strflocaltime("%H:%M:%S")), $v[0], $v[1], $v[2]] | @tsv' | awk -F'\t' -v sta="$STA" -v lta="$LTA" -v ratio="$RATIO" \ -v csv="$CSV" -v ev="$EVENTS" ' { m = sqrt($3*$3 + $4*$4 + $5*$5) # total acceleration, m/s^2 n++ if (n == 1) g = m; else g += (m - g) / lta # slow average = gravity d = m - g; if (d < 0) d = -d # deviation = shaking s += (d - s) / sta # short-term average l += (d - l) / lta # long-term average r = (l > 0) ? s / l : 0 printf "%.3f,%s,%.4f,%.4f,%.4f,%.4f,%.2f\n", $1, $2, $3, $4, $5, d, r >> csv if (n > lta && r > ratio && !on) { on = 1 printf "%s TRIGGER STA/LTA %.1f dev %.3f m/s2\n", $2, r, d >> ev fflush(ev) printf "\n%s shake detected (STA/LTA %.1f)\n", $2, r } if (on && r < ratio / 2) on = 0 if (n % 20 == 0) { printf "\r%s dev %.4f m/s2 STA/LTA %5.2f ", $2, d, r; fflush() } }'How it works:
jqpulls x, y, z out of each JSON reading and adds a timestamp.awkcomputes the total acceleration, keeps a slow running average of it (≈ gravity), and treats the difference as shaking. It then keeps a short-term average (STA, about half a second) and a long-term average (LTA, about 36 seconds) of that shaking. When STA/LTA jumps above the threshold, something sudden happened. It re-arms once the ratio drops below half the threshold. Both averages are simple exponential averages, a lightweight stand-in for the fixed windows real recorders use.Step 6: Run a test
chmod +x ~/bin/shakelog.sh bash -n ~/bin/shakelog.sh && echo "syntax OK" ~/bin/shakelog.sh
Lay the phone flat on a hard floor or table and don’t touch it. The trigger stays quiet for the first 600 readings (about 36 seconds) while the long-term average settles. Then knock on the table or stamp on the floor a step away: you should see “shake detected”. Press Ctrl+C to stop; the script releases the sensor and wake lock and prints the CSV path and any triggers. Arguments are optional: delay_ms, STA samples, LTA samples, threshold, for example
shakelog.sh 60 8 600 6.Step 7: Look at what you recorded
cd ~/shake && ls f=$(ls -t shake-*.csv | head -n 1) awk -F, 'NR > 1 && $6 > max { max = $6; t = $2 } END { printf "peak deviation %.3f m/s2 at %s\n", max, t }' "$f" gnuplot -e "set terminal dumb 100 30; set datafile separator ','; set key off; plot '$f' every ::1 using 0:6 with lines"The CSV columns are epoch, time, x, y, z, dev, ratio. The
gnuplotline draws column 6 (deviation) as ASCII art in the terminal: a flat line with spikes where something shook. Copy the CSV to shared storage to open it in a spreadsheet (see storage deep dive).Step 8: Tune the trigger
- Too many triggers? Raise the threshold (4 → 6 or 8) or make STA longer. A seismology guide to STA/LTA notes that a threshold around 4 suits quiet sites, noisy sites need higher, and longer STA windows are less sensitive to short spikes.
- Missing knocks? Lower the threshold a little or shorten STA.
- Put the phone on the floor of a quiet room, not on a desk you type on.
- Compare your trigger times with real events on the USGS Latest Earthquakes map. Most triggers will turn out to be local noise.
Tips
FAQ
Can this detect earthquakes?
Sometimes, if the shaking is strong and close enough for a phone to feel. It can’t tell an earthquake from a door slam, and it isn’t a warning system. Use official sources for real earthquake information.
termux-sensor prints nothing or hangs.
Make sure the Termux:API app is installed from the same source as Termux. Try termux-sensor -l first, and run termux-sensor -c to release a stuck sensor.
Why is the z value about 9.8 when the phone is still?
Android’s accelerometer reports acceleration including gravity, and 9.8 m/s² is gravity. The script removes it with a slow running average.
Why does nothing trigger for the first half minute?
The long-term average needs time to learn the background level. The trigger is armed only after 600 readings.
Can I get more samples per second?
Not with termux-sensor. Termux:API listens at Android’s UI rate. Faster sampling would need a dedicated Android app.
Ctrl+C left the sensor running.
Run termux-sensor -c to release it, and termux-wake-unlock if the wake lock is still held.
Sources
- termux-api-package: termux-sensor script (options)
- Termux:API source: SensorAPI.java (JSON output, SENSOR_DELAY_UI, name matching)
- Termux Wiki: termux-sensor
- Android Developers: Motion sensors (accelerometer includes gravity, m/s²)
- Android Developers: Sensors overview (SENSOR_DELAY_UI, suggested delay)
- Trnkoczy (GFZ, NMSOP-2): Understanding and parameter setting of STA/LTA trigger algorithm
- UC Berkeley Seismology Lab: MyShake
- USGS: Latest Earthquakes