Siddhant Kumar
Project 059 · Industrial

Machine Vibration Monitor.

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.

Advanced 16–24 hours 34 min read PredictiveAccelIndustry
Jump to source Bill of materials
Machine Vibration Monitor — reference build illustration MCU VCC · GND · SIG · NC
Difficulty
Advanced
Build time
16–24 hours
Indicative cost
₹3,200 – ₹5,500
Platform
ESP32 DevKit V1 (ESP-WROOM-32)
Category
Industrial
Last updated
28 July 2026
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.

Automated machinery on a factory production line
An accelerometer on a motor reads vibration whose spectrum reveals developing faults. Photograph sourced from Wikimedia Commons — Factory automation.jpg. Reused under the licence stated on that page; please check it before republishing.

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

SettingHow it is used
Motors, pumps, fansContinuous condition monitoring of rotating plant to catch bearing/imbalance/misalignment faults early.
Predictive maintenance programmesTrending vibration across many machines to schedule repairs before failure and cut unplanned downtime.
Gearboxes / compressorsWatching for developing mechanical faults in critical drivetrain equipment.
Fleet / building servicesHVAC, 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

AttributeValue
Difficulty levelAdvanced
Estimated completion time16–24 hours
Indicative build cost₹3,200 – ₹5,500
Primary disciplineIndustrial
Reference platformESP32 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.

ComponentKey specificationQtyApprox. 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 DAC1₹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 Hz1₹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 DMP1₹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²C1₹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–SF121₹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 recommended1₹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 protection1₹350
High-rate/low-noise accelerometer
Bandwidth and noise floor set what faults you can see
ADXL345/ADXL355-class or industrial IEPE for real bandwidth1₹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 scaling1₹300
Industrial enclosureVibration/temperature-tolerant housing on or near the machine1₹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

PartSpecificationSupplyInterfaceReference
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 DAC3.3 V logic / 5 V USBUART, SPI, I²C, I²S, CAN, PWMDatasheet
ADXL345 3-axis accelerometer±2/4/8/16 g, 13-bit, 0.004 g/LSB, tap and free-fall interrupts, 3200 Hz2.0–3.6 VI²C / SPIDatasheet
MPU-6050 6-axis IMU3-axis gyro ±250–2000 °/s, 3-axis accel ±2–16 g, 16-bit ADC, on-chip DMP2.375–3.46 V (module 5 V tolerant)I²C (0x68/0x69)Datasheet
0.96″ SSD1306 OLED display128 × 64 monochrome, 1.3–3.3 V logic, 100 kHz–400 kHz I²C3.3–5 VI²C (0x3C)Datasheet
SX1278 LoRa 433 MHz module (Ra-02)−148 dBm sensitivity, +20 dBm output, up to 10 km line of sight, SF7–SF123.3 VSPIDatasheet
microSD card 32 GB A1 classA1 rated, 10 MB/s random write, UHS-I, endurance-grade recommended3.3 VSDIO / SPIDatasheet
5 V 3 A regulated SMPS adapter100–240 VAC in, 5 V ±5 % out, 3 A, short-circuit and over-voltage protection5 VDC barrel / USBDatasheet

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.

LoadSupply railTypical current (mA)Notes
ESP32 DevKit V1 (ESP-WROOM-32)3.3 V logic / 5 V USB160Wi-Fi transmit bursts peak near 500 mA — size the regulator accordingly.
ADXL345 3-axis accelerometer2.0–3.6 V0.14Built-in activity/free-fall interrupts let the MCU deep-sleep until something moves.
MPU-6050 6-axis IMU2.375–3.46 V (module 5 V tolerant)3.9Gyro bias drifts with temperature — re-zero at boot while the device is still.
0.96″ SSD1306 OLED display3.3–5 V20Static images burn in — invert or scroll the screen periodically.
SX1278 LoRa 433 MHz module (Ra-02)3.3 V120Never power the radio without an antenna — the PA will destroy itself.
microSD card 32 GB A1 class3.3 V100For 24/7 loggers buy a high-endurance card — normal cards die in months.
5 V 3 A regulated SMPS adapter5 V3000Measure 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.json under 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 dialout group: sudo usermod -aG dialout $USER and 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

