
Switch
byrantech/laptop
anyon_e, a highly integrated, high end, open source laptop. Attempt the impossible.

Arduino Uno controller for Fully Jarvis standing desk via RJ-12 serial protocol
Jarvis desk is an open-source printed circuit board by benSlaughter, from the benSlaughter/jarvis-desk-controller repository on GitHub, published under the MIT licence. It is a 2-layer board of 40 × 25 mm with 6 parts on 5 nets.
Its parts include 2 resistors, 1 IC and 1 connector. It belongs with the interfaces and adapters boards and the ESP32 and RISC-V boards of this library.
Control a Jarvis/Jiecang standing desk via the RJ-12 port using the reverse-engineered serial protocol from phord/Jarvis.
Two platforms are supported:
| Platform | Interface | Features |
|---|---|---|
| Arduino Uno | USB Serial CLI | Direct serial commands, interactive terminal |
| ESP32-C6 | WiFi + MQTT | Home Assistant auto-discovery, OTA updates |
The RJ-12 port is the 6-pin telephone-style jack on the desk controller (used for the optional Bluetooth add-on). Only the center 4 pins are needed.
RJ-12 Jack (front view, tab down)
┌──────────┐
│ 1 2 3 4 5 6 │
└──┬─┬─┬─┬─┬─┬──┘
│ │ │ │ │ │
NC│ │ │ │ NC
│ │ │ │
│ │ │ └── Pin 5: HTX (to desk) ──[1kΩ]── Arduino Pin 3
│ │ └──── Pin 4: VCC (5V out) (see power notes below)
│ └────── Pin 3: DTX (from desk) ──[1kΩ]── Arduino Pin 2
└──────── Pin 2: GND ──────────── Arduino GND| RJ-12 Pin | Label | Arduino Uno | Notes |
|---|---|---|---|
| 1 | NC | — | Not connected |
| 2 | GND | GND | Common ground (REQUIRED) |
| 3 | DTX | Pin 2 (RX) | Via 1kΩ series resistor |
| 4 | VCC | — | 5V from desk (see below) |
| 5 | HTX | Pin 3 (TX) | Via 1kΩ series resistor |
| 6 | NC | — | Not connected |
The 1kΩ resistors protect both the Arduino and the desk controller from shorts, voltage spikes during hot-plugging, and current surges. They don't affect signal integrity at 9600 baud.
For development (recommended): Power the Arduino via USB. Leave RJ-12 Pin 4 (VCC) disconnected.
For standalone deployment: You can power the Arduino from the desk's 5V supply on RJ-12 Pin 4 → Arduino 5V pin. However:
⚠️ Never connect both USB and desk 5V simultaneously — this back-powers the USB host and can damage your computer or the desk controller. Use a diode or power switch if you need both.
The ESP32 can be powered directly from the desk's 5V supply — no USB needed after the first firmware upload (use OTA for updates).
DFRobot Beetle ESP32-C6
┌─────────────────────┐
│ │
RJ-12 │ VIN ←── 5V power │
┌──────┐ │ GND ←── Ground │
│1 6│ │ │
│ NC NC│ │ GPIO17 (RX) ←─┐ │
│ │ │ │ │
│2 GND─┼──────────→│ GND │ │
│ │ │ │ │
│3 DTX─┼──[1kΩ]──┬─┼─────────────────┘ │
│ │ │ │ │
│ │ [2kΩ] │
│ │ │ │ │
│ │ GND│ │
│ │ │ │
│4 VCC─┼──────────→│ VIN (5V) │
│ │ │ │
│5 HTX─┼──────────→│ GPIO18 (TX) │
│ │ │ │
│6 NC │ └─────────────────────┘
└──────┘| RJ-12 Pin | Label | ESP32-C6 | Notes |
|---|---|---|---|
| 2 | GND | GND | Common ground (REQUIRED) |
| 3 | DTX | GPIO17 (RX) | Via 1kΩ + 2kΩ voltage divider |
| 4 | VCC | VIN (5V) | Powers the ESP32 from desk |
| 5 | HTX | GPIO18 (TX) | Direct connection — 3.3V is fine |
Parts needed: 1× 1kΩ resistor, 1× 2kΩ resistor (or 2× 1kΩ in series)
The desk sends data at 5V. The ESP32-C6 GPIOs are rated for 3.3V max. Without a divider, 5V goes straight into a 3.3V pin — this will damage the chip.
Two resistors drop the voltage: 5V × 2kΩ / (1kΩ + 2kΩ) = 3.33V ✅
The TX line (ESP32→desk) doesn't need this because the ESP32 outputs 3.3V, which the desk's 5V logic reads as HIGH (above the ~2.5V threshold).
⚠️ Never connect USB and desk 5V at the same time — this back-powers the USB host. Disconnect the RJ-12 before plugging in USB, or use OTA for all updates after the first upload.
Current budget: The desk provides ~300mA at 5V. The ESP32-C6 draws ~120-180mA during WiFi activity — well within budget.
Live testing on a Jiecang JCB36N2CA (Fully Jarvis) confirmed normal UART polarity — standard 9600/8N1 with no inversion needed. Earlier documentation suggested inverted logic, but this was not the case on the tested controller.
The code uses SoftwareSerial with inverse_logic = false (standard polarity). If you get garbage data, try toggling this flag — some controller models may differ.
This project uses PlatformIO for build/upload/serial monitoring.
platformio.platformio-ide)platformio.ini automaticallyUse the PlatformIO toolbar at the bottom of VSCode, or:
# Arduino Uno
pio run -e uno
pio run -e uno --target upload
# ESP32-C6
pio run -e esp32c6
pio run -e esp32c6 --target upload
# Tests
pio test -e native
# Open serial monitor (115200 baud)
pio device monitor
# Build + upload + monitor in one shot
pio run -e uno --target upload && pio device monitorinclude/config.example.h to include/config.hconfig.h with your WiFi SSID/password and MQTT broker IPpio run -e esp32c6pio run -e esp32c6 --target uploadpio device monitorThe ESP32 firmware publishes MQTT auto-discovery messages. After connecting:
| Topic | Direction | Description |
|---|---|---|
jarvis-desk/status | ESP→broker | Online/offline status (retained LWT) |
jarvis-desk/height/state | ESP→broker | Current height in mm (retained) |
jarvis-desk/height/set | broker→ESP | Move to target height in mm |
jarvis-desk/preset/set | broker→ESP | Move to preset (payload: 1–4) |
jarvis-desk/command | broker→ESP | Send command: up, down, stop |
jarvis-desk/collision/set | broker→ESP | Set collision sensitivity: high, medium, low |
After the first upload via USB, subsequent updates can use OTA:
pio run -e esp32c6 --target upload --upload-port jarvis-desk.localIf you prefer the Arduino IDE, copy files from src/ and include/ into a single
folder named jarvis-desk-controller/, rename main.cpp → jarvis-desk-controller.ino,
and open it in the Arduino IDE.
Open the Serial Monitor at 115200 baud. Type commands and press Enter:
| Command | Action |
|---|---|
up / raise | Raise desk one step |
down/lower | Lower desk one step |
1 2 3 4 | Move to memory preset |
save1..save4 | Save current height to preset |
height | Request current height |
settings | Request all desk settings |
limits | Request min/max limits |
wake | Send wake signal |
cm / in | Set display units |
status | Show connection state |
help | List all commands |
=== Jarvis Desk Controller ===
Type 'help' for commands
Waking desk...
[DESK] HEIGHT (05 06 07) height=1286
> Moving to preset 1
[DESK] HEIGHT (03 CA 07) height=970[addr][addr][cmd][len][params...][checksum][0x7E]0xF1 0xF10xF2 0xF2(cmd + len + params...), i.e. & 0xFFFull protocol documentation: https://github.com/phord/Jarvis
Tested on a Jiecang JCB36N2CA (Fully Jarvis, RJ-12 port). The RJ-12 interface works standalone — no handset required.
| Cmd | Name | Params | Response | Notes |
|---|---|---|---|---|
| 0x01 | RAISE | 0 | HEIGHT stream | Continuous raise when sent repeatedly |
| 0x02 | LOWER | 0 | HEIGHT stream | Continuous lower when sent repeatedly |
| 0x05 | MOVE_1 | 0 | HEIGHT stream | Moves to preset 1, auto-stops |
| 0x06 | MOVE_2 | 0 | HEIGHT stream | Moves to preset 2, auto-stops |
| 0x07 | SETTINGS | 0 | POS_1–4 + HEIGHT | Returns all 4 presets and current height |
| 0x0C | PHYS_LIMITS | 0 | 0x07 (HI HI LO LO) | Physical motion limits: max/min in mm |
| 0x1B | GOTO_HEIGHT | 2 (HI, LO) | 0x1B echo + HEIGHT stream | Native goto-height. Desk handles accel/decel/stop |
| 0x20 | LIMITS | 0 | 0x20 (00) | User-set limits bitmask. 0x00 = none set |
| 0x27 | MOVE_3 | 0 | HEIGHT stream | Moves to preset 3, auto-stops |
| 0x28 | MOVE_4 | 0 | HEIGHT stream | Moves to preset 4, auto-stops |
| 0x29 | WAKE | 0 | none (display only) | Wakes display. No data response on RJ-12 |
| 0x2B | STOP | 0 | none | Stops all movement immediately |
| Resp | Name | Params | Meaning |
|---|---|---|---|
| 0x01 | HEIGHT | 3 | {P0,P1} = height mm, P2 = flags (always 0x0F here) |
| 0x07 | PHYS_LIMITS | 4 | {P0,P1} = max mm, {P2,P3} = min mm |
| 0x1B | GOTO_ACK | 2 | Echoes target height |
| 0x20 | LIMITS | 1 | Bitmask of user-set limits |
| 0x25–0x28 | POS_1–4 | 2 | Raw encoder value (NOT display mm) |
This project uses the RJ-12 interface (6-pin, Bluetooth add-on port). The larger RJ-45 port (8-pin, handset port) has additional button mux lines (HS0-HS3) not available on RJ-12.
On RJ-12, some responses differ:
SETTINGS returns fewer response packetsLIMIT_STOP and REP_PRESET are not sent| Problem | Try |
|---|---|
| No response from desk | Check GND connection. Try wake command repeatedly. |
| Garbage data | Toggle inverse_logic in the SoftwareSerial constructor. Normal polarity (false) confirmed on JCB36N2CA. |
| Partial/corrupt packets | Check series resistors are connected. Reduce Serial.print debug output. |
| Desk doesn't move | The raise/lower commands send a single step. You may need to send repeatedly. |
This project is for personal/educational use. The protocol was reverse-engineered by phord.
| Qty | Value | Footprint | References |
|---|---|---|---|
| 2 | MountingHole_M2 | MountingHole:MountingHole_2.2mm_M2 | H1, H2 |
| 1 | 1k | Resistor_SMD:R_0805_2012Metric | R1 |
| 1 | 2k | Resistor_SMD:R_0805_2012Metric | R2 |
| 1 | Beetle_ESP32-C6 | libs:Beetle_ESP32-C6 | U1 |
| 1 | RJ12_6P6C | Connector_RJ:RJ12_Amphenol_54601 | J1 |
It measures 40 × 25 mm and has 2 copper layers, 1.6 mm thick.
6 parts. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
From the benSlaughter/jarvis-desk-controller repository on GitHub, at the commit this page was made from: the board is hardware/kicad/jarvis-desk.kicad_pcb and its schematic hardware/kicad/jarvis-desk.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository publishes it under the MIT licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).

byrantech/laptop
anyon_e, a highly integrated, high end, open source laptop. Attempt the impossible.


Jcparkyn/dpoint
Open-source digital stylus using camera tracking and inertial measurements

VoronDesign/Voron-Hardware
Cool Hardware designed by the Voron Design group

hoglet67/RGBtoHDMI
Bare-metal Raspberry Pi project that provides pixel-perfect sampling of Retro Computer RGB/YUV video and conversion to HDMI

hackclub/OnBoard
💡 Join 1,000 teenagers and make your first PCB with a $100 grant!

Luos-io/luos_engine
Open-source and real-time orchestrator for cyber-physical-systems, to easily design, test and deploy embedded applications and digital twins.
