const int PIN_JX = 26; // X-axis: ADC0 (GP26)
const int PIN_JY = 27; // Y-axis: ADC1 (GP27)
const int PIN_BTN = 22; // Button: Digital GPIO
// === LED Definition - Cross-board Compatible ===
#ifndef LED_BUILTIN
#define LED_BUILTIN 25 // Fallback for original Pico/Pico 2
#endif
// === ADC Configuration ===
const int ADC_BITS = 12; // RP2040 supports 12-bit ADC
const int ADC_MAX = 4095; // Max value for 12-bit
const int ADC_CENTER = ADC_MAX / 2; // ~2048
const int CENTER_THRESHOLD = 200; // Deadzone around center
void setup() {
// Initialize Serial1 for debugging
Serial1.begin(115200);
while (!Serial1); // Wait for native USB Serial1 connection
// ⚠️ CRITICAL: Set ADC resolution to 12-bit for full range
analogReadResolution(ADC_BITS);
// Configure button with internal pull-up resistor
pinMode(PIN_BTN, INPUT_PULLUP);
// Configure onboard LED (compatible with all Pico variants)
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW); // Start with LED OFF
Serial1.println("🎮 Joystick Initialized - Raspberry Pi Pico (Arduino)");
Serial1.printf("ADC Resolution: %d-bit (Range: 0-%d)\n", ADC_BITS, ADC_MAX);
Serial1.println("Move joystick or press button to see values...");
}
void loop() {
// Read analog axes (12-bit: 0-4095 after analogReadResolution(12))
int xVal = analogRead(PIN_JX);
int yVal = analogRead(PIN_JY);
// Read button state (LOW = pressed, due to INPUT_PULLUP)
bool btnPressed = (digitalRead(PIN_BTN) == LOW);
// Calculate direction with deadzone filtering
String xDir = getDirection(xVal, "X");
String yDir = getDirection(yVal, "Y");
// Output to Serial1 Monitor
Serial1.print("X: "); Serial1.print(xVal); Serial1.print(" ("); Serial1.print(xDir); Serial1.print(") | ");
Serial1.print("Y: "); Serial1.print(yVal); Serial1.print(" ("); Serial1.print(yDir); Serial1.print(") | ");
Serial1.print("Button: "); Serial1.println(btnPressed ? "PRESSED" : "Released");
// Visual feedback: Toggle onboard LED on button press
digitalWrite(LED_BUILTIN, btnPressed ? HIGH : LOW);
delay(100); // Polling interval
}
// Helper: Determine direction with deadzone to ignore drift
String getDirection(int value, String axis) {
if (abs(value - ADC_CENTER) < CENTER_THRESHOLD) {
return "CENTER";
} else if (value < ADC_CENTER) {
return (axis == "X") ? "LEFT" : "DOWN";
} else {
return (axis == "X") ? "RIGHT" : "UP";
}
}