2014년 2월 13일 목요일

자이로센서(MPU 6050) - 블루투스를 이용한 자동차 키트 + 안드로이드 컨트롤러


---------------------------------------------------------------------------------

자동차 키드에서 가장 필요할거 같지만 저는 결국 활용을 못한 센서입니다.
MPU 6050 - 자이로+가속도 센서


MPU 6000,6050 datasheet

가속도계랑 자이로센서, 온도계가 있는데요  SDA (data line) and SCL (clock line)라는 선을 이용합니다. Arduino Uno와 같은 다른 Arduino에서는 따로 구분이 안되어 있어 그냥 사용 하면 되지만 Arduino 2560 Mega에서는 정해진 SCL,SDA선에 연결을 해야 하더군요. 그래서 별거 아닌데 몇 시간을 잡아 먹었습니다. ㅠ 



Arduino 2560 Mega

2560Mega에서는 20,21번에 연결하면 된다는 것을 알수 있습니다.
제가 고생하면서 다른곳에 연결한(고의x ㅠ) 결과, 센서의 결과값들이 상당히 튀면서 값이 들어오는 것을 알 수 있었습니다. 사용하는 방법을 찾아봤었는데 다른 곳에서는 INT를 사용하는 사용하지만, 센서값을 읽어오는 목적에서는 문제가 없습니다.

위의 MPU 6050의 pdf를 읽어보면 3.3v를 사용한다는 것을 알 수 있습니다.

위의 내용를 정리하여 정리하면
VCC는 3.3v, GND는 GND
SCL은 21, SDA는 20번
에 연결을 하면 되겠습니다.



아두이노의 스케치를 살펴보겠습니다.

출처는 아마.. 플레이아두이노 였던것으로 기억합니다.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#define MPU6050_ACCEL_XOUT_H 0x3B // R
#define MPU6050_PWR_MGMT_1 0x6B // R/W
#define MPU6050_PWR_MGMT_2 0x6C // R/W
#define MPU6050_WHO_AM_I 0x75 // R
#define MPU6050_I2C_ADDRESS 0x68
....
typedef union accel_t_gyro_union
{
  struct
  {
    uint8_t x_accel_h;
    uint8_t x_accel_l;
    uint8_t y_accel_h;
    uint8_t y_accel_l;
    uint8_t z_accel_h;
    uint8_t z_accel_l;
    uint8_t t_h;
    uint8_t t_l;
    uint8_t x_gyro_h;
    uint8_t x_gyro_l;
    uint8_t y_gyro_h;
    uint8_t y_gyro_l;
    uint8_t z_gyro_h;
    uint8_t z_gyro_l;
  }
  reg;
  struct
  {
    int x_accel;
    int y_accel;
    int z_accel;
    int temperature;
    int x_gyro;
    int y_gyro;
    int z_gyro;
  }
  value;
};
...

void setup(){
  ...
  error = MPU6050_read (MPU6050_WHO_AM_I, &c, 1);
  Serial.print(F("WHO_AM_I : "));
  Serial.print(c,HEX);
  Serial.print(F(", error = "));
  Serial.println(error,DEC);
  error = MPU6050_read (MPU6050_PWR_MGMT_2, &c, 1);
  Serial.print(F("PWR_MGMT_2 : "));
  Serial.print(c,HEX);
  Serial.print(F(", error = "));
  Serial.println(error,DEC);
  MPU6050_write_reg (MPU6050_PWR_MGMT_1, 0);
  ...
}


void loop(){
........
    int error;
    double dT;
    accel_t_gyro_union accel_t_gyro;
    Serial.println(F(""));
    Serial.println(F("MPU-6050"));
    // Read the raw values.
    // Read 14 bytes at once,
    // containing acceleration, temperature and gyro.
    // With the default settings of the MPU-6050,
    // there is no filter enabled, and the values
    // are not very stable.
    error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro));
    Serial.print(F("Read accel, temp and gyro, error = "));
    Serial.println(error,DEC);
    // Swap all high and low bytes.
    // After this, the registers values are swapped,
    // so the structure name like x_accel_l does no
    // longer contain the lower byte.
    uint8_t swap;
#define SWAP(x,y) swap = x; x = y; y = swap
    SWAP (accel_t_gyro.reg.x_accel_h, accel_t_gyro.reg.x_accel_l);
    SWAP (accel_t_gyro.reg.y_accel_h, accel_t_gyro.reg.y_accel_l);
    SWAP (accel_t_gyro.reg.z_accel_h, accel_t_gyro.reg.z_accel_l);
    SWAP (accel_t_gyro.reg.t_h, accel_t_gyro.reg.t_l);
    SWAP (accel_t_gyro.reg.x_gyro_h, accel_t_gyro.reg.x_gyro_l);
    SWAP (accel_t_gyro.reg.y_gyro_h, accel_t_gyro.reg.y_gyro_l);
    SWAP (accel_t_gyro.reg.z_gyro_h, accel_t_gyro.reg.z_gyro_l);
    dT = ( (double) accel_t_gyro.value.temperature + 12412.0) / 340.0;

...........
}


int MPU6050_read(int start, uint8_t *buffer, int size)
{
  int i, n, error;
  Wire.beginTransmission(MPU6050_I2C_ADDRESS);
  n = Wire.write(start);
  if (n != 1)
    return (-10);
  n = Wire.endTransmission(false); // hold the I2C-bus
  if (n != 0)
    return (n);
  // Third parameter is true: relase I2C-bus after data is read.
  Wire.requestFrom(MPU6050_I2C_ADDRESS, size, true);
  i = 0;
  while(Wire.available() && i<size)
  {
    buffer[i++]=Wire.read();
  }
  if ( i != size)
    return (-11);
  return (0); // return : no error
}
int MPU6050_write(int start, const uint8_t *pData, int size)
{
  int n, error;
  Wire.beginTransmission(MPU6050_I2C_ADDRESS);
  n = Wire.write(start); // write the start address
  if (n != 1)
    return (-20);
  n = Wire.write(pData, size); // write data bytes
  if (n != size)
    return (-21);
  error = Wire.endTransmission(true); // release the I2C-bus
  if (error != 0)
    return (error);
  return (0); // return : no error
}
int MPU6050_write_reg(int reg, uint8_t data)
{
  int error;
  error = MPU6050_write(reg, &data, 1);
  return (error);
}
위와 같이 작성한 결과를 통해

accel_t_gyro.value.temperature
accel_t_gyro.value.x_accel
accel_t_gyro.value.y_accel
accel_t_gyro.value.z_accel
accel_t_gyro.value.x_gyro
accel_t_gyro.value.y_gyro
accel_t_gyro.value.z_gyro

위의 이름으로 값을 받을 수 있습니다.

아래 3줄이 MPU 6050으로 부터 얻은 값들입니다.
이것을 활용을 해야하는데 못하겠어요 ㅠ

그리고 실험을 해보면 값들이 흔들리는 걸 볼 수 있는데
(위 그림에서 자동차 키트는 움직이지 않았습니다.)
PWM으로 신호를 받아와서 그렇다고 합니다.

댓글 없음:

댓글 쓰기