Fully Wireless · Volume 4
Latency, Lost Packets, a Crowded House, Four Guns and Pairing
What each link adds to the gun's latency against the cable, what a lost packet does to aim, buttons and recoil, where 2.4 GHz interference in a house comes from, how four guns share the air, and how each route pairs a gun with its receiver
4.1 The Latency Budget Against the Cable
The gun’s own share of latency, from a camera frame to a USB report leaving it, is worked through in Aiming Maths and Calibration Vol 7, 7.5: about 2.7 to 8.8 ms on OpenFIRE v6.2 with Average smoothing, 5.6 ms on average, of which the last term is the 0 to 1 ms wait for the host’s USB poll. Fully Wired Vol 5, 5.7 adds that the cable itself contributes about 20 ns. A radio replaces that last term with a longer chain:
Table 1 — The gun's own share of latency, from a camera frame to a USB report leaving it, is worked through in [Aiming Maths and Calibration Vol 7, 7.5](/light-guns/sensing-and-aiming/aiming-maths-and-calibration/vol-7/): about 2.7 to 8.8 ms on OpenFIRE v6.2 with Average smoothing, 5.6 ms on average, of which the last term is the 0 to 1 ms wait for the host's USB poll. [Fully Wired Vol 5, 5.7](/light-guns/power-and-connectivity/fully-wired/vol-5/) adds that the cable itself contributes about 20 ns. A radio replaces that last term with a longer chain
| Stage | Cabled gun | Gun with a dongle | Gun on the PC’s Bluetooth |
|---|---|---|---|
| Camera frame, read, maths, smoothing | 2.7 to 7.8 ms | the same | the same |
| Report waits for the air | — | ESP-NOW and ESB: channel access, tens to hundreds of µs; LLPM: 0 to 1 ms | 0 to one connection interval (7.5 ms or more) |
| On the air, with acknowledgement | — | ~0.15 to 0.3 ms | ~0.1 to 0.3 ms |
| A retry, if the first try is lost | — | ~0.35 ms each | one more connection interval |
| Dongle hands the report to its USB stack | — | tens of µs (assumed 0.05 ms) | — |
| Waits for the host’s poll | 0 to 1 ms | 0 to 1 ms | — (the PC’s Bluetooth stack instead, unknown) |

