본문 바로가기
Developer/Drone DIY

드론 DIY | 아두이노 mpu6050 각도 코드 및 이론

by Doony 2016. 2. 9.


음.. 사실 이 드론 DIY 포스팅의 목적은, 누구나 쉽게 이해할 수 있도록 서술하는 것이다. 음... 조금만 목적을 바꾸기로 했다.

누구나 조금만 관심있게 찾아본다면 드론을 만들 수 있도록?


그리고 기존에 이 드론의 형상은 말그대로 비행기형상이었다. 두개의 프로펠러를 가지고, 가벼운 비행기 형태의 프레임으로 제작하려고 했는데 상황이 상황인만큼, 그냥 일반적인 쿼드콥터로 진행해보려고 한다.


이번 포스팅에서는 mpu6050 이라는 각도 센서에서 각도를 추출하는 방법과 기본적인 회전 이론에 대해 다루고자 한다.


지난 포스팅에 아두이노가 대체 왜 필요한지에 대해 서술했다. 대체 아두이노란 녀석이 드론에서 뭐하는 녀석인지.. 

정리하자면 바로 두뇌였다. 내가 원하는 움직임을 위해 모든 명령을 전달할 놈이 바로 아두이노.

그렇다면 명령을 위해 필요한 도구들이 있어야하지 않겠는가!


이를테면 현재 드론이 수평선을 기준으로 어느정도 기울어져 있는지를 알아야 명령을 내리던지 말건지 할게 아닌가.

그 기울어져 있는 걸 쉽게 우리는 각도라고 말할 것이다. 그리고 그 각도를 계산하는 것도 역시 아두이노의 역할이다.


아두이노 자체만으로는 각도를 추출할 수 없다. 센서가 없기 때문이다.

따라서 각도 측정을 위해 각속도값, 그리고 가속도 값을 측정하는 센서가 필요한데 mpu6050이 그 하나의 예시인 것이다.

mpu6050 말고도 각도 측정을 위한 센서는 다양하다. 다만 내가 해본게 mpu6050이고해서 이걸로 결정!



우리는 3차원 세계에 살고 있다. x축, y축, z축이 바로 그러하다. 이과생이라면 당연히 받아들이겠지만 혹시 문과생일 수 있으므로 간단히 설명을 하자면,

지금 당장 손가락을 펴서 아래 그림과 비교해보길 바란다.




사실 이건 플레밍의 왼손법칙을 나타내는거긴 한데, 그건 무시하고 손가락만 저렇게 하면 된다.

자, 이 때 중지가 x축, 엄지가 y축, 검지가 z축이 되는 셈이다. 세 손가락을 기준으로 손을 회전시키면 각자 독립된 방향으로 회전하는 것을 알 수 있다.

내가 말해놓고도 헷갈리는데 사실 뭔소린지 이해가 안가면 그냥 넘어가도 무방..


암튼, 우리는 3개의 축을 가진 세상에 살고 있는 것이다!!

드론을 하나 놓고 생각해보자. 이 녀석이 회전할 수 있는 방향이 3개가 있는 것이다. 왜? 독립된 축이 3개가 존재하니까 말이다.

인터넷에서 드론 조사하다보면 쉽게 접할 수 있는 pitch, roll, yaw 가 바로 그 3개의 축인 것이다.


pitch는 위 손가락에서 중지에 해당하고, roll은 위 손가락에서 엄지에 해당한다. 그리고 yaw는 검지, 즉 제자리 회전에 해당하는 축이다.

보다시피, 드론이 자세제어에 필요한 축은 pitch와 roll이다. yaw는 제자리 회전이기 때문에 떠있는데는 굳이 필요하지 않다. (아주 엄격히 말해서는 아니겠지만)


mpu6050이 가진 센서는 각 3개의 축에 대한 각속도, 그리고 가속도를 측정할 수 있다. 6축 센서인 것이다. (3+3이니까)

이를 통해 검출할 수 있는 각도는 2개이다. pitch에 대한 것, roll에 대한 것. 즉 축을 기준으로 각도가 얼마나 기울어졌는지 측정가능하다.

그렇다면 yaw는? yaw는 z축에 해당하는데 이를 알기 위해서는 자기장 센서가 따로 필요하다. mpu6050에 자기장까지 포함하여 9축 센서 모듈이 따로 있는데 정확한 모델은 잘 생각이.. 9축이라고 되어있으면 아무튼 yaw까지도 구할 수 있다.


하나하나 짚어보도록 하자.




내가 만들고자 하는 드론은 yaw제어는 하지 않는다. 

왜? 내가 mpu6050밖에 없기 때문에.. 

yaw제어를 하지 않는다는 것은 드론이 제자리회전을 해도 막을 수 없다는 것이다. 그런데 생각해보자. 왜 드론이 제자리 회전을 할까?

