Datasheet & User Manual · MODEL E04XXXX REV.A · Document rev 1.1 · 2026-06-18
The EDGE 4IO Modbus I/O Module is an industrial I/O device with 4 digital inputs and 4 digital outputs. It is exposed simultaneously over Modbus TCP (Ethernet) and Modbus RTU (RS-485), sharing one register map, and is discoverable on the LAN via mDNS / Zeroconf. A supervisory platform browses mDNS, reads capability metadata from TXT records, then polls/controls the device — no static IP or manual register-map documentation required for integration.
| Parameter | Value |
|---|---|
| Power supply | 24 Vdc |
| Firmware | e04_modbus v1.0.3 |
| Inputs | 4 × digital, 24 / 0 Vdc type, debounced (3 consistent reads @ 10 ms) |
| Outputs | 4 × digital, 24 Vdc / 0 Vdc (on/off) |
| Ethernet | 10 Mbps, full-duplex (RJ45) |
| Serial | RS-485 half-duplex (terminals A / B) |
| Protocols | Modbus TCP (port 502) + Modbus RTU, concurrent; mDNS |
| Addressing | DHCP client; static IP fallback configurable |
24-pin terminal block. Ethernet is on the separate RJ45 jack.
| No | Symbol | Type | Description |
|---|---|---|---|
| 1 | Vss | Power | Power supply ( 24 Vdc ) |
| 2 | GND | GND ( 0 Vdc ) | |
| 3 | Vss | Power supply ( 24 Vdc ) | |
| 4 | GND | GND ( 0 Vdc ) | |
| 5 | O1+ | Digital Output | Positive signal output ( 24Vdc/0Vdc ) |
| 6 | O1- | Negative signal output ( 24Vdc/0Vdc ) | |
| 7 | O2+ | Positive signal output ( 24Vdc/0Vdc ) | |
| 8 | O2- | Negative signal output ( 24Vdc/0Vdc ) | |
| 9 | O3+ | Positive signal output ( 24Vdc/0Vdc ) | |
| 10 | O3- | Negative signal output ( 24Vdc/0Vdc ) | |
| 11 | O4+ | Positive signal output ( 24Vdc/0Vdc ) | |
| 12 | O4- | Negative signal output ( 24Vdc/0Vdc ) | |
| 13 | J1 | Debug | For setting ( connect J1 and J2 for setup mode ) |
| 14 | J2 | For setting ( connect J1 and J2 for setup mode ) | |
| 15 | A | Modbus | D+ ( modbus rtu signal ) |
| 16 | B | D- ( modbus rtu signal ) | |
| 17 | DI1+ | Digital Input | Positive signal digital input ( 24/0 Vdc type ) |
| 18 | DI1- | Negative signal digital input ( 24/0 Vdc type ) | |
| 19 | DI2+ | Positive signal digital input ( 24/0 Vdc type ) | |
| 20 | DI2- | Negative signal digital input ( 24/0 Vdc type ) | |
| 21 | DI3+ | Positive signal digital input ( 24/0 Vdc type ) | |
| 22 | DI3- | Negative signal digital input ( 24/0 Vdc type ) | |
| 23 | DI4+ | Positive signal digital input ( 24/0 Vdc type ) | |
| 24 | DI4- | Negative signal digital input ( 24/0 Vdc type ) |
Connect J1–J2 at power-on to enter setup/provisioning mode.
All 4 inputs are digital. Each is debounced (3 consistent reads at a 10 ms poll interval)
and reported over Modbus as 0 / 1 in its input register.
Invert: any input can be inverted (report 0↔1) via the
config portal — set the Invert inputs bitmask (bits 0–3 = inputs 1–4). Use it when
the field wiring/sensor is active-low. Default off.
Each of the 4 outputs is driven from its output register: any non-zero value sets the output ON (24 Vdc), zero sets it OFF (0 Vdc). Writes take effect immediately. At boot and during fail-safe the outputs are forced to a defined state.
e04-<wifi_mac_no_colon>.localedge_modbus._tcp.local, port 502TXT records (capability advertisement):
| Key | Example | Meaning |
|---|---|---|
model | e04_modbus | Device model |
fw | 1.0.0 | Firmware version |
i | 4 | Input channels |
o | 4 | Output channels |
unit | 1 | Modbus unit/slave ID |
proto | modbus-tcp | Protocol identifier |
mac | B4E62DDE225D | WiFi MAC (no colons) |
| Parameter | TCP | RTU (RS-485) |
|---|---|---|
| Role | Slave / Server (always) | Selectable: Off / Slave / Master |
| Transport | Ethernet (RJ45) or WiFi, port 502 | RS-485 (terminals A / B) |
| Address | Unit ID (MBAP) | Slave address = Unit ID register |
| Default line | — | 9600 baud, 8N1 (configurable) |
| Function codes | 03 (read holding), 06 (write single holding); as a master it also issues 04 (read input) | |
| Byte order | Big-endian (standard Modbus) | |
RS-485 mode, baud / parity / stop-bits and the unit/slave id take effect after a reboot (the Modbus controllers are created once at startup).
There is a single RS-485 port, so it is either a slave or a master — never both. Modbus TCP keeps serving as a slave in all three modes.
| Mode | Value | Behaviour |
|---|---|---|
| Off | 0 | RS-485 idle; TCP only. |
| Slave | 1 | Default. A remote master reads/writes this device over RS-485, sharing the same registers as TCP. |
| Master | 2 | This device polls remote slaves and republishes what it reads into its own registers, so a TCP client reads local I/O and remote values from one table. See §8.1. |
Read with FC 03, write with FC 06. Layout: configuration block first, then live I/O.
| Addr | Register | Access | Persist | Notes |
|---|---|---|---|---|
| 0 | Unit ID / RTU address | R/W | NVS | 1–247; effective after reboot |
| 1 | Fail-safe output bitmask | R/W | NVS | bits 0–3 → outputs 1–4 |
| 2 | Fail-safe timeout (s) | R/W | NVS | 0 = disabled |
| 3 | RS-485 mode | R/W | NVS | 0=off, 1=slave, 2=master; effective after reboot |
| 4 | RTU baud / 100 | R/W | NVS | 96=9600 … 1152=115200 |
| 5 | RTU parity | R/W | NVS | 0=none, 1=odd, 2=even |
| 6 | RTU stop bits | R/W | NVS | 1 or 2 |
| 7 | Input 1 value | R | — | 0 / 1 (debounced) |
| 8 | Input 2 value | R | — | 0 / 1 |
| 9 | Input 3 value | R | — | 0 / 1 |
| 10 | Input 4 value | R | — | 0 / 1 |
| 11 | Output 1 | R/W | — | 0 = OFF, non-zero = ON |
| 12 | Output 2 | R/W | — | 0 / 1 |
| 13 | Output 3 | R/W | — | 0 / 1 |
| 14 | Output 4 | R/W | — | 0 / 1 |
| 15 | Status flags | R | — | bitfield (below) |
| 16 | Master poll status | R | — | bit i = poll entry i failed (master mode only) |
| 17–48 | Master poll results | R | — | remote registers, packed in entry order (master mode only) |
Registers 16–48 exist on every build but read 0 unless RS-485 is in master mode. Addresses 0–15 are unchanged from earlier firmware.
| Bit | Mask | Meaning |
|---|---|---|
| 0 | 0x01 | Ethernet link / IP up |
| 1 | 0x02 | Modbus master polled recently (any transport) |
| 4 | 0x10 | Outputs forced to fail-safe |
| 5 | 0x20 | RS-485 running as a slave |
| 6 | 0x40 | RS-485 running as a master (polling) |
In master mode the device polls up to 8 entries, each a block read from one
remote slave, repeating the whole sweep every sweep interval (default 1000 ms, min 100 ms).
Entries are configured in the web portal (§11.2) as slave,fc,start,count.
| Field | Range | Meaning |
|---|---|---|
slave | 1–247 | remote device address on the RS-485 bus |
fc | 3 or 4 | 3 = read holding registers, 4 = read input registers |
start | 0–65535 | first register address on the remote device |
count | 1–16 | how many consecutive registers to read |
Results are packed in entry order starting at register 17, up to 32 registers in total. Example:
| Entry | Configured as | Lands in |
|---|---|---|
| P0 | 5,3,100,4 | registers 17–20 (slave 5, holding 100–103) |
| P1 | 7,4,0,2 | registers 21–22 (slave 7, input 0–1) |
Unused or invalid entries are skipped and take no result registers; they are reported on the serial console at boot. A total exceeding 32 registers drops the overflowing entries.
Bits 2–3 (wire-break) are defined in the shared register layout but are only meaningful on the E02 (4–20 mA) variant; they read 0 on the E04.
| State | LED | Meaning |
|---|---|---|
| Provisioning | Fast blink | Config mode (SoftAP portal active) |
| Initializing | Slow blink | Booting, network not ready |
| Running | Solid ON | Normal operation (Modbus serving) |
Boot sequence: init I/O + safe outputs (LED slow-blink) → bring up Ethernet, acquire DHCP → start mDNS + Modbus TCP/RTU slaves (LED solid) → enter input-poll loop.
Write configuration registers (0–6) with FC 06. Config values persist to NVS. Transport/serial params (unit id, RTU baud/parity/stop/enable) apply on the next reboot; fail-safe bitmask/timeout and the outputs apply live.
Every firmware (Converter and Timestamp) uses the same way to enter config mode; only the settings shown on the page differ by firmware.
http://<device-ip>/) during operation — no jumper needed. It asks for a password (any user name; default edge12345, change it under Security on that page), because it shows the stored WiFi and MQTT passwords. Use the SoftAP route below when the device has no usable network yet.Enter config mode (identical for all firmwares):
E04-xxxxxx (password edge12345).http://192.168.4.1/.Common to all firmwares — network:
| Field | Purpose |
|---|---|
| WiFi SSID / Password | WiFi STA join (blank SSID = WiFi off) |
| WiFi static IP + IP / Gateway / Subnet / DNS1 / DNS2 | fixed IP on WiFi (unchecked = DHCP) |
| Ethernet static IP + IP / Gateway / Subnet / DNS1 / DNS2 | fixed IP on Ethernet (unchecked = DHCP) |
Converter firmware — Modbus settings (shown only on the Converter build):
| Field | Purpose |
|---|---|
| Unit ID / RTU address | Modbus slave id |
| Fail-safe outputs bitmask (0–15) | outputs applied on Modbus loss / boot (bit 0 = output 1 … bit 3 = output 4) |
| Fail-safe timeout s | 0 = disabled |
| Invert inputs (bitmask) | bit 0 = input 1 … bit 3 = input 4 (report 0↔1) |
| RS-485 Modbus RTU mode | Off / Slave / Master (applies on reboot) — see §7.1 |
| Baud / Parity / Stop bits | RS-485 line settings, both modes (applies on reboot) |
| Sweep interval ms | Master mode: how often the whole polling plan repeats (min 100) |
| P0 … P7 | Master mode: polling plan, one entry per box as
slave,fc,start,count; blank = unused. See §8.1 |
The 4 inputs are always digital on the E04SD — there is no input-mode field.
Timestamp firmware — MQTT / event settings (shown only on the Timestamp build): broker host/port, client id, username, password, device code, NTP server and Input edge. See §14 · Provisioning for the full list.
Update the firmware over USB from a Chrome / Edge browser — no tools to install. Open the web flasher, pick the model and version, connect, and flash:
Stored configuration (unit id, RS-485, fail-safe, etc.) is preserved across an update unless you choose Erase device.
| Symptom | Check |
|---|---|
| No IP / not discoverable | Ethernet cable & RJ45 link; DHCP server present; LED stuck slow-blink = no IP yet |
| TCP master can't connect | Confirm the device IP, port 502 open, only the needed master polling |
| RTU no response | RS-485 mode = 1 (slave) in reg 3; matching baud/parity/stop & slave address; A/B terminals (15/16) & ground |
| Master poll fails (bit set in reg 16) | RS-485 mode = 2; remote slave address / FC / register range correct; matching line settings; A/B wiring & termination |
| Input always 0 or 1 | Verify field wiring & 24/0 Vdc signal level on the DI± terminals |
| Output doesn't switch | Write to registers 11–14; check fail-safe isn't active (status bit 4) |
| Can't enter config mode | Short J1–J2 (terminals 13–14) at power-on; LED should switch to fast blink |
An alternative firmware for the same board that timestamps input edges (proximity / counting sensors) and streams each event to the new_owl IIoT platform over MQTT — instead of the Modbus register interface. Select Timestamp Firmware in the web flasher. Same pinout & terminals.
| Item | Behaviour |
|---|---|
| Inputs | All 4 digital inputs are edge event inputs with a selectable capture edge (rising / falling / both, set in the config portal). No input-mode selection — single fixed function. (Outputs are unused in this firmware.) |
| Per event | Publishes {"tags":{"inK":1},"ts":<epoch_ms>} to device/<device_code>/telemetry (K = input 1–4). |
| Timestamp | Each edge is stamped locally from an SNTP-synced clock (epoch ms). The server honours the device timestamp, so buffered / back-dated events keep their real event time. |
| Store-and-forward | RAM ring buffer (2048 events) retries on network / broker outage or backpressure; QoS 1 with delivery ack (an event leaves the buffer only after the broker confirms). |
| Broker | MQTT (EMQX), plain TCP port 1883. |
Two independent ceilings apply — how fast edges can be captured, and how fast events can be delivered to the server. Event timestamps are stamped in the interrupt at microsecond resolution, so timing stays accurate even when delivery lags.
| Limit | Value | Set by |
|---|---|---|
| Capture rate (per input) | set by the configurable debounce (default 1 ms → up to 1 kHz): edges closer together than the debounce on the same input are discarded. Max rate per input ≈ 1000 / debounce_ms. Inputs are debounced independently, so the aggregate is 4× that across the 4 inputs. | debounce setting (config portal) |
| Timestamp resolution | microsecond (captured in the ISR) — buffered / back-dated events keep their true event time | hardware timer |
| Sustained delivery (to server) | one QoS 1 publish at a time (waits for the broker PUBACK before the next), so the continuous rate ≈ 1 / broker round-trip: ~200–1000 ev/s on the same LAN, ~65–200 ev/s over WiFi to a LAN broker, ~10–30 ev/s across the internet | QoS 1 ack round-trip (network) |
| Burst headroom | 2048 events — short bursts above the sustained rate are buffered in RAM and drained later. If the average input rate stays above the sustained delivery rate, the buffer fills and the oldest events are dropped. | RAM ring buffer size |
Typical proximity / counting use (< 50 Hz) sits well within every limit. For higher sustained rates: shorten the debounce (cleaner signals only), or batch several events per MQTT message (requires a matching change on new_owl).
Create the device on the new_owl server, then copy its MQTT fields into the config portal
(short J1–J2 at boot → http://192.168.4.1/):
| Portal field | From the new_owl device |
|---|---|
| Broker host / port | your EMQX broker (platform host : 1883) |
| Client ID | mqtt_client_id |
| Username | mqtt_username |
| Password | mqtt_password |
| Device code | device_code → topic device/<code>/telemetry |
| NTP server | a reachable NTP host (default pool.ntp.org) — needed for event epoch time |
| Input edge | capture edge: 0=rising, 1=falling, 2=both (default 0) |
| Debounce ms | blanking time after an accepted edge, per input (default 1, 0=off, max 10000) — see below |
A noisy or bouncing sensor can register several edges for one real pulse, inflating counts. Raising the Debounce ms value ignores further edges on that input for the given time.
The device log (viewable in the web flasher) prints a status line every 5 seconds:
status: link=1(eth=1,wifi=0) mqtt=1 time=1 | in=[0101] buf=0 captured=12 sent=12 dropped=0 bounced=37
| Symptom | Meaning | Action |
|---|---|---|
bounced rising, counts now correct | debounce is filtering the noise | keep the current value |
bounced ~0 but counts still too high | the extra counts are not bounce (wiring / EMI / wrong edge) | check wiring and Input edge, not the debounce |
| real pulses missing | debounce exceeds the pulse interval | lower it |
1, or on release (rising) with 0; both give the same pulse count. WiFi & static IP are configured as usual; the device also connects over Ethernet. Events captured before the clock syncs or while offline are buffered and sent with their correct timestamp once connected.A third firmware for the same board. It samples the I/O on a fixed interval and publishes the readings as named tags to the new_owl platform over MQTT — what the legacy Edge firmware did over CoAP, but with every setting entered in the web portal instead of being pushed by the server. Select Edge-MQTT Firmware in the web flasher. Same pinout & terminals.
| Item | Behaviour |
|---|---|
| Sources | the 4 local inputs, plus any registers read from remote slaves in RS-485 master mode. Only channels you give a tag name to are published. |
| Per publish | {"tags":{"<your_tag>":<value>,...},"ts":<epoch_ms>}
to device/<device_code>/telemetry — the same shape the Timestamp firmware uses,
so new_owl auto-creates the tags from the names you choose. |
| Interval | Publish interval s in the portal (default 60 s, range 1–3600). |
| Store-and-forward | RAM ring of 48 payloads; samples taken while the broker is unreachable are sent later with their original timestamp. QoS 1 — a payload leaves the buffer only once the broker confirms it. Oldest is dropped if the buffer fills. |
| Not included | no Modbus slave interface (nothing reads this device), and no commands from the server — it only publishes. |
| Portal field | Meaning |
|---|---|
| Input 1–4 tag | tag name for that local input. Blank = not published. |
Poll entry P0..P7 | one remote read per box, written as
tag,slave,fc,start,count,dtype,order. fc: 3=holding, 4=input.
dtype: 0=u16, 1=s16, 2=u32, 3=s32, 4=float32. order: 0=high word first
(Modbus default), 1=low word first. count is how many registers make up the value
(1 for 16-bit, 2 for 32-bit). Each entry becomes one tag; a blank tag is not published. |