AVR 임베디드 학습/AVR 이론 공부

ATmega328 i2c통신 학습하기(feat.mpu6050)(4탄)

9bexel9 2024. 11. 3. 20:19

3탄에 이어 mpu6050을 통해 가속도 값을 받아보겠다. 

acceleration sensor(feat.joop Brokking) 


가속도계를 상상할 때 다음과 같은 중력이 없는 큐브 모양에 상자를 상상해 보자! 우주라고 생각해 보면 다음과 같이 중력가속도는 0이므로 X, Y, Z = 0이 될 것이다.( 우리는 중력가속도 값을 9.8m/s^2 = 1g으로 생각해야 한다.)

두 번째로 상자를 갑자기 왼쪽으로 움직이면 공은 당연하게도 X-벽에 부딪힌다. 이때 공이 벽에 작용하는 압력을 측정하면 X축에 -1g 값을 출력한다. 여기서 가속도계는 실제로 가속도 벡터와 반대 방향으로 향하는 힘을 감지한다. 즉 관성력을 뜻하는데... 이는 겉보기 힘으로 가속도 벡터값과 반대 방향으로 향하는 힘을 뜻한다.

다음으로 튜브를 지구에 가져다 놓아보겠다. 그러면 당연하게도 Z-벽으로 공은 떨어지게 되고 그림과 같이 하단 벽에 1g에 힘을 가하게 된다. 이 경우 위에서 말한 관성력으로 Z 축에서 -1g 힘을 얻게 된다.

이번에는 단일 축에서 가속도계의 출력을 분석하는 것이 아니라 3축 가속도계에서 출력을 공부해 보자.. 다음 그림과 같이 Z-, X-의 2개의 벽에 45 º로 닿아있다. 이때 위에서 사용한 원리를 활용하면 중력가속도 값 1g 값이 각각 -0.71g로 나뉘어 값이 나타나는 것을 확인할 수 있다 여기서 -0.71g은 SQRT(1/2)에 대한 근사치라고 생각하면 된다.

이전 그림에서는 중력을 고정하고 가상의 상자를 회전시켰지만 이번에는 좌표계를 가속도계의 축에 고정하고 가속도 벡터의 방향을 변경하였을 때를 가정하고 공부해 보자! (여기서 벡터 R은 가속도 센서가 측정할 가속도 벡터이고 각 Rx, Ry, Rz는 x, y, z 축에 벡터 R이 투영된 벡터라고 생각하면 된다.)

즉 R^2 = Rx^2 + Ry^2 + Rz^2 임을 알 수 있다.(3D 피타고라스의 정리 활용)

이전에 우리는 중력가속도 값이 1g이라는 것을 확인했었다. 즉 R = 1 Rx = -SQRT (1/2), Ry = 0, Rz = -SQRT (1/2) 임을 확인할 수 있다.(큐브 모양 그림을 참고해 보자!)

따라서 위 공식을 대입해 보면 1^2 = -SQRT (1/2)^2 + 0^2 + -SQRT (1/2)^2 임을 알 수 있다!!

 

 

이제 센서를 통해 가속도 값이 어떻게 우리한테 값을 전달하여 각도로 변환할 수 있는지를 학습해 보겠다.

다음 그림에서 확인할 수 있듯이 mpu6050은 아날로그 ADC를 사용하여 우리에게 값을 전달하는 방식을 수행하고 있다.

예를 들어 3.3v에 기준전압을 가진 10비트 ADC 모듈이 3개의 가속도계 축에 대해 다음과 같은 값을 제공했다고 예를 들어보자.

 

AdcRx = 586

AdcRy = 630

AdcRz = 561

 

이 값을 10bit adc 값을 전압 값으로 변환하면 다음과 같은 값을 얻을 수 있다.

 

VoltRx = AdcRx * Vref/1023 -> 576 * 3.3/1023 = 1.89v 

VoltRy = AdcRy * Vref/1023 -> 630 * 3.3/1023 = 2.03v 

VoltRz = AdcRz * Vref/1023 -> 561 * 3.3/1023 = 1.81v

 