The simulated means, set into the gun’s 5.6 ms:
Table 2 — The simulated means, set into the gun's 5.6 ms
| Link | Link’s share, mean (99.9th percentile) | Gun’s share end to end, mean |
|---|---|---|
| Cable | 0.5 ms (1.0) | 5.6 ms |
| ESP-NOW dongle, clean channel | 0.8 ms (1.3) | 5.9 ms |
| ESP-NOW dongle, 5 % first-try loss | 0.8 ms (1.7) | 5.9 ms |
| ESB dongle, on demand | 0.8 ms (1.7) | 5.9 ms |
| LLPM dongle, 1 ms interval | 1.3 ms (2.3) | 6.4 ms |
| Bluetooth LE HID to the PC, 7.5 ms | 4.1 ms (7.8), radio only | 9.2 ms plus the host stack |
| Bluetooth LE HID to the PC, 15 ms | 7.8 ms (15.3), radio only | 12.9 ms plus the host stack |
A dongle link costs about a third of a millisecond on average, under one millisecond at the tail. That is a tenth of the gun’s own share and a few per cent of a 60 Hz frame. Bluetooth to the PC costs most of a camera frame at the shortest interval the specification allows, before the host’s stack is counted, and the host may well grant a longer one.
4.2 What the Numbers Assume, and What They Leave Out
The simulation (04-templates/wireless_calcs.py, output in calc_output.txt) is arithmetic on published protocol timing, not a measurement. Its assumptions, each a bench item in Volume 6:
- Report size 32 bytes on air for every link. The port’s real framing was not counted byte by byte.
- Channel access for ESP-NOW as an 802.11g station on an idle channel: 28 µs plus a random 0 to 15 slots of 9 µs. On a busy channel the wait is however long the other stations talk; that is Section 4.5.
- A lost first try costs 0.35 ms (time-out and a resend), and 5 % of first tries are lost in the second ESP-NOW row. Both numbers are placeholders for a measured loss rate.
- The ESP-IDF Wi-Fi task and the dongle’s FreeRTOS hand-off are taken as 0.05 ms. Espressif publishes no figure for the time from
esp_now_send()to the antenna or from reception to the callback. - The host’s operating system after it reads the report is not modelled for any row. For the dongle rows it is the same as for a cable. For the Bluetooth rows it is the PC’s Bluetooth stack and HID-over-GATT driver, which no source found quantifies; the true cost of that route is higher than shown.
4.3 What the Player Feels
Two properties of a light gun soften the numbers above.
Aim and trigger travel together. OpenFIRE sends the cursor and the button state in the same reports, so a game sees a trigger pull at the cursor position of the same instant. A shot lands where the cursor was, whatever the link delay; delay only moves the cursor behind the gun’s motion (Aiming Maths and Calibration Vol 7, 7.5). A radio does not split the two, because both are in the same packet.
A fixed delay is learned; a variable one is felt (CRT Timing Vol 7). The cable’s poll already adds a uniform 0 to 1 ms of variation and the camera’s frame wait 0 to 4.8 ms. A dongle link widens the spread by well under a millisecond; Bluetooth to the PC widens it by a whole connection interval.
Recoil is local by default. The gun fires its own solenoid on a trigger pull (Open-Source Firmware Vol 5), so the radio is not in the kick’s timing. Only game-driven feedback (serial handoff, Open-Source Firmware Vol 6, 6.7) crosses the link backwards: the dongle polls the PC’s serial port each millisecond and forwards the bytes at once in the ESP32 port; in an ESB design that carries them in acknowledgements, they wait for the gun’s next report, up to 4.8 ms.
4.4 What a Lost Packet Does
Table 3 — 4.4 What a Lost Packet Does
| What is lost | Cable | Radio with newest-report-wins | What to watch on the bench |
|---|---|---|---|
| One position report | — | The next one, 4.8 ms later, replaces it; the cursor pauses for a frame | Visible jitter only at high loss |
| A burst of reports (say 50 ms) | — | The cursor freezes at its last position, then jumps | Bursts, not average loss, are what players notice; log them |
| A button change | — | The new state is in every later report, so it arrives with the next one. A press and release that both fall inside one outage are lost; buttons are debounced over 15 to 20 ms, so that takes an outage of that length | Count trigger pulls sent against received |
| A held trigger during an outage | — | The PC keeps the last state: the button stays down until the link returns | The gun’s own recoil follows the trigger locally, so the solenoid stops when the finger lifts |
| A serial force-feedback command | — | Depends on the link’s own retries. ESP-NOW retries at the MAC layer, but Espressif warns delivery to the application is not guaranteed; whether the port adds its own acknowledgement was not established | A lost F0x0 leaves the coil on to the firmware’s 2 s cut-off; count commands sent against acted on |
| The whole link | The gun disappears from the PC | The ESP32 dongle stays enumerated with its last state; the gun reconnects “almost instantly” if only the gun restarts | Time to reconnect after the gun is switched off and on |
The design rule this table implies is “never queue position, never drop commands”: position goes newest-first with no retransmission beyond what the radio does in a fraction of a millisecond; serial bytes go reliably, sequence-numbered and acknowledged. The ESP32 port does the first. Route B would be written to do both (Volume 3, 3.5).
4.5 Interference in a House

