/* * JoystickBridge.ino — Arduino Uno <-> Godot (ArduinoGodot/Main.gd) * * Talks plain serial lines to the UDP<->serial bridge process, which forwards * telemetry to Godot on UDP 4242 and relays LED commands from UDP 4243. * * PROTOCOL (must match Main.gd) * OUT (Uno -> host): "x,y,btn\n" raw 10-bit ADC, e.g. "512,498,1" * btn = 1 when the stick's push-button is pressed. * IN (host -> Uno): "L1" = LED on, "L0" = LED off (newline optional) * * WIRING (KY-023 2-axis analog joystick + external LED) * Joystick +5V / VCC -> 5V * Joystick GND -> GND * Joystick VRx -> A0 * Joystick VRy -> A1 * Joystick SW -> D2 (uses internal pull-up; pressed = LOW) * * LED: D13 -> 220 ohm resistor -> LED anode (+, long leg) * LED cathode (-, short leg) -> GND * (D13 is also the Uno's onboard LED, so it flashes during every upload — * a free "is this pin alive" check. 220-330 ohm keeps it near ~15 mA.) */ const uint8_t PIN_VRX = A0; // joystick X axis const uint8_t PIN_VRY = A1; // joystick Y axis const uint8_t PIN_SW = 2; // joystick push-button (active LOW) const uint8_t PIN_LED = 13; // external LED through a 220 ohm resistor (also onboard LED) const unsigned long BAUD = 115200; // must match the bridge process const unsigned long SEND_MS = 16; // ~60 Hz telemetry unsigned long lastSend = 0; char cmdBuf[8]; uint8_t cmdLen = 0; void setup() { Serial.begin(BAUD); pinMode(PIN_SW, INPUT_PULLUP); pinMode(PIN_LED, OUTPUT); digitalWrite(PIN_LED, LOW); } void loop() { handleCommands(); unsigned long now = millis(); if (now - lastSend >= SEND_MS) { lastSend = now; int x = analogRead(PIN_VRX); // 0..1023 int y = analogRead(PIN_VRY); // 0..1023 int btn = (digitalRead(PIN_SW) == LOW) // pull-up: LOW == pressed ? 1 : 0; // Godot wants 1 = pressed // "x,y,btn\n" Serial.print(x); Serial.print(','); Serial.print(y); Serial.print(','); Serial.println(btn); } } // Parse newline-terminated commands. Recognizes "L1" / "L0". void handleCommands() { while (Serial.available() > 0) { char c = Serial.read(); if (c == '\n' || c == '\r') { if (cmdLen >= 2 && cmdBuf[0] == 'L') { digitalWrite(PIN_LED, cmdBuf[1] == '1' ? HIGH : LOW); } cmdLen = 0; } else if (cmdLen < sizeof(cmdBuf) - 1) { cmdBuf[cmdLen++] = c; } else { cmdLen = 0; // overflow guard: drop the runt line } } }