가속도계 센서는 각 축에 대하여 0g일 때 전압 레벨을 갖고 있다.(데이터 시트 참고)

따라서 전압 값을 얻으려면 전압 차이를 계산해야 한다. 즉 0g 전압 레벨이 VzeroG = 1.65v 일 때 0g 전압에서의 전압 이동을 계산해야 한다.

 

Delta voltRx = 1.89v - 1.65v = 0.24v

Delta voltRy = 2.03v - 1.65v = 0.38v

Delta voltRz = 1.81v - 1.65v = 0.16v

 

다음과 같은 값을 얻을 수 있다. 하지만 아직 가속도계 판독값이 볼트 단위이며 이 값을 g(9.8m/s^2)으로 바꿔줘야 한다. 즉 최종 변환을 이뤄주기 위해 mV/g로 표시되는 가속도계 감도를 적용해야 한다. 이를 위해서는 감도 값을 나눠줘야 하는데 이는 데이터 시트를 참고하면 된다. 여기서는 감도 = 478.5mV/g = 0.478V/g로 가정해 보겠다. 이제 g로 표현된 최종 힘의 값을 얻어보겠다. 

공식은 Rx= DeltaVoltsRx/감도이다.

 

rx = 0.24v/0.4785v/g = 0.5g

ry = 0.38v/0.4785v/g = 0.79g

rz = 0.16v/0.4785v/g = 0.33g

 

이고 지금까지 한 공식을 최종으로 나타내본다면

 

Rx = (AdcRx * Vref / 1032 -vZeroG) / 감도

Ry = (AdcRy * Vref / 1032 -vZeroG) / 감도 

Rz = (AdcRz * Vref / 1032 -vZeroG) / 감도로 나타낼 수 있다.

 

이제 이 g 값을 활용하여 각도를 계산해 보자!

위에 그림을 통해 X, Y, Z 축과 힘 벡터 R 사이에 각도를 Axr, Ayr, Azr로 나타낼 수 있다.

 

cos(Axr) = Rx/R

cos(Ayr) = Ry/R

cos(Azr) = Rz/R

R = SQRT(Rx^2 + Ry^2 + Rz^2)로 나타낼 수 있고 이는 다시

 

Axr = arccos(RX/R)

Ayr = arccos(RY/R)

Azr = arccos(RZ/R) 임을 확인할 수 있다..

 

따라서 위 식을 이용하여 가속도센서에서 실제 가속도를 받은 방향과 각 축과의 각도를 계산할 수 있다는 말이다.

(사실 이후에 오일러 각을 활용해서도 가속도 센서의 각도를 구할 수 있는데 정확하게 이해를 못 했다.. 이 방식이랑 같은 건가 다른 건가...)

 

Accelerometer(feat.joop Brokking)


 

우선적으로 acceleration의 Full-Scale부터 세팅해줘야 한다.

다음과 같이 AFS_SEL = 2로 설정해 주면 -8g ~ +8g까지 중력을 감지할 수 있도록 설정해 주었다.

따라서 mpu6050은 16bit ADC 값을 사용하므로 -32,768 ~ 32767까지의 값을 표현할 수 있다. 즉 1g당 4096의 값을 얻을 수 있다는 말이 된다.(2^16 = 32,768이고 32768/8을 하면 4096이기 때문이다!)

 

다음 그림과 같이 mpu6050을 정면으로 놓았을 때 중력가속도 방향과 반대방향인 관성력을 측정하므로 1g 값인 4096 값과 유사한 값이 나타난 것을 확인할 수 있고 mpu6050을 뒤집어 놓았을 때는 -4096과 유사한 값이 나타난 것을 확인할 수 있다.

 

 

왼쪽 그림과 같이 mpu6050을 45 º로 기울이면 약 2920이라는 값을 얻을 수 있고 이를 활용하여 Fgravity이 4129로 4096과 유사한 것을 확인할 수 있다.

마지막으로 삼각함수를 활용하여 45 º 를 얻은 것을 확인할 수 있다.