제자리에서 회전을 하는 이유는, 회전모멘트가 0이 아니라 양의 값, 혹은 음의 값을 가지기 때문이다. 이론적인거 복잡하게 따질 필요 없이 쉽게 생각해보자. 


출처: https://en.wikipedia.org/wiki/Quadcopter



보다시피 쿼드콥터의 날개 4개는 2개는 시계방향, 2개는 반시계 방향으로 돌아야한다. 만약 모두 시계방향으로 돌면, 회전하려는 성질이 모두 시계방향에 가있기 때문에 드론 기체 자체도 시계방향으로 회전하려는 성질을 갖게 된다. 프롭이나 드론이나 다 붙어있으니까!!!

때문에 회전하려는 성질을 분산하기 위해 2개씩 다른 방향으로 둔 것이고, 각각 2개씩 회전하려는 성질의 크기가 똑같다면 제자리에서 회전하지 않고 그대로 멈추어 있을 수 있는 것이다.

그런데 2개씩 다른 방향으로 했는데도 제자리 회전을 한다? 그건 2개와 나머지 2개의 추력 정도가 다르기 때문이다.


나중에 할 이야기지만, PID 제어에서 중요한 부분 중 하나가 여기에 있다. pitch와 roll은 각각 다른 PID 값을 가지게 된다. 이 때 제어하는 PID 수치가 서로 많이 다르게 되면 당연히 제어에 들어가는 추력의 크기도 다르게 되고 때문에 제자리회전할 가능성이 생긴다.

비슷한 PID 게인값을 가지기 위해서는 되도록 무게 균형을 잘 맞추는 것이 중요하다. 한 축에만 무게가 쏠리게 되면 당연히 PID 값이 달라질 수밖에 없다. 되도록 대칭을 이루도록!!

암튼 이건 나중에 더 자세히.







PID 게인값들을 잘 맞춰서, 4개의 모터에 들어가는 추력이 어느정도 대칭성을 이룬다면 제자리 회전이 크게 문제가 되진 않는다.

따라서 mpu6050으로 구할 건 pitch와 roll부분이다. 피치 롤 이런 말도 사실 딱히 신경쓸 필요없다. 그냥 x축 y축이라고 봐도 무방. 정확히 얘기하면 나도 피치 롤이 어느쪽이고 어디고인지는 헷갈린다 알아봐야 나온다 ㅋㅋㅋ



그렇다면 대체 센서를 통해 어떻게 각도를 얻을 것인가?

크게 3가지 방법이 있는 듯 하다. 


상보필터 | 칼만필터 | DMP


모두 오픈소스로 인터넷에 자료가 배포되어 있다. 따라서 가져다 쓰기만 하면 되는건데 사실 드론 처음 만드는 사람 입장에서는 오픈소스라고 해도 갖다 쓰기가 힘들다. 고로 하나씩 짚어보도록하자.


그 전에 mpu6050과 아두이노를 연결해주어야 하는데 회로는 아래와 같다.



그냥 이대로 핀 꼽고 해주면 된다. 참고로 아두이노 우노가 아니라 메가나 다른 버젼을 쓰는 분들은 아두이노 홈페이지에 가서 SCL, SDA가 어느 핀인지 먼저 정보를 얻어야 한다. 메가 같은 경우 SCL, SDA라는 글자가 따로 써있던 것으로 기억한다. 우노라면 A4와 A5에 넣어주면 된다.



상보필터와 칼만필터는 위에서 얘기한 6개의 값, 3개의 각속도와 3개의 가속도값을 가지고 각도를 추출하는 필터들이다. 수식적으로 뭔가 있는데 그건 중요하지 않고 우리는 오로지 각도에만 초점을 맞추도록 하자. 왜냐!! 나도 잘 모르니까. 일단 소스를 받도록 하자.

아래 파일을 받자.







파일과 같은 이름의 폴더 안에 3개의 파일을 넣고, kalman_comp_filter.ino 파일을 업로드 하자. 기본적으로 파일은 칼만필터를 통해 구한 X축, Y축 각도 값이 시리얼모니터를 통해 출력되게 되어있다. (baud rate은 230400으로 맞춰주면 나온다)

그리고 그 파일에서 다음의 변수를 살펴볼 필요가 있다.


compAngleX : 상보필터로 구한 X축 각도

compAngleY : 상보필터로 구한 Y축 각도

kalAngleX : 칼만필터로 구한 X축 각도

kalAngleY : 칼만필터로 구한 Y축 각도


업로드 한 뒤, mpu6050 센서를 이리저리 흔들어보면 위 4개의 값이 다 흔들리는 것을 알 수 있는데 특정 축을 기준으로 돌려보면 하나만 변하는 것을 알 수 있다. 아무튼 상보필터만 쓰든~ 칼만필터만 쓰든 하면 되는데..