The sources, roughly in order of how often they will matter:
- The house’s Wi-Fi. An access point on the same or an adjacent channel as an ESP-NOW link takes airtime the gun must wait for; heavy traffic (a video stream, a game download) is exactly when the channel is busiest. The port’s dongle scans for the quietest channel at plug-in and stays there; an access point that changes channel later, as many do automatically, is not followed until the dongle is replugged. Bluetooth LE and LLPM hop and mark bad channels; ESB stays where the firmware puts it.
- USB 3 at the PC. Intel’s April 2012 white paper, USB 3.0 Radio Frequency Interference Impact on 2.4 GHz Wireless Devices, describes broadband noise from USB 3.0 connectors, cables and peripherals in the 2.4 GHz band that reduces the range of wireless keyboards and mice, and lists placing the receiver away from USB 3.0 ports, on a USB 2.0 extension cable, among the mitigations (Intel’s summary and support article; the PDF itself was not read). The same applies to a light-gun dongle: put it on a short USB 2.0 extension, away from USB 3 devices and the PC’s metal case, in view of where the player stands.
- The player’s own body, and the gun’s shell. The 2.4 GHz band is strongly absorbed by the body. The gun points at the screen, and the dongle sits at the screen, so in normal play the path is clear; it is the antenna’s position inside the gun, under a hand or behind the receiver’s metal parts and solenoid leads, that decides the margin (Volume 5).
- A microwave oven in use leaks around 2450 MHz, across Wi-Fi channels 6 to 11 and the middle of the Bluetooth band. It is an occasional event, not a design case, but a gun that drops out whenever someone heats a drink is a bad gun; it is a bench case in Volume 6.
- Other Bluetooth and 802.15.4 devices. Low duty cycle, hopping; minor.
Range itself is not the problem at living-room distances. The port transmits at 17 dBm; a Nordic part at 0 to 8 dBm. What fails first in a house is not the link budget at 3 m but coexistence and blockage, which is why the bench plan measures loss in the room, inside the shell, with traffic on the channel, rather than range in an open field.
4.6 Four Guns at Once
Table 4 — 4.6 Four Guns at Once
| ESP32 port | Route B, ESB | Route B, LLPM (nRF Desktop style) | Bluetooth to the PC | |
|---|---|---|---|---|
| Receivers | One dongle per gun | One dongle per gun (proposed) | One dongle for up to four guns is available (dongle_4llpmconn), or one each | The PC’s radio |
| Air use | 4.6 % of a Wi-Fi channel per gun; each dongle picks its own channel at plug-in, so two may coincide | ~6 % of a channel per gun at 209 Hz; channels set by the firmware | Shared hopping schedule per central | Shared by the PC |
| Player identity | The dongle takes the gun’s name, player and serial, so “it does not matter which dongle a gun pairs with” (port README) | Copied the same way | Per gun, if the dongle presents four devices | Per device as the PC enumerates them |
| MiSTer and hook programs | Work: four separate USB devices with OpenFIRE identities | Work, if each dongle is its own device | One dongle with four guns must present four separate OpenFIRE devices; a single composite device with one vendor and product ID and one serial number is not what MiSTer and the App look for | No serial path |
One dongle per gun is proposed (WL-8). It costs a few dollars and a USB port per player, and in exchange each gun is exactly what Open-Source Firmware Vol 6, 6.6 describes for cabled multiplayer: its own device, own product ID, own serial port. Four guns at 4.6 % each use under a fifth of one Wi-Fi channel; on separate channels, almost nothing.
4.7 Pairing
ESP32 port. Automatic and exclusive. Plug the dongle in and wait about 15 seconds while it scans and chooses a channel; switch the gun on without its USB cable; “the first free dongle answers and the two pair exclusively.” The gun remembers its dongle and pedal and “reconnects almost instantly” after it alone restarts; a replugged dongle forgets and must be paired again, with the gun power-cycled. With several guns, switch them on one at a time. Frames are not encrypted (Volume 2, 2.3); nobody nearby gains anything by reading a cursor position, and injecting commands would need the gun’s paired address. It is a reasonable posture for a toy, stated so that a kit’s documentation can say it.
Bluetooth to the PC. The operating system’s own pairing and bonding, once per PC. Simple, and the only route where the gun can move between machines without its own receiver, at the costs in Volume 2.
LLPM (nRF Desktop model). Bluetooth LE bonding between the gun and its dongle, with the application’s peer-control buttons to erase and re-bond, and the dongle scanning for known peers when one disconnects. Mature, and already written in Nordic’s reference design.
ESB. No pairing in the protocol at all: two radios talk if they share a channel and an address. A route-B design needs a small pairing step of its own: hold a button at power-on, exchange a random address and channel on a fixed pairing channel at low power, store both in flash on each side. This is the least-specified part of route B and should be designed with the same “first free receiver, exclusive, remembered” behaviour players will already know from the ESP32 port.
4.8 What Could Not Be Verified
- The time ESP-IDF takes from
esp_now_send()to the air and from reception to the callback; no Espressif figure was found. - The connection interval Windows, Linux or a Raspberry Pi grants a Bluetooth LE HID gun, and its host-stack latency.
- Whether the ESP32 port acknowledges serial force-feedback bytes at the application level.
- The real loss rate and burst length in a house, inside a shell; the 5 % figure is a placeholder.
- The Intel white paper’s measured figures (only Intel’s own summary was read).
Sources
- This dive’s model:
04-templates/wireless_calcs.pyandcalc_output.txt. - Alessandro Satanassi, OpenFIRE-Firmware-ESP32: README,
dongle/README.md,lightgun/src/README.md(“Multiple guns and multiplayer”),dongle/src/main.cpp— https://github.com/alessandro-satanassi/OpenFIRE-Firmware-ESP32 (read 2026-10-19). - Espressif, ESP-NOW, ESP-IDF Programming Guide (ESP32-S3) (read 2026-10-19).
- Nordic Semiconductor, nRF Connect SDK: nRF Desktop description and board configuration; LLPM and ESB samples (read 2026-10-19).
- Intel, USB 3.0 Radio Frequency Interference Impact on 2.4 GHz Wireless Devices, white paper, April 2012 — https://www.intel.com/content/www/us/en/content-details/841692/usb-3-0-radio-frequency-interference-impact-on-2-4-ghz-wireless-devices-white-paper.html, and Intel support article 000095026 (summaries read 2026-10-19; PDF not read).
Comments (0)