Arduino Uno에서 조이스틱 모듈을 테스트해봤습니다.
테스트에 사용한 보드는 Arduino Uno R4 WiFi이지만 코드를 봤을땐 Arduino Uno 이전 버전에서도 문제 없이 동작할 듯합니다.
2025. 11. 9 최초작성
테무에서 아두이노 키트를 엄청 싸게(만원대로) 구입한 후, 잊고 지내다가 이제서야 하나씩 꺼내서 테스트해보려고 합니다.
아무런 정보 없이 아두이노 키트만 받은거라 어떻게 진행할까 하다가 구글 렌즈로 확인해보니 조이스틱 모듈이라고 알려주는 군요.

클로드에게 조이스틱 배열의 핀배열을 설명해주고 아두이노 우노와 연결을 어떻게 해야 하는지와 작동시킬 코드를 받았습니다.
어떤 결과가 예상되는 지도 알려주네요. 클로드의 예상대로 동작했습니다.
아두이노 우노와 조이스틱 모듈을 다음처럼 연결합니다.

다음 코드를 아두이노 우노에 업로드합니다.
// 조이스틱 핀 설정 const int VRX_PIN = A0; // X축 아날로그 입력 const int VRY_PIN = A1; // Y축 아날로그 입력 const int SW_PIN = 2; // 스위치 디지털 입력
void setup() { // 시리얼 통신 시작 Serial.begin(9600); // 스위치 핀을 입력 풀업으로 설정 pinMode(SW_PIN, INPUT_PULLUP); Serial.println("조이스틱 테스트 시작!"); Serial.println("========================"); }
void loop() { // 아날로그 값 읽기 (0-1023) int xValue = analogRead(VRX_PIN); int yValue = analogRead(VRY_PIN); // 스위치 상태 읽기 (LOW = 눌림, HIGH = 안눌림) int swState = digitalRead(SW_PIN); // 시리얼 모니터에 출력 Serial.print("X축: "); Serial.print(xValue); Serial.print(" | Y축: "); Serial.print(yValue); Serial.print(" | 스위치: "); if (swState == LOW) { Serial.println("눌림"); } else { Serial.println("안눌림"); } // 방향 판단 (선택사항) if (xValue < 400) { Serial.println(" → 왼쪽"); } else if (xValue > 600) { Serial.println(" → 오른쪽"); } if (yValue < 400) { Serial.println(" → 아래"); } else if (yValue > 600) { Serial.println(" → 위"); } Serial.println("------------------------"); delay(200); // 200ms 대기 } |
보드에 인쇄된 글자가 정방향이 된 상태에서 시리얼 모니터에서 확인합니다.
초기상태는 X축, Y축 모두 500 근처에서 값이 변화합니다. 아날로그 센서라서 어쩔 수 없는 듯합니다.

조이스틱을 위로 올리니
X축은 500 근처 값이 출력되고 Y축이 0이 됩니다. 보드에 인쇄된 글자와 달리 위아래가 바뀌어 있는 듯합니다.
조이스틱을 아래로 내리니
X축은 500 근처 값이 출력되고 Y축은 1000 근처 값이 출력 됩니다.
조이스틱을 왼쪽으로 이동하니
X축은 0이 되고 Y축은 500근처 값이 출력됩니다. 위아래가 뒤바뀌어 있는게 맞다 싶지만 구현에 따라 위아래가 뒤바뀔 수도 있나 싶기도합니다.
조이스틱을 오른쪽으로 이동하니
X축은 1000 근처 값이 출력되고 Y축은 500근처 값이 출력됩니다.
조이스틱을 수직으로 꾹 누르면 스위치가 눌림으로 출력됩니다.
이번엔 조이스틱으로 파이썬 프로그램의 노랑원을 움직이도록 해봅니다.
아두이노 우노에 다음 코드를 업로드합니다.
const int VRX_PIN = A0; const int VRY_PIN = A1; const int SW_PIN = 2;
void setup() { Serial.begin(9600); pinMode(SW_PIN, INPUT_PULLUP); }
void loop() { int xValue = analogRead(VRX_PIN); int yValue = analogRead(VRY_PIN); int swState = digitalRead(SW_PIN); // 데이터를 쉼표로 구분하여 전송 Serial.print(xValue); Serial.print(","); Serial.print(yValue); Serial.print(","); Serial.println(swState); delay(50); // 50ms 간격 } |
시리얼 모니터에 다음처럼 파이썬 코드에서 파싱하기 좋게 조이스틱 모듈의 값이 출력됩니다.

이제 다음 파이썬 코드를 실행하여 테스트해봅니다.
시리얼로 넘어온(USB 선이지만) 데이터를 파이썬 코드에서 사용하여 노랑색원의 위치를 변경하는데 사용합니다.
다음 패키지를 설치해야합니다.
pip install pygame pyserial
코드에서 다음 부분은 아두이노 IDE에서 확인된 포트로 변경한 후, 아두이노 IDE를 종료합니다.
SERIAL_PORT = 'COM3'
import pygame import serial import sys
# 시리얼 포트 설정 (본인의 포트로 변경하세요) # Windows: 'COM3', 'COM4' 등 # Mac/Linux: '/dev/ttyUSB0', '/dev/cu.usbmodem14101' 등 SERIAL_PORT = 'COM3' # 본인의 포트로 변경! BAUD_RATE = 9600
# Pygame 초기화 pygame.init()
# 화면 설정 WIDTH, HEIGHT = 800, 600 screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("조이스틱 제어 - 노란색 원")
# 색상 정의 BLACK = (0, 0, 0) YELLOW = (255, 255, 0)
# 원의 초기 위치 및 크기 circle_x = WIDTH // 2 circle_y = HEIGHT // 2 circle_radius = 20
# 이동 속도 speed = 5
# 시리얼 포트 연결 try: ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1) print(f"시리얼 포트 {SERIAL_PORT} 연결 성공!") except Exception as e: print(f"시리얼 포트 연결 실패: {e}") print("포트 이름을 확인하세요!") sys.exit(1)
# 게임 루프 clock = pygame.time.Clock() running = True
print("프로그램 시작! 조이스틱으로 노란색 원을 움직여보세요.")
while running: # 이벤트 처리 for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # 시리얼 데이터 읽기 if ser.in_waiting > 0: try: line = ser.readline().decode('utf-8').strip() data = line.split(',') if len(data) == 3: x_value = int(data[0]) # 0-1023 y_value = int(data[1]) # 0-1023 sw_state = int(data[2]) # 0 or 1 # 조이스틱 값을 방향으로 변환 # X축: 왼쪽(0) ~ 중앙(512) ~ 오른쪽(1023) if x_value < 400: # 왼쪽 circle_x -= speed elif x_value > 600: # 오른쪽 circle_x += speed # Y축: 위(0) ~ 중앙(512) ~ 아래(1023) # 조이스틱을 위로 움직이면 y_value가 작아지고, 화면에서 위로 이동 if y_value < 400: # 조이스틱 위 -> 화면 위 circle_y -= speed elif y_value > 600: # 조이스틱 아래 -> 화면 아래 circle_y += speed # 스위치를 누르면 중앙으로 리셋 if sw_state == 0: # 눌림 circle_x = WIDTH // 2 circle_y = HEIGHT // 2 print("위치 리셋!") # 화면 경계 체크 circle_x = max(circle_radius, min(WIDTH - circle_radius, circle_x)) circle_y = max(circle_radius, min(HEIGHT - circle_radius, circle_y)) except Exception as e: pass # 데이터 파싱 오류 무시 # 화면 그리기 screen.fill(BLACK) pygame.draw.circle(screen, YELLOW, (int(circle_x), int(circle_y)), circle_radius) # 화면 업데이트 pygame.display.flip() clock.tick(60) # 60 FPS
# 종료 ser.close() pygame.quit() print("프로그램 종료") |
조이스틱을 이동해보면 직선 방향은 괜찮지만 원을 그리면 좀 어색해보입니다.
동작 영상은 다음 유튜브 영상에서 확인하세요.
https://www.youtube.com/shorts/v6stv3ronhU