이 필터들의 문제점은 아두이노에서 다 계산이 이루어지고.. 진동에 취약하다는 점이다. 실제로 상보필터와 칼만필터를 적용하여 코드를 돌려보면 각도가 아주 잘~~~~ 나온다. 그런데 문제는, 모터를 동작시키는 순간 엄청 튄다는 것이다.


그래서 한가지 방법이 뭐냐! 바로 low pass filter을 사용하는 것이다. 엥 이것도 필터???

음.. 위에서 상보필터, 칼만필터를 통해 구한 각도 값을 또 한번 필터링 하는게 바로 low pass filter이다. 이걸 실험하기 위해서는 코드에서 아래부분을 찾자.


i2cData[1] = 0x00;


이 부분이 DLPF, 즉 digital low pass filter을 변경하는 코드 부분이다. 


0x00 : 256hz

0x01 : 199hz

0x02 : 98 hz

0x03 : 42 hz


이렇게 뒤에 숫자를 바꿔주면 필터링할 주파수를 변경시킬 수 있다. Hz 수치가 낮아질수록 더 많이 필터링 한다는? 표현이 좀 애매한데 암튼 진동으로 인해 튀는 값들을 더 많이 필터링해버린다. 그렇게 되면 기존에 빠릿빠릿하게 계산해주는 각도값이 느릿느릿하게 계산되는 것과 같은 꼴이 되기 때문에, 당연히 반응성이 조금 낮아지게 된다. 다만 그 만큼 진동으로 튄 값을 보정해줄 수는 있다.


그러나 이렇게 해본 결과, 반응성이 너무 떨어져서인지 사실 제어가 제대로 되지 않았다. Low pass filter을 사용하는 것은 나쁘지 않은데, 문제는 진동 자체가 워낙 커서.. 손으로 심하게 느껴질 정도라 아무래도 필터링만으로는 한계가 있는 듯 했다.

애초에 방진을 위한 장치를 잘 해놓거나 해야하는데 mpu6050을 바로 드론 프레임이 붙여버리면 아마 이방법으로는 드론을 제대로 제어하기가 쉽지 않을 것이다.







엥.. 그렇다면 방법이 없는 것인가!!!! 

아니다 방법이 있다. 아직 소인에겐 DMP라는 것이 남아있사옵니다. DMP는 대체 뭔가!??? 약어는 까먹었다. 의미보다도 되는게 중요하니까!!

DMP라는 방법은, mpu6050 센서 자체를 더 효율적으로 사용하는 것이다. 내부 레지스터를 통해서 뭐 계산한다고 어쩌고 하는 글을 본 기억이 난다.

아무튼 일단 코드를 다운 받자.





이 안에는 2개 폴더가 있다. 하나는 libraries인데, 이건 아두이노 라이브러리 폴더에 들어가야한다. 지금 하는 것과 관련없는 부분도 있는데 아무튼 필요한 부분이므로 libraries에 미리 복붙해주도록 하자. 경로는 컴터마다 다르겠지만 나의 경우, C:\Program Files (x86)\Arduino\libraries 이다.


암튼 그 후에 dmp_mpu6050.ino 파일을 실행.

아래의 변수에 주목하자.


ypr[1] : DMP를 통해 구한 X축 각도

ypr[2] : DMP를 통해 구한 Y축 각도


위 두개를 Serial.print 함수를 통해 출력해보면 각도값이 나오는 걸 알 수 있다. 자세한 이유는 잘 모르겠지만 아무튼 이 방법은 진동을 받아도 값이 튀지 않고 비교적 정확하게 나온다. 그래서 드론 제어를 할 때 매우 용이하다.




사실 이 코드를 드론에 적용하기 위해서는 한번 더 캘리브레이션하는 과정이 필요하다.

지난 포스팅에 ESC 캘리브레이션 하는 건 포스팅했는데, 각도추출을 위한 캘리브레이션이 또 한번 필요한 셈!

생각해보면 당연한 얘기다. mpu6050이라는 센서가 정확히 수평상태로 드론에 장착될 수 없기 때문이다.

어느쪽으로든, 살짝은 기울어져서 드론에 장착될 것이다. 혹은 드론 프레임이 조금 기울었을 수도 있고. 그래서 평지에 놨을 때 각도센서가 기울어져 있게 되는데, 이 때 살짝 기울어진 상태에 영점을 맞추는 과정이 필요한 것이다.


여기에는 다른 아두이노 소스들이 좀 더 필요한데 이건 나중에 드론을 실제로 만들 때 포스팅해야겠다.





이렇게 필터든, dmp든 각도를 추출했으면 이제 드론 PID 제어에 사용하게 된다. 즉 센서가 각도를 추출해냈으니, 아두이노는 이 각도를 드론 자세제어에 사용하게 되는 것이다.


오늘은 여기까지!!!!



댓글