
OTTOtact
cester-ino/OTTO-hardware
those specs refer to the tactile buttons version, but a led backlight button version is in the works too.

Use of PlatformIO
Alaafia PCB local is an open-source printed circuit board by BigSmartt01, from the BigSmartt01/Fall_Sensor repository on GitHub. It is a 2-layer board of 72.9 × 57.1 mm with 12 parts on 27 nets, routed with 101 tracks and 0 vias.
It is built around the MT3608, BMI160 and TP4056. Its parts include 3 ICs, 3 connectors, 1 resistor and 1 inductor. It belongs with the ESP32 and RISC-V boards of this library.

3D render of the Fall Sensor carrier PCB (v1, single-layer)
An intelligent wearable fall detection system built on the ESP32-C3 Super Mini with BMI160 IMU, targeting elderly users with waist/lower-back placement. The system combines a 4-stage rule-based state machine with an on-device CNN (TFLite Micro, int8 QAT) for high-confidence detection. A persistent alerted state holds the alert active until the person's posture changes or they self-dismiss, preventing the common problem of fall alerts clearing while the person is still on the floor.
Real-time data streams over WiFi TCP to a PyQtGraph dashboard and InfluxDB/Grafana stack for threshold tuning and post-event analysis. A dual-purpose button handles both "I'm okay" dismissal and manual "I need help" alerts.
| Component | Part | Notes |
|---|---|---|
| MCU | ESP32-C3 Super Mini | USB-CDC, BLE, WiFi |
| IMU | BMI160 | I2C 0x68, ODR 200Hz |
| Charger | TP4056 | LiPo, 4.2V cutoff |
| Boost converter | MT3608 | Battery -> 5V rail |
| Buzzer | Passive buzzer | Active LOW driver |
| Button | Tactile switch | Dual-purpose: dismiss/SOS |
| Board | 5x7cm perfboard | Power/signal zone separated |
| Board | 5x7cm perfboard | Power/signal zone separated |

Hand-soldered perfboard build, ESP32-C3 Super Mini + BMI160
Pin assignments (ESP32-C3 Super Mini):
| Pin | Function |
|---|---|
| GPIO8 | SDA (BMI160) |
| GPIO9 | SCL (BMI160) |
| GPIO2 | Buzzer |
| GPIO3 | Button (INPUT_PULLUP, active LOW) |
| GPIO4 | BMI160 INT1 (reserved) |
| GPIO5 | BMI160 INT2 (reserved) |
Power path: LiPo -> TP4056 (charge management) -> MT3608 (boost to 5V) -> ESP32-C3 5V pin -> onboard LDO -> 3.3V rail -> BMI160 VCC
Fall_Sensor/
├── firmware_idf/ # ESP-IDF project (active)
│ ├── CMakeLists.txt
│ ├── partitions.csv # custom 3MB app partition for ESP32-C3 4MB flash
│ ├── sdkconfig.defaults
│ ├── main/
│ │ ├── CMakeLists.txt
│ │ ├── fall_sensor.cpp # app_main() entry point
│ │ ├── main.cpp # state machine + BMI160 + tasks
│ │ ├── inference.cpp # TFLite Micro wrapper + consecutive filter
│ │ ├── inference.h
│ │ ├── wifi_stream.cpp # WiFi TCP server for dashboard streaming
│ │ ├── wifi_stream.h
│ │ └── fall_model.h # auto-generated model C header
│ └── components/
│ ├── esp-tflite-micro/ # git submodule (espressif official)
│ ├── DFRobot_BMI160/ # git submodule (unmodified)
│ └── DFRobot_BMI160_wrapper/ # local CMakeLists.txt wrapper (tracked)
├── firmware/ # legacy PlatformIO attempt - kept for reference
├── docs/
│ ├── ERRORS_AND_FIXES.md
│ └── ML_README.md
├── hardware/ # KiCad schematics, BOM, perfboard layout
├── visualization/This project uses git submodules. Clone with:
git clone --recurse-submodules <repo-url>If already cloned:
git submodule update --init --recursiveOpen ESP-IDF terminal in VS Code (Ctrl+Shift+P -> ESP-IDF: Open ESP-IDF Terminal):
cd firmware_idf
idf.py set-target esp32c3
idf.py build
idf.py -p COM7 flash monitorExit monitor: Ctrl+]
On first build after a clean or target change, delete sdkconfig (not sdkconfig.defaults) before running set-target to avoid stale target conflicts.
STATE_NORMAL
accelMag < 3.0 m/s² -> STATE_FREEFALL (timeout 400ms)
STATE_FREEFALL
accelMag > 20.0 m/s² -> STATE_IMPACT (window 500ms)
STATE_IMPACT
gyroMag < 25 deg/s -> STATE_POST_IMPACT_STILLNESS
STATE_POST_IMPACT_STILLNESS
stillness 2.5s + orientation change + NN confirms -> STATE_FALL_CONFIRMED
STATE_FALL_CONFIRMED
captures fall orientation, triggers buzzer, fires FALL event
-> STATE_FALL_ALERTED (persistent - does not auto-clear)
STATE_FALL_ALERTED
re-buzzes every 10s
posture change > 2.0 m/s² delta -> STATE_NORMAL
button press ("I'm okay") -> STATE_NORMALAny state: button press outside STATE_FALL_ALERTED -> manual "I need help" alert
BMI160 ODR set to 200Hz via direct register write after I2cInit():
Wire.beginTransmission(0x68);
Wire.write(0x40); Wire.write(0x09); // ACC_CONF: 200Hz
Wire.endTransmission();
Wire.beginTransmission(0x68);
Wire.write(0x42); Wire.write(0x09); // GYR_CONF: 200Hz
Wire.endTransmission();BMI160 init order matters: softReset() must be called before I2cInit(). Reversed order causes silent all-zero readings.
DATA,<timestamp_ms>,<accelMag>,<gyroMag>,<state>
FALL,<timestamp_ms>State values: 0=NORMAL, 1=FREEFALL, 2=IMPACT, 3=POST-IMPACT STILLNESS, 4=FALL CONFIRMED, 5=FALL ALERTED
Output goes to both USB Serial (printf) and WiFi TCP simultaneously.
cd visualization
python dashboard.pySwitch between serial and WiFi at the top of the file:
CONNECTION_MODE = "serial" # or "wifi"
WIFI_HOST = "192.168.x.x" # ESP32-C3 IP printed on boot
WIFI_PORT = 3333The ESP32-C3 IP is printed on boot: [WiFi] Connect dashboard with: TCP <IP>:3333

