Sharjah, UAE GST
Home/ Projects/ Lesson 3: Motion Data Lab
Lesson 3 of 5 Sensing Intermediate ◎ 30 min

Lesson 3: Motion Data Lab

Draw the total g-force on a live graph and count every jolt and every drop - the two signals the main build looks for.

ESP32 Fall-Detection Learning Prototype
One of 5 projects in the ESP32 Fall-Detection Learning Prototype — the parts below are from that kit.

Before you start

Time
30 min
Do these first
On your own
You can do this lesson on your own. Use a padded, unoccupied test platform - never a person.

Exact parts

PartHow many
Wiring from Lesson 2 - nothing new
A book or card with the breadboard taped on, and a cushion (yours)

Not in the box

  • A cushion or foam pad to drop the test platform onto (yours)

What you build and learn

  • Free fall reads near 0 g; a landing spikes above 2 g
  • Counting a crossing once, not every reading above a line
  • Choosing limits (thresholds) from measurements
  • Live graphs in the Serial Plotter

The sketch combines x, y and z into one number, the total g: about 1.0 when still, whichever way the sensor faces.

It sets the sensor to ±8 g so a hard landing does not go off the scale (Lesson 2 used ±2 g for finer angles).

A crossing is counted once: only when total g goes above 2.5 g (or below 0.45 g) after being on the other side.

The Serial Plotter draws total_g with the two limits as flat lines, so you can see how close each movement gets.

New words

Free fall
Falling freely: the sensor feels almost no force, so total g drops towards 0.
Impact
A sudden stop: total g spikes far above 1.
Threshold
A limit, such as 2.5 g, where the behaviour changes.
Serial Plotter
Tools → Serial Plotter: draws the numbers the board sends as moving lines.

What this project uses

Every item below is in the kit. Not in the box: A cushion or foam pad to drop the test platform onto (yours).

Build this with

ESP32 Fall-Detection Learning Prototype

All 6 parts in one box, with this project and 4 more to build from them.

Price on request See the kit Request this kit
Need only these parts? Order them loose · from AED 133.07
Used in this project tick what you still need
Selected parts AED 133.07

One of each part. Packs (resistor assortment, jumper wires) already hold more than a single build needs. a foam pad or cushion (yours): included in the kit, ask us for it loose. Backorder parts ship once they arrive. Delivery is AED 20, free on orders AED 100+.

Connections

Unplug USB before you change any wire. Pin names are the labels printed on the board.

Lesson 3: Motion Data Lab - connection diagram with labelled pins
Connection diagram, drawn from this lesson's pin plan - not a photo of a tested build. Tap to open it full size. The table below says the same thing in words.
Part / pinConnect toNote
No changesSame as Lesson 2GY-521 and OLED on GPIO21/22, button on GPIO26

Step by step

One thing at a time. Tick nothing off until it matches the diagram.

  1. Upload the Lesson 3 code. No wiring changes are needed.
  2. Close the Serial Monitor, then open Tools → Serial Plotter at 115200 baud.Watch out: Only one of the two can be open at a time.
  3. With the platform still on the table, total_g sits near 1.0.
  4. Lift the platform 10 cm above a cushion and let go. Watch the dip and the spike.Watch out: Keep the USB cable slack and the drop short. Use only a padded, unoccupied platform - never a person.
  5. Try gentle bumps, a tap on the table and a slow tilt. Which ones cross the lines? Press the button to reset the counts between tests.

Sketch for this project

Written for the board in the kit. Copy it into the Arduino IDE; change the pin numbers if you wire it differently.

lesson3_motion_data.ino arduino
/*
  DIY KIT - ESP32 Fall-Detection Learning Prototype
  Lesson 3 of 5: Motion Data Lab

  WIRING: the same as Lesson 2 (OLED and GY-521 on GPIO21/22, button on GPIO26).

  WHAT SHOULD HAPPEN
    Open Tools > Serial Plotter at 115200 baud. The total_g line sits at about
    1.0 while the sensor is still. Lift and drop the test platform gently onto
    foam: total_g dips towards 0 while it falls and spikes when it lands.
    The OLED counts every IMPACT (above 2.5 g) and FREE FALL (below 0.45 g).
    Press the button to set the counts back to 0.
    Use a padded, unoccupied test platform - never a person.
*/

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

