BYTESLIP ← Back
Knowledge Base // Tutorial 95 · Termux

Turn Your Phone Into a Toy Seismograph With termux-sensor

Difficulty: Medium ~25–40 min Termux · Termux:API · Sensors

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.

Safety // Read First

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).

Checklist // Before You Start

What You Need

Walkthrough // Steps 01–08

Install → list → read → script → shake → plot → tune

  1. 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.

  2. 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: -s accepts part of a name, ignores case, and if several sensors match it picks the one with the shortest name.

  3. Step 3: Read the accelerometer

    termux-sensor -s accelerometer -d 500 -n 5

    -d 500 prints a reading every 500 ms and -n 5 stops after five. Each reading is a JSON object keyed by the sensor’s name, with a values array 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 with termux-sensor -c.

  4. Step 4: Know the limits before you trust a squiggle

    • Sample rate: Termux:API registers the sensor at Android’s SENSOR_DELAY_UI rate, which Android documents as a suggested 60,000 microseconds (about 16 readings a second). -d only 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.
  5. 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: jq pulls x, y, z out of each JSON reading and adds a timestamp. awk computes 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.

  6. 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.

  7. 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 gnuplot line 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).

  8. 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.
Pro Tips

Tips

Troubleshooting // FAQ

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.

References // Sources

Sources

← All Tutorials Termux tutorials Big Island Hazard Pager