LibraryWhy it is neededInstall
WiFi (ESP32 core) bundledStation/AP connection management for the ESP32.Bundled with the ESP32 Arduino core
PubSubClient 2.8Lightweight MQTT 3.1.1 client for constrained devices.Library Manager → "PubSubClient" by Nick O'Leary
Adafruit SSD1306 + GFX 2.5.xFramebuffer and text/graphics primitives for the OLED.Library Manager → "Adafruit SSD1306"
LoRa (sandeepmistry) 0.8.0SX127x radio configuration, packet TX/RX and callbacks.Library Manager → "LoRa" by Sandeep Mistry
ArduinoJson 7.xZero-allocation JSON serialisation and parsing.Library Manager → "ArduinoJson" by Benoit Blanchon
Preferences (NVS) bundledWear-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.

Machine Vibration Monitor — system block diagramFunctional block diagram of the Machine Vibration Monitor system. SenseAccelerometerhigh-rate, rigid mountSpeed (opt)tachoAnalyseFFTspectrumFeaturesRMS, 1×, 2×, bearingsDiagnoseESP32vs baseline trendHealth classISO levelWarnDashboardtrendsAlertrising faultrightrightnone
Machine Vibration Monitor — system block diagram

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.

Machine Vibration Monitor — wiring schematicConnection schematic showing which controller pin drives each peripheral. Sensors / InputsControllerActuators / OutputsESP32 DevKit V1(ESP-WROOM-32)3.3 V logic / 5 V USBAccelerometerGPIO 18/19/23/5 or 21/22High-rate vibrationAccelerometerGPIO 34Data-ready (pacedsampling)Tacho (opt)GPIO 27Running speedreferenceOLEDGPIO 21/22Level/spectrumdisplayLoRa/Wi-FiSPI / on-chipFeatures/trendsuplinkmicroSDshared + CSOptional raw/featurelog5V supply3V3 regPower
Machine Vibration Monitor — wiring schematic
PeripheralPeripheral pinController pinSignal
AccelerometerSPI/I²CGPIO 18/19/23/5 or 21/22High-rate vibration
AccelerometerINTGPIO 34Data-ready (paced sampling)
Tacho (opt)PULSEGPIO 27Running speed reference
OLEDSDA/SCLGPIO 21/22Level/spectrum display
LoRa/Wi-FibusSPI / on-chipFeatures/trends uplink
microSDSPIshared + CSOptional raw/feature log
5V supply+/–3V3 regPower

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.
An ESP32 development board with the ESP-WROOM-32 module and USB connector
ESP32 module computing the FFT and extracting imbalance, misalignment and bearing signatures. Photograph sourced from Wikimedia Commons — ESP32 Espressif ESP-WROOM-32 Dev Board.jpg. Reused under the licence stated on that page; please check it before republishing.

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.

Machine Vibration Monitor — architecture stackLayered architecture from hardware to user interface. Hardware layerESP32 DevKit V1 (ESP-WROOM-32) · MPU-6050 6-axis IMUDriver layerwifi · pubsub · ssd1306 · lorolibApplication logicsampling loop · filtering · thresholds · state machineTransport layerLoRa/Wi-Fi → maintenance dashboard · TLS · retry and backoffPresentation layerdashboard · mobile notifications · historical charts
Machine Vibration Monitor — architecture stack

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 ; 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 quantifies imbalance; at , 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

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

plainISO 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

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

Machine Vibration Monitor — firmware flowchartControl flow through the main program loop. Sample vibration blockWindow + FFT → spectrumExtract RMS, 1×, 2×, bearingbandsAny feature above baselinetrend?Alert: developing faultUpdate trendAlert: developing faultUpdate trendReport features; sleepinterval
Machine Vibration Monitor — firmware flowchart