Live dashboard showing a detected fall event: freefall, impact, then post-impact stillness
cd visualization
docker compose up -dSee docs/ML_README.md for full training and quantization details.
Quick retrain after any model or dataset change:
cd tests/three_classes
venv_compat\Scripts\activate # Python 3.10 required - TF not yet on 3.13+
python train_qat.py
python convert_to_header.py # outputs firmware_idf/main/fall_model.h
cd ../../firmware_idf
idf.py build
idf.py -p COM7 flash monitor| Metric | Value |
|---|---|
| Overall accuracy | 95.21% |
| Fall recall | 97.38% |
| ADL recall | 95.16% |
| Flash | 16.9 KB |
| Inference RAM | 47.1 KB |
| Window | 512 samples at 200Hz = 2.56s |
pip install -r requirements.txtML training scripts require Python 3.10 in a separate venv (venv_compat) - TensorFlow does not support Python 3.13+.
Smart Ayodele ayosmart129@gmail.com
| Qty | Value | Footprint | References |
|---|---|---|---|
| 2 | NetTie_2 | PCM_SL_Jumpers:JUP_P5.08mm | NT1, NT3 |
| 1 | 10K | Resistor_THT:R_Axial_DIN0411_L9.9mm_D3.6mm_P15.24mm_Horizontal | R1 |
| 1 | BATTERY | Connector_JST:JST_EH_B2B-EH-A_1x02_P2.50mm_Vertical | J1 |
| 1 | BMI160 | Alaafia_Footprint:BMI160 | U2 |
| 1 | BUTTON | Connector_JST:JST_EH_B2B-EH-A_1x02_P2.50mm_Vertical | J2 |
| 1 | Buzzer_5V | Buzzer_Beeper:MagneticBuzzer_ProSignal_ABT-410-RC | BZ1 |
| 1 | ESP32-C3_SUPERMINI_TH | footprint:MODULE_ESP32-C3_SUPERMINI_TH | U1 |
| 1 | GSM | Connector_JST:JST_EH_B6B-EH-A_1x06_P2.50mm_Vertical | J3 |
| 1 | MT3608 | Alaafia_Footprint:MT3608 | U3 |
| 1 | NetTie_2 | PCM_SL_Jumpers:JUP_P14mm | NT2 |
| 1 | TP4056 | Alaafia_Footprint:TP4056 | L1 |
It measures 72.9 × 57.1 mm and has 2 copper layers, 1.6 mm thick.
12 parts, built around the MT3608, BMI160 and TP4056. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
From the BigSmartt01/Fall_Sensor repository on GitHub, at the commit this page was made from: the board is hardware/One-Layer/Alaafia_PCB_local.kicad_pcb and its schematic hardware/One-Layer/Alaafia_PCB_local.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository states no licence, so its author keeps all rights: ask BigSmartt01 before reusing the design.

cester-ino/OTTO-hardware
those specs refer to the tactile buttons version, but a led backlight button version is in the works too.

szbeni/forcegauge
Traning for climbing. Load cell with HX711 and real time plotting,

martinberlin/H-cinread-it8951
CINWRITE pcb is the Hardware repository for the HAT that provides GoodDisplay DEXA-C097 controller a fast way to talk SPI and 5V boost converter.

rowr111/blinky-badge-light
lighting badge with unique patterns and sound reactivity

sailframes/core
Open-source sailboat racing data logger and analytics platform.

alxhoff/gameboy-dmg-pcb
PCB for Gameboy DMG with audio and GPIO expander to provide I2C interface to push buttons

enwi/PiSupply
Uninterruptable power supply for Raspberry Pi's, which can also power external HDDs
