이전 조이스틱 마우스 프로젝트와 유사하지만, 스마트폰 앱에 가상 조이스틱 2개를 구현해 커서 이동, 스크롤, 좌/우 클릭을 모두 트랙패드처럼 제어합니다.
작동 원리
스마트폰 앱(MIT App Inventor 제작)이 조이스틱 X/Y 값, 좌/우 클릭, 스크롤 상태를 블루투스로 전송
HC-05가 수신해 아두이노 우노로 전달
아두이노가 현재 커서 좌표(0~1279, 0~799)에 수신값을 더해 새 좌표 계산
결과 데이터(새 X, 새 Y, 클릭/스크롤 코드)를 시리얼로 출력
파이썬 스크립트(mouse, pyserial 모듈 사용)가 시리얼 읽어 마우스 액션 실행
스마트폰 앱 구조
MIT App Inventor로 제작. 메인 화면에 가상 조이스틱 2개, 클릭/스크롤 버튼 배치.
데이터 전송 프로토콜 (20ms 주기):
시작 바이트: 255 (1바이트)
조이스틱 X축 값 (1바이트)
조이스틱 Y축 값 (1바이트)
버튼/스크롤 상태 (1바이트): 1=좌클릭, 2=우클릭, 3=스크롤 다운, 4=스크롤 업
아두이노 측 처리
수신 바이트를 배열에 저장하고, 시작 바이트(255)로 패킷 동기화. 조이스틱 값(중립 약 110~120)을 감도(sensitivity=20)에 맞춰 마우스 이동량으로 매핑. 버튼 상태 변화 감지(이전 상태와 비교)로 단일 클릭 인식. 최종적으로 Serial.print("X:Y:CLICK") 형식으로 출력.
파이썬 프로그래밍
Python 3 필수. 명령 프롬프트에서:
cd <파이썬 설치 경로>
py -m pip install --upgrade pip
py -m pip install mouse
py -m pip install pyserial
파이썬 코드에서 아두이노 COM 포트 지정 후 실행. mouse.move(x, y)로 커서 이동, mouse.click(), mouse.wheel()로 클릭/스크롤 수행.
실행 순서
스마트폰에 'Bluetooth Mouse Control' 앱 설치
아두이노 스케치 업로드 및 회로 연결 (회로도 참조)
파이썬 코드에서 COM 포트 수정 후 .py 저장 → IDLE에서 실행
앱에서 HC-05와 블루투스 페어링/연결
가상 조이스틱으로 커서 제어 확인
소스 코드
아두이노 코드
int datareceived[5] = {0,0,0,0};
int in_byte = 0, array_index = 0;
int l_prev=0, r_prev=0;
int height=0, width=0;
void setup() { Serial.begin(9600); }
void loop() {
int clicks=0, sensitivity=20, xpos=0, ypos=0;
if (Serial.available() > 0) {
in_byte = Serial.read();
if (in_byte == 255) array_index = 0;
datareceived[array_index] = in_byte;
array_index++;
// 조이스틱 값 → 이동량 매핑
if (datareceived[1] >= 110) xpos = map(datareceived[1], 110, 172, 0, sensitivity);
if (datareceived[1] <= 70) xpos = map(datareceived[1], 60, 1, 0, -sensitivity);
if (datareceived[2] >= 110) ypos = map(datareceived[2], 110, 255, 0, sensitivity);
if (datareceived[2] <= 60) ypos = map(datareceived[2], 70, 1, 0, -sensitivity);
// 버튼/스크롤 처리
if (datareceived[3]==1 && l_prev==0) clicks=1;
else if (datareceived[3]==2 && r_prev==0) clicks=2;
else if (datareceived[3]==3 || datareceived[3]==4) clicks=datareceived[3];
l_prev = datareceived[3]; r_prev = datareceived[3];
// 좌표 업데이트 및 경계 제한
if (xpos||ypos||clicks) {
height += ypos; width += xpos;
height = constrain(height, 0, 799);
width = constrain(width, 0, 1279);
Serial.print(width); Serial.print(":"); Serial.print(height); Serial.print(":"); Serial.println(clicks);
}
}
}
파이썬 코드
import mouse, sys, time, serial
mouse.FAILSAFE = False
ArduinoSerial = serial.Serial('COM3', 9600) # 본인 COM 포트로 변경
time.sleep(1)
while True:
data = str(ArduinoSerial.readline().decode('ascii'))
x, y, z = data.split(":")
x, y = int(x), int(y)
mouse.move(x, y)
if '1' in z: mouse.click(button="left")
elif '2' in z: mouse.click(button="right")
elif '3' in z: mouse.wheel(delta=-1)
elif '4' in z: mouse.wheel(delta=1)