Assembly Instructions

Build on a breadboard first and only commit to solder once the whole system has run for an hour without a fault.

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

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

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

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

cppmachine-vibration-monitor.ino
/* ═══════════════════════════════════════════════════════════════
   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
}
void sampleBlock()Captures a block of vibration at a precise, steady rate — essential, because jittery sampling smears the spectrum and invalidates the frequency features.
FFT.windowing(FFT_WIN_TYP_HANN, FFT_FORWARD)Windows the block before the FFT to control spectral leakage, keeping the diagnostic peaks sharp.
if (base.lvl == 0) {On first run the current healthy spectrum is stored as the machine's baseline, because diagnosis is about change from this machine's own normal, not an absolute number.
if (lvl > 2.5*base.lvl) fault = "overall level high"Alerts fire when a feature rises to a multiple of its healthy baseline, giving per-machine early warning rather than a universal threshold that fits no machine.
else if (eo > 4*base.bo) fault = "bearing outer race"Rising energy at the outer-race defect frequency names the specific failing element — the actionable diagnosis predictive maintenance needs.

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.

  1. Mounting/sampling

    Verify the mount is rigid and the sample rate avoids aliasing (a known excitation should appear at the right frequency, not aliased).

  2. Baseline

    Capture the healthy spectrum over a period of normal operation to establish a stable baseline before trusting alerts.

  3. Bearing frequencies

    Confirm the computed BPFO/BPFI/BSF/FTF against the bearing datasheet and the running speed.

Network Architecture & Connectivity

Machine Vibration Monitor — network topologyPath taken by telemetry from field node to end user. Edge nodesGatewayCloudClientsVibration nodeESP32Other machinesfleetLoRa / Wi-FiPlant gatewayto MQTTMQTT 1883CMMS/dashboardfeatures + trendsMaintenancetrends + alertsPhoneearly warnings
Machine Vibration Monitor — network topology

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 / endpointDirectionPayload
vib/machine1/featuresnode → brokerlevel, 1x, 2x, bearing-band energies
vib/machine1/alertnode → brokerdeveloping fault (which signature)
vib/machine1/statusnode → brokerbaseline, 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.

TestWhat you should see
Excite a known frequencyPeak appears at the correct frequency (no aliasing) after correct mounting/sampling
Add imbalance (test mass)1× amplitude rises; imbalance flagged when above baseline
Introduce misalignment2× 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 mountHigh-frequency content collapses when loosely mounted — proving mounting matters
Trend over timeA 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.

jsonvib-features.json
{
  "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.

A brushed DC gear motor
Trended against each machine's baseline, a rising fault signature warns weeks before a breakdown. Photograph sourced from Wikimedia Commons — DC motor.jpg. Reused under the licence stated on that page; please check it before republishing.

Troubleshooting: Common Errors & Fixes

Spectrum looks like noise / no clear peaks

Likely cause. Loose mounting or jittery sampling

Fix. Mount rigidly (stud/magnet on bare metal); use steady-rate sampling; window before FFT

False low-frequency peaks

Likely cause. Aliasing (sample rate too low)

Fix. Increase the sample rate above 2.5× f_max; add anti-alias filtering

Bearing frequencies not where expected

Likely cause. Wrong geometry or running speed

Fix. Verify n/d/D/θ and the actual shaft speed (use a tacho)

Alerts on a healthy machine

Likely cause. No/poor baseline or universal thresholds

Fix. Learn a proper per-machine baseline; alert on multiples of it

Can't see high-frequency bearing faults

Likely cause. MEMS bandwidth/mount limits

Fix. Use a higher-bandwidth/low-noise sensor and better mounting; know the sensor's limits

The sketch will not upload — "Failed to connect" or "avrdude: stk500_recv()"

Likely cause. The bootloader is not being reached: wrong port, wrong board, a serial monitor holding the port open, or a USB cable that only carries power.

Fix. Close every serial monitor, confirm Tools → Board and Port, and swap to a known data-capable USB cable. On an ESP32 hold BOOT while the IDE prints "Connecting…", then release. If a peripheral is wired to the UART pins (GPIO 1/3 on ESP32, D0/D1 on Uno) unplug it — it fights the programmer.

The board resets in a loop, or the serial monitor prints "Brownout detector was triggered"

Likely cause. The supply cannot deliver peak current. Wi-Fi transmit bursts, relay coils and servos all pull far more than their average draw.

Fix. Power peripherals from a separate regulated supply with a common ground rather than from the board 5 V pin. Add a 470–1000 µF electrolytic capacitor across the supply near the load, and use a real power adapter rather than a laptop USB port.

Serial monitor shows garbage characters

Likely cause. Baud rate mismatch between Serial.begin() and the monitor, or a floating/shared UART line.

Fix. Set the monitor to 115200 to match the sketch. If it still garbles, the crystal or the USB bridge is being confused by noise — shorten the cable and keep motor wiring away from the USB lead.

An I²C device is not detected

Likely cause. Wrong address, missing pull-ups, swapped SDA/SCL, or a bus too long for the pull-up value.

Fix. Run an I²C scanner sketch first — it should print the device address. Most breakout boards include 4.7 kΩ pull-ups, but if you have chained four of them the parallel resistance is too low; remove the pull-ups from all but one board. Keep the bus under 30 cm at 100 kHz.

Wi-Fi connects but MQTT never does (state -2)

Likely cause. Wrong broker address or port, a firewall in the way, or the broker requiring credentials the sketch is not sending.

Fix. Test from a laptop on the same network first: mosquitto_sub -h <broker> -t "#" -v. If that works, the problem is on the device — check the IP literal, port 1883 (or 8883 for TLS), and that client.setServer() runs before connect(). PubSubClient state codes are documented in its header.

Readings arrive for a while and then stop

Likely cause. The Wi-Fi or MQTT session dropped and the sketch never reconnects, or the broker dropped the client on keep-alive timeout.

Fix. Never assume the link stays up. Check WiFi.status() and client.connected() at the top of every loop and reconnect with exponential backoff. Add a watchdog so a wedged network stack reboots the device instead of going silent.

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 a millis() 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_t where 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

How can vibration predict a failure weeks ahead?

Faults inject energy at specific frequencies that grow as the fault develops. A bearing defect frequency rising out of the noise floor over weeks is the bearing beginning to fail — visible in the spectrum long before the machine actually breaks.

Why is the FFT necessary?

Because each fault lives at a specific frequency. A raw amplitude just says the machine shakes; the FFT separates the vibration by frequency so you can see imbalance at 1×, misalignment at 2×, and bearing defects at their calculated frequencies.

Why does mounting matter so much?

A loose or compliant mount filters out the high frequencies where bearing faults appear, making the most important faults invisible. A rigid stud/magnet coupling to bare metal is essential for a faithful spectrum.

Is a cheap MEMS sensor good enough?

For trending and catching clear developing faults, yes — that is the core value. It does not match a calibrated industrial analyser's resolution and depth, so critical decisions should be escalated to proper analysis.

Why compare to a baseline instead of a fixed limit?

Every machine's healthy spectrum is different, so absolute numbers are not comparable. Diagnosis is about change: the monitor learns each machine's normal and alerts when a feature rises above it.

References & Learning Resources

These are the primary sources worth reading in full. Manufacturer datasheets always outrank forum posts when the two disagree.

  1. Vibration analysis and machinery diagnosticsReference
  2. ISO 10816 / 20816 vibration severityReference
  3. Rolling-element bearing defect frequenciesReference
  4. Fast Fourier TransformReference
  5. Predictive maintenance / condition monitoringReference