VFD Pump Predictive Maintenance

This reference application is here to give you ideas and help you get started quickly. It's built on specific hardware that may not match yours, so focus on the sections that fit your use case. If you'd like to talk through your project and whether it's a good fit for Blues, reach out.
Building with an AI assistant? Point it at this accelerator's firmware in firmware/vfd_pump_monitor/ so it can learn how the device works and help you adapt it to your hardware.
This project is a downtime prevention reference design for industrial centrifugal pumps. The pump's VFD (variable frequency drive) already knows a lot about how the pump is doing. This design reads that data over Modbus RTU with an industrial PLC (programmable logic controller) and sends it out through a cellular Notecard, so the pump can be monitored remotely and serviced before it fails.
1. Project Overview
The problem. Nearly every industrial centrifugal pump runs behind a VFD. Modern drives from ABB, Yaskawa, Danfoss, and Schneider all publish the pump's operating telemetry in Modbus holding registers: motor current, output frequency, output torque, drive temperature, runtime hours, and the active fault code. Almost nobody reads them. The VFD sits in the cabinet doing the work with all of that data on hand, and there's no network path to get it off the plant floor.
A failing pump rarely just stops. It usually warns you first. Motor current can shift at constant frequency as bearing drag, fouling, valve position, fluid viscosity, or impeller condition change the load on the drive. Transient electrical faults can cluster on a stressed contactor or in a cavitating hydraulic regime. Actual runtime can creep above the expected duty cycle as a downstream valve fouls and the pump runs longer to do the same work. None of these shifts is diagnostic on its own, but a maintenance team would happily act on any of them a week early. This device catches those anomalies and sends them out before a tank runs dry on a Saturday night. The Signal limitations note covers what this telemetry can and can't tell you.
Why Notecard. Pump rooms sit on isolated OT (operational technology) networks. Plant policy usually keeps corporate WiFi off-limits for instrumentation, and nobody is going to retrofit an OT-friendly access point for every pump. Cellular gets the data out without plant LAN credentials, VLAN provisioning, site WiFi, or a local gateway. Some sites will still want an OT/security review before they allow any wireless instrumentation, but the device itself never needs access to the plant network. Because Notecard bundles global cellular data and service, the same firmware and architecture work in every region. Just pick the Blues Wireless for OPTA cellular variant that matches where you're deploying. WiFi stays available as an opportunistic fallback for the rare site that can offer a rooftop AP, and the design stays cellular-first.
New to Blues?
Learn what we do in this 3-minute video that walks you through how we simplify wireless connectivity.
Learn what we do in this 3-minute video that walks you through how we simplify wireless connectivity.
Why OPTA. Wireless for OPTA was made for jobs like this one, where a real industrial PLC reads a real industrial Modbus device with no PC or gateway in between. The Finder OPTA mounts on a DIN rail, runs on 12–24 VDC, and takes both Arduino sketches and IEC 61131-3 PLC languages. That means it installs the same way at every plant, including the ones whose IT and OT teams will never agree on a network plan. Blues Wireless for OPTA adds cellular and WiFi to a device that already speaks the plant's language.
Deployment scenario. One OPTA with Wireless for OPTA clips onto the DIN rail next to the VFD inside the pump's electrical panel. RS-485 daisy-chains to the drive's communication port, and the antenna lead runs out through a cable gland to a magnetic-mount whip on the cabinet roof. Power comes from the 24 VDC panel supply that's already there. You don't need a PC, a gateway, or anything from the plant LAN.
2. System Architecture
Device-side responsibilities. Inside the pump panel, the OPTA's Cortex-M7
acts as the Modbus RTU client (master) to the VFD's server (slave). Once
a minute it polls six holding registers through the onboard RS-485 transceiver.
Between polls it keeps rolling hourly statistics (mean, peak, and count) in RAM
and runs four anomaly-detection rules against them to decide, event by event,
whether the plant needs to hear about what it just saw. When something is worth
reporting, the host hands a JSON Note to the
Notecard over I²C through the AUX connector on Blues Wireless for OPTA. The host
never deals with modem AT commands, a session state machine, or raw sockets.
The note-arduino library's JAdd* helpers build the request, and the
Notecard handles everything after that.
Notecard responsibilities. The Notecard queues every Note the host writes
and ships them on the
hub.set outbound
cadence (hourly by default). Anything tagged sync:true jumps the queue, and
the radio comes up right away. On every inbound sync the Notecard also pulls
environment
variables.
That's how a maintenance lead can retune thresholds, or even point the firmware
at a different drive vendor's register addresses, from a browser without anyone
visiting the panel.
Notehub responsibilities. Blues Notehub ingests and stores every event, and project-level routes forward them to your other systems. Each plant's VFDs may use different register addresses, so per-fleet environment variables are what let a single firmware image run an ABB plant in Ohio and a Yaskawa plant in São Paulo. Smart Fleets can group devices by vendor or by site.
Routing to the cloud (high level). Notehub can route to HTTP, MQTT, AWS, Azure, GCP, Snowflake, and several other destinations. Route setup depends on your project, so see the Notehub routing docs for details.
3. Technical Summary
What you'll have when done: An OPTA and Notecard assembly mounted in a pump panel. It reads six telemetry registers from the VFD once a minute, reports hourly summaries to Notehub, and sends an alert right away whenever one of four anomaly rules trips.
Minimum steps (60–90 minutes, assuming site access and a calibrated VFD):
- Install Arduino core + libraries (
Arduino Mbed OS Opta Boards,note-arduino,ArduinoModbus,ArduinoRS485) via Library Manager. - Set
PRODUCT_UIDin the firmware, then compile and flash witharduino-cli(see §8. Build and Flash below). - On Notehub: create a project, claim the Notecard, create one fleet, and set
modbus_slave_idandmodbus_baudto match your VFD's configuration. - Wire the OPTA's RS-485 to the VFD's Modbus port, and confirm 120 Ω termination at each end of the bus.
- Power up and watch a serial monitor.
card.statusshould report healthy, and the firstvfd_summary.qoNote should reach Notehub within about two hours. The firmware writes it at the end of the first 60-minute report window, and it ships on the next hourly outbound sync.
Here is a sample Note this device emits:
{
"f_hz_mean": 59.8, "f_hz_peak": 60.1,
"i_a_mean": 12.4, "i_a_peak": 13.7,
"trq_mean": 68, "trq_peak": 74,
"drv_c_mean": 42, "drv_c_peak": 51,
"run_min": 53, "stop_min": 7,
"hrs_total": 18234,
"fault_count_hour": 0,
"last_fault": "0"
}4. Hardware Requirements
| Part | Qty | Rationale |
|---|---|---|
| Finder OPTA Codesys (8A.04.9.024.832C) | 1 | Industrial PLC with an onboard RS-485 transceiver, DIN-rail mount, and 12–24 VDC supply, included in the Wireless for OPTA Bundle. For this project it runs Arduino firmware (see §8) that hosts the Modbus client and edge logic. |
| Blues Wireless for OPTA | 1 | Snaps onto the OPTA's expansion port and adds a Notecard Cell+WiFi (WBNAW) over I²C. Cellular coverage is regional, so pick the SKU that matches where you're deploying. The Notecard manages its own cellular session on supported carrier networks worldwide through its embedded global SIM. |
| External cellular antenna(s) w/ SMA, ~3m lead (e.g. SparkFun CEL-16432) | 1 required, 2 recommended | At minimum, route the primary cellular antenna outside any metal cabinet, since rubber-duck antennas inside a steel panel won't work reliably. For the best LTE Cat-1 performance, route the diversity antenna outside too if the layout allows. SMA bulkhead leads through cable glands keep the IP rating intact. |
| Mojo | 1 | Coulomb counter for checking the per-session energy of the Wireless for OPTA + Notecard subsystem during commissioning. It stays on the bench and isn't deployed to the field. |
| 24 VDC DIN-rail supply, ≥10W (e.g. MeanWell HDR-15-24) | 1 | Powers the OPTA and expansion. Most pump panels already have one, so you may not need to buy it. |
| 120 Ω termination resistor | 1–2 | RS-485 termination at each end of the bus. The OPTA's onboard transceiver doesn't include a permanent terminator. |
| Shielded twisted pair, 22 AWG, RS-485 rated, ~1m | 1 | A → A, B → B, shield → drive ground. Length depends on the panel layout. |
| DIN rail, ~10 cm | 1 | Mount for the OPTA and expansion. The panel probably has one already. |
Alternative hosts. The Arduino Opta RS485 and Arduino Opta WiFi also work, with no firmware changes. The Arduino Opta Lite has no onboard RS-485, so it won't work for this project.
The Blues hardware ships with an active SIM that includes 500 MB of data and 10 years of service, with no activation fees and no monthly commitment.
5. Wiring and Assembly
Safety. VFD cabinets contain hazardous voltages even when the control wiring is low-voltage. Installation must be done by qualified personnel following site lockout/tagout procedures, the VFD manufacturer's instructions, and applicable electrical codes. This reference design is read-only over Modbus. It never commands pump start/stop or speed.
- Mount and power. Snap the OPTA onto the DIN rail, then snap Blues
Wireless for OPTA onto the OPTA's right-hand expansion port. Join the two
with the supplied solderless AUX connector, which carries the I²C lines the
Notecard talks over. Wire 24 VDC from the panel supply to the OPTA's
+and-terminals. As the Wireless for OPTA Quickstart points out, USB-C doesn't power the OPTA's outputs, so use the 12–24 VDC supply for anything beyond bench testing. Jumper the OPTA's+24Vto the expansion's+24Vterminal so both share the same supply. - Antennas. Thread an SMA-female bulkhead lead through a cable gland for the primary cellular antenna and screw it onto the first antenna port on Wireless for OPTA. If the layout allows, do the same for the diversity port, which improves LTE Cat-1 performance at sites with marginal signal. The bundled rubber-duck antennas are for bench testing only, so don't count on them inside a metal cabinet.
- Modbus bus. Wire the OPTA's RS-485 terminals to the VFD's communication
port:
- OPTA
A (+)→ VFDA (+) - OPTA
B (-)→ VFDB (-) - OPTA
COM(RS-485 GND) → VFD communication ground (check the drive's manual: ABB ACS580 calls itAGND, Yaskawa GA500 calls itSC, and Danfoss FC-302 calls itCommon). - Put a 120 Ω resistor across A/B at each end of the bus. With one OPTA and one drive, that's two terminators total (one at each device).
- OPTA
- Drive configuration. Configure the VFD as a Modbus RTU server
(slave), with the OPTA as the Modbus client (master). The firmware ships
with slave ID
1, baud rate19200, 8 data bits, no parity, and 1 stop bit (8N1). Real drives vary, so match baud, parity, stop bits, and slave address to however the VFD is set up, and override the firmware's defaults with themodbus_*environment variables on Notehub. You'll find these settings in parameter group ABB5800–5805, YaskawaH5-xx, Danfoss8-3x, or SchneiderComm-1.x. - Bench validation. During first-light testing, splice the Mojo inline between the 24 VDC supply and the Wireless for OPTA power input so it can measure the per-session energy of the expansion + Notecard subsystem. The OPTA itself is line-powered, so it isn't part of the measurement.
6. Notehub Setup
-
Create a project. Sign up at Notehub and create a project. Copy the ProductUID and paste it into
firmware/vfd_pump_monitor/vfd_pump_monitor.inoasPRODUCT_UID. -
Claim the Notecard. Power up the panel. The Notecard associates itself with your project on its first cellular session.
-
Create a Fleet per plant. Fleets group devices for shared configuration and routing. The natural unit here is one fleet per plant. Pumps in the same plant usually share a VFD vendor and register map, so fleet-level environment variables can say "this plant's pumps all run ABB drives at register 0x0103 for output frequency."
-
Set environment variables. In Notehub, go to Projects → your project → Fleets → your fleet → Environment. The defaults below are reasonable starting points. Any value you set in Notehub overrides the firmware default on the device's next inbound sync, and the register-address variables let one firmware image work with all four common drive vendors without a recompile.
Variable Default Purpose sample_minutes1Minutes between Modbus polls. report_minutes60Minutes between summary Notes ( vfd_summary.qo).modbus_slave_id1Modbus server (slave) address of the drive. modbus_baud19200Bus baud rate. Must match the VFD configuration. modbus_paritynoneParity setting: none,even, orodd. Must match the VFD.modbus_stop_bits1Stop bits: 1or2. Must match the VFD.vfd_profiledemo_contiguousPlaceholder naming the register-map convention this firmware build targets. The shipped firmware only implements demo_contiguous. See Limitations for the production path.reg_freq259Holding-register address (wire-level, 0-based) for output frequency. Demo firmware assumes 0.01 Hz units. reg_current260Holding-register address for motor current. Demo firmware assumes 0.01 A units. reg_torque261Holding-register address for output torque. Demo firmware assumes % of nominal (signed 16-bit). reg_drive_temp262Holding-register address for drive heatsink temperature. Demo firmware assumes °C (signed 16-bit). reg_runtime_hours263Holding-register address for cumulative runtime hours. Demo firmware reads a single 16-bit register. reg_fault_code264Holding-register address for the active fault code (0 = no fault). This is not a fault history log. See Limitations. current_alarm_factor1.20Fires load_anomalywhen hourly mean current exceeds the rolling baseline by this factor while running.transient_fault_window_hours4Window for transient-fault clustering. transient_fault_count3Number of distinct fault transitions within the window at or above which transient_faultsfires.drive_temp_alarm_c75.0Drive heatsink °C above which drive_overtempfires.expected_run_hours_per_day12.0Expected runtime per day. Runtime drifting > 25% above this fires runtime_drift.note VFD register-map gotchas. The defaults above are only examples. Real VFDs differ in 0-based vs 1-based addressing (Modicon "40001" notation vs raw), per-register scaling (current may be 0.1 A, 0.01 A, or % of rated), signedness (torque and temperature are often signed), 32-bit values that span two registers (runtime hours often does, with vendor-specific word order), and whether a register holds the active fault code or a fault history log. The shipped firmware reads six contiguous 16-bit registers with hardcoded scaling, so production deployments need a vendor-specific firmware build that handles all of this properly.
-
Configure routes. Add one route for
vfd_event.qo(alerts: low-volume, real-time delivery to a CMMS or on-call endpoint) and a second forvfd_summary.qo(long-term storage: batched delivery to an analytics/historian system). Because the two Notefiles are split at the source, each one can go to a different destination with a different urgency, and the routes don't need any filter logic.
7. Firmware Design
Everything lives in one sketch:
firmware/vfd_pump_monitor/vfd_pump_monitor.ino.
Dependencies:
- Arduino Mbed OS Opta Boards core (install it from the Arduino IDE Boards Manager).
Blues Wireless Notecard(thenote-arduinolibrary). Install it from the Arduino Library Manager or witharduino-cli lib install "Blues Wireless Notecard".ArduinoModbusandArduinoRS485(official Arduino libraries, also from the Library Manager).
Modules
| Responsibility | Where |
|---|---|
Notecard configuration (hub.set, templates) | notecardConfigure, defineTemplates |
| Environment-variable fetch + clamp | fetchEnvOverrides (clampU32, clampF) |
Re-init bus / re-issue hub.set on env change | applyModbusSerialIfChanged, applyHubSetIfChanged |
| Modbus polling of six registers | pollVfd, modbusReadOne |
| Rolling hourly stats | RollingStats struct, accumulate |
| Edge logic (load anomaly, transient faults, runtime drift, drive overtemp) | evaluateRules (with frequency-binned baselines and edge-triggered alerts) |
| Outbound Note emission (summary + event) | sendSummary, sendEvent |
| Periodic cycle scheduler (no sleep, line-powered) | loop() |
Sensor reading strategy
The firmware pulls all six holding registers in a single Modbus transaction
(requestFrom with HOLDING_REGISTERS, quantity 6, starting at the reg_freq
address). One transaction puts 25 bytes on the bus instead of 90 and takes
roughly 4–6× less time than six separate reads, depending on how quickly the
drive responds. This assumes the six registers are contiguous. On drives
where they aren't, override the reg_* variables one by one and the firmware
falls back to per-register reads.
The polling cadence is sample_minutes (1 minute by default). For each sample,
accumulate updates the rolling hourly windows for current, frequency, torque,
and drive temperature. It keeps samples taken while the pump is running
(frequency > 1 Hz) apart from samples taken while it's stopped, because a hot
drive at 0 Hz means something different from a hot drive under load.
Event payload design
The device writes to two template-backed Notefiles. Templates give the summary and alert records a stable schema, store them on the Notecard as fixed-length records instead of free-form JSON, and keep the on-wire payload small. That adds up at 24 summary Notes per pump per day over a multi-year deployment. Real cellular data usage depends on sync cadence, signal conditions, routing behavior, and how often events fire, so check it against Notehub usage data before a production rollout.
vfd_summary.qo (hourly):
{
"file": "vfd_summary.qo",
"body": {
"f_hz_mean": 59.8, "f_hz_peak": 60.1,
"i_a_mean": 12.4, "i_a_peak": 13.7,
"trq_mean": 68, "trq_peak": 74,
"drv_c_mean": 42, "drv_c_peak": 51,
"run_min": 53, "stop_min": 7,
"hrs_total": 18234,
"fault_count_hour": 0,
"last_fault": "0"
}
}vfd_event.qo (immediate, sync:true):
{
"file": "vfd_event.qo",
"body": {
"alert": "load_anomaly",
"f_hz": 0,
"i_a": 0,
"v1": 59.8,
"v2": 14.9,
"v3": 12.3,
"fault_code": 0,
"hrs_total": 18234
}
}The event template carries eight fixed fields. When a specific sample
triggers the alert, f_hz and i_a hold that sample's values (a Modbus
failure event, for example, captures the last-known sample state). When an
hourly aggregate triggers it, those two fields are zero and the relevant
aggregates go into three generic numeric slots, v1 / v2 / v3, whose
meaning depends on the alert type:
| Alert | v1 | v2 | v3 |
|---|---|---|---|
load_anomaly | hourly mean frequency | hourly mean current | bin baseline current |
transient_faults | distinct fault transitions in window | window hours | unused (0) |
drive_overtemp | hourly peak heatsink °C | hourly mean heatsink °C | unused (0) |
runtime_drift | observed daily runtime hours | expected daily runtime hours | unused (0) |
modbus_unreachable | unused (0) | unused (0) | unused (0) |
A production build could rename these to alert-specific fields (for example
i_a_mean and i_a_baseline), but that costs a separate template per alert.
The v1/v2/v3 shape keeps one shared template for every alert type, and
it's what the demo firmware emits.
Power and sync strategy
The OPTA and expansion are line-powered (24 VDC), so the goal here is bus and
bandwidth efficiency, not MCU sleep. The Notecard runs in
hub.set periodic mode
with outbound:60 and inbound:120 (minutes). Summary Notes pile up in the
on-device queue and go out together in one session every hour. Alert Notes set
sync:true and go out as soon as a session can be established after the
trigger, usually within ~15–60 seconds.
Retry and error handling
- The firmware retries a failed Modbus read up to 3× per cycle. If all three
fail, it skips that sample and emits a
separate
modbus_unreachableevent Note. A NaN never shows up in a payload, since JSON has no validNaNliteral and templated Notes validate field types. The event is rate-limited to once an hour so nobody gets buried in alarms while the drive is powered off for service. - The
env.getrequest goes throughnotecard.requestAndResponse(), and the firmware checks for both aNULLreturn and anerrfield on the response before trusting the values. The other requests (hub.set,note.template,note.add) go out once withsendRequest(), and the firmware ignores thetrue/falseresult. A request the Notecard rejects isn't retried, and the error only shows up in note-arduino's debug output on the serial port. For an alert, that means a lost Note. The rule's edge trigger is already set, so the same alert won't fire again until its condition clears and trips again (or, formodbus_unreachable, until the hourly rate limit lets it through).
Key code snippets
Once at boot, notecardConfigure() sets the Notecard up for periodic sync
(defineTemplates() registers the templates for both Notefiles before it). The
cadence comes from g_report_minutes, which setup() reads from the
report_minutes environment variable first, so the defaults work out to
outbound 60 and inbound 120 minutes:
J *req = notecard.newRequest("hub.set");
if (req) {
JAddStringToObject(req, "product", PRODUCT_UID);
JAddStringToObject(req, "mode", "periodic");
JAddNumberToObject(req, "outbound", g_report_minutes);
JAddNumberToObject(req, "inbound", g_report_minutes * 2);
notecard.sendRequest(req);
g_last_hubset_outbound = g_report_minutes;
}Polling the VFD takes one Modbus transaction that reads all six contiguous
holding registers, which then feed the hourly stats. pollVfd() makes up to
three attempts and returns false if they all fail, which is what triggers
modbus_unreachable:
for (uint8_t attempt = 0; attempt < MAX_TRIES; attempt++) {
if (isContiguousMap() &&
ModbusRTUClient.requestFrom(g_modbus_slave_id, HOLDING_REGISTERS, g_reg_freq, 6)) {
out.frequency_hz = ModbusRTUClient.read() / 100.0f;
out.current_a = ModbusRTUClient.read() / 100.0f;
out.torque_pct = (int16_t)ModbusRTUClient.read();
out.drive_temp_c = (int16_t)ModbusRTUClient.read();
out.runtime_hours = (uint32_t)(uint16_t)ModbusRTUClient.read();
out.fault_code = (uint16_t)ModbusRTUClient.read();
out.valid = true;
return true;
}
// ...
}
return false;Then there's the load-anomaly rule. Rising current at a comparable output frequency is one of the things maintenance techs watch for. The firmware sorts samples into 5 Hz frequency bins and tracks an EWMA-smoothed baseline current for each bin, so 30 Hz operation never gets compared against a 60 Hz baseline. The rule only runs when the hour had more than five running samples. The first such hour in a bin seeds that bin's baseline. After that, the baseline only moves while the alert isn't tripping, 5% of the way toward each new hourly mean. The alert is edge-triggered. It fires once on the rising edge and rearms when the bin's mean drops back below the threshold:
if (run > 5 && f_hz_mean > 1.0f) {
const uint8_t bin = freqBin(f_hz_mean);
const float baseline = g_current_baseline_by_bin[bin];
if (!g_baseline_seeded[bin]) {
// Cold-start for this frequency bin: seed from the first valid hour
// we observed running in this bin.
g_current_baseline_by_bin[bin] = i_a_mean;
g_baseline_seeded[bin] = true;
} else if (i_a_mean > baseline * g_current_alarm_factor) {
if (!g_active_load_anomaly) {
sendEvent("load_anomaly", nullptr, f_hz_mean, i_a_mean, baseline);
g_active_load_anomaly = true;
}
} else {
// EWMA update on the bin's baseline (alpha = 0.05 over hourly
// samples) and rearm if we were active.
g_current_baseline_by_bin[bin] = 0.95f * baseline + 0.05f * i_a_mean;
g_active_load_anomaly = false;
}
}8. Build and Flash
Prerequisites: Arduino IDE (or arduino-cli on the command line) with the
following installed from the Boards Manager and Library Manager:
- Boards:
Arduino Mbed OS Opta Boards - Libraries:
Blues Wireless Notecard,ArduinoModbus,ArduinoRS485
Steps:
-
Clone or download the repo and open
firmware/vfd_pump_monitor/vfd_pump_monitor.inoin the Arduino IDE. -
Replace the placeholder value of
PRODUCT_UIDat the top of the sketch (com.your-company.your-name:vfd_pump_monitor) with your Notehub ProductUID:#define PRODUCT_UID "com.your-company.your-name:vfd_pump_monitor"(Find it in Notehub under Dashboard → Project Settings → ProductUID, or see Finding a ProductUID.)
-
Via Arduino IDE: Select Tools → Board →
Arduino Opta, select the correct COM/tty port, then Sketch → Upload. -
Via command line (arduino-cli):
arduino-cli compile --fqbn arduino:mbed_opta:opta firmware/vfd_pump_monitor/ arduino-cli upload -p /dev/ttyACM0 --fqbn arduino:mbed_opta:opta firmware/vfd_pump_monitor/(Replace
/dev/ttyACM0with your OPTA's serial port. On macOS it's usually something like/dev/cu.usbmodem*.)
The Finder OPTA Codesys ships running the CODESYS runtime. The first time you upload Arduino firmware to it, you have to put it into bootloader mode yourself by double-tapping its RESET button, as described in the Wireless for OPTA Quickstart. That upload replaces the CODESYS runtime, and later uploads don't need the double tap.
- Open the Arduino IDE Serial Monitor (115200 baud) to check that the sketch
boots. The firmware turns on note-arduino's debug output, so you'll see each
Notecard request and response (
note.template,env.get,hub.set) go by.
9. Data Flow
Collected. Every sample_minutes: output frequency, motor current, output
torque, drive heatsink temperature, cumulative runtime hours, and the
active fault code (only the live fault register, not the fault history
log).
Summarized. Every report_minutes (hourly by default): the mean and peak of
each scalar, separate run and stop minute counts, total runtime hours, the
number of distinct fault transitions seen in the hour, and the last non-zero
fault code.
Transmitted.
vfd_summary.qo: once perreport_minutes(24 Notes per day by default), queued and shipped on the Notecard's hourly outbound sync.vfd_event.qo: right away when a rule trips, withsync:trueso it skips the outbound interval.
Routed. Notehub sends vfd_event.qo to whatever real-time channel the
operator uses (CMMS tickets, on-call paging, Slack, and so on) and
vfd_summary.qo to long-term storage for trend analysis.
Triggers. Four rules fire alerts:
load_anomaly: hourly mean current exceeds the rolling baseline bycurrent_alarm_factorwhile the pump is running. Lots of things can cause this (bearing drag, fouling, valve position, viscosity, debris, some impeller conditions), so treat it as an anomaly worth investigating, not a specific failure mode.transient_faults:transient_fault_countor more distinct fault transitions withintransient_fault_window_hours. The rule counts0 → nonzeroandcode-changedevents, not the number of samples taken while a fault is asserted.runtime_drift: observed daily runtime exceedsexpected_run_hours_per_dayby more than 25%.drive_overtemp: heatsink temperature exceedsdrive_temp_alarm_c.
10. Validation and Testing
On a healthy pump in steady state, expect one summary Note per hour and no
event Notes. The Notecard's
card.status and
hub.status requests
make good smoke tests during commissioning.
Modbus first-light. Before you connect to the real drive, run the firmware against a software Modbus simulator (Modbus Mechanic, ModRSsim2, or similar) through a USB-to-RS-485 adapter wired to the OPTA's RS-485 terminals. Check that the six register reads match what the simulator is publishing.
Power validation with Mojo. Here's Notecard's published current envelope, from the Notecard low-power-design docs and the NOTE-WBNAW datasheet:
| Phase | Expected current |
|---|---|
| Notecard idle (radio off, between syncs) | ~8–18 µA @ 5V |
| Modem active (cellular session) | ~250 mA average, with ≤2 A bursts during GSM transmit |
| WiFi active (when WiFi fallback engaged) | ~80 mA average |
Splice the
Mojo
inline on the Wireless for OPTA power input and confirm three things: idle
current between syncs sits in the published µA range, per-session energy lands
in the few-mAh range for an hourly outbound sync, and total energy per day stays
consistent from run to run. Keep in mind that you're measuring the whole
expansion subsystem: the Notecard plus the expansion's onboard regulators and
I²C glue. You'll only see the Notecard by itself if you physically isolate its
VMODEM_P rail. Notecard also only reaches its lowest-power state when VUSB
is absent and AUX_EN isn't held high. The Notecard low-power-design
docs cover those
gating conditions.
Fault simulation. The easiest way to simulate a fault is to drop
current_alarm_factor to 1.01 in the Fleet's environment variables. That's
the lowest value the firmware accepts, and it ignores anything outside
1.01–5.0. The next inbound sync pulls the new value, and the next hourly
summary trips load_anomaly if that hour's mean current runs more than 1% over
the baseline for its frequency bin. The event lands in Notehub as soon as a
session comes up.
11. Troubleshooting
Notecard not claiming to the project.
- Check that
PRODUCT_UIDin the sketch exactly matches the ProductUID on Notehub (Projects → Project Settings). - Confirm cellular signal. In the Blues In-Browser Terminal, run
card.wirelessand checkbarsandnet.rsrp. LTE Cat-1 needs at least -100 dBm. - If you're deploying indoors or in a metal cabinet without an external antenna, the bundled rubber-duck antenna won't work. Thread the external SMA antenna through a cable gland and screw it onto the primary antenna port.
Modbus reads failing (firmware logs [modbus] read failed or no data in
summary Notes).
- Check the RS-485 A/B/COM wiring. A and B are easy to swap, and the drive won't respond if they're reversed.
- Make sure a 120 Ω termination resistor is present at both ends of the bus. With one OPTA and one drive, that's two resistors total (one at the OPTA, one at the drive).
- Check the slave ID and baud rate. In Notehub's Fleet Environment, confirm
modbus_slave_idandmodbus_baudmatch the VFD's configuration. After the next sync, runenv.getin the terminal to confirm the Notecard pulled the new values, andhub.sync.statusto see when that sync finished. The firmware applies them at its next hourly summary. - Before connecting to the real drive, test with a USB-to-RS-485 adapter and a software Modbus simulator (Modbus Mechanic, ModRSsim2) wired to the OPTA's RS-485 terminals, and make sure the firmware reads all six registers correctly.
First event not appearing in Notehub after 60+ seconds.
- Check Notehub's Events tab, where every Note (summary and alert) shows up. If it's empty, the firmware hasn't established a cellular session yet. Wait for the first outbound sync (60 minutes by default) or power-cycle the OPTA to force a session sooner.
- Confirm the Notecard has cellular coverage (see the
card.wirelesscheck above). - If you need a test alert, drop
current_alarm_factorto 1.01 (its minimum) in the Fleet Environment. Once a sync pulls the new threshold, the next hourly summary can triggerload_anomaly(see Fault simulation above). The alert posts as soon as a session comes up, typically 15–60 seconds after that summary.
Environment variables not taking effect.
- The Notecard fetches environment variables at least once per inbound sync
interval (120 minutes by default), and the firmware reads them at its next
hourly summary. To force an immediate fetch, power-cycle the OPTA, or set the
_sync_inbound_minsenvironment variable to1while you're commissioning. - Make sure the variables are set on the correct Fleet, not at the project level. In Notehub, that's Projects → Project Name → Fleets → Fleet Name → Environment.
Antenna placement considerations.
- The rubber-duck antennas that come with Wireless for OPTA are for bench testing only. They won't hold reliable LTE Cat-1 coverage inside a metal pump cabinet.
- Route the primary antenna outside the cabinet through a cable gland. If the layout allows, route the diversity antenna (second SMA port) outside too, for better performance where signal is marginal.
- Keep the primary antenna at least 2 m away from high-power electrical equipment (motor starters, VFDs) to cut down on RF interference.
12. Limitations and Next Steps
A reference design meant for thousands of different drive configurations has to be clear about what it does and doesn't claim. The biggest question is what VFD telemetry can actually tell you. Everything else is the usual list of scope choices that get refined once a real fleet starts deploying.
Signal limitations. VFD telemetry is valuable, but it isn't a substitute for full pump instrumentation. Current, torque, speed, temperature, and active fault codes can spot abnormal patterns. Without context like suction/discharge pressure, flow, vibration, or a known duty cycle, though, they can't reliably tell a worn impeller from a clogged suction strainer, a closed discharge valve, cavitation, bearing drag, increased fluid viscosity, debris, or a process change. Treat every alert this firmware sends as an early maintenance indicator, not a diagnosis.
Simplified for this reference design
Beyond the signal limits above, the firmware deliberately keeps its scope narrow in a few places. A real fleet deployment will extend the design at each of them.
Vendor-specific register addresses, scaling, signedness, and word counts.
The defaults describe a made-up contiguous map. Each VFD vendor publishes its
own Modbus map, so commissioning a real plant means looking up the actual
addresses, scaling factors (current may be 0.1 A, 0.01 A, or % of rated),
signedness (torque and temperature are often signed), word counts (runtime hours
are often a 32-bit value across two registers with vendor-specific word order),
and addressing convention (0-based wire-level vs. 1-based / Modicon "40001"
notation). The shipped firmware reads six contiguous 16-bit registers with
hardcoded scaling, so production builds need vendor-specific firmware, one
build per vfd_profile.
Active fault code only, not fault history log. The firmware reads the active-fault register once per cycle. Reading a vendor-specific fault log, which is usually a multi-register block with circular-buffer semantics, is left for a future version.
Single drive per OPTA. The firmware reads one slave ID. A pump room with N drives needs either N OPTAs or a firmware extension that round-robins across slave IDs on the same RS-485 bus.
Heuristic thresholds. Four threshold-based rules catch common load-anomaly, transient-fault, runtime-drift, and overtemp patterns. They won't catch every failure mode, and they'll sometimes fire on harmless conditions like a seasonally hotter room or a deliberate process change. In production, tune the thresholds for each pump after a baseline period.
No Modbus writes. The firmware only reads. Writing setpoints to the drive (start/stop, speed reference, and so on) is out of scope on purpose. That's a different safety conversation, one that involves E-stop wiring, lockout/tagout, and functional safety certification.
No host firmware updates wired up. Notecard Outboard Firmware Update supports STM32H7 (the OPTA's MCU family), but it needs AUX wiring that Blues Wireless for OPTA doesn't break out today. For now, host firmware updates are local-only via USB-C.
Production Next Steps
Once a real fleet starts deploying, the scope choices above turn into the roadmap. Here they are, roughly from most immediately useful to most infrastructure-dependent.
Vendor-specific vfd_profile builds come first: ABB ACS580, Yaskawa
GA500, Danfoss FC-302, and Schneider ATV, each with the right register
addresses, scaling, signedness, and word handling baked in.
Per-pump baseline learning makes detection a lot sharper. With rolling
30-day current-vs-frequency tables stored in flash, the firmware can trigger
load_anomaly against the learned curve instead of a static factor.
Fault history log readout captures the events leading up to a trip, not just the active fault. It's vendor-specific and usually spans multiple registers with timestamps.
Multi-drive support through round-robin polling and per-slave-ID summaries lets a single OPTA cover an entire pump room.
A vfd_command.qi inbound Notefile would let a service tech request a
diagnostic dump on demand.
Wiring ODFU to the OPTA's BOOT/RESET pins is the furthest out. Once the hardware path exists, it enables over-the-air host updates across the fleet.
13. Summary
The maintenance team that used to find out about a struggling pump from a dry tank on a Saturday night now gets a CMMS ticket on Tuesday afternoon about a load anomaly, a creeping drive temperature, or a cluster of transient faults. Six Modbus registers, one cellular session an hour, and four anomaly rules turn telemetry the VFD already had into early warnings. A plant electrician can clip the device onto a DIN rail in fifteen minutes, and it never touches the corporate network.