본문 바로가기

Development/Embedded

ATmega128 MPU6050

ATmega128 에서 MPU6050 의 가속도 자이로 값을 읽어오는 방법 100Hz로 샘플링을 하기 위해
타이머 오버플로우로 0.01초마다 인터럽트가 걸리게 설정함
TIMSK = 0x01;
TCCR0 = 0x07;
TCNT0 = 99;
SREG = 0x80;

그리고 인터럽트 소스를 작성

interrupt [TIM0_OVF] void timer_int0(void)
{       
    getRawData();
    getAcclDegree();
    getGyroDegree();
    compFilter();
    TCNT0 = 99;
}

가속도 센서와 자이로 센서 값을 읽어오는건 이전에 올린 소스가 있음
MPU6050_read() 함수는 지난 포스팅 참조 -Click-
void getRawData()
{
    buffer[0] = MPU6050_read(0x3B);
    buffer[1] = MPU6050_read(0x3C);
    buffer[2] = MPU6050_read(0x3D);
    buffer[3] = MPU6050_read(0x3E);
    buffer[4] = MPU6050_read(0x3F);
    buffer[5] = MPU6050_read(0x40);
     
    buffer[6] = MPU6050_read(0x43);
    buffer[7] = MPU6050_read(0x44);
    buffer[8] = MPU6050_read(0x45);
    buffer[9] = MPU6050_read(0x46);
    buffer[10] = MPU6050_read(0x47);
    buffer[11] = MPU6050_read(0x48);
     
    ax = (int)buffer[0] << 8 | (int)buffer[1];
    ay = (int)buffer[2] << 8 | (int)buffer[3];
    az = (int)buffer[4] << 8 | (int)buffer[5];
    gx = (int)buffer[6] << 8 | (int)buffer[7];
    gy = (int)buffer[8] << 8 | (int)buffer[9];
    gz = (int)buffer[10] << 8 | (int)buffer[11];
}
읽어온 값을 라디안 값으로 변환시켜줌

void getAcclDegree(void)
{
    x_aTmp1 = ((long)ay * (long)ay) + ((long)az * (long)az);
    y_aTmp1 = ((long)ax * (long)ax) + ((long)az * (long)az);
    z_aTmp1 = ((long)ay * (long)ay) + ((long)az * (long)az);
    
    x_aTmp2 = sqrt((float)x_aTmp1);
    y_aTmp2 = sqrt((float)y_aTmp1);
    z_aTmp2 = sqrt((float)z_aTmp1);
    
    x_aResult = atan((float)ax / x_aTmp2);
    y_aResult = atan((float)ay / y_aTmp2);
    z_aResult = atan(z_aTmp2 / (float)az);
}
void getGyroDegree(void)
{
    x_gTmp1 = (float)gx / 65536;
    y_gTmp1 = (float)gy / 65536;
    
    x_gTmp1 = x_gTmp1 * 1.8;
    y_gTmp1 = y_gTmp1 * 1.8;
    
    x_gResult = x_gTmp1;
    y_gResult = y_gTmp1;
}

volatile int gx = 0, gy = 0, gz = 0, ax = 0, ay = 0, az = 0;
volatile long x_aTmp1, y_aTmp1, z_aTmp1;
volatile float x_aTmp2, y_aTmp2, z_aTmp2, x_aResult, y_aResult, z_aResult;
volatile float x_gTmp1, y_gTmp1, x_gResult, y_gResult;
기본적으로 위의 모든 변수들은 float 혹은 double형으로 선언해두고
가속도 부분의 x_aTmp1, y_aTmp1, z_aTmp1 이 세개만 long형으로 선언
gx gy gz ax ay az는 raw data를 최초로 저장하는 변수임
참고로 gy-521의 MPU-6050모듈은 16bit ADC이고 레지스터 당 8비트니까
High bit / Low bit를 나눠서 읽어온 다음 쉬프트 연산과 OR 연산을 적절히 사용해 합쳐주는 방법을 사용했음.
마지막으로 필터부분
void compFilter(void)
{
    xTmp1 = (-y_aResult) + (float)xFilterAngle;
    xIntTmp1 = (float)xIntTmp1 + (xTmp1 * 0.01);
    xTmp2 = (-kp * xTmp1) + (-ki * (float)xIntTmp1) + x_gResult;
    xFilterAngle = xFilterAngle + (xTmp2 * 0.01);
    pitch = (int)(xFilterAngle * 180 / PI);
    
    yTmp1 = (-x_aResult) + (float)yFilterAngle;
    yIntTmp1 = (float)yIntTmp1 + (yTmp1 * 0.01);
    yTmp2 = (-kp * yTmp1) + (-ki * (float)yIntTmp1) + y_gResult;
    yFilterAngle = yFilterAngle + (yTmp2 * 0.01);
    roll = (int)(yFilterAngle * 180 / PI);
}
변수 선언은
float kp = 12.0f, ki = 1.0f;
volatile float xTmp1, yTmp1, xTmp2, yTmp2, xIntTmp1, yIntTmp1;
volatile float xFilterAngle = 0.0f, yFilterAngle = 0.0f;
volatile int pitch = 0, roll = 0;
위와 같이 하였다
지금까지 선언한 변수들은 쓰기 편하게 전역변수로 선언하고 그냥 가져다 쓰는 방식

2014 / 03 / 18 - 20:04 최초 작성


'Development > Embedded' 카테고리의 다른 글

Bike POV DIY (Spoke POV)  (0) 2015.06.04
ATmega128 MPU6050  (18) 2014.03.18
Getting Start STM32F103 Dev  (0) 2014.02.28
STM32F103 - QuadCopter 참고 소스  (0) 2014.02.19
STM32F103 - PWM 소스  (0) 2014.02.19
FB155BC 설정 with USB2UART Downloader  (0) 2014.02.19