Gyro Accel MPU 6050 - FabLabSeoul/WingProject GitHub Wiki

(GY-521 breakout๋ณด๋“œ์— MPU-6050์ด ์žฅ์ฐฉ๋˜์–ด ์žˆ๋‹ค.)

STM32 Value line ๋ณด๋“œ์—์„œ GY-521 breakout ๋ณด๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ MPU-6050์„ ํ…Œ์ŠคํŠธ ํ•œ๋‹ค. ์†Œ์Šค๋Š” STM32\stm32vldiscovery_package\Project\Examples\MPU-6050 ์— ์žˆ๋‹ค.

์ด ํ”„๋กœ์ ํŠธ ์†Œ์Šค๋Š” MPU-6050๊ณผ I2C ํ†ต์‹ ์œผ๋กœ ๊ฐ€์†๋„ x,y,z (๋‹จ์œ„ g), ์ž์ด๋กœ x,y,z (๋‹จ์œ„ ๊ฐ์†๋„, degree/seconds) ๊ฐ’์„ ๊ฐ€์ ธ์™€์„œ roll, pitch, yaw ๊ฐ์„ ๊ณ„์‚ฐํ•œ๋‹ค. ๊ณ„์‚ฐ์€ Stm32์—์„œ ์ด๋ค„์ง€๊ณ , ๊ฒฐ๊ณผ๋ฅผ ์‹œ๋ฆฌ์–ผ ํ†ต์‹ ์œผ๋กœ ๋ณด๋‚ธ๋‹ค. ์‹œ๋ฆฌ์–ผ ์ •๋ณด๋ฅผ ๋ฐ›์€ ์ปดํ“จํ„ฐ๋Š” Processing ํ”„๋กœ๊ทธ๋žจ์„ ํ†ตํ•ด 3์ฐจ์› ๋ชจ๋ธ๋กœ ์ถœ๋ ฅํ•œ๋‹ค.

์•„์ง Stm32 Value line ๋ณด๋“œ๋กœ ์ปดํ“จํ„ฐ์™€ ์‹œ๋ฆฌ์–ผํ†ต์‹ ์„ ํ•˜๋Š” ๋ฒ•์„ ๋ชฐ๋ผ์„œ, ์•„๋‘์ด๋…ธ๋ฅผ ๊ฑฐ์ณ ์ปดํ“จํ„ฐ์— ์‹œ๋ฆฌ์–ผ ์ •๋ณด๋ฅผ ๋ณด๋‚ธ๋‹ค. ์„ผ์„œ์ •๋ณด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ˜๋Ÿฌ๊ฐ„๋‹ค. GY-521 -> Stm32 -> Arduino -> Computer -> Processing (์ด ๋ฌธ์ œ ํ•ด๊ฒฐ์€ Stm32 printf Debugging, Stm32 Serial Debugging ๋ฌธ์„œ์—์„œ ํ™•์ธํ•  ์ˆ˜์žˆ๋‹ค.)

์ด ์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค๊ธฐ์œ„ํ•ด ๋‘๊ฐœ์˜ ์˜คํ”ˆ ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜์˜€๋‹ค. MPU-6050์—์„œ I2C ํ†ต์‹ ์œผ๋กœ ์ž์ด๋กœ, ๊ฐ€์†๋„ ๊ฐ’์„ ๋ฐ›์•„์˜ค๋Š” ๋ถ€๋ถ„์€ https://harinadha.wordpress.com/2012/05/23/mpu6050lib/ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ–ˆ๋‹ค. (์ด ์†Œ์Šค๋Š” ACK๋ฅผ ๋ฌดํ•œ์ • ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋ฒ„๊ทธ๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ ํ๋ธŒ์—์„œ๋Š” ์“ฐ์ง€ ์•Š์„ ๊ณ„ํš์ด๋‹ค.)

MPU-6050์œผ๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ์ •๋ณด๋ฅผ ์‹ค์ œ๋กœ ์“ฐ์ผ Roll, Pitch, Yaw ๊ฐ์œผ๋กœ ๋ฐ”๊พธ๋Š” ๊ณ„์‚ฐ์€ http://m.kocoafab.cc/tutorial/view/239 ์„ ์ด์šฉํ–ˆ๋‹ค.

