728x90
반응형

에어 마우스: https://jinho-study.tistory.com/247

 

아두이노 에어 마우스(자이로센서)

2019년 창의적 종합설계 경진대회 때 만들었던 에어 마우스이다. 하루면 만들 수 있는 작품인데, 알 수 없는 통신에러 때문에 몇 주일을 날렸었다. 알고 보니 핀 문제였는데 각 핀마다 어느 정도 �

jinho-study.tistory.com

에어 마우스에서 필요 없는 기능만(민감도 조절) 빼면 바로 완성이다. 

그렇기 때문에 새로운 코드는 없다.

#include<Wire.h> // 통신? 때문에 필요
#include<Mouse.h> // 마우스 움직여야지!

/*
 SDA 2번 Pin, SCL 3번 Pin
 Int 7번 Pin
 Int 무조건 박아야됨. 
 */
 
#define MPU6050_INT_PIN 7 // 레오나르도에서는 무조건 박아주자

#define MPU6050_INT digitalPinToInterrupt(MPU6050_INT_PIN)

const int MPU_addr=0x68;  // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;

void setup()
{
  // 설정인데 안 건드는게 좋음. 잘 되있음.
  Serial.begin(9600);

  Serial.println("start");
  Serial.print(MPU6050_INT); Serial.print(" on pin "); Serial.print(MPU6050_INT_PIN);
  
  Wire.begin();
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  pinMode(10, INPUT); // 좌클릭 버튼
  pinMode(11, INPUT); // 우클릭 버튼
  Mouse.begin();
  pinMode(MPU6050_INT, INPUT);
  //attachInterrupt(MPU6050_INT, dmpDataReady, RISdlfhgk62ING);
}

void loop()
{
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr,14,true);  // request a total of 14 registers
  AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)     
  AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  Tmp=Wire.read()<<8|Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
  GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
  GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
  GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
  // 여기 위까지는 코드 건들지 않는 걸 추천. 여기 아래부터 수정 ㄱㄱ

  int lb = digitalRead(10); // 1이면 누른 상태, 0이면 안 누른 상태임.
  int rb = digitalRead(11); // 위와 마찬가지
  
  float gyroY, gyroZ;
  int sens = 1100;
  gyroZ = GyZ / sens;
  gyroY = -GyY / sens;

if(lb == 1) // Left button이 1이라는건 좌클릭을 하고 있다는 상태이므로 
  {                                       // 마우스를 누른 상태로 유지시켜주는 Mouse.press()를 사용함.
    Mouse.press(); // 좌클릭 한 상태 유지
  }
  if (rb == 1) // 우클릭
  {
    Mouse.press(MOUSE_RIGHT);
  } 
  if (lb == 0) 
  {
    Mouse.release(); //클릭 상태 해제
  }
   if (rb == 0) 
  {
    Mouse.release(MOUSE_RIGHT); //클릭 상태 해제
  }

  Sprint1(gyroY, gyroZ, lb, rb);
  Mouse.move(gyroZ, gyroY); // 마우스를 움직이는 함수
}

void Sprint1(int gyroY, int gyroZ, int lb, int rb) // 자이로, 버튼 값 확인용 시리얼 프린트 함수
{
  Serial.print("X축: "); 
  Serial.print(gyroZ);
  Serial.print(" // Y축: "); 
  Serial.print(-gyroY);
  Serial.print(" // 좌 클릭: ");
  Serial.print(lb);
  Serial.print(" // 우 클릭: ");
  Serial.println(rb);
}

필요한 재료는 다이소에서 파는 2000원? 짜리 장난감 총, 인두기, 접착제 정도이다. 

1. 장난감 총을 완전히 분해한다.

2. 방아쇠 부분과 손잡이 옆쪽 부분을 인두기로 뚫고 그 구멍 사이에 각각 버튼이 삐죽 튀어나도록 붙인다.

3. 손잡이 아래부분에 구멍을 뚫고, 점퍼선들을 잘 정리해서 그 구멍에서 빼냄.

4. 다시 조립하면 완성!

탕탕탕
728x90
반응형

'Projects > 에어 마우스' 카테고리의 다른 글

아두이노 에어 마우스(자이로센서)  (0) 2020.06.20
아두이노 조이스틱 마우스  (0) 2020.06.19
728x90
반응형

2019년 창의적 종합설계 경진대회 때 만들었던 에어 마우스이다. 

하루면 만들 수 있는 작품인데, 알 수 없는 통신에러 때문에 몇 주일을 날렸었다. 

