Gestures
Every gesture is the same two-machine dance: the X/Y arm drives the stylus to the bbox center, then a solenoid drops the tip onto the glass and lifts it. The Z axis is not a servo and there’s no depth to calibrate — the tip sits at a fixed height, and the only thing that varies is timing. What makes a tap a tap and a long-press a hold is how long the coil stays energized.
The solenoid, in one paragraph
Section titled “The solenoid, in one paragraph”The stylus tip is pushed down by a solenoid wired to the GRBL spindle PWM pin, so it’s
driven with spindle G-code: M3 S<duty> energizes the coil at a PWM duty on a 0–1000
scale, and M5 releases it. A return spring lifts the tip when the coil cuts. A solenoid
burns its coil out if held at full current, so PhysiClaw uses a hit-and-keep profile:
strike hard to pull the iron core in, then drop to a lower hold current to keep it seated.
| Constant | Value | What it is |
|---|---|---|
HIT_S | 1000 | strike duty — pulls the core in (brief only) |
HOLD_S | 750 | hold duty — safe to sustain (long-press, swipe slide) |
SETTLE_MS | 80ms | dwell after the strike before dropping to the hold level |
RELEASE_MS | 200ms | spring-rebound dwell after M5, before any XY move |
DOUBLE_TAP_GAP_MS | 100ms | brief lift between the two strikes of a double-tap |
After every M5, PhysiClaw dwells RELEASE_MS so the spring can lift the tip clear before
the next XY move starts — otherwise the tip would drag a line across the screen.
A momentary press: strike at HIT_S, hold for the tap duration (80ms), release. The press
is short enough that the reduced hold current isn’t needed — S1000 for 80ms gives a crisp
contact without cooking the coil.
G0 X.. Y.. ; arm moves to the bbox centerM3 S1000 ; strike (stylus down)G4 P0.08 ; hold 80 msM5 ; releaseG4 P0.2 ; spring-rebound dwell (tip clears the glass)Double-tap
Section titled “Double-tap”Two strikes separated only by a brief contact-breaking lift — not the full spring-clear dwell. The whole pair runs as one gesture so down-to-down stays well under the iOS ~300ms double-tap window; chaining two independent taps (each with its 200ms release) pushed it to ~280ms, and timing jitter then split the gesture into two single taps.
M3 S1000 ; strike 1G4 P0.08 ; hold 80 msM5 ; lift briefly…G4 P0.1 ; …100 ms, just enough to break contactM3 S1000 ; strike 2G4 P0.08 ; hold 80 msM5 ; releaseG4 P0.2 ; spring-rebound dwellLong-press
Section titled “Long-press”Here the hit-and-keep profile earns its name: strike, settle, drop to the hold current, and keep the tip seated for the full long-press duration (1.2s) before lifting. iOS/Android register a long-press at ~500ms; 1.2s leaves comfortable margin.
G0 X.. Y.. ; arm moves to the bbox centerM3 S1000 ; strikeG4 P0.08 ; settle 80 msM3 S750 ; drop to hold currentG4 P1.2 ; hold 1.2 sM5 ; releaseG4 P0.2 ; spring-rebound dwellA swipe presses, then moves under load. The tip is held down at HOLD_S for the whole slide
while the arm runs a controlled G1 move (not a rapid G0) from the origin to the endpoint,
then lifts. Stroke length comes from the size argument; the speed argument sets the G1
feed rate:
speed | Feed | Feel |
|---|---|---|
slow | F3000 | careful scroll / drag |
medium | F6000 | normal swipe (~100 mm/s) |
fast | F10000 | fling, page switch |
G0 X.. Y.. ; arm moves to the startM3 S1000 ; strikeG4 P0.08 ; settle 80 msM3 S750 ; drop to hold current (tip stays down for the slide)G1 X.. Y.. F6000 ; drag to the endpoint at the chosen feedM5 ; releaseG4 P0.2 ; spring-rebound dwellSummary
Section titled “Summary”| Gesture | Down | Hold | Move | Up |
|---|---|---|---|---|
| Tap | S1000 | 80ms | — | M5 + 200ms dwell |
| Double-tap | S1000 ×2 | 80ms each, 100ms gap | — | M5 + 200ms dwell |
| Long-press | S1000 → S750 | 1.2s | — | M5 + 200ms dwell |
| Swipe | S1000 → S750 | for the slide | G1 at F3000/6000/10000 | M5 + 200ms dwell |