const int SDA_PIN = 21;
const int SCL_PIN = 22;
const int BUTTON_PIN = 26;
const float IMPACT_G = 2.5;           // the same limits as Lesson 5
const float FREEFALL_G = 0.45;
const unsigned long SAMPLE_MS = 20;   // 50 readings a second
const unsigned long REPORT_MS = 100;  // 10 plotter points a second

Adafruit_SSD1306 display(128, 64, &Wire, -1);
bool displayOk = false;
int mpuAddress = 0;
int impacts = 0, freefalls = 0;
bool wasImpact = false, wasFreefall = false;
float peakG = 0, lowestG = 10;
unsigned long lastSample = 0, lastReport = 0;
bool lastButton = HIGH;

bool answers(int address) {
  Wire.beginTransmission(address);
  return Wire.endTransmission() == 0;
}

bool writeRegister(int reg, int value) {
  Wire.beginTransmission(mpuAddress);
  Wire.write(reg);
  Wire.write(value);
  return Wire.endTransmission() == 0;
}

bool readAccel(float &x, float &y, float &z) {
  Wire.beginTransmission(mpuAddress);
  Wire.write(0x3B);
  if (Wire.endTransmission(false) != 0) return false;
  if (Wire.requestFrom(mpuAddress, 6) != 6) return false;
  int16_t rx = (int16_t)((Wire.read() << 8) | Wire.read());
  int16_t ry = (int16_t)((Wire.read() << 8) | Wire.read());
  int16_t rz = (int16_t)((Wire.read() << 8) | Wire.read());
  x = rx / 4096.0;                    // +-8 g range: 4096 counts per g
  y = ry / 4096.0;
  z = rz / 4096.0;
  return true;
}

void showCounts(float g) {
  if (!displayOk) return;
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.println("MOTION DATA LAB");
  display.setTextSize(2);
  display.setCursor(0, 12);
  display.print(g, 2);
  display.println(" g");
  display.setTextSize(1);
  display.setCursor(0, 34);
  display.print("impacts   "); display.println(impacts);
  display.print("free falls "); display.println(freefalls);
  display.print("peak "); display.print(peakG, 1); display.print("  low "); display.println(lowestG, 2);
  display.display();
}

void setup() {
  Serial.begin(115200);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  Wire.begin(SDA_PIN, SCL_PIN);
  displayOk = display.begin(SSD1306_SWITCHCAPVCC, 0x3C) || display.begin(SSD1306_SWITCHCAPVCC, 0x3D);
  if (answers(0x68)) mpuAddress = 0x68;
  else if (answers(0x69)) mpuAddress = 0x69;
  if (mpuAddress == 0 || !writeRegister(0x6B, 0x00) || !writeRegister(0x1C, 0x10)) {   // wake up, +-8 g
    Serial.println("GY-521 not found - see Lesson 2");
    while (true) delay(1000);
  }
  Serial.println("Lesson 3: open the Serial Plotter");
}

void loop() {
  bool button = digitalRead(BUTTON_PIN);
  if (button == LOW && lastButton == HIGH) {   // press: reset the counts
    impacts = 0; freefalls = 0; peakG = 0; lowestG = 10;
  }
  lastButton = button;

  if (millis() - lastSample < SAMPLE_MS) return;
  lastSample = millis();
  float x, y, z;
  if (!readAccel(x, y, z)) return;
  float g = sqrt(x * x + y * y + z * z);   // total g-force, whichever way it points
  if (g > peakG) peakG = g;
  if (g < lowestG) lowestG = g;

  // Count each crossing once, not every reading above the line.
  bool impact = g > IMPACT_G;
  if (impact && !wasImpact) impacts++;
  wasImpact = impact;
  bool freefall = g < FREEFALL_G;
  if (freefall && !wasFreefall) freefalls++;
  wasFreefall = freefall;

  if (millis() - lastReport >= REPORT_MS) {
    lastReport = millis();
    Serial.print("total_g:");
    Serial.print(g, 2);
    Serial.print(",impact_line:");
    Serial.print(IMPACT_G, 2);
    Serial.print(",freefall_line:");
    Serial.println(FREEFALL_G, 2);
    showCounts(g);
  }
}
ℹCompiler-checked for ESP32 Dev Module (ESP32 core 3.3.11, Adafruit SSD1306 2.5.17 / GFX 1.12.6 / BusIO 1.17.4, 0 warnings) and run in the kit simulator. Not yet bench-tested on the shipped parts.