알고 보니 핀 문제였는데 각 핀마다 어느 정도 정해진 역할 같은 것이 있는 건 알고 있었지만 

이런 식으로 통신에서 오류가 날줄은 몰랐다. 덕분에 큰 깨달음을 얻었다.. ㅜㅜ

 

시연 영상

시연 영상이다. 

사실 단순하게 자이로 센서와 버튼 센서만 있으면 되는 작품이지만 뭔가 내용이 너무 모자란 것 같아 민감도 설정 기능을 추가했다.

그리고 발표날에 사람들이 우리 작품 많이 보고 갔으면 좋겠다는 생각에 다이소 2000원짜리 장난감 총과

에어 마우스를 합체시킨 에어 건? 을 만들었고 이걸로 발표날 아침부터 부스에서 배틀그라운드를 했다.

학생들에게는 반응은 매우 좋았지만, 교수님들에게는 작품이 좀 애매한 것 같다?라는 평을 많이 들었다. 

몸으로는 그 말이 이해가 됐는데 지금 말로 설명하려니 좀 어려운 것 같다.

그래도 다행히 동상이라도 받았기에, 좋은 경험이었던 것 같다. 

#include<Wire.h> // 통신 때문에 필요
#include<Mouse.h> // 마우스 움직여야지!

/*
 SDA 2번 Pin, SCL 3번 Pin, Int 7번 Pin
 Int 무조건 박아야됨. 
*/
 
#define MPU6050_INT_PIN 7 // 레오나르도에서는 무조건 7번 Pin에 박아주자
#define MPU6050_INT digitalPinToInterrupt(MPU6050_INT_PIN)

const int MPU_addr=0x68;  // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;

//민감도 조절 변수
int timer1 = 0;
int sens = 1100; // sens_num = 3
int sens_num = 3; // sens = 1100;

int Led1 = 9;
int Led2 = 10;
int Led3 = 11;
int Led4 = 12;
int Led5 = 13;

void setup()
{
  // 설정인데 안 건드는게 좋음. 잘 되있음.
  Serial.begin(9600);
  Serial.println("start");
  Serial.print(MPU6050_INT); Serial.print(" on pin "); Serial.print(MPU6050_INT_PIN);
  
  Mouse.begin();

  Wire.begin();
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  
  pinMode(4, INPUT); // 좌클릭 버튼
  pinMode(8, INPUT); // 우클릭 버튼
  pinMode(MPU6050_INT, INPUT);
  
  //attachInterrupt(MPU6050_INT, dmpDataReady, RISdlfhgk62ING);
  pinMode(Led1, OUTPUT);
  pinMode(Led2, OUTPUT);
  pinMode(Led3, OUTPUT);
  pinMode(Led4, OUTPUT);
  pinMode(Led5, OUTPUT);
}