ํšŒ๋กœ๊ตฌ์„ฑ์€ https://harinadha.wordpress.com/tag/stm32/ ์„ ์ฐธ๊ณ ํ•˜์ž. Stm32 I2CํฌํŠธ๋กœ ์“ฐ์ผ PB10,11์„ GY-521์˜ SCL, SDA ํ•€์— ์—ฐ๊ฒฐํ•˜๋ฉด ๋œ๋‹ค. ์ •ํ™•ํžˆ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • GY-521 Vcc -> 3.3V or 5V
  • GY-521 Gnd -> Ground
  • Stm32 PB10(I2C2 SCL) -> GY-521 SCL
  • Stm32 PB11(I2C2 SDA) -> GY-521 SDA

I2C ์„ค์ •

MPU-6050๊ณผ ํ†ต์‹ ์„ ํ•˜๊ธฐ ์œ„ํ•œ I2C ์ดˆ๊ธฐํ™” ์ฝ”๋“œ๋‹ค. ์ด๋Š” STM32 I2C๋ฌธ์„œ์™€ ํฌ๊ฒŒ ๋‹ค๋ฅด์ง€ ์•Š๋‹ค. PB10,11 ํฌํŠธ๋Š” MPU-6050๊ณผ์˜ ํ†ต์‹ ์„ ์œ„ํ•ด ์“ฐ์ด๊ณ , I2C์ฃผ์†Œ๋ฅผ 0x68๋กœ ์„ค์ •ํ•œ๋‹ค. ๋งˆ์Šคํ„ฐ์ธ Stm32 MCU๋Š” ์Šฌ๋ž˜์ด๋ธŒ์ธ MPU-6050์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด 0x68์ฃผ์†Œ๋กœ I2Cํ†ต์‹ ์„ ์‹œ์ž‘ํ•˜๊ฒŒ ๋œ๋‹ค.

