[아두이노 쿼드콥터] mpu6050 센서값 보정하기

Posted by Doony
2015. 10. 14. 21:22 아두이노 드론 프로젝트

아두이노로 쿼드콥터를 제어하는 데 있어서 x, y, z축 각도값을 센싱하는 것은 필수적입니다.

저희는 가장 흔한 센서인 mpu6050을 사용하였는데요.


여기서 문제가 발생했습니다. 저희가 만든 알고리즘은, pid 제어를 시작하는 변수를 따로 두고 시작하기 전에는 각도값만 출력하도록 하고 있었습니다.

pid 제어를 시작하기 전에 시리얼 통신을 통해 출력되는 값은 아주 정상적이었습니다. 오차라고 해봐야 0.1도 정도 왔다갔다하는 정도???


그런데 pid제어를 시작하고 나면, 0.1도 정도 오차만을 가지던 값이 10배 정도로 오차가 커지더군요. 

그래서 엑셀로 그 데이터를 한번 뽑아봤습니다.



다 보이진 않지만, 정수는 시리얼 통신으로 얻어온 데이터 개수를 의미하고, 그 옆 소수는 왼쪽부터 각도값, 각속도값입니다.

각속도는 이전 포스팅을 보시면 아시겠지만, 루프를 돌기전 각도와 현재 각도 값 차이를 일정한 시간 간격으로 나누어준 값입니다. (대체로 루프 도는 시간이 0.0065~0.007 s 정도 되는 것을 확인했습니다.)


각도 오차가 0.1도 날때는 각속도 오차도 그만큼 작았지만, 각도 오차가 10배로 증가하니 각속도 값이 요동치는 것을 수치를 통해 확인하실 수 있는데요.


저희 생각에는...

애초에 mpu6050을 통해 각도값 만들어낼때, 상보필터니 칼만필터니 하는 걸로 각도 오차를 최소화 시키는 것 같은데..

왜 이런 오차가 또 발생하는걸까요? 이해가 안갔습니다.


아두이노가 불량인건지, 센서가 불량인건지.. 온갖 추측들을 실험을 통해 검증해보았지만.. 전부 문제가 없는 것 같더라구요. 즉, 알고리즘 상에서 pid 제어를 시작하게 되면서 뭔가 꼬이는 듯 했습니다.



왜 꼬이는지 이유를 아직 판단하지 못해서 저희 나름대로 대안을 세워봤습니다.

상보필터나 칼만필터를 통해 얻어진 각도값을.. 한번더 필터링해서 오차를 최소화해보자는 것입니다.


그래서 생각한 알고리즘은, 일정한 개수만큼의 데이터의 평균값을 사용하는 것입니다.

즉, 지난 9개의 각도값과 현재 계산된 각도값 1개를 더한 뒤 10으로 나눠주는 식인거죠.


지난 값들이 있기 때문에, 바로 다음 값에서 오차가 좀 심하게 나더라도, 평균화하는 과정에서 그 비율이 최소화되지 않을까 했습니다.


그래서 MATLAB으로, 위 엑셀 데이터를 불러들여 코딩을 해보았습니다.






angle_sum=0.0;             %% 일정 개수만큼의 각도값의 합

angle_average(1:424)=0.0;          %% 평균값은 행렬 형태로 정의

rate(1:424)=0.0;            %%각속도도 마찬가지로 행렬로 정의

a=30;                    %%a는 위에서 언급한 '일정 개수'. 즉, a=30이면 30개의 평균치를 사용

for i=1:424

    if i<=a            %%초기값, 즉 30개가 되기 전에는 

        angle_sum=angle(i)+angle_sum;    %%하나씩 더해가면서 평균을 구함

        angle_average(i)=angle_sum/i;

        if i>=2        %% 두번째 이상의 루프에서는, 속도를 구할 수 있음.

            rate(i)=(angle_average(i)-angle_average(i-1))/0.65;

        end

    else

        angle_sum=angle_sum-angle(i-a);    %%30번 이상의 루프에서.

        angle_sum=angle_sum+angle(i);

        angle_average(i)=angle_sum/a;

        rate(i)=(angle_average(i)-angle_average(i-1))/0.65;

        

    end

    x(i)=i;

end

plot(x, angle_average, x, angle, 'r', x, rate, 'g');

legend('original','adjusted');

ylabel('angle value');

xlabel('numbers');






그래서 plot된 그래프를 비교해보았습니다.

빨간색이 원래 데이터, 파란색이 평균치를 사용한 데이터입니다.




1. a=5


5개씩 평균치를 통해 출력한 각도 값입니다.

보시다시피, 기존 빨간 그래프와 큰 차이가 없습니다. 시리얼 baud rate으로 저희가 230400을 사용하는데, 무지 빠른 속도로 출력되는 값을 생각해보면 사실 당연한 결과입니다. 5개가 출력되는데 걸리는 시간은 매우 짧죠. 즉 그만큼 평균치도 큰 의미가 없다고 볼 수 있습니다.




2. a=10


이번엔 10개를 평균으로 잡아보았습니다. 위와는 확실히 다르죠? 오차가 좀 더 보정된 것을 보실 수 있습니다.

그런데 y축을 보시면, 역시 각도 값이 0.5도는 튀는 것을 보실 수 있죠.. 

(참고로 가운데 이상하게 튀는 구간은, 센싱 문제가 아니라 저희가 손으로 살짝 건드린 부분 같습니다.)





3. a=20


이번엔 20개를 평균치로 구해봤습니다. 오차가 확실히 줄어들었죠. 심지어 저희가 손으로 친 부분도 크게 줄었는데요.

이 이상 넘어가면, 오차뿐만 아니라 실제 변화량까지 줄여버리는게 아닐까 걱정이 슬슬 되네요...




4. a=40


심심해서 40개도 평균치를 구해봤습니다. 확실히.. 줄었죠.





위와 같은 알고리즘을 통해 오차를 한번 더 필터링 할 수 있을 것으로 기대됩니다. 그러나 실제 적용했을 때, 적당한 개수를 잘 구하는 게 관건이 될 듯 하네요. 

너무 작게 잡으면 오차 보정 효과가 미미할 것이고, 너무 크게 잡으면 실제 각도 변화까지 오차로 인식해버릴 우려가 있습니다.

실험을 통해 검증해봐야겠죠?
사실 결론적으로는, 이 방법을 사용하지 않아도 될지도 모릅니다. 센싱이 갑자기 튀는 이유만 밝혀낼 수 있다면요!


오늘 포스팅은 여기까지입니다!! 학기가 시작하고 나니, 일 진행이 좀 더딘 감이 좀 있네요. 하지만 금방 해낼 수 있으리라 믿습니다!!!!!!!!