void loop()
{
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr,14,true);  // request a total of 14 registers
  AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)     
  AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  Tmp=Wire.read()<<8|Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
  GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
  GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
  GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
  // 여기 위까지는 코드 건들지 않는 걸 추천. 여기 아래부터 수정 ㄱㄱ

  // 버튼의 센서값을 읽음 -> 누르면 1, 안 누르면 0
  int lb = digitalRead(4); // 좌클릭, 1이면 누른 상태, 0이면 안 누른 상태임.
  int rb = digitalRead(8); // 우클릭, 위와 마찬가지
  
  float gyroY, gyroZ;
  
  // 좌우클릭을 동시에 함 
  if (lb == 1 && rb == 1) {
    ++timer1;
    delay(20);
    // 1초 동안 동시에 좌우클릭 -> 민감도 설정 모드
    if (timer1 > 50) {
      Serial.println("민감도 설정 모드\n");
      delay(500); // 이거 없으면 민감도 설정 모드 바로 탈출하게 됨. 꼭 필요함.
      Serial.print("민감도:  ");
      Serial.println(sens_num);
      
      while(1) { 
        lb = digitalRead(4); // 좌클릭 
        rb = digitalRead(8); // 우클릭

        // 민감도 설정 모드 안에서 한번 더 좌우 클릭을 동시에 한 경우 
        if(lb == 1 && rb == 1) { 
          break; // 민감도 설정 모드 탈출 
        }        
        
        else if(lb == 0 && rb == 1) { 
          if(sens_num > 1) { 
            --sens_num; //분모가 커지니까 gyro값 작아짐 >> 민감도 작아짐  
            Serial.print("민감도:  ");
            Serial.println(sens_num);
            delay(500);
          }
        }
        
        else if(lb == 1 && rb == 0) {
          if(sens_num < 5) { 
            ++sens_num; //분모가 작아지니까 gyro값 커짐 >> 민감도 커짐
            Serial.print("민감도:  ");
            Serial.println(sens_num);
            delay(500);
          }    
        }
        
        switch(sens_num) {
           case 5: sens = 820; Sens_Led_On(sens_num); break;
           case 4: sens = 850; Sens_Led_On(sens_num); break;
           case 3: sens = 1100; Sens_Led_On(sens_num); break;
           case 2: sens = 1220; Sens_Led_On(sens_num); break;
           case 1: sens = 1380; Sens_Led_On(sens_num); break;
           default: break;
        }
        //Sprint2(timer1, sens, sens_num);
      }
      timer1 = 0;
      Serial.println("\n민감도 설정 완료!");
      Serial.print("현재 민감도: ");
      Serial.println(sens_num);     
      delay(500);
    }
  }
  // 좌우클릭을 1초 동안 하지 않은 경우
  else { 
    timer1 = 0; // timer1 변수 값 0으로 초기화
  }
  
  gyroZ = GyZ / sens;  // X축
  gyroY = -GyY / sens; // Y축
  
  // lb 가 1 -> 좌클릭을 한 경우
  if(lb == 1)  {
    // 마우스를 누른 상태로 유지시켜주는 Mouse.press()를 사용함.           
    Mouse.press(); // 좌클릭 한 상태 유지
  }

  // rb 가 1 -> 우클릭을 한 경우
  else if (rb == 1) {
    Mouse.click(MOUSE_RIGHT); // 우클릭
    delay(200);
  } 

  // 좌우클릭 둘 다 안했으므로 클릭 상태 해제
  else if (lb == 0 && rb == 0) {
    Mouse.release(); //클릭 상태 해제
  }

  Sprint1(gyroY, gyroZ, lb, rb); // 센서 값을 출력해줌
  //digitalWrite(8 + sens_num, HIGH); // 민감도에 대응되는 LED를 킴
  Mouse.move(gyroZ, gyroY); // 마우스를 움직여주는 함수
}

// 민감도에 따른 LED On/Off 함수
void Sens_Led_On(int sens_num) 
{
  // 우선 다 끄고 시작함
  digitalWrite(Led1, LOW);
  digitalWrite(Led2, LOW);
  digitalWrite(Led3, LOW);
  digitalWrite(Led4, LOW);
  digitalWrite(Led5, LOW);
  
  /*
  민감도에 대응되는 LED 하나만 켜야 됨.  
  8 + sens_num --> Led1,2,3,4,5 에 대응되는 9, 10, 11, 12, 13번 핀을 의미
  Example) Sens_num이 3일 때 8 + sens_num은 11 즉 Led3을 키게 된다. 
  다른 4가지 경우도 똑같이 작동함. 
  */
  digitalWrite(8 + sens_num, HIGH); // Led On
}

// 센서 값을 출력해줌는 함수(자이로, 버튼)
void Sprint1(int gyroY, int gyroZ, int lb, int rb)
{
  Serial.print("X축: "); 
  Serial.print(gyroZ);
  Serial.print(" // Y축: "); 
  Serial.print(-gyroY);
  Serial.print(" // 좌 클릭: ");
  Serial.print(rb);
  Serial.print(" // 우 클릭: ");
  Serial.println(lb);
}

 

대략적인 설명은 코드 안에 주석을 달아놓은 것 같다. 

조이스틱 마우스와 마찬가지로 에어 마우스도 아두이노 우노에서는 동작하지 않는다. 

무조건 레오나르도여야 된다. 

Loop 시작부터 GyZ=Wire.read()<<8 부분까지는 건들지 않는 게 좋을 것 같고

그 아래부터는 원하는 본인이 원하는 대로 바꿔서 사용하면 될 것 같다.  

github: https://github.com/kimjinho1/Air_Mouse/blob/master/Air_Mouse_V2_%2B.ino

 

kimjinho1/Air_Mouse

2019 Incheon University(INU) Capstone Design. Contribute to kimjinho1/Air_Mouse development by creating an account on GitHub.

github.com

조이스틱 마우스: https://jinho-study.tistory.com/246

 

아두이노 조이스틱 마우스