์ด ์†Œ์Šค์ฝ”๋“œ๋Š” Harinadha Reddy๊ฐ€ ์ง  ์ฝ”๋“œ์˜ ์ผ๋ถ€๋‹ค. (https://harinadha.wordpress.com/about/)

#define MPU6050_I2C                  I2C2
#define MPU6050_I2C_RCC_Periph       RCC_APB1Periph_I2C2
#define MPU6050_I2C_Port             GPIOB
#define MPU6050_I2C_SCL_Pin          GPIO_Pin_10
#define MPU6050_I2C_SDA_Pin          GPIO_Pin_11
#define MPU6050_I2C_RCC_Port         RCC_APB2Periph_GPIOB
#define MPU6050_I2C_Speed            100000 // 100kHz standard mode

MPU6050_I2C_Init();

/**
 * @brief  Initializes the I2C peripheral used to drive the MPU6050
 * @param  None
 * @return None
 */
void MPU6050_I2C_Init()
{
    I2C_InitTypeDef I2C_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    /* Enable I2C and GPIO clocks */
    RCC_APB1PeriphClockCmd(MPU6050_I2C_RCC_Periph, ENABLE);
    RCC_APB2PeriphClockCmd(MPU6050_I2C_RCC_Port, ENABLE);

    /* Configure I2C pins: SCL and SDA */
    GPIO_InitStructure.GPIO_Pin = MPU6050_I2C_SCL_Pin | MPU6050_I2C_SDA_Pin;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_Init(MPU6050_I2C_Port, &GPIO_InitStructure);

    /* I2C configuration */
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = MPU6050_DEFAULT_ADDRESS; // MPU6050 7-bit adress = 0x68, 8-bit adress = 0xD0;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = MPU6050_I2C_Speed;

    /* Apply I2C configuration after enabling it */
    I2C_Init(MPU6050_I2C, &I2C_InitStructure);
    /* I2C Peripheral Enable */
    I2C_Cmd(MPU6050_I2C, ENABLE);
}

I2C๋ฅผ ํ†ตํ•œ MPU-6050 ์ดˆ๊ธฐํ™”

MPU-6050๊ณผ I2Cํ†ต์‹ ์„ํ•ด์„œ ์˜ต์…˜์„ ์„ค์ •ํ•œ๋‹ค. ์˜ต์…˜์€ MPU-6050์˜ ๊ณ ์œ  ๋ ˆ์ง€์Šคํ„ฐ ์ฃผ์†Œ๊ฐ’์— ์ •๋ณด๋ฅผ ์“ฐ๋Š” ๊ฒƒ์„ ๋ฐ”ํƒ•์œผ๋กœ ํ•œ๋‹ค. I2C ํ†ต์‹ ์„ ํ†ตํ•ด MPU-6050 ๋ ˆ์ง€์Šคํ„ฐ์— ๋ฐ์ดํƒ€๋ฅผ ์“ฐ๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.


MPU-6050์— ์ •๋ณด๋ฅผ ์“ธ ๋•Œ.

  • ๋งˆ์Šคํ„ฐ๊ฐ€ MPU-6050์— Start์‹ ํ˜ธ๋ฅผ ๋ณด๋‚ธ๋‹ค. (์“ฐ๊ธฐ ๋ชจ๋“œ W)
  • ๊ธฐ๋ณธ ๊ณผ์ •์„ ๊ฑฐ์นœ๋‹ค. ~ (ACK)
  • ๊ฐ’์„ ๋ฐ”๊ฟ€ MPU-6050์˜ ๋ ˆ์ง€์Šคํ„ฐ ์ฃผ์†Œ๊ฐ’์„ ๋ณด๋‚ธ๋‹ค. (RA)
  • ๊ธฐ๋ณธ ๊ณผ์ •์„ ๊ฑฐ์นœ๋‹ค. ~ (ACK)
  • ํ•ด๋‹น ๋ ˆ์ง€์Šคํ„ฐ ์ฃผ์†Œ์— ์ €์žฅํ•  ์ •๋ณด๋ฅผ ํ•œ ๋ฐ”์ดํŠธ์”ฉ ์†ก์‹ ํ•œ๋‹ค. (DATA)
    • ์ ‘์†์„ ๋Š์„ ๋•Œ๊นŒ์ง€ ์ •๋ณด๊ฐ€ ์†ก์‹ ๋˜๊ณ , ๋ฐ›๋Š” ์ธก์—์„œ๋Š” ์ž๋™์ ์œผ๋กœ ๋‹ค์Œ ์ฃผ์†Œ๋ฅผ ๊ฐ€๋ฅดํ‚ค๊ฒŒ ๋œ๋‹ค.
  • ์—ฐ๊ฒฐ์„ ๋Š๋Š”๋‹ค.

MPU-6050 ์ •๋ณด๋ฅผ ๋ฐ›์•„ ์˜ฌ ๋•Œ.

  • ๋งˆ์Šคํ„ฐ๊ฐ€ MPU-6050์— Start์‹ ํ˜ธ๋ฅผ ๋ณด๋‚ธ๋‹ค. (์“ฐ๊ธฐ ๋ชจ๋“œ W)
  • ๊ธฐ๋ณธ ๊ณผ์ •์„ ๊ฑฐ์นœ๋‹ค. ~ (ACK)
  • ๊ฐ’์„ ์–ป์–ด์˜ฌ MPU-6050์˜ ๋ ˆ์ง€์Šคํ„ฐ ์ฃผ์†Œ๊ฐ’์„ ๋ณด๋‚ธ๋‹ค. (RA)
  • ๋‹ค์‹œ Start์‹ ํ˜ธ๋ฅผ ๋ณด๋‚ธ๋‹ค. (์ฝ๊ธฐ ๋ชจ๋“œ R)
  • ๊ธฐ๋ณธ ๊ณผ์ •์„ ๊ฑฐ์นœ๋‹ค. ~ (ACK)
  • ๋ฐ์ดํƒ€๋ฅผ ํ•œ ๋ฐ”์ดํŠธ์”ฉ ์›ํ•˜๋Š” ํšŸ์ˆ˜๋งŒํผ ๋ฐ›๋Š”๋‹ค. (DATA)
    • ACK๋ฅผ ๋ณด๋‚ธ ํšŸ์ˆ˜๋งŒํผ ์ •๋ณด๋ฅผ ๋ฐ›๊ณ , ๋ณด๋‚ด๋Š” ์ชฝ์—์„œ ์ž๋™์ ์œผ๋กœ ๋‹ค์Œ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ๊ฐ€๋ฅดํ‚ค๊ฒŒ ๋œ๋‹ค.
  • ์—ฐ๊ฒฐ์„ ๋Š๋Š”๋‹ค.

MPU-6050์˜ ๋ ˆ์ง€์Šคํ„ฐ ์ฃผ์†Œ๋Š” ๋งค๋‰ด์–ผ์„ ์ฐธ์กฐํ•˜์ž. ์ผ๋‹จ ์šฐ๋ฆฌ๊ฐ€ ๊ด€์‹ฌ์„ ๊ฐ€์ง€๋Š” gyro_x,y,z, accel_x,y,z ๋ ˆ์ง€์Šคํ„ฐ ์ฃผ์†Œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. ๋ฉ”๋ชจ๋ฆฌ์ฃผ์†Œ๊ฐ€ ์ˆœ์„œ๋Œ€๋กœ ACCEL_XOUT_H ~ GYRO_ZOUT_L ๊นŒ์ง€ ๋‚˜์—ด๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ํ•œ ๋ฒˆ์˜ ์ ‘์†์œผ๋กœ ์ˆœ์„œ๋Œ€๋กœ ์ฝ์œผ๋ฉด ๋ชจ๋‘ ์ฝ์–ด ์˜ฌ ์ˆ˜ ์žˆ๋‹ค. ๊ฐ€์šด๋ฐ ์˜จ๋„์„ผ์„œ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค์ง€๋งŒ(TEMP_OUT_H,L), ์ด ๊ฐ’์€ ๋ฌด์‹œํ•œ๋‹ค.

MPU-6050์ดˆ๊ธฐํ™” ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. MPU-6050 ์˜ต์…˜์€ ๋งค๋‰ด์–ผ์„ ํ†ตํ•ด ํ™•์ธํ•˜์ž.

์ž์ด๋กœ ์„ผ์‹ฑ ๋ฒ”์œ„, ๊ฐ€์†๋„ ์„ผ์‹ฑ ๋ฒ”์œ„๋ฅผ ๊ฐ๊ฐ +-250 degree/s, +-2g ๋กœ ์„ค์ •ํ–ˆ๋‹ค.

/** Power on and prepare for general usage.
 * This will activate the device and take it out of sleep mode (which must be done
 * after start-up). This function also sets both the accelerometer and the gyroscope
 * to their most sensitive settings, namely +/- 2g and +/- 250 degrees/sec, and sets
 * the clock source to use the X Gyro for reference, which is slightly better than
 * the default internal clock source.
 */
void MPU6050_Initialize()
{
    MPU6050_SetClockSource(MPU6050_CLOCK_PLL_XGYRO);
    MPU6050_SetFullScaleGyroRange(MPU6050_GYRO_FS_250);
    MPU6050_SetFullScaleAccelRange(MPU6050_ACCEL_FS_2);
    MPU6050_SetSleepModeStatus(DISABLE);
}

MPU-6050 ๋งค๋‰ด์–ผ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

์ž์ด๋กœ์„ผ์„œ Scale Factor, ๊ฐ€์†์„ผ์„œ Scale Factor๊ฐ€ ๊ฐ๊ฐ +-250, 2g์ผ ๋•Œ, 131, 16384์ธ ๊ฒƒ์„ ํ™•์ธํ•˜์ž. ๋‚˜์ค‘์— ์ด ๊ฐ’์œผ๋กœ roll, pitch, yaw ๊ฐ’์„ ๊ณ„์‚ฐํ•œ๋‹ค.


MPU_6050๊ณผ I2C ํ†ต์‹ ์„ ํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์˜ˆ๋กœ, ์ž์ด๋กœ ์„ผ์„œ ๋ฒ”์œ„ ์„ค์ •ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋ณด์ž. MPU6050_RA_GYRO_CONFIG ๋ ˆ์ง€์Šคํ„ฐ ์ฃผ์†Œ์— ์ •๋ณด๋ฅผ ์“ฐ๊ธฐ์ „์—, ์˜ต์…˜์ด ๋ฎ์–ด ์”Œ์–ด์งˆ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๊ธฐ์กด ์˜ต์…˜ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜จ ํ›„, ๋ฐ”๊ฟ€ ๋น„ํŠธ๊ฐ’๋งŒ ์—…๋ฐ์ดํŠธ ํ•œ๋‹ค. ์ด ๊ณผ์ •์€ MPU6050_WriteBits() ํ•จ์ˆ˜์— ์ฒ˜๋ฆฌ ํ•œ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์ฃผ๋ชฉํ•  ๊ฒƒ์€, ์ •๋ณด๋ฅผ ์“ธ ๋•Œ, ์–ด๋–ค ํ๋ฆ„์œผ๋กœ I2Cํ†ต์‹ ์„ ํ•˜๋Š๋ƒ์ด๋‹ˆ MPU6050_I2C_ByteWrite()ํ•จ์ˆ˜๋ฅผ ๋ณด์ž. MPU-6050๊ณผ ์ ‘์†์„ ์‹œ์ž‘ํ•œ ํ›„, ๋ ˆ์ง€์Šคํ„ฐ ์ฃผ์†Œ๋ฅผ ์†ก์‹ ํ•˜๊ณ , ์ด ํ›„์— ์“ธ ๋ฐ์ดํƒ€๋ฅผ ๋ณด๋‚ด๊ณ  ์žˆ๋‹ค.

์ด ์ฝ”๋“œ๋Š” Harinadha Reddy๊ฐ€ ์ž‘์„ฑํ–ˆ๋‹ค.

MPU-6050์—์„œ I2Cํ†ต์‹ ์œผ๋กœ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ถ€๋ถ„์€ MPU6050_I2C_BufferRead() ํ•จ์ˆ˜๋ฅผ ํ™•์ธํ•˜์ž. ์œ„์— ๋‚˜์˜จ ์‹œํ€€์Šค ๋‹ค์ด์–ด๊ทธ๋žจ๊ณผ ์ผ์น˜ํ•œ๋‹ค.

MPU6050_I2C_ByteWrite(MPU6050_DEFAULT_ADDRESS, data, MPU6050_RA_GYRO_CONFIG);

void MPU6050_I2C_ByteWrite(u8 slaveAddr, u8* pBuffer, u8 writeAddr)
{
    // ENTR_CRT_SECTION();

    /* Send START condition */
    I2C_GenerateSTART(MPU6050_I2C, ENABLE);

    /* Test on EV5 and clear it */
    while (!I2C_CheckEvent(MPU6050_I2C, I2C_EVENT_MASTER_MODE_SELECT));

    /* Send MPU6050 address for write */
    I2C_Send7bitAddress(MPU6050_I2C, slaveAddr, I2C_Direction_Transmitter);

    /* Test on EV6 and clear it */
    while (!I2C_CheckEvent(MPU6050_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

    /* Send the MPU6050's internal address to write to */
    I2C_SendData(MPU6050_I2C, writeAddr);

    /* Test on EV8 and clear it */
    while (!I2C_CheckEvent(MPU6050_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    /* Send the byte to be written */
    I2C_SendData(MPU6050_I2C, *pBuffer);

    /* Test on EV8 and clear it */
    while (!I2C_CheckEvent(MPU6050_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    /* Send STOP condition */
    I2C_GenerateSTOP(MPU6050_I2C, ENABLE);

    // EXT_CRT_SECTION();
}

MPU-6050๊ณผ ์ •์ƒ์ ์œผ๋กœ ์—ฐ๊ฒฐ๋˜์—ˆ๋Š”์ง€๋ฅผ ํ™•์ธํ•˜๊ณ , ์„ผ์„œ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.

MPU-6050๊ณผ ์ •์ƒ์ ์œผ๋กœ ์—ฐ๊ฒฐ์ด ๋˜์—ˆ๋‹ค๋ฉด, MPU6050_GetRawAccelGyro() ํ•จ์ˆ˜๋กœ ์„ผ์„œ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. 6๊ฐœ์˜ ์ •์ˆ˜๊ฐ’์€ ์ˆœ์„œ๋Œ€๋กœ ๊ฐ€์†๋„ x,y,z ์ž์ด๋กœ์„ผ์„œ x,y,z ๊ฐ’์„ ๊ฐ€์ ธ์˜จ๋‹ค.

int16_t  AccelGyro[6]={0};

if (MPU6050_TestConnection() != 0)
{
 // connection success
}
else
{
	 // connection failed
	return 0;
}
 	
MPU6050_GetRawAccelGyro(AccelGyro);

MPU-6050 ์„ผ์„œ์ •๋ณด๋ฅผ Roll,Pitch,Yaw ๊ฐ์œผ๋กœ ๋ณ€ํ™˜

์ด ์ฝ”๋“œ๋Š” http://m.kocoafab.cc/tutorial/view/239 ์—์„œ ๊ฐ€์ ธ ์™”๊ณ , ์›๋ณธ์€ Krodal์ด ์ž‘์„ฑํ–ˆ๋‹ค.

๊ฐ€์†๋„ ์„ผ์„œ์™€ ์ž์ด๋กœ ์„ผ์„œ๋ฅผ ๊ฐ„๋‹จํ•œ ์ƒ๋ณดํ•„ํ„ฐ๋ฅผ ์ด์šฉํ•ด์„œ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋‹ค. ๊ฐ€์†๋„๋ฅผ roll, pitch, yaw๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณต์‹์€ ์—ฌ๋Ÿฌ ์‚ฌ์ดํŠธ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” yaw๊ฐ’์€ ๊ตฌํ•˜์ง€ ์•Š๊ณ  ์žˆ๋‹ค.

//
// ์†Œ์Šค ์ฐธ์กฐ. ์•„๋‘์ด๋…ธ ์†Œ์Šค๋ฅผ stm32 ์†Œ์Šค๋กœ ๋ฐ”๊ฟจ๋‹ค.
// http://m.kocoafab.cc/tutorial/view/239
//
void SendSerialAccelGryro( int16_t accelgyro[6] )
{
	//  250 degree/s ๋ฒ”์œ„๋ฅผ ๊ฐ€์ง€๊ณ , ์ด ๊ฐ’์„ 16 bit ๋ถ„ํ•ด๋Šฅ์œผ๋กœ ํ‘œํ˜„ํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ, 
	// mpu-6050์—์„œ ๋ณด๋‚ด๋Š” ๊ฐ’์€ -32766 ~ +32766 ๊ฐ’์ด๋‹ค.
	// ๊ทธ๋Ÿฌ๋ฏ€๋กœ ์ด ๊ฐ’์„ ์‹ค์ œ 250 degree/s ๋กœ ๋ณ€ํ™˜ํ•˜๋ ค๋ฉด 131๋กœ ๋‚˜๋ˆ ์ค˜์•ผ ํ•œ๋‹ค. ๋ฒ”์œ„๊ฐ€
	// ๋‹ค๋ฅด๋ฉด ์ด ๊ฐ’๋„ ๊ฐ™์ด ๋ฐ”๊ปด์•ผํ•œ๋‹ค.
	float FS_SEL = 131;
	
	  //ํšŒ์ „์„ ํ–ˆ์„ ๋–„ ์‹œ๊ฐ„ ์•Œ๊ธฐ
  unsigned long t_now = GetTickCount();

	
  float gyro_x = (accelgyro[3] - base_x_gyro)/FS_SEL;
  float gyro_y = (accelgyro[4] - base_y_gyro)/FS_SEL;
  float gyro_z = (accelgyro[5] - base_z_gyro)/FS_SEL;


// ๊ฐ€์†๋„ ๊ฐ’ ๋ฒ”์œ„๋Š”?
// 16bit ๋‹ˆ -32766 ~ +32766 ๋ฒ”์œ„์ด๊ณ ,
//	 +-2g ๋ฒ”์œ„๋ผ๋ฉด mpu-6050์œผ๋กœ๋ถ€ํ„ฐ ๋„˜์–ด์˜จ ๊ฐ’์„ ์‹ค์ œ g๋‹จ์œ„๋กœ ํ™˜์‚ฐํ•˜๋ ค๋ฉด
//	  scale factor(16384)๋กœ ๋‚˜๋ˆ ์ค˜์•ผ ํ•œ๋‹ค. +-2g ๋ฒ”์œ„๋Š” +-32766๊ฐ’์ด๋‹ค. ์ฆ‰ 32766๊ฐ’์ด๋ฉด 2๊ฐ€ ๋œ๋‹ค.	

  //acceleration ์›์‹œ ๋ฐ์ดํ„ฐ ์ €์žฅ
  float accel_x = accelgyro[0];
  float accel_y = accelgyro[1];
  float accel_z = accelgyro[2];
	
	 
  //accelerometer๋กœ ๋ถ€ํ„ฐ ๊ฐ๋„ ์–ป๊ธฐ
  float RADIANS_TO_DEGREES = 180/3.14159;

  // float accel_vector_length = sqrt(pow(accel_x,2) + pow(accel_y,2) + pow(accel_z,2));
  float accel_angle_y = atan(-1*accel_x/sqrt(pow(accel_y,2) + pow(accel_z,2)))*RADIANS_TO_DEGREES;
  float accel_angle_x = atan(accel_y/sqrt(pow(accel_x,2) + pow(accel_z,2)))*RADIANS_TO_DEGREES;
  float accel_angle_z = 0;
	

  //gyro angles ๊ณ„์‚ฐ1
  float dt =(t_now - get_last_time())/1000.0;
  float gyro_angle_x = gyro_x*dt + get_last_x_angle();
  float gyro_angle_y = gyro_y*dt + get_last_y_angle();
  float gyro_angle_z = gyro_z*dt + get_last_z_angle();
  
  //gyro angles ๊ณ„์‚ฐ2
  float unfiltered_gyro_angle_x = gyro_x*dt + get_last_gyro_x_angle();
  float unfiltered_gyro_angle_y = gyro_y*dt + get_last_gyro_y_angle();
  float unfiltered_gyro_angle_z = gyro_z*dt + get_last_gyro_z_angle();
  
  //์•ŒํŒŒ๋ฅผ ์ด์šฉํ•ด์„œ ์ตœ์ข… ๊ฐ๋„ ๊ณ„์‚ฐ3
  float alpha = 0.96;
  float angle_x = alpha*gyro_angle_x + (1.0 - alpha)*accel_angle_x;
  float angle_y = alpha*gyro_angle_y + (1.0 - alpha)*accel_angle_y;
  float angle_z = gyro_angle_z;  //Accelerometer๋Š” z-angle ์—†์Œ	
	
	
 //์ตœ์ข… ๊ฐ๋„ ์ €์žฅ
  set_last_read_angle_data(t_now, angle_x, angle_y, angle_z, unfiltered_gyro_angle_x, unfiltered_gyro_angle_y, unfiltered_gyro_angle_z);
 	
	// ์‹œ์ž‘ ๋ฌธ์ž ์ „์†ก
	print_byte('S');	
	
	print_byte( (int16_t)dt );
	
	// 2 ๋ฐ”์ดํŠธ ์ •์ˆ˜๋กœ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด 100์„ ๊ณฑํ•˜๊ณ , ๋ฐ›์„ ๋•Œ, 100์„ ๋‚˜๋ˆ ์ค€๋‹ค. 
	print_short( (int16_t)(accel_angle_x*100) );
	print_short( (int16_t)(accel_angle_y*100) );
	print_short( (int16_t)(accel_angle_z*100) );

	print_short( (int16_t)(unfiltered_gyro_angle_x*100) );
	print_short( (int16_t)(unfiltered_gyro_angle_y*100) );
	print_short( (int16_t)(unfiltered_gyro_angle_z*100) );
	
	print_short( (int16_t)(angle_x*100) );
	print_short( (int16_t)(angle_y*100) );
	print_short( (int16_t)(angle_z*100) );
}

๋ ˆํผ๋Ÿฐ์Šค