Upload it

  1. Click Copy (or Download .ino and open the file).
  2. In the Arduino IDE choose File → New Sketch, select everything in it and paste.
  3. Check the bottom of the window says Arduino Uno and your port (Start here, step 5).
  4. Click Upload (the → arrow) and wait for Done uploading.

How the code works

In the codeWhat it does
writeRegister(0x1C, 0x10)Sets the sensor's range to ±8 g: 4096 counts per g.
sqrt(x*x + y*y + z*z)The total g-force, whichever way the sensor points.
if (impact && !wasImpact) impacts++;Counts a crossing only when it starts, not every reading above the line.
Serial.print("total_g:")"name:value" pairs are what the Serial Plotter draws as labelled lines.

Change it and see

Change: Change IMPACT_G from 2.5 to 1.5.What happens: Small bumps now count as impacts too.
Change: Change REPORT_MS from 100 to 20.What happens: The graph shows every reading - short spikes are easier to see.

What you should see or hear

  • Still: total_g about 1.0, a flat line between the two limit lines.
  • A short drop onto a cushion: a dip towards 0 (free fall) then a spike (impact). The OLED counts each.
  • A slow tilt: total_g stays near 1.0 - tilting alone is not an impact.

If it doesn't work

ProblemWhat to check
"GY-521 not found"Unplug USB. Check VCC to 3V3, GND, SDA to GPIO21 and SCL to GPIO22. Are the GY-521 header pins soldered? Loose pins pushed through the holes do not make contact.
The Plotter shows nothingClose the Serial Monitor first, then open the Plotter at 115200 baud.
Nothing ever crosses the impact lineA soft cushion slows the landing. Try a firmer pad, or lower IMPACT_G to see the data.
Counts go up while it sits stillA loose wire or loose sensor. Tape everything down and check SDA and SCL.

Small experiment

Drop the platform 5 times from 10 cm and 5 times from 20 cm. Write down the peak g each time. Does a higher drop always give a bigger spike?

Check what you learned

What does total g read in free fall?

Close to 0.

Why count only the start of a crossing?

Otherwise one impact lasting several readings would count many times.

Why is ±8 g used here instead of ±2 g?

A landing can go far above 2 g; ±8 g keeps it on the scale.

▶In the simulator: In the simulator the g slider sets total g directly - drag it above 2.5 or below 0.45 to see the counts change.

Next

  • Lesson 4 adds the buzzer so the alert can be heard.

Stuck?

Most problems are one wire in the wrong hole. Check these first:

  1. Unplug, then compare every wire with the lesson's diagram and table. One pin off is the most common problem.
  2. Are all VCC wires on 3V3 (not 5V or VIN), and all GND wires on GND?
  3. OLED and GY-521: SDA on GPIO21 and SCL on GPIO22, by the labels on each module?
  4. Serial Monitor: is it set to 115200 baud?
  5. Upload problems: Tools → Board = ESP32 Dev Module, the right port, and hold BOOT if it stops at "Connecting". (Start here, step 6.)
Still stuck? Ask us on WhatsApp. Send this message with a photo of your wiring - it tells us exactly where you are.
Hi DIY KIT, I'm stuck on the ESP32 Fall-Detection Learning Prototype.
Lesson: __
Step number: __
What should happen: __
What happens instead: __
Error message (copied exactly): __
I'll attach a photo of my wiring.
Message us on WhatsApp

More from this kit

All projects →

Bot
ECHO
Online — usually replies instantly
Catalog assistant: verify final stock/price on the product page before checkout.