Contents — 26 sections
Project Overview
Reads a machine's vibration and turns its frequency spectrum into an early warning — spotting the tell-tale signatures of bearing wear, imbalance and misalignment weeks before failure.
Rotating machines — motors, pumps, fans, gearboxes — announce their decline through vibration long before they fail, and each fault has a distinct signature buried in the vibration's frequency spectrum. A worn bearing generates energy at specific defect frequencies set by its geometry; imbalance shows up as a peak at the running speed; misalignment appears at twice the running speed; looseness scatters harmonics. To a human the machine just hums, but to an accelerometer plus a frequency analysis, these signatures are readable — which is the foundation of predictive maintenance: fixing a machine when the data says it is starting to fail, weeks in advance, instead of after it has failed and taken the production line down with it.
This monitor bolts an accelerometer to a machine, samples its vibration at high rate, and computes the FFT (Fast Fourier Transform) to reveal the spectrum — the amount of vibration at each frequency. From that spectrum it extracts the diagnostic features: the overall vibration level (an ISO-standard velocity RMS that classifies the machine's general health as good/acceptable/unacceptable), the peak at running speed (imbalance), the peak at 2× (misalignment), and energy at the calculated bearing defect frequencies (BPFO, BPFI, BSF, FTF) that pinpoint which part of a bearing is failing. Tracked over time against each machine's own healthy baseline, a rising trend in any of these is an early warning.
The value is entirely in trend and early warning, not a single reading. A machine has a characteristic healthy spectrum; the monitor learns it, then watches for the specific peaks to grow — a bearing defect frequency climbing out of the noise floor over weeks is a bearing beginning to fail, caught while there is still time to schedule the replacement during planned downtime rather than suffer an unplanned breakdown. The design is honest that low-cost MEMS accelerometers and edge FFTs are indicative — good for trending and catching clear developing faults, less so for the fine diagnosis a calibrated industrial analyser gives — and that mounting and sampling done wrong will corrupt the spectrum. But as an affordable, always-on condition monitor that turns vibration into readable, trended fault signatures, it delivers the core promise of predictive maintenance: knowing a machine is going to fail before it does.
What this project does
- Samples machine vibration at high rate with an accelerometer
- Computes the FFT to reveal the vibration spectrum
- Measures an ISO-standard overall vibration level (velocity RMS) for health class
- Extracts imbalance (1×), misalignment (2×) and looseness signatures
- Computes and watches bearing defect frequencies (BPFO/BPFI/BSF/FTF)
- Trends features against each machine's baseline for early warning
- Alerts when a fault signature rises — weeks before failure
Real-World Applications
| Setting | How it is used |
|---|---|
| Motors, pumps, fans | Continuous condition monitoring of rotating plant to catch bearing/imbalance/misalignment faults early. |
| Predictive maintenance programmes | Trending vibration across many machines to schedule repairs before failure and cut unplanned downtime. |
| Gearboxes / compressors | Watching for developing mechanical faults in critical drivetrain equipment. |
| Fleet / building services | HVAC, pumps and fans monitored cheaply and always-on across a facility. |
Deployment contexts where a build of this kind earns its keep.
Features & Capabilities
- FFT spectral analysis on the edge
- ISO 10816-style overall-level health classification
- Fault-specific signatures (imbalance, misalignment, looseness, bearings)
- Bearing defect-frequency computation from bearing geometry
- Per-machine baseline trending for predictive maintenance
- Early-warning alerts before breakdown
- Honest about MEMS/edge-FFT limits vs industrial analysers
Difficulty, Time & Required Skills
| Attribute | Value |
|---|---|
| Difficulty level | Advanced |
| Estimated completion time | 16–24 hours |
| Indicative build cost | ₹3,200 – ₹5,500 |
| Primary discipline | Industrial |
| Reference platform | ESP32 DevKit V1 (ESP-WROOM-32) |
Skills you should have (or will pick up)
- High-rate accelerometer sampling and correct mounting
- FFT/spectral analysis and windowing
- ISO velocity-RMS overall level and health classes
- Bearing defect-frequency calculation and interpretation
- Baseline trending and early-warning alerting
Bill of Materials
Every part below is commonly available from Indian and international hobby-electronics suppliers. Prices are indicative 2026 retail figures in Indian rupees and will drift — treat them as a budgeting guide, not a quotation.
| Component | Key specification | Qty | Approx. cost |
|---|---|---|---|
| ESP32 DevKit V1 (ESP-WROOM-32) Wi-Fi transmit bursts peak near 500 mA — size the regulator accordingly. | Dual-core Xtensa LX6 @ 240 MHz, 520 KB SRAM, 4 MB flash, Wi-Fi 802.11 b/g/n + BLE 4.2, 34 GPIO, 18× 12-bit ADC, 2× 8-bit DAC | 1 | ₹450 |
| ADXL345 3-axis accelerometer Built-in activity/free-fall interrupts let the MCU deep-sleep until something moves. | ±2/4/8/16 g, 13-bit, 0.004 g/LSB, tap and free-fall interrupts, 3200 Hz | 1 | ₹220 |
| MPU-6050 6-axis IMU Gyro bias drifts with temperature — re-zero at boot while the device is still. | 3-axis gyro ±250–2000 °/s, 3-axis accel ±2–16 g, 16-bit ADC, on-chip DMP | 1 | ₹190 |
| 0.96″ SSD1306 OLED display Static images burn in — invert or scroll the screen periodically. | 128 × 64 monochrome, 1.3–3.3 V logic, 100 kHz–400 kHz I²C | 1 | ₹250 |
| SX1278 LoRa 433 MHz module (Ra-02) Never power the radio without an antenna — the PA will destroy itself. | −148 dBm sensitivity, +20 dBm output, up to 10 km line of sight, SF7–SF12 | 1 | ₹480 |
| microSD card 32 GB A1 class For 24/7 loggers buy a high-endurance card — normal cards die in months. | A1 rated, 10 MB/s random write, UHS-I, endurance-grade recommended | 1 | ₹450 |
| 5 V 3 A regulated SMPS adapter Measure the real output — many "3 A" adapters sag below 4.7 V at 2 A. | 100–240 VAC in, 5 V ±5 % out, 3 A, short-circuit and over-voltage protection | 1 | ₹350 |
| High-rate/low-noise accelerometer Bandwidth and noise floor set what faults you can see | ADXL345/ADXL355-class or industrial IEPE for real bandwidth | 1 | ₹600 |
| Stud/magnetic mount Mounting quality dominates high-frequency fidelity | Rigid coupling to the machine (stud on bare metal best; magnet acceptable) | 1 | ₹250 |
| Tacho / speed reference (optional) | To know running speed for 1×/2× and bearing-frequency scaling | 1 | ₹300 |
| Industrial enclosure | Vibration/temperature-tolerant housing on or near the machine | 1 | ₹400 |
Estimated total: ₹3,940, excluding tools, shipping and consumables.
Tools and consumables
- Soldering iron (temperature controlled, 350 °C) with 0.8 mm 60/40 or lead-free solder
- Digital multimeter — continuity, DC volts and current ranges
- Wire strippers, flush cutters and a small set of precision screwdrivers
- Heat-shrink tubing and a heat gun (or a lighter, carefully)
- A laptop with a USB port and the toolchain listed above
Hardware Specifications
| Part | Specification | Supply | Interface | Reference |
|---|---|---|---|---|
| ESP32 DevKit V1 (ESP-WROOM-32) | Dual-core Xtensa LX6 @ 240 MHz, 520 KB SRAM, 4 MB flash, Wi-Fi 802.11 b/g/n + BLE 4.2, 34 GPIO, 18× 12-bit ADC, 2× 8-bit DAC | 3.3 V logic / 5 V USB | UART, SPI, I²C, I²S, CAN, PWM | Datasheet |
| ADXL345 3-axis accelerometer | ±2/4/8/16 g, 13-bit, 0.004 g/LSB, tap and free-fall interrupts, 3200 Hz | 2.0–3.6 V | I²C / SPI | Datasheet |
| MPU-6050 6-axis IMU | 3-axis gyro ±250–2000 °/s, 3-axis accel ±2–16 g, 16-bit ADC, on-chip DMP | 2.375–3.46 V (module 5 V tolerant) | I²C (0x68/0x69) | Datasheet |
| 0.96″ SSD1306 OLED display | 128 × 64 monochrome, 1.3–3.3 V logic, 100 kHz–400 kHz I²C | 3.3–5 V | I²C (0x3C) | Datasheet |
| SX1278 LoRa 433 MHz module (Ra-02) | −148 dBm sensitivity, +20 dBm output, up to 10 km line of sight, SF7–SF12 | 3.3 V | SPI | Datasheet |
| microSD card 32 GB A1 class | A1 rated, 10 MB/s random write, UHS-I, endurance-grade recommended | 3.3 V | SDIO / SPI | Datasheet |
| 5 V 3 A regulated SMPS adapter | 100–240 VAC in, 5 V ±5 % out, 3 A, short-circuit and over-voltage protection | 5 V | DC barrel / USB | Datasheet |
Consolidated electrical and interface specifications for every active part in the build.
Power Budget & Supply Sizing
Add up the typical active current of every part, then size the supply with at least 50 % headroom so transmit bursts and motor inrush never brown out the controller.
| Load | Supply rail | Typical current (mA) | Notes |
|---|---|---|---|
| ESP32 DevKit V1 (ESP-WROOM-32) | 3.3 V logic / 5 V USB | 160 | Wi-Fi transmit bursts peak near 500 mA — size the regulator accordingly. |
| ADXL345 3-axis accelerometer | 2.0–3.6 V | 0.14 | Built-in activity/free-fall interrupts let the MCU deep-sleep until something moves. |
| MPU-6050 6-axis IMU | 2.375–3.46 V (module 5 V tolerant) | 3.9 | Gyro bias drifts with temperature — re-zero at boot while the device is still. |
| 0.96″ SSD1306 OLED display | 3.3–5 V | 20 | Static images burn in — invert or scroll the screen periodically. |
| SX1278 LoRa 433 MHz module (Ra-02) | 3.3 V | 120 | Never power the radio without an antenna — the PA will destroy itself. |
| microSD card 32 GB A1 class | 3.3 V | 100 | For 24/7 loggers buy a high-endurance card — normal cards die in months. |
| 5 V 3 A regulated SMPS adapter | 5 V | 3000 | Measure the real output — many "3 A" adapters sag below 4.7 V at 2 A. |
Summed typical draw is 3404.04 mA. With a 1.5× design margin the supply should deliver at least 5200 mA continuously at the stated rail voltage.
Software Requirements & Development Environment
Reference toolchain: Arduino IDE 2.3.x with the ESP32 board package 3.x (or PlatformIO on VS Code). Anything newer normally works; anything older may lack the board definitions used here.
- Install the Arduino IDE 2.3.x (or PlatformIO if you prefer a real editor and dependency locking).
- Add
https://espressif.github.io/arduino-esp32/package_esp32_index.jsonunder File → Preferences → Additional Board Manager URLs, then install esp32 from the Boards Manager. - Set the correct port under Tools → Port. On Linux add yourself to the
dialoutgroup:sudo usermod -aG dialout $USERand log out and back in. - Open the Serial Monitor at 115200 baud — every sketch here logs its state there.
- Keep File → Preferences → Show verbose output during: compilation switched on while you are debugging build errors.
Required libraries
| Library | Why it is needed | Install |
|---|---|---|
| WiFi (ESP32 core) bundled | Station/AP connection management for the ESP32. | Bundled with the ESP32 Arduino core |
| PubSubClient 2.8 | Lightweight MQTT 3.1.1 client for constrained devices. | Library Manager → "PubSubClient" by Nick O'Leary |
| Adafruit SSD1306 + GFX 2.5.x | Framebuffer and text/graphics primitives for the OLED. | Library Manager → "Adafruit SSD1306" |
| LoRa (sandeepmistry) 0.8.0 | SX127x radio configuration, packet TX/RX and callbacks. | Library Manager → "LoRa" by Sandeep Mistry |
| ArduinoJson 7.x | Zero-allocation JSON serialisation and parsing. | Library Manager → "ArduinoJson" by Benoit Blanchon |
| Preferences (NVS) bundled | Wear-levelled key/value storage in ESP32 flash for settings. | Bundled with the ESP32 core |
Block Diagram
The block diagram shows the functional decomposition of the system — what senses, what decides, what acts, and where the data ends up.
Circuit Diagram & Wiring
Every signal line in the build is shown below, followed by a pin-by-pin connection table you can work through with a multimeter in hand.
| Peripheral | Peripheral pin | Controller pin | Signal |
|---|---|---|---|
| Accelerometer | SPI/I²C | GPIO 18/19/23/5 or 21/22 | High-rate vibration |
| Accelerometer | INT | GPIO 34 | Data-ready (paced sampling) |
| Tacho (opt) | PULSE | GPIO 27 | Running speed reference |
| OLED | SDA/SCL | GPIO 21/22 | Level/spectrum display |
| LoRa/Wi-Fi | bus | SPI / on-chip | Features/trends uplink |
| microSD | SPI | shared + CS | Optional raw/feature log |
| 5V supply | +/– | 3V3 reg | Power |
Wire one row at a time and tick it off — most "it does not work" reports trace back to a single swapped pair.
Wiring explanation
- Rigidly couple the accelerometer to the machine — a stud into bare metal is best; a strong magnet on a clean flat surface is acceptable; anything loose (tape, a wobbly bracket) destroys the high-frequency spectrum.
- Sample at a steady, known rate using the sensor's data-ready interrupt, at least ~2.5× the highest frequency of interest (bearing defect frequencies can be several kHz).
- Orient the accelerometer consistently (radial/axial) and record it; different directions reveal different faults.
- If available, feed a tacho/speed reference so 1×/2× and bearing frequencies scale with actual running speed.
- Keep the mount and cabling free of resonances that would add spurious peaks.
System Architecture
Read the stack from the bottom up: physical hardware, the firmware that drives it, the transport that moves data off the device, and the software a human actually looks at.
Working Principle
Vibration analysis works because a rotating machine's faults each inject energy at predictable frequencies, and separating vibration by frequency (the spectrum) exposes them. The physics is direct: a mass imbalance on a rotor pulls once per revolution, so it appears as a peak at the running speed (1×); a misaligned coupling flexes twice per revolution, giving a peak at 2×; mechanical looseness rattles and scatters energy across many harmonics; and a defect on a bearing race or rolling element strikes at a specific, calculable frequency every time it passes the load, producing energy at the bearing defect frequencies. A raw vibration amplitude tells you only that the machine shakes; the spectrum tells you why.
Getting the spectrum requires the FFT, and getting it right requires respecting the sampling. The accelerometer samples the vibration at a high, steady rate; the FFT converts a block of those samples into amplitude-versus-frequency. Two constraints dominate: the sample rate must exceed about 2.5× the highest frequency of interest (bearing defects can reach several kHz) or those frequencies alias into false low-frequency peaks; and the sample block should be windowed (e.g. Hann) before the FFT to avoid spectral leakage smearing the peaks. Above all, the accelerometer must be rigidly mounted — a stud into bare metal, or at least a magnet on a clean surface — because a loose or compliant mount acts as a mechanical filter that kills the high-frequency content where bearing faults live, so poor mounting silently makes the most important faults invisible.
From the spectrum the monitor extracts diagnostic features, each answering a specific question. The overall vibration level — conventionally a velocity RMS in the ISO 10816 band — classifies the machine's general condition (good / acceptable / unacceptable / danger) and is the headline health number. The amplitude at 1× quantifies imbalance; at 2×, misalignment; the pattern of harmonics, looseness. And energy in narrow bands around the computed bearing defect frequencies (outer race BPFO, inner race BPFI, ball BSF, cage FTF — each derived from the bearing's ball count, diameter and contact angle) pinpoints not just that a bearing is failing but which element. This turns a spectrum into a named diagnosis rather than a wall of peaks.
The decisive principle, though, is that the value lives in the trend against a baseline, not any single measurement. Every machine has a characteristic healthy spectrum with its own peaks and noise floor; the absolute numbers vary hugely between machines, so what matters is change. The monitor learns each machine's healthy baseline and then watches for the diagnostic features to grow over time — a bearing defect frequency rising out of the noise floor over days and weeks is a bearing entering failure, and catching that early is the entire point of predictive maintenance: it converts an unplanned, production-stopping breakdown into a planned repair during scheduled downtime. The design is candid about its ceiling — a low-cost MEMS accelerometer and an edge FFT are excellent for trending and catching clear developing faults but do not match a calibrated industrial analyser's resolution and diagnostic depth, and mounting or sampling done poorly will mislead. Used honestly, though — rigidly mounted, correctly sampled, and trended against each machine's own baseline — it delivers predictive maintenance's core value cheaply and continuously: it sees the failure coming.
The maths behind it
Sampling and FFT resolution
To see up to f_max without aliasing:
f_sample > 2.5·f_max (bearing defects reach several kHz)
FFT of N samples at f_sample gives:
resolution Δf = f_sample / N
→ more samples = finer peaks (needed to resolve close
bearing frequencies). Window (Hann) before FFT to reduce
spectral leakage.
ISO overall level (velocity RMS)
Integrate acceleration to velocity; overall RMS in the
10–1000 Hz band classifies condition (ISO 10816-style):
v_rms = sqrt( mean( v(t)^2 ) )
zones (machine-class dependent):
A good | B acceptable | C unsatisfactory | D danger
Rising v_rms = worsening general condition.
Bearing defect frequencies
For a bearing: n balls, ball dia d, pitch dia D, contact
angle θ, shaft speed f_r (rev/s):
BPFO = (n/2)·f_r·(1 − (d/D)cosθ) outer race
BPFI = (n/2)·f_r·(1 + (d/D)cosθ) inner race
BSF = (D/2d)·f_r·(1 − ((d/D)cosθ)²) ball
FTF = (1/2)·f_r·(1 − (d/D)cosθ) cage
Energy at these = the corresponding element failing.
Program Flowchart
The firmware is a single cooperative loop. Nothing blocks for long, so networking, sensing and the user interface all stay responsive.
Assembly Instructions
Build on a breadboard first and only commit to solder once the whole system has run for an hour without a fault.
Mount the accelerometer rigidly
Couple the accelerometer to the machine with a stud into bare metal where possible (best high-frequency fidelity), or a strong magnet on a clean, flat surface. Orient it consistently (radial and/or axial) and record the orientation.
Avoid tape, adhesive pads or flexible brackets — they filter out the high frequencies where bearing faults appear.
Set up high-rate sampling
Sample at a steady, known rate (well above 2.5× your highest bearing frequency) using the sensor's data-ready interrupt, and capture blocks long enough for the frequency resolution you need.
Feed a speed reference if available so 1×/2× and bearing frequencies scale with running speed.
Set up analysis, display and reporting
Run the windowed FFT and feature extraction on the ESP32, show the level/spectrum on an OLED, and report features/trends over LoRa/Wi-Fi (optionally logging raw blocks to SD).
Step-by-Step Implementation Guide
Work through these in order. Each step ends in something you can observe, so a failure is always localised to the step you just finished.
Compute the spectrum and features
Window the sample block, FFT it, then extract the overall level, the 1×/2× amplitudes and the energy in bands around each computed bearing defect frequency.
cppvibration-features.ino#include <arduinoFFT.h> #define NS 2048 // samples per block double vReal[NS], vImag[NS]; ArduinoFFT<double> FFT(vReal, vImag, NS, F_SAMPLE); struct Bearing { int n; double d, D, thetaDeg; }; // Bearing defect frequencies at shaft speed fr (rev/s). void bearingFreqs(const Bearing &b, double fr, double &bpfo,double &bpfi,double &bsf,double &ftf){ double r = (b.d/b.D)*cos(b.thetaDeg*M_PI/180.0); bpfo=(b.n/2.0)*fr*(1-r); bpfi=(b.n/2.0)*fr*(1+r); bsf =(b.D/(2*b.d))*fr*(1-r*r); ftf=0.5*fr*(1-r); } double bandEnergy(double centreHz,double halfWidthHz){ double df = F_SAMPLE/(double)NS, e=0; int lo=(centreHz-halfWidthHz)/df, hi=(centreHz+halfWidthHz)/df; for(int k=max(1,lo);k<=hi && k<NS/2;k++) e += vReal[k]*vReal[k]; return sqrt(e); } void analyse(double fr, const Bearing &b, double &lvl, double &x1,double &x2,double &bo,double &bi){ FFT.windowing(FFT_WIN_TYP_HANN, FFT_FORWARD); // reduce leakage FFT.compute(FFT_FORWARD); FFT.complexToMagnitude(); // spectrum in vReal[] lvl = overallLevel(vReal, NS); // ISO velocity RMS x1 = bandEnergy(fr, fr*0.05); // 1x imbalance x2 = bandEnergy(2*fr, fr*0.05); // 2x misalignment double bpfo,bpfi,bsf,ftf; bearingFreqs(b,fr,bpfo,bpfi,bsf,ftf); bo = bandEnergy(bpfo, 5); // outer-race energy bi = bandEnergy(bpfi, 5); // inner-race energy }FFT.windowing(FFT_WIN_TYP_HANN, FFT_FORWARD)A Hann window is applied before the FFT to reduce spectral leakage, so the diagnostic peaks stay sharp rather than smearing into their neighbours.void bearingFreqs(The bearing's defect frequencies are computed from its geometry and the shaft speed, so the monitor knows exactly which frequencies to watch for each bearing.double bandEnergy(double centreHz,double halfWidthHz)Energy is summed in a narrow band around a target frequency, so the feature tracks a specific fault (a bearing race, 1×, 2×) rather than the whole spectrum.lvl = overallLevel(vReal, NS)The ISO-style overall velocity RMS gives the headline health number that classifies the machine good/acceptable/unacceptable.bo = bandEnergy(bpfo, 5)Energy in the outer-race band is exactly the feature whose rise over weeks signals a developing outer-race bearing defect.Baseline, trend and alert
Learn each machine's healthy feature baseline, trend the features over time, and alert when any rises significantly above baseline — the early warning of a developing fault.
Complete Source Code
The listing below is complete and compiles as written — there are no elided sections. Read the annotations under each block before you upload it.
/* ═══════════════════════════════════════════════════════════════
Machine Vibration Monitor — ESP32 + accelerometer, FFT diagnostics
Samples vibration at high rate, computes the FFT, extracts the ISO
overall level and imbalance/misalignment/bearing signatures, and
trends them against each machine's baseline for early-warning alerts.
══════════════════════════════════════════════════════════════════ */
#include <arduinoFFT.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <Preferences.h>
#include <math.h>
#define NS 2048
#define F_SAMPLE 8000 // Hz — set from your f_max
#define SHAFT_HZ 24.5f // running speed (from tacho or nameplate)
double vReal[NS], vImag[NS];
ArduinoFFT<double> FFT(vReal, vImag, NS, F_SAMPLE);
Preferences prefs;
WiFiClient net; PubSubClient mqtt(net);
struct Bearing { int n; double d, D, thetaDeg; } brg = {8, 7.94, 39.0, 0};
struct Baseline { double lvl, x1, x2, bo, bi; } base;
void sampleBlock() {
uint32_t period_us = 1000000UL / F_SAMPLE;
uint32_t next = micros();
for (int i = 0; i < NS; i++) {
while ((int32_t)(micros() - next) < 0) {}
next += period_us;
vReal[i] = readAccel(); // one axis, steady-rate
vImag[i] = 0;
}
}
double bandEnergy(double f, double hw) {
double df = F_SAMPLE/(double)NS, e=0;
int lo=(f-hw)/df, hi=(f+hw)/df;
for (int k=max(1,lo); k<=hi && k<NS/2; k++) e += vReal[k]*vReal[k];
return sqrt(e);
}
void bearingFreqs(double fr,double&o,double&i){
double r=(brg.d/brg.D)*cos(brg.thetaDeg*M_PI/180.0);
o=(brg.n/2.0)*fr*(1-r); i=(brg.n/2.0)*fr*(1+r);
}
void loadBaseline(){
prefs.begin("vib",true);
base.lvl=prefs.getDouble("lvl",0); base.x1=prefs.getDouble("x1",0);
base.x2=prefs.getDouble("x2",0); base.bo=prefs.getDouble("bo",0);
base.bi=prefs.getDouble("bi",0); prefs.end();
}
void setup(){
Serial.begin(115200);
loadBaseline();
WiFi.begin(WIFI_SSID,WIFI_PASS);
mqtt.setServer(MQTT_HOST,1883);
}
void loop(){
if(!mqtt.connected()&&WiFi.status()==WL_CONNECTED) mqtt.connect("vib-1");
mqtt.loop();
sampleBlock();
FFT.windowing(FFT_WIN_TYP_HANN, FFT_FORWARD);
FFT.compute(FFT_FORWARD);
FFT.complexToMagnitude();
double lvl = overallLevel(vReal, NS); // ISO velocity RMS
double x1 = bandEnergy(SHAFT_HZ, SHAFT_HZ*0.05);
double x2 = bandEnergy(2*SHAFT_HZ, SHAFT_HZ*0.05);
double bo, bi; bearingFreqs(SHAFT_HZ, bo, bi);
double eo = bandEnergy(bo, 5), ei = bandEnergy(bi, 5);
// If unbaselined, learn this as the healthy baseline.
if (base.lvl == 0) {
base = {lvl, x1, x2, eo, ei};
prefs.begin("vib",false);
prefs.putDouble("lvl",lvl); prefs.putDouble("x1",x1);
prefs.putDouble("x2",x2); prefs.putDouble("bo",eo);
prefs.putDouble("bi",ei); prefs.end();
}
// Alert when a feature rises well above its healthy baseline.
const char *fault = nullptr;
if (lvl > 2.5*base.lvl) fault = "overall level high";
else if (x1 > 3*base.x1) fault = "imbalance (1x)";
else if (x2 > 3*base.x2) fault = "misalignment (2x)";
else if (eo > 4*base.bo) fault = "bearing outer race";
else if (ei > 4*base.bi) fault = "bearing inner race";
char m[240];
snprintf(m,sizeof m,
"{\"lvl\":%.3f,\"x1\":%.3f,\"x2\":%.3f,\"bpfo\":%.3f,"
"\"bpfi\":%.3f,\"fault\":\"%s\"}",
lvl,x1,x2,eo,ei, fault?fault:"none");
mqtt.publish("vib/machine1/features", m);
if (fault) mqtt.publish("vib/machine1/alert", fault);
delay(60000); // one analysis per minute
}
Configuration & Calibration
Configuration steps
- Set F_SAMPLE and block size for your highest frequency of interest and the resolution you need.
- Enter the running speed (or tacho) and the bearing geometry (n, d, D, θ) for defect-frequency computation.
- Set the baseline-learning behaviour and the per-feature alert multipliers.
- Configure reporting (LoRa/Wi-Fi) and any raw-block logging.
Calibration procedure
An uncalibrated sensor produces confident, precise, wrong numbers. Do this once per physical unit and record the constants.
Mounting/sampling
Verify the mount is rigid and the sample rate avoids aliasing (a known excitation should appear at the right frequency, not aliased).
Baseline
Capture the healthy spectrum over a period of normal operation to establish a stable baseline before trusting alerts.
Bearing frequencies
Confirm the computed BPFO/BPFI/BSF/FTF against the bearing datasheet and the running speed.
Network Architecture & Connectivity
Communication protocol
Nodes report extracted features (level, 1×, 2×, bearing bands) and trends — not raw waveforms — on a slow cadence, with immediate alerts when a feature rises above baseline.
| Topic / endpoint | Direction | Payload |
|---|---|---|
vib/machine1/features | node → broker | level, 1x, 2x, bearing-band energies |
vib/machine1/alert | node → broker | developing fault (which signature) |
vib/machine1/status | node → broker | baseline, health class, uptime |
Message contract between the device and the broker.
Cloud platform configuration
A maintenance dashboard / CMMS trends each machine's features against baseline, classifies health, and raises work orders on early warnings, turning breakdowns into planned repairs.
Dashboard setup
Per-machine health class, spectrum snapshot, and trend charts of 1×/2×/bearing energies with baseline and alert markers.
Mobile app integration
Early-warning alerts naming the machine and the developing fault (imbalance, misalignment, bearing element).
Security considerations
- Authenticate nodes so plant condition data cannot be spoofed.
- Report features/trends (not raw waveforms) to keep bandwidth and exposure low.
- Alert on node silence so a failed monitor is noticed.
Testing Procedure & Expected Output
Test from the bottom up. Confirm power, then each sensor in isolation, then the integrated loop — the first failing step tells you exactly where to look.
| Test | What you should see |
|---|---|
| Excite a known frequency | Peak appears at the correct frequency (no aliasing) after correct mounting/sampling |
| Add imbalance (test mass) | 1× amplitude rises; imbalance flagged when above baseline |
| Introduce misalignment | 2× amplitude rises; misalignment flagged |
| Run with a worn bearing (or simulate) | Energy grows at the bearing defect frequency; bearing fault flagged |
| Compare loose vs rigid mount | High-frequency content collapses when loosely mounted — proving mounting matters |
| Trend over time | A rising feature triggers an early-warning alert before failure |
Bench-test checklist. If a row fails, stop and fix it before moving on.
Expected output
The dashboard shows the overall level (health class), the spectrum, and trends of 1×/2×/bearing-band energy against baseline; a rising feature raises an early-warning alert.
{
"lvl": 4.8,
"x1": 0.9,
"x2": 0.4,
"bpfo": 2.7,
"bpfi": 0.6,
"fault": "bearing outer race"
}
Here the outer-race bearing energy (bpfo) has climbed well above its baseline, flagging a developing outer-race bearing fault — an alert raised while the machine still runs, allowing the bearing to be replaced during planned downtime.
Troubleshooting: Common Errors & Fixes
Performance Optimisation
- Sample at a precise steady rate; do the FFT on a block and report features, not raw data.
- Choose block size for the frequency resolution needed to separate close bearing frequencies.
- Analyse periodically (e.g. once a minute) — faults develop over days, so high rate wastes power.
- Keep per-machine baselines and trends so alerts are meaningful and lightweight.
- Replace every
delay()with amillis()comparison — blocking delays are the single most common cause of dropped readings. - Sample sensors on a fixed cadence and publish on a slower one; you almost never need to transmit at the sampling rate.
- Move networking into its own FreeRTOS task so a slow DNS lookup cannot stall the control loop.
- Use
uint8_t/uint16_twhere the range allows; on an 8-bit AVR a 32-bit add costs four times as much. - Batch several samples into one MQTT publish. Radio time, not CPU time, dominates the energy budget.
- Set the MQTT keep-alive to a value that matches your reporting interval so the broker does not churn reconnections.
- For battery builds use deep sleep between samples: an ESP32 drops from ~160 mA awake to about 10 µA asleep, which is the difference between days and months of runtime.
Safety Precautions
- Mount and service on running machinery safely, following lockout/tagout for any hands-on work.
- This is indicative condition monitoring (low-cost MEMS + edge FFT), not a calibrated industrial analyser — use it for trending and clear faults, and escalate to proper analysis for critical decisions.
- Act on early warnings by scheduling inspection/repair, not by ignoring them until failure.
- Ensure the sensor and enclosure tolerate the machine's temperature and vibration environment.
- Never power an RF module without its antenna fitted — the reflected power destroys the output stage. Check your local licence-free band and duty-cycle limits before transmitting.
- Wear eye protection when soldering or cutting, and solder in a ventilated space — rosin flux fumes are a respiratory irritant.
- Power the circuit through a bench supply with a current limit while you are testing. A 300 mA limit turns a wiring mistake into a beep instead of a dead board.
- Disconnect power before changing any wiring. Hot-plugging a sensor onto a live bus is the fastest way to lose a controller.
Maintenance
- Re-baseline after any repair, re-mount, or speed change.
- Check the mount remains rigid; a loosened sensor degrades the spectrum.
- Verify sample rate and bearing parameters if machines change.
- Correlate alerts with actual findings to tune the alert multipliers.
- Re-check every screw terminal and header after the first week — thermal cycling loosens connections that felt tight on day one.
- Rotate the microSD card annually and keep an image of the working system. Cards used as loggers wear out silently.
- Keep the broker and dashboard containers patched, and rotate device credentials at least once a year.
- Recalibrate at the interval given in the calibration section, and keep the constants in a text file next to the firmware — not only in flash.
- Keep a short logbook of firmware versions and what changed. Six months later you will not remember why that constant is 1.083.
Future Improvements & Upgrades
A working v1 is a platform, not a finish line. These are the upgrades that add the most capability for the least rework.
- Add order tracking (speed-normalised spectra) for variable-speed machines.
- Add envelope/demodulation analysis for earlier bearing-fault detection.
- Add temperature and current signatures for multi-parameter diagnosis.
- Train an ML classifier on labelled fault spectra for automatic diagnosis.
- Design a proper PCB. Once the breadboard version has run for a month, moving to a two-layer board removes the intermittent-contact failures that dominate prototype faults.
- Add over-the-air firmware updates so you never have to physically reach a deployed node again.
- Add persistent local storage (microSD or the on-chip flash) so a network outage does not create a hole in your data.
- Move configuration out of the source: a captive-portal setup page or a JSON config file makes the build reusable without a recompile.
- Add a battery and solar option so the unit survives a power cut and can be sited away from a socket.
- Write a small test harness that feeds synthetic sensor values through the decision logic, so you can validate thresholds without physically triggering the event.
Frequently Asked Questions
References & Learning Resources
These are the primary sources worth reading in full. Manufacturer datasheets always outrank forum posts when the two disagree.