정보나눔

오픈소스하드웨어 프로젝트에 대한 다양한 정보를 나누는 공간입니다.

아두이노 우노 + mpu6050 + 블루투스에 관한 질문입니다.
신기환 | 2017-02-06

아두이노 입문자로서 세가지의 제품을 통해

사람의 걸음걸이 분석을 확인할 수 있는 프로젝트를 하나 하려고합니다...

 

일단 기초적으로 공부한 것이..

아두이노와 MPU6050을 유선으로 연결하여 시리얼모니터로 x,y,z값들의 출력을 확인하였습니다.[COM3]

블루투스를 컴퓨터에 장치 추가하여 테라텀과 안드로이드로 장치가 이상없는 것을 확인하였습니다.[COM5] 

 

 

1. 유선이 아닌 외부 전원(9v)와 블루투스를 이용하여 mpu6050센서에서 받은 값을 시리얼 모니터로 확인하고 싶은데, 방법이 없을까요? 

 

2. 블루투스는 시리얼통신프로그램을 써야하는것인가요??

 

3. mpu6050+블루투스의 각각의 코드를 제가 짬뽕시켰는데, 혹시 스케치 되어 있는 코드 다운받을 곳 없나요? 정확성을 위해..

 

 

 

프로필사진

수박쨈 2017-02-06 13:52:08

1. 가능합니다.

아두이노에 블루투스 모듈을 연결하고 컴퓨터에서 장치추가로 아두이노의 블루투스를 추가합니다.

추가하면 송수신 포트가 나오는데 그 포트를 시리얼 모니터에서 확인하면 데이터를 볼 수 있습니다.

http://kocoafab.cc/tutorial/view/594 이쪽 링크의 방법을 참조하시면 이해가 좀 더 빠를거라 봅니다.

 

2. 무슨 말인지 이해를 잘 못했는데 블루투스 모듈자체가 아두이노와 시리얼통신(UART)을 하고 아두이노 또한 컴퓨터와 시리얼통신(UART)으로 데이터를 송수신합니다. 그렇기 때문에 시리얼통신프로그램으로 데이터를 확인합니다. 아두이노 모듈이 시리얼 통신이 아닌 다른 방법으로 아두이노와 통신한다면 시리얼 통신 프로그램을 사용하지는 않겠죠

 

3. 원하시는 코드를 다운받을 수 있는 곳은 찾기 힘들거 같습니다.

찾는 수고를 코딩하는데 투자하는게 더 빠를거에요...

프로필사진

신기환 2017-02-06 15:34:27

수박쨈님 질문에 대한 답변 감사합니다!
2, 3번에 대한 말씀은 다 이해했는데... 1번에 대해 잘 이해가 되지 않아 이렇게 질문을 남깁니다.

블루투스를 장치추가하여 송수신 포트까지 확인하였습니다. 블루투스 포트로 시리얼 모니터로 확인하려고 하니 아두이노 포트가 연결되어 있지 않다고 업로드 자체가 실행되지않습니다.(유선인거같은데...) 스크래치 설명으로 하기엔 어려운감이 있습니다.

프로필사진

수박쨈 2017-02-06 17:49:45

제가 이해한 질문은 아두이노는 컴퓨터와 연결하지 않고 현재 9V의 어댑터로 연결된 상태에서

컴퓨터에서 블루투스 통신으로 아두이노에서 데이터를 받아와 시리얼모니터로 출력하고 싶으신걸로 이해했는데 맞나요?

 

시리얼 모니터를 아두이노IDE에 있는것이 아닌 다른 프로그램을 써서 (예를들어 herculus와 같은 프로그램)을 보세요.

 

일단 같이 확인해 보도록 하겠습니다.

프로필사진

신기환 2017-02-06 18:44:16

 

이 소스코드를 사용하고있습니다!

#include <math.h>
#include <Wire.h>
#include <SoftwareSerial.h>


/* Bluetooth */
SoftwareSerial BTSerial(2, 3); //Connect HC-06. Use your (TX, RX) settings

/* time */
#define SENDING_INTERVAL 1000
#define SENSOR_READ_INTERVAL 50
unsigned long prevSensoredTime = 0;
unsigned long curSensoredTime = 0;

/* Data buffer */
#define ACCEL_BUFFER_COUNT 125
byte aAccelBuffer[ACCEL_BUFFER_COUNT];
int iAccelIndex = 2;

/* MPU-6050 sensor */
#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() {
    int error;
    uint8_t c;

    Serial.begin(9600);
    Wire.begin();
    BTSerial.begin(9600);  // set the data rate for the BT port

    // default at power-up:
    // Gyro at 250 degrees second
    // Acceleration at 2g
    // Clock source at internal 8MHz
    // The device is in sleep mode.
    //
    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);

    // According to the datasheet, the 'sleep' bit
    // should read a '1'. But I read a '0'.
    // That bit has to be cleared, since the sensor
    // is in sleep mode at power-up. Even if the
    // bit reads '0'.
    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);

    // Clear the 'sleep' bit to start the sensor.
    MPU6050_write_reg (MPU6050_PWR_MGMT_1, 0);

    initBuffer();
}