에어 마우스를 만들기 전에 만들었던 조이스틱 마우스이다.  /* 버튼 코드 참조: https://kikiai.tistory.com/29 마우스 코드 참조: https://www.arduino.cc/reference/ko/language/functions/usb/mouse/mousemov..

jinho-study.tistory.com

728x90
반응형

'Projects > 에어 마우스' 카테고리의 다른 글

아두이노 에어 마우스로 총게임 하기  (6) 2020.06.20
아두이노 조이스틱 마우스  (0) 2020.06.19
728x90
반응형

에어 마우스를 만들기 전에 만들었던 조이스틱 마우스이다.  

/* 버튼 코드 참조: https://kikiai.tistory.com/29
   마우스 코드 참조: https://www.arduino.cc/reference/ko/language/functions/usb/mouse/mousemove/
   위의 링크에 마우스 관련 함수 다 설명되있음. 
   조이스틱 코드 참조: http://blog.naver.com/PostView.nhn?blogId=boilmint7&logNo=220927175653
   조이스틱에도 버튼이 있지만 사용하기 힘들어서 안썼음.

   버튼: 핀 4개 있는데 2개 버리고 2개중 하나에 +5V, 하나는 그라운드랑 Pin2에 박으면 됨.
   
   조이스틱: 그라운드랑 +5V는 말 그대로 그라운드랑 +5V에 연결 
   VRX, VRY 는 각각 A0, A1에 연결함. 나는 조이스틱핀이 아래를 보는 방향으로 구현해서 x, y축이 바뀜.
   그래서 아래 코드 보면 A0, A1 순서가 다름. 
*/


#include <Mouse.h> // 마우스 헤더(레오나르도가 아니면 라이브러리 깔아도 오류 뜸!, 무조건 레오나르도로 ㄱㄱ)

void setup() {
  pinMode(2, INPUT); // 좌클릭 버튼
  pinMode(4, INPUT); // 우클릭 버튼
  Mouse.begin(); // 마우스 제어 시작
  Serial.begin(9600); //시리얼 통신을 시작
}

void loop() {/* 다 다르겠지만 나는 조이스틱 초기 값이 x: 517, y: 506 정도였음. 이게 의미하는건 
                중심 좌표가 (512, 512) 쯤이라는건데, 사용하기 불편하므로 중심을 (0, 0)로 만들었다. 
                200을 나눈건 마우스가 너무 큰 범위로 움직이게 되기 때문에 크기를 줄여줬다.*/
  int x = (analogRead(A1) - 517) / 260; /* 나누는 값은 맘대로 바꿔도 된다. 다만 500이 넘어가면 마우스가 움직이지 않게 된다.
                                         왜냐하면 (analogRead(A1) - 517)의 최대값이 500정도 되는데, 거기에 500을 나눠버리면 0이 되기 때문*/
  int y = - (analogRead(A0) - 506) / 260; /* 조이스틱을 위로 올리면 같이 +가 되야 되는데,
                                             -가 되길래 그냥 -곱해줬다.*/
  int Left_button = digitalRead(2); // 1이면 누른 상태, 0이면 안 누른 상태임.
  int Right_button = digitalRead(4); // 위와 마찬가지
  Sprint(x, y, Left_button, Right_button); // 시리얼 프린트
  
  if (Left_button == 1) // Left button이 1이라는건 좌클릭을 하고 있다는 상태이므로 마우스를 누른 상태로 유지시켜주는 Mouse.press()를 사용함
  {
    Mouse.press(MOUSE_LEFT); // 좌클릭 한 상태 유지
  }
  else if (Left_button == 0 && Right_button == 0) 
  {
    Mouse.release(); //클릭 상태 해제
  }
  else if (Right_button == 1) // 우클릭
  {
    Mouse.click(MOUSE_RIGHT);
  } 
  Mouse.move(x, y); // 마우스를 움직이는 함수
}

// 루프안에 여러줄 있는거 꼴보기 싫어서 함수로 만듬. 별 의미 없음.
void Sprint(int x, int y, int lb, int rb) 
{
  Serial.print("X: ");
  Serial.print(x);
  Serial.print(' ');
  Serial.print("Y: ");
  Serial.print(-y); // 시리얼프린트에 -로 출력되길래 부호 바꿔줌.
  Serial.print(' ');
  Serial.print("Left_button: ");
  Serial.print(lb);
  Serial.print(' ');
  Serial.print("Rigft_button: ");
  Serial.println(rb);
}

 

대략적인 설명은 코드 안에 주석을 달아놓은 것 같다. 

아두이노 우노로는 마우스를 제어할 수가 없다. 무조건 레오나르도여야 한다.

github: https://github.com/kimjinho1/Air_Mouse/blob/master/Joystick_Mouse.ino

 

kimjinho1/Air_Mouse

2019 Incheon University(INU) Capstone Design. Contribute to kimjinho1/Air_Mouse development by creating an account on GitHub.

github.com

728x90
반응형

+ Recent posts