From e6fdd54ba39c395d888998e571fb53d3b821c6f3 Mon Sep 17 00:00:00 2001 From: David Montero Date: Fri, 22 May 2026 18:57:11 +0200 Subject: [PATCH] fix(joystick): map wokwi-analog-joystick direction (-1/0/+1) to ADC voltage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PartSimulationRegistry handler for 'analog-joystick' was reading `el.xValue` / `el.yValue` and computing `(value / 1023) * vcc` as if the component were a potentiometer producing a raw 0..1023 reading. It is not — `@wokwi/elements/analog-joystick-element` emits xValue / yValue as a tri-state DIRECTION signal: * xValue = -1 → "left" (mousedown on left zone) * xValue = 0 → centered (mouseup snap-back) * xValue = +1 → "right" (mousedown on right zone) (same for yValue with up/down) `(±1) / 1023 ≈ ±0.001`, so the ADC channel sat at ~0 V no matter which directional zone was clicked. Center-button clicks worked because that path is digital (`setPinState(SEL, …)`) and bypasses the analog map. Fix: * Tri-state → voltage with explicit map: -1 → 0V, 0 → Vcc/2, +1 → Vcc. * Vcc was hardcoded to 5V for "not RP2040" — wrong for ESP32 / S3 / Nano-ESP32 / etc., which all run at 3.3V like the Pi Pico. Detect ESP32 via the BridgeShim's `setAdcVoltage` method and select 3.3V for everything that isn't pure AVR. Reported on /example/esp32-joystick where center-button-only worked but directional zones did nothing. Verification via Chrome MCP after deploy. --- frontend/src/simulation/parts/ComplexParts.ts | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/frontend/src/simulation/parts/ComplexParts.ts b/frontend/src/simulation/parts/ComplexParts.ts index bfaa05aa..25d2cce9 100644 --- a/frontend/src/simulation/parts/ComplexParts.ts +++ b/frontend/src/simulation/parts/ComplexParts.ts @@ -217,9 +217,17 @@ PartSimulationRegistry.register('analog-joystick', { const pinSW = getArduinoPinHelper('SEL') ?? getArduinoPinHelper('SW'); const el = element as any; - // RP2040 uses 3.3V reference; AVR uses 5V - const vcc = avrSimulator instanceof RP2040Simulator ? 3.3 : 5.0; + // wokwi-analog-joystick exposes xValue/yValue as DIRECTION (-1 / 0 / +1), + // not pot-style 0..1023. See @wokwi/elements analog-joystick-element.js: + // arrow-zone clicks call mousedown(e, dx, dy) where dx,dy ∈ {-1, 0, +1}; + // mouseup snaps back to 0. Map that tri-state to an ADC voltage: + // -1 → 0 V | 0 → VCC/2 (center) | +1 → VCC + // AVR uses 5 V; everything else (RP2040, ESP32, ESP32-S3, …) runs at 3.3 V. + const isAvr = !(avrSimulator instanceof RP2040Simulator) + && typeof (avrSimulator as any).setAdcVoltage !== 'function'; + const vcc = isAvr ? 5.0 : 3.3; const centerV = vcc / 2; + const dirToVolts = (d: number) => ((Math.max(-1, Math.min(1, d)) + 1) / 2) * vcc; // Initialize to center position and button not pressed if (pinX !== null) setAdcVoltage(avrSimulator, pinX, centerV); @@ -227,14 +235,11 @@ PartSimulationRegistry.register('analog-joystick', { if (pinSW !== null) avrSimulator.setPinState(pinSW, true); // HIGH = not pressed const onMove = () => { - // xValue / yValue are 0-1023 if (pinX !== null) { - const vx = ((el.xValue ?? 512) / 1023.0) * vcc; - setAdcVoltage(avrSimulator, pinX, vx); + setAdcVoltage(avrSimulator, pinX, dirToVolts(Number(el.xValue ?? 0))); } if (pinY !== null) { - const vy = ((el.yValue ?? 512) / 1023.0) * vcc; - setAdcVoltage(avrSimulator, pinY, vy); + setAdcVoltage(avrSimulator, pinY, dirToVolts(Number(el.yValue ?? 0))); } };