void loop() {
  curSensoredTime = millis();
  
  // Read from sensor
  if(curSensoredTime - prevSensoredTime > SENSOR_READ_INTERVAL) {
    readFromSensor();  // Read from sensor
    prevSensoredTime = curSensoredTime;
    
    // Send buffer data to remote
    if(iAccelIndex >= ACCEL_BUFFER_COUNT - 3) {
      sendToRemote();
      initBuffer();
      Serial.println("------------- Send 20 accel data to remote");
    }
  }
}

/**************************************************
 * BT Transaction
 **************************************************/
void sendToRemote() {
  // Write gabage bytes
  BTSerial.write( "accel" );
  // Write accel data
  BTSerial.write( (char*)aAccelBuffer );
  // Flush buffer
  //BTSerial.flush();
}

/**************************************************
 * Read data from sensor and save it
 **************************************************/
void readFromSensor() {
  int error;
  double dT;
  accel_t_gyro_union accel_t_gyro;
  
  error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro));
  if(error != 0) {
    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);
  
  // Print the raw acceleration values
  Serial.print(F("accel x,y,z: "));
  Serial.print(accel_t_gyro.value.x_accel, DEC);
  Serial.print(F(", "));
  Serial.print(accel_t_gyro.value.y_accel, DEC);
  Serial.print(F(", "));
  Serial.print(accel_t_gyro.value.z_accel, DEC);
  Serial.print(F(", at "));
  Serial.print(iAccelIndex);
  Serial.println(F(""));
  
  if(iAccelIndex < ACCEL_BUFFER_COUNT && iAccelIndex > 1) {
    int tempX = accel_t_gyro.value.x_accel;
    int tempY = accel_t_gyro.value.y_accel;
    int tempZ = accel_t_gyro.value.z_accel;
    /*
    // Check min, max value
    if(tempX > 16380) tempX = 16380;
    if(tempY > 16380) tempY = 16380;
    if(tempZ > 16380) tempZ = 16380;
    
    if(tempX < -16380) tempX = -16380;
    if(tempY < -16380) tempY = -16380;
    if(tempZ < -16380) tempZ = -16380;
    
    // We dont use negative value
    tempX += 16380;
    tempY += 16380;
    tempZ += 16380;
    */
    char temp = (char)(tempX >> 8);
    if(temp == 0x00)
      temp = 0x7f;
    aAccelBuffer[iAccelIndex] = temp;
    iAccelIndex++;
    temp = (char)(tempX);
    if(temp == 0x00)
      temp = 0x01;
    aAccelBuffer[iAccelIndex] = temp;
    iAccelIndex++;
    
    temp = (char)(tempY >> 8);
    if(temp == 0x00)
      temp = 0x7f;
    aAccelBuffer[iAccelIndex] = temp;
    iAccelIndex++;
    temp = (char)(tempY);
    if(temp == 0x00)
      temp = 0x01;
    aAccelBuffer[iAccelIndex] = temp;
    iAccelIndex++;
    
    temp = (char)(tempZ >> 8);
    if(temp == 0x00)
      temp = 0x7f;
    aAccelBuffer[iAccelIndex] = temp;
    iAccelIndex++;
    temp = (char)(tempZ);
    if(temp == 0x00)
      temp = 0x01;
    aAccelBuffer[iAccelIndex] = temp;
    iAccelIndex++;
  }
  
  // The temperature sensor is -40 to +85 degrees Celsius.
  // It is a signed integer.
  // According to the datasheet:
  // 340 per degrees Celsius, -512 at 35 degrees.
  // At 0 degrees: -512 - (340 * 35) = -12412
//  Serial.print(F("temperature: "));
//  dT = ( (double) accel_t_gyro.value.temperature + 12412.0) / 340.0;
//  Serial.print(dT, 3);
//  Serial.print(F(" degrees Celsius"));
//  Serial.println(F(""));

  // Print the raw gyro values.
//  Serial.print(F("gyro x,y,z : "));
//  Serial.print(accel_t_gyro.value.x_gyro, DEC);
//  Serial.print(F(", "));
//  Serial.print(accel_t_gyro.value.y_gyro, DEC);
//  Serial.print(F(", "));
//  Serial.print(accel_t_gyro.value.z_gyro, DEC);
//  Serial.println(F(""));
}

/**************************************************
 * MPU-6050 Sensor read/write
 **************************************************/
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);
}


/**************************************************
 * Utilities
 **************************************************/
void initBuffer() {
  iAccelIndex = 2;
  for(int i=iAccelIndex; i<ACCEL_BUFFER_COUNT; i++) {
    aAccelBuffer[i] = 0x00;
  }
  aAccelBuffer[0] = 0xfe;
  aAccelBuffer[1] = 0xfd;
  aAccelBuffer[122] = 0xfd;
  aAccelBuffer[123] = 0xfe;
  aAccelBuffer[124] = 0x00;
}

프로필사진

신기환 2017-02-07 16:53:54

수박쨈님 스케치된 소스코드를 아두이노에 업로딩 시킨 후 USB포트를 제거하고 외부전원(9V)을 인가하고 아두이노의 포트(송신부 COM5-블루투스)로 설정하고 시리얼 모니터를 on하니깐 시리얼모니터가 저런식으로 뜨는데..

 

이전글   |    사진전송에 쓸 방식하고 사용할 보드 추천좀 해주세요... 2017-02-06
다음글   |    아두이노 회로 프로그램 Fritzing의 라이브러리 관련 질문입니다.... 2017-02-07