Projects / Drones
Altitude & Orientation Logger
A flight logger for drones, rockets and RC planes — attitude, heading and altitude at 50 Hz.
Overview
The ET-S04 BNO085 does its own sensor fusion and outputs ready-made orientation, so the ESP32 doesn't have to run a filter. The ET-S15 BMP390 barometer resolves height changes of a few centimetres.
The logger records roll, pitch, heading and relative altitude to a CSV file in the ESP32's flash at 50 Hz. It runs from a small LiPo through a 5 V boost, and you download the file over USB after the flight.
- Roll, pitch and heading from on-chip fusion
- Relative altitude to ±0.25 m
- 50 Hz CSV logging to flash
- Light: one LiPo cell, USB-C charging
What you need
ElectroTrical boards
Boards total: AED 155.00
These boards are being manufactured. Open a board's page to see when it's back, or ask us about a kit.
You'll also need
- ESP32-S3 DevKitC-1 (or any ESP32-S3 board) with a USB-C data cable. Not sold by ElectroTrical.
- Qwiic / STEMMA QT cables (JST SH 4-pin) to chain the boards, or jumper wires
- Small 1S LiPo, 300–1,000 mAh
- Foam or 3D-printed mount with a small vent hole for the barometer
Wiring
Wire the first board's header to the ESP32 as shown, then link the other I²C boards with Qwiic cables. Every board carries VIN, GND, SDA and SCL through both Qwiic sockets, so the chain needs no extra wires. Addresses: BNO085 0x4A, BMP390 0x77.
Power
| From | To | Note |
|---|---|---|
| LiPo JST-PH | ET-P01 battery socket | |
| ET-P01 VBAT | ET-P05 VBAT | |
| ET-P01 GND | ET-P05 GND | |
| ET-P05 5V | ESP32 5V | |
| ET-P05 GND | ESP32 GND |
ESP32 → ET-S04 header
| From | To | Note |
|---|---|---|
| ESP32 3V3 | VIN | VIN sets the I²C logic level. Keep it at 3.3 V for the ESP32. |
| ESP32 GND | GND | |
| ESP32 GPIO8 | SDA | |
| ESP32 GPIO9 | SCL | |
| ESP32 GPIO15 | INT | Optional data-ready |
| ESP32 GPIO16 | RST | Optional reset |
Qwiic chain
| From | To | Note |
|---|---|---|
| ET-S04 Qwiic | ET-S15 Qwiic |
Build it
- 01
Set up the Arduino IDE
Install Arduino IDE 2, add the Espressif ESP32 board package (Boards Manager → “esp32” by Espressif), select “ESP32S3 Dev Module” and turn on USB CDC On Boot so Serial prints over USB. Install the libraries listed above the sketch from Library Manager.
- 02
Choose the flash layout
In Tools → Partition Scheme, select one with a large SPIFFS/LittleFS area (for example “Huge APP (3MB No OTA/1MB SPIFFS)” or a 16 MB option if your board has 16 MB flash).
- 03
Calibrate the compass
After power-up, wave the logger slowly in a figure-eight for 20 seconds, away from motors and metal. The BNO085 stores its calibration as it learns.
- 04
Mount it
Fix the boards with the arrows on the ET-S04 pointing forward. Isolate the board from motor vibration with foam, and shield the barometer from prop wash with open-cell foam over the vent.
- 05
Log a flight
Power up on the ground — altitude zero is taken at boot. After landing, plug in USB and type d in Serial Monitor to dump the CSV, or x to erase it.
Arduino code
Written for the ESP32-S3 DevKitC-1 with the Espressif Arduino core. Install these libraries from the Arduino Library Manager:
- Adafruit BNO08x
- Adafruit BMP3XX Library
#include <Wire.h>
#include <LittleFS.h>
#include <Adafruit_BNO08x.h>
#include <Adafruit_BMP3XX.h>
Adafruit_BNO08x bno(16); // RST on GPIO16
Adafruit_BMP3XX bmp;
sh2_SensorValue_t ev;
float roll, pitch, yaw, groundHpa;
void toEuler(float r, float i, float j, float k) {
roll = atan2(2 * (r * i + j * k), 1 - 2 * (i * i + j * j)) * RAD_TO_DEG;
pitch = asin(constrain(2 * (r * j - k * i), -1.0f, 1.0f)) * RAD_TO_DEG;
yaw = atan2(2 * (r * k + i * j), 1 - 2 * (j * j + k * k)) * RAD_TO_DEG;
}
void setup() {
Serial.begin(115200);
Wire.begin(8, 9);
Wire.setClock(400000);
LittleFS.begin(true);
if (!bno.begin_I2C(0x4A)) Serial.println("BNO085 not found");
bno.enableReport(SH2_ROTATION_VECTOR, 20000); // 50 Hz
if (!bmp.begin_I2C(0x77)) Serial.println("BMP390 not found");
bmp.setPressureOversampling(BMP3_OVERSAMPLING_8X);
bmp.setTemperatureOversampling(BMP3_OVERSAMPLING_2X);
bmp.setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_3);
bmp.setOutputDataRate(BMP3_ODR_50_HZ);
delay(500);
float sum = 0;
for (int n = 0; n < 20; n++) { bmp.performReading(); sum += bmp.pressure / 100.0; delay(20); }
groundHpa = sum / 20; // altitude zero = here
File f = LittleFS.open("/flight.csv", FILE_APPEND);
f.println("ms,roll,pitch,yaw,alt_m");
f.close();
Serial.println("Logging. d = dump, x = erase");
}
void loop() {
if (bno.wasReset()) bno.enableReport(SH2_ROTATION_VECTOR, 20000);
if (bno.getSensorEvent(&ev) && ev.sensorId == SH2_ROTATION_VECTOR) {
auto q = ev.un.rotationVector;
toEuler(q.real, q.i, q.j, q.k);
bmp.performReading();
float alt = bmp.readAltitude(groundHpa);
File f = LittleFS.open("/flight.csv", FILE_APPEND);
f.printf("%lu,%.1f,%.1f,%.1f,%.2f\n", millis(), roll, pitch, yaw, alt);
f.close();
}
if (Serial.available()) {
char c = Serial.read();
if (c == 'd') { File f = LittleFS.open("/flight.csv"); while (f.available()) Serial.write(f.read()); f.close(); }
if (c == 'x') { LittleFS.remove("/flight.csv"); Serial.println("Erased"); }
}
}
Troubleshooting
Heading drifts or jumps
Redo the figure-eight calibration away from metal, and keep the board away from motors, ESCs and battery leads, which distort the magnetic field.
Altitude jumps when the props spin
Prop wash changes the air pressure at the sensor. Cover the barometer with open-cell foam and keep it inside the frame.
Log stops after a few minutes
The flash partition is full. Choose a partition scheme with more file-system space, or log at 10–20 Hz.
Take it further
- Add the ET-S41 GNSS receiver for position and ground speed
- Trigger a parachute servo at apogee for model rockets
- Use the ET-S27 ICM-42688-P for high-rate vibration logging
Turning this into a product?
We design custom boards that combine these sensors on one PCB, with firmware and production.