Paylee Device
Operator Guide
Everything you need to install, commission, and maintain Paylee devices in the field — from first boot to firmware updates.
Device overview
The Paylee device is a compact PCB that mounts inside any coin-operated pool table. It runs on an ESP32-C6 microcontroller with WiFi, connects to your venue network, and reports every transaction to the cloud.
This guide covers hardware v1.2 (Vending Device 1.2). Earlier hardware revisions (1.0, 1.1) share the same commissioning and operation steps but differ in some connector positions. Refer to the PCB silkscreen for your board version.
Key components
| Component | Description | Notes |
|---|---|---|
| ESP32-C6 | Main microcontroller — 4MB flash, WiFi 2.4GHz | Does not support 5GHz networks |
| LP5813 RGB Driver | I²C RGB LED driver — powers the player queue indicator LED | Addr 0x58–0x5B |
| FM25CL16B FRAM | 2KB non-volatile memory — stores dispense log across power cycles | Up to 511 dispense records |
| ADXL345 | Accelerometer — tamper/tilt detection | Triggers alert to dashboard on motion |
| Motor driver | Controls ball-dispense mechanism with current-sense stall detection | 5s safety timeout |
| Coin switch | Detects physical coin insertion via interrupt | Active low, IO05 |
| Battery monitor | 12V SLA battery voltage sense via ADC divider | 64-sample average per wake |
GPIO reference
All GPIO assignments for the ESP32-C6. Do not alter these connections — the firmware expects the exact mapping below.
RJ45 external connector pinout
| Pin | Colour | Signal | Description |
|---|---|---|---|
| 1 | Orange/White | OperateBtn | Dispense button — connect to NO momentary switch, GND other side |
| 2 | Orange | CoinSwitch | Coin mechanism switch — active low on coin detect |
| 3 | Green/White | LastBall | Last-ball switch — active low when ball leaves dispense chute |
| 4 | Blue | 12V+ | Regulated 12V supply from battery or mains adapter |
| 5 | Blue/White | 12V+ | 12V supply (parallel with pin 4) |
| 6 | Green | MtrDrv Out | Motor drive line to existing ball dispense mechanism |
| 7 | Brown/White | GND | Ground reference |
| 8 | Brown | GND | Ground (parallel with pin 7) |
On-board devices
Three I²C devices share the 400kHz bus on IO06/IO07. All have external pull-ups — do not enable software pull-ups in firmware.
| Device | Address | Function | Notes |
|---|---|---|---|
| LP5813CDRRR | 0x58–0x5B | RGB LED driver — player queue colour indicator | Common anode: OUT0=Anode, OUT1=Green, OUT2=Red, OUT3=Blue. Low-current mode, Vout >4V for blue LED. |
| FM25CL16B | 0x50–0x57 | 2KB FRAM — non-volatile dispense log | Stores last 4 bytes of 511 dispense UUIDs. Survives power loss. No wear-levelling needed. |
| ADXL345 | 0x1D | Accelerometer — tilt and tamper detection | Motion interrupt on INT1 (IO18). Triggers critical alert to dashboard on tilt event. |
Installing the device
The Paylee PCB mounts inside the table's existing electronics bay. It connects to the existing coin mechanism and motor driver via the RJ45 connector.
Ensure the pool table is disconnected from mains power and the 12V battery is disconnected before handling the PCB or making any wiring connections.
Mount the PCB
Secure the Paylee PCB in the table's electronics bay using the four M3 mounting holes. Ensure adequate clearance from metal surfaces — use the included nylon standoffs.
Connect the RJ45 cable
Route the RJ45 cable from the PCB connector to the table's coin mechanism and motor driver. Match the pinout in Section 02 above. Secure with the cable clip provided.
Connect the RGB LED
Mount the RGB LED in the provided bezel hole on the table's exterior. Connect the 4-pin JST connector to the RGB header on the PCB (labelled RGB OUT).
Connect the battery
Connect the 12V SLA battery using the supplied Anderson connector. Polarity is marked on the PCB — red (+), black (−). The battery should measure 12.4–12.8V before connecting.
Power on & verify
Apply mains power. The RGB LED will show a slow white breathe pattern for 3–5 seconds during boot, then enter commissioning mode (steady blue pulse) if this is a first boot. Proceed to Commissioning.
First-time WiFi setup
New devices must be connected to the venue's WiFi network before they can report transactions. This is done via a captive portal on the device's own temporary WiFi network.
To re-commission an existing device (e.g. after a venue WiFi change), hold the OperateBtn for 5 seconds during boot. The LED will switch to steady blue pulse confirming commissioning mode is active.
Connect to the device's WiFi
On your phone or laptop, look for a WiFi network named VendingDevice-XXXXXX (last 6 chars of the device MAC). Connect using password: Setup123!
Open the captive portal
Your device should auto-redirect to the setup page. If not, open a browser and navigate to http://192.168.4.1
Enter WiFi credentials
Select your venue's 2.4GHz WiFi network from the list and enter the password. Optionally set a static IP if your network requires it. Note: 5GHz networks are not supported.
Set the API URL (if non-default)
The default API endpoint is pre-configured. Only change this if you're running a self-hosted Paylee instance. Leave blank to use the default.
Save & wait for reboot
Tap Save. The device reboots, joins the venue WiFi, and performs its first check-in. The RGB LED will turn off (no pending games) within 15 seconds if connection was successful.
Register the device in the dashboard
Log in to your Paylee operator dashboard, go to Devices → Add device, and enter the MAC address printed on the PCB label. Assign it to the correct venue and give it a name (e.g. "Table 1").
Once the device appears as "Online" in your dashboard with a recent last-seen timestamp, commissioning is complete. The device is now ready to accept payments.
What the colours mean
The RGB LED on the table exterior communicates device state to both players and staff. This is the complete reference for every LED pattern.
Player-facing states
Breathing (player colour)
A pending game is in the queue. The device is in sleep mode between check-ins. Colour matches the player's assigned queue colour.
Solid (player colour)
This player's turn is now active. The dispense button is live — pressing it will release the balls. Colour matches the player's assigned queue colour.
Fast pulse — white
A coin was just inserted. Device is processing the payment and dispensing immediately. Also shown while a card payment check-in is in progress.
Off
No pending games in the queue. The device is sleeping and will wake on the next check-in interval or when a payment is made.
Staff & maintenance states
Slow breathe — white
OTA firmware update in progress. Do not disconnect power. The device will reboot automatically when complete. Takes 30–90 seconds.
Slow pulse — blue
Device is in commissioning / setup mode. Connect to its WiFi network to configure. See Section 05 — Commissioning.
Fast pulse — player colour
LastBall switch warning: the dispense timeout is about to expire (5 seconds remaining). The balls will be marked as uncollected if the switch isn't triggered.
Wake sources & behaviour
The device uses light sleep between events to conserve battery. It wakes automatically in response to these sources.
| Wake source | Trigger | What happens |
|---|---|---|
| OperateBtn | Player presses the dispense button | If a game is queued: LED shows solid colour → motor runs → balls dispense. If no game queued: checks in with server first, dispenses if a game appears. |
| CoinSwitch | Coin inserted into slot | LED pulses white → motor dispenses immediately → POST to cloud. No UUID returned — coin dispenses are fire-and-forget. |
| RTC Timer | Periodic timer (60s on-peak, 15 min off-peak) | Posts check-in to cloud, receives updated game queue and sleep interval. No dispense occurs. |
| AccelTamper | ADXL345 detects motion/tilt | Clears interrupt, sends tamper fault to dashboard (critical alert). Does not affect game queue. |
| LastBall | Ball exits dispense chute (if enabled) | Only active during an open dispense. Confirms consumption. Sent to cloud as consumed event. |
Check-in frequency is controlled by the server based on your venue's configured hours. On-peak (e.g. 08:00–20:00): every 60 seconds. Off-peak: every 15 minutes. This balances responsiveness with battery life.
Battery guide
The device runs from a 12V sealed lead-acid (SLA) battery. At ~200μA sleep current, a 7Ah battery provides months of standby life.
Charging
Voltage >12.8V. Shown as 100% + charging icon in dashboard. Mains power connected.
Low battery
Below 20%. Dashboard sends email alert to venue and operator. Recharge soon.
Critical
Below ~10% (11.7V). Device may stop checking in. Recharge immediately.
Charging procedure
Connect mains power
Plug the table's mains supply into a working outlet. The onboard charging circuit maintains the SLA battery automatically — no separate charger needed.
Monitor in dashboard
Battery percentage and charging status update every check-in cycle. When charging, the dashboard shows "Charging" next to the battery percentage.
Verify full charge
A full charge reads >12.8V (shown as 100% + charging). Typical charge time from flat is 12–16 hours on a 7Ah SLA battery.
Replace the SLA battery every 3–4 years or if it can no longer hold charge. Use a 12V 7Ah sealed lead-acid battery (same footprint as standard alarm batteries). Dispose of old batteries at an approved recycling point.
How a game is dispensed
Understanding the dispense sequence helps diagnose problems. Here's what happens from button press to balls dropping.
// Player presses OperateBtn
Wake from light sleep (~10ms)
│
├── Queue in RAM has entries?
│ │
│ ├── YES → Show solid colour on RGB LED
│ │ Run motor (watch MtrIsns for stall)
│ │ Log UUID tail to FRAM
│ │ POST /device/checkin/dispensed
│ │ 10s button lockout starts
│ │ │
│ │ └── product_ready enabled?
│ │ ├── YES → Wait for LastBall (1s debounce)
│ │ │ ├── Triggered → POST /consumed
│ │ │ └── Timeout → POST /timeout
│ │ └── NO → Hold colour → sleep
│ │
│ └── NO → Pulse white LED
│ POST /device/checkin/
│ │
│ ├── Game in response → Dispense immediately
│ └── No game → LED off → sleep
Over-the-air updates
Firmware updates are pushed remotely from the operator dashboard. No physical access to the device is required.
When an update is available, the operator dashboard sends an ota_url field in the next check-in response. The device will:
- Show a slow white breathe pattern on the LED (do not power off)
- Download the firmware binary over HTTPS
- Verify and flash to the alternate OTA partition (1.75MB slot)
- Reboot into the new firmware automatically
- Resume normal operation — check-in interval unchanged
If power is lost mid-update, the device will revert to the previous firmware slot and retry on next connection. However, repeated interrupted updates can corrupt the OTA state — avoid interrupting if possible.
Update status and firmware version for each device are visible in the operator dashboard under Devices → Firmware.
Common issues
Work through these before raising a support ticket. Most issues are WiFi or wiring related.
- Confirm the device has been registered in the dashboard with the correct MAC address (printed on PCB label)
- Re-commission the device: hold OperateBtn 5s at boot, reconnect to VendingDevice-XXXXXX WiFi
- Verify the venue WiFi is 2.4GHz — ESP32-C6 does not support 5GHz networks
- Check WiFi signal strength at the table location — weak signal causes connection failures
- If using static IP, verify the address is in the correct subnet and not conflicting
- Check the CoinSwitch wiring at the RJ45 connector — pins 2 and 7 (GND)
- Verify the coin mechanism switch is closing correctly — use a multimeter in continuity mode across pins 2 and 7 of the RJ45 while inserting a coin
- Check that the device is online in the dashboard (last seen within last 15 minutes)
- Confirm the device is not marked as inactive in the dashboard
- Check for physical obstruction in the ball dispense chute — clear any jammed balls
- Verify MtrDrv wiring at the RJ45 connector (pin 6) and GND (pin 7 or 8)
- Check motor current sense wiring (IO03 / MtrIsns) — incorrect calibration can cause false stall detection
- The motor has a 5-second safety timeout and a 3A stall threshold — if consistently triggering, the mechanism may need lubrication
- Dashboard will show a dispense_fault alert — resolve the mechanical issue then clear the alert
- A motor stall or mechanical fault was detected — check the dispense chute for obstructions
- A critical fault alert has been sent to dashboard — check Devices → Alerts
- First dispense fault: game is re-queued and retried once automatically
- Second consecutive fault on same game: game is marked permanent fault, players should be refunded manually via dashboard
- ADXL345 sensitivity may be too high for the installation environment — vibration from adjacent machinery can trigger it
- Check that the PCB is secured firmly with all 4 standoffs — loose mounting causes vibration-induced false triggers
- Resolve the alert in the dashboard — it will not repeat until another motion event is detected
- Persistent false alerts: contact support for accelerometer sensitivity adjustment via OTA config update
- Verify mains power is connected and the charging circuit is working — check dashboard for charging status
- High check-in frequency (on-peak mode) uses more power — verify on-peak hours are configured correctly in the venue settings
- WiFi connection failures cause repeated retry loops which drain battery quickly — check for network issues
- RGBEnable signal should not be latched on during sleep — if LED is always on, this indicates a firmware or wiring issue
- Battery may be end-of-life (3–4 years typical) — replace with 12V 7Ah SLA
- Card payments go through Stripe/Square → cloud → device on next check-in (up to 60s delay on-peak)
- Verify the webhook is configured correctly in Stripe/Square dashboard pointing to /api/tokens/webhook
- Check dashboard Transactions to confirm the payment was received by the cloud
- If payment appears in dashboard but no game on device: check device is online and check-in interval is reasonable
At a glance
| Task | Action |
|---|---|
| First-time WiFi setup | Connect to VendingDevice-XXXXXX WiFi → http://192.168.4.1 |
| Re-commission device | Hold OperateBtn 5 seconds during boot |
| Check battery % | Dashboard → Devices → select device → Battery column |
| Push firmware update | Dashboard → Devices → Firmware → select version → Push update |
| Set free game period | Dashboard → Venues → select venue → Free game period |
| Add staff dispenses | Dashboard → Venues → Staff dispenses → set daily limit |
| Clear a fault alert | Dashboard → Devices → Alerts → Mark resolved |
| Export revenue report | Dashboard → Reports → select date range → Export CSV |
| Default commissioning password | setup1234 |
| Check-in interval (on-peak) | 60 seconds (configurable per venue) |
| Check-in interval (off-peak) | 15 minutes (configurable per venue) |
| Motor stall threshold | >3A for >100ms |
| Dispense button lockout | 10 seconds after dispense (prevents double-press) |
| Dispense reservation window | 5 minutes — expired if device doesn't check in |