fix(joystick): map wokwi-analog-joystick direction (-1/0/+1) to ADC voltage

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.
This commit is contained in:
David Montero 2026-05-22 18:57:11 +02:00
parent dccb70aacd
commit e6fdd54ba3
1 changed files with 12 additions and 7 deletions

View File

@ -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)));
}
};