OpenValence Download

How it fits together

The whole system, one script action on its way to the motor, and the access tiers. The numbers come from the spec and the firmware as of October 2026.

The system

The OpenValence systemAn app talks Valence to the machine over Wi-Fi, or over BLE for setup. On the OSSM Flagship board an ESP32-C6 radio passes the traffic over SDIO to the ESP32-P4 running Nucleus. There the Valence hub hands motion to the Kinetic planner, which keeps a 128 ms strip of positions on a 1 ms grid. Every millisecond the low-power core gets a speed, a fence and a 4 ms lease, and sends A/B quadrature to the servo drive, which turns the motor. The drive reports alarms back, and the P4 can read it over RS485.Phosphor, or any appdesktop app, the page the machineserves, scripts, pluginsValenceWebSocket over Wi-FiBLE for setup and offlineOSSM Flagship boardESP32-C6 · radioWi-Fi and BLE, Espressif's esp_hostedruns none of our codeSDIO, 4-bitESP32-P4 · NucleusValence hubsessions, catalog, limits, 5 ms tickKinetic² planner1 ms grid, 128 ms strip of positionsspeed + fence4 ms leaseLP coreA/B quadrature from a 40 MHz crystalparks itself if the lease runs outA/B quadraturealarm, RS485 readsServo drivecloses the loop on the motorMotor and rail
Blue is motion going out, violet is information coming back. The radio chip only moves bytes; everything that decides anything runs on the ESP32-P4.

The planner keeps a 128 ms buffer of positions, one per millisecond. A planner stall shorter than that does not reach the motor. Below it, the low-power core gets a speed that stays valid for 4 ms, renewed every millisecond. If the main cores hang, the motor keeps its last speed for at most 4 ms, then stops.

How a funscript action reaches the motor

Every stage runs on the same clock. The player sends each action 900 ms early, the hub holds it until it is due, Kinetic² renders it on a 1 ms grid into a 128 ms buffer, and the low-power core turns that into quadrature. The curve is real planner output; the wire leg is slowed down to be visible.
How a funscript action reaches the motorTen steps. In Phosphor the player loads the script, scales positions to the travel window, maps each shown video frame to media time, schedules up to 32 segments once a frame, then stamps them on the machine's clock and sends them up to the horizon minus 100 ms ahead. They cross the wire as a Valence STREAM. On the machine the hub admits the control owner's segments, the Kinetic planner renders them on a 1 ms grid into a 128 ms strip, the steer gives the low-power core a speed and a 4 ms lease every millisecond, and the low-power core sends quadrature to the servo drive. Motion state returns to Phosphor, 50 times a second by default.Phosphor · the funscript player01Loadactions {at ms, pos 0 to 100}plus V8 and V9 axes02Scalemanual or auto, to a shareof the travel window03Clockeach shown video frame mappedto media time04Scheduleonce a frame, up to 32 segments;a gap over 500 ms ends in a rest05Stamp and paceon the machine's clock; sliversunder 10 ms dropped; sent up tohorizon minus 100 ms aheadThe wire · Valence over WebSocket06STREAMsegments channel, found by role;CLOCK resync every 10 sThe machine · Nucleus on the ESP32-P407Hubadmits the control owner'ssegments, 5 ms tick08Kinetic² planner1 ms grid, 128 ms strip, underthe speed, accel, jerk ceilings09Steerevery 1 ms: a speed for the LPcore, renewed 4 ms lease10LP coreA/B quadrature to the servo drivemotion state back, 50 Hz by default, and the plan strip
Steps 01 to 05 run in Phosphor, 07 to 10 on the machine. The dashed line is what comes back.

The machine picks how far ahead it accepts motion: 250, 500 or 1000 ms, and it ships at 1000. Phosphor sends each segment up to 100 ms short of that look-ahead limit, so 900 ms by default. A Wi-Fi stall shorter than that doesn't reach the stroke, because the machine already holds the next stretch.

V8 and V9, the oscillation axes, take a separate path. Phosphor resamples them at the rate the machine grants and sends them about 176 to 226 ms ahead on their own stream, and the planner adds them on top of the stroke.

Access tiers and pairing

Access tiers and the ways inThree tiers, each including the one below. Watch sees everything and is open by default. Control can also move the machine. Configure can also change setup and decide who gets in. Stop works at every tier. The first client to knock on a factory-fresh machine, or on one booted in config mode, gets configure. A pairing window, a PIN or a yes from a configure client grants a paired tier, control by default. Connecting with no token gives watch.configuresetup, network, who gets inin: a fresh machine's first knock,config mode, or a configure yescontrolmove it: patterns, scriptsin: Pair window, PIN, or a yesfrom a configure clientwatchsee everything, stop itin: just connect, no tokenstop works at every tier
Each tier includes the one below it. A paired client gets control unless it asked for configure and someone with configure said yes.

Anyone can watch, and anyone connected can stop the machine. Moving it takes a pairing. The page the machine serves from its own address gets control through a one-time token, never configure. A factory-fresh machine gives configure to the first client that asks, since that is normally the owner setting it up.

The Pair button

GestureWhat it doesStatus
PressOpens a 120 s pairing window. The first client to ask gets in.spec · details draft (RFC-114)
Double pressSays yes to the one client waiting for configure. If two are waiting, it approves neither.draft (RFC-114)
Hold 5 sDrops every paired client to watch and ends their sessions. Pairings stay on file.draft (RFC-114)
Hold while powering onConfig mode: Bluetooth and USB only, no Wi-Fi. The first client to ask gets configure.spec (§13.4.1)
Power-cycle three times (no button)Three boots in a row, each shorter than 10 s, open the pairing window on the next boot.spec (§12.3)
Press while offlineApproves the one configure request that came over Bluetooth or USB.draft (RFC-117)

Draft gestures are in the firmware and can change before the spec adopts them. The spec also asks for a factory-reset gesture, which is not built yet.