/*
Wokwi 虛擬測試:ESP32 + ILI9341 + Joystick
目的:驗證搖桿座標移動邏輯
*/
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
// --- Wokwi 腳位設定 ---
#define TFT_CS 26 // ★ ILI9341 需要 CS
#define TFT_DC 2
#define TFT_RST 4
// MOSI=23, SCK=18 (預設硬體 SPI)
// 搖桿腳位
#define JOY_X 34
#define JOY_Y 35
#define JOY_SW 25
// 建立螢幕物件
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
// 變數
int cursorX = 120;
int cursorY = 160;
int oldX = 120;
int oldY = 160;
void setup() {
Serial.begin(115200);
// 1. 初始化搖桿
pinMode(JOY_SW, INPUT_PULLUP);
// 2. 初始化螢幕
tft.begin();
tft.setRotation(3); // 轉橫向 (ILI9341 的 3 號方向通常是橫的)
tft.fillScreen(ILI9341_BLACK);
// 畫個框框
tft.drawRect(0, 0, 320, 240, ILI9341_BLUE);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.setCursor(10, 10);
tft.print("Virtual Joystick");
}
void loop() {
// --- A. 讀取模擬搖桿 ---
// Wokwi 的搖桿數值通常很標準 (中間 2048)
int xVal = analogRead(JOY_X);
int yVal = analogRead(JOY_Y);
int btnVal = digitalRead(JOY_SW);
// --- B. 顯示數值在 Serial (讓你觀察) ---
// 這裡可以驗證你的判定邏輯對不對
Serial.print("X:"); Serial.print(xVal);
Serial.print(" Y:"); Serial.print(yVal);
Serial.print(" SW:"); Serial.println(btnVal);
// --- C. 移動邏輯 (速度控制) ---
int speedX = 0;
int speedY = 0;
// 判斷 X 軸 (Wokwi 搖桿:左邊是0,右邊是4095)
if (xVal < 1000) speedX = -3; // 向左
else if (xVal > 3000) speedX = 3; // 向右
// 判斷 Y 軸 (Wokwi 搖桿:上面是0,下面是4095)
if (yVal < 1000) speedY = -3; // 向上
else if (yVal > 3000) speedY = 3; // 向下
// 更新座標
cursorX += speedX;
cursorY += speedY;
// --- D. 邊界限制 ---
if (cursorX < 10) cursorX = 10;
if (cursorX > 310) cursorX = 310;
if (cursorY < 10) cursorY = 10;
if (cursorY > 230) cursorY = 230;
// --- E. 繪圖 (只有動的時候才重畫) ---
if (cursorX != oldX || cursorY != oldY || btnVal == LOW) {
// 擦掉舊的
tft.fillCircle(oldX, oldY, 5, ILI9341_BLACK);
// 畫新的
if (btnVal == LOW) {
tft.fillCircle(cursorX, cursorY, 5, ILI9341_RED); // 按下變紅
} else {
tft.fillCircle(cursorX, cursorY, 5, ILI9341_GREEN); // 平常是綠
}
oldX = cursorX;
oldY = cursorY;
}
delay(20); // 模擬順暢度
}