라이브러리를 이용한 관성센서 제어
이번에는 라이브러리를 이용하여 MPU-9250을 제어하는 방법에 대해서 알아보자. 앞서 소개한 두 가지 예제는 SPI 통신과 I2C 통신 방법을 설명하기 위해 기본적인 데이터만 MPU-9250으로부터 받아왔다.
이 센서를 이용하여 차후 다룰 이륜 밸런싱 로봇, 블루투스 자동차, RC-자동차, 드론 등 다양한 예제에서 사용된다.
그러기 위해서는 MPU-9250과 같은 관성센서를 이용하여 움직임(모션)을 분석하거나, 관성 값을 추측하거나, 진행방향(Heading direction)을 인지해야 한다. 이와 같은 데이터를 얻기 위해서는 관성센서에서 얻은 데이터를 우리가 원하는 형태의 단위나 논리적인 연산을 통해 가공해야한다. 일반적으로 센서 데이터의 단위나 스케일을 수정하는 방법은 사용하는 제품의 사양서(Specification manual)와 레지스터 맵(register map)을 참고하여 라이브러리를 작성한다.
하지만 라이브러리를 만드는 것은 제품을 사양을 완전히 이해해야 하며, 프로그래밍 수준이 어느 정도 되어야 잘 동작하도록 만들 수 있다. 게다가 센서의 로 데이터(raw data)를 응용하고자 하는 분야의 전문지식을 프로그램 코드로 녹여내기란 참 어려운 일이다.
센서를 내가 원하는 목적에 맞게 사용하는데 많은 어려움이 따르지만, 다행스럽게도 아두이노의 오픈소스 하드웨어(Open-source Hardware)와 오픈소스 소프트웨어(Open-source Software) 운동을 아래 많은 사용자들이 자신의 라이브러리를 공유하고 있다. 그렇기 때문에 잘 구성된 라이브러리를 우리의 사용목적에 맞게 가져와 사용하면 된다. 그리고 무언가 새로운 걸 해냈다면, 우리도 자료를 다른 아두이노 사용자들에게 공유해주도록 하자.
우선, 대표적인 오픈소스 코드 저장소인 GitHub를 이용하여 MPU-9250 라이브러리를 가져와 설치해 보자. GitHub란 분산 버전 관리 툴인 깃(Git)을 사용하는 프로젝트를 지원하는 웹호스팅 서비스로, 영리적인 서비스와 오픈소스를 위한 무상 서비스를 모두 제공하기 때문에 편리하게 이용가능하다.
라이브러리 설치방법
아두이노 라이브러리는 크게 두 가지로 분류할 수 있다.
첫번째로는 라이브러리를 직접 만들거나 GitHub와 같은 라이브러리 공유사이트에서 가져와 아두이노 라이브러리 폴더 하위로 붙여놓으면 된다. 두 번째 방법은 아두이노 통합개발환경(IDE)에서 라이브러리 관리자(매니저)를 통하여 가져오는 방법이다.
• 라이브러리 추가방법 1. 라이브러리를 아두이노 라이브러리 하위 폴더 위치시키기
• 라이브러리 추가방법 2. 아두이노 IDE 라이브러리 관리자를 통해 라이브러리 다운로드
첫번째 라이브러리 추가방법으로 라이브러리를 생성하거나 라이브러리 공유사이트(ex. GitHub)에서 내려받아 사용하는 방법 다음과 같은 절차를 거친다.
< 라이브러리 추가방법 1 >
라이브러리는 블로그나 카페에서 가져올 수 있지만, 전 세계적으로 이용하는 공개용 프로그램 소스 공유 웹사이트 GitHub를 이용하면 쉽고 빠르게 자신이 원하는 라이브러리를 얻을 수 있다.
< GitHub에서 라이브러리 다운로드 >
두번째 라이브러리 추가방법으로는 아두이노 통합개발환경(IDE)에서 라이브러리를 다운로드하는 방법이다.
<라이브러리 추가방법 2>
사용자의 컴퓨터에서 인터넷 연결이 된다면 아두이노 IDE를 통해 쉽게 라이브러리를 가져올 수 있다. 이 기능은 아두이노 라이브러리 관리자을 이용할 수 있으며 아두이노 IDE에 설치 가능한 라이브러리 목록을 보여준다. 아두이노 IDE의 옵션 바에서 ‘스케치’ 하위에 ‘라이브러리 포함하기’에서 ‘라이브러리 관리...’를 실행시킨다. 라이브러리 관리자(매니저)에서는 설치 가능한 라이브러리들이 보이며, 원하는 라이브러리 관련 단어를 통해 원하는 자료를 빠르게 찾을 수 있다.
<아두이노 IDE 라이브러리 관리자>
< 라이브러리 관리자에서 라이브러리 설치 >
라이브러리 관리자에서 설치한 자료는 아두이노 라이브러리 폴더에 위치하게 되는데, 일반적으로 사용자 PC의 ‘문서’ 하위 폴더 ‘Arduino’의 ‘libraries’에 설치된다. 자신이 설치한 라이브러리들을 확인하고 싶다면 아두이노 라이브러리 폴더에서 확인해 볼 수 있다.
참고로 기존 아두이노 기본 라이브러리들이 있다. 이 라이브러리들은 아두이노 프로그램을 설치한 하위 폴더에 존재하며 ‘문서’ 폴더에 존재하는 아두이노 라이브러리 폴더는 사용자 추가 라이브러리 폴더이다. 그렇게 때문에 설치한 라이브러리의 예제를 실행시키기 위하여 아두이노 IDE 옵션바에서 ‘파일’ → ‘예제’ → ‘사용자 지정 라이브러리 예제’에서 자신이 추가한 라이브러리 예제를 확인해 볼 수 있다.
< 아두이노 라이브러리 폴더에서 설치 확인 >
< 아두이노 IDE 추가된 예제실행 >
MPU-9250 라이브러리는 I2C와 SPI 통신을 모두 구현했기 때문에 ‘회로 1-1 SPI를 이용한 6축 모션센서 모듈-아두이노 연결회로도’ 또는 ‘회로 1-2 I2C를 이용한 9축 모션센서 모듈(GY9250)-아두이노 연결 회로도’ 중 아무거나 사용해도 된다. 우리는 I2C 통신을 이용한 회로도를 사용하였으며 예제 코드는 다음과 같다.
스케치코드 | 라이브러리를 이용한 관성센서 제어 예제
코드 설명
단순히 센서(sensor)를 이용해 측정한 주어진 환경의 데이터는 대부분이 의미가 없는 데이터이다. 그 이유는 실제 우리의 환경은 시시때때로 다양한 요인에 의하여 변하기 때문이다. 단적인 예로 시간에 따라 기온이 변하고, 센서를 잡고 있는 손도 떨리고 있기 때문에 가속도, 각속도가 검출된다. 그렇기 때문에 센서들은 대부분 미가공 데이터(raw data)는 보정(calibration) 과정을 통하여 의미 있는 값이 된다. 고가의 센서는 불안정한 센서에 대한 보정작업과 필터(filter)가 포함돼 있어 안정적인 측정데이터를 사용자에게 제공한다. 하지만 아두이노에서 사용하는 저가용 센서는 보통 이러한 데이터 보정작업이 없는 센서를 사용하기 때문에 대부분 라이브러리(library)를 포함하여 사용한다.
이 예제에서는 I2C 통신을 사용하여 수신 받은 9가지의 미가공 데이터를 의미 있는 데이터로 가공하는 작업으로써, MPU-9250 라이브러리에 포함된 다양한 레지스터(register) 정보를 이용하여 각기 다른 센서와 축에 대한 보정작업을 수행하는 프로그램이다.
라이브러리에 포함된 요소들은 .(포인트) 연산자를 통해 사용가능한데, 이 라이브러리에 정의된 클래스(class)를 우리 프로그램에서는 IMU로 (참조변수)선언하여 이용한다.
|
|
b. 가속도‧자이로센서의 축 | |
| |
a. 프로그램 처리과정 | c. 지자기센서의 축 |
[ MPU9250 프로그램 처리과정과 센서의 축 ] |
이 예제에서 수행하는 보정(calibaration)작은 크게 4 가지 과정을 통해서 수행한다. 첫 번째 단계는 자가진단(self-test) 단계로, 자가진단 모드 레지스터로 전환하고 다수의 측정데이터를 사용해 그 각각의 축에 대한 평균 전류 값, 평균 미가공 데이터 값, 공장 조정 값(factory trim)을 계산한다. MPU-9250에서는 200개의 샘플 데이터를 사용하며, AK8963에서는 40개의 샘플 데이터를 사용한다. 두 번째 단계는 보정 (calibration)작업으로 바이어스(bias)를 계산한다. 바이어스란 동작 기준점을 정하기 위하여 신호전극 등에 가하는 전압 또는 전류이다.
|
|
a. 입력신호 | b. 바이어스 신호에 의한 출력신호 |
[바이어스 신호를 통한 입력신호의 변화] |
세번째 단계에서는 센서 데이터를 받기 위해 모든 센서를 활성화(enable)시키고 레지스터에 설정된 값으로 초기화하는 작업이다. 초기화 설정된 값은
아래와 같다.
• 대역폭(Bandwidth) - 가속도센서 : 1.13 kHz - 자이로센서 : 42 Hz
• 샘플링 시간(sample rate) 가속도센서 : 4 kHz 자이로센서 : 200 Hz 지자기센서 : 139 Hz (하지만, 0 ~ 200 Hz로 제한되어 있음)
• 최대 크기 범위(full scale range) - 가속도센서 : +-2g - 자이로센서 : +-250deg/s - 지자기센서 : 16bit |
• 센서 융합 업데이트 속도 - 170 Hz = 1/5.9 ms (최소지연시간)
• 민감도 가속도센서 : 16,384 LSB/g 자이로센서 : 131 LBS/degrees/sec 지자기센서 : 1.6 LSB/uT
|
마지막 단계는 설정 값과, 계산된 바이어스(bias) 및 공장 조정(factory-trim)값을 사용하여 각각의 센서 축에 대한 측정 데이터를 보정(calibration)을 해주는 작업을 수행한다. 보정 작업이 끝난 데이터는 시리얼 통신을 통해 PC로 전송된다. 참고로 가속도센서와 자이로센서의 축 방향이 자이로센서와 달라 방향을 반전 시켜주기 위해 -1값을 곱해주었다.
< 코드예제 결과 >
심화 | 함수설명
uint8_t MPU9250::readByte(uint8_t deviceAddress, uint8_t registerAddress); | |
매개변수 | uint8_t 형, I2C 주소와 고유 레지스터 주소를 받는다. |
설명 | MPU9250 클래스에 정의된 함수로써 I2C 통신을 사용할 때 필요한 센서의 I2C 주소와 고유 레지스터 주소를 가져온다. 코드에서는 아두이노와 센서 간의 통신을 위한 WHO_AM_I (고유)레지스터를 읽어오는 중요한 역할을 한다. 최종적으로 I2C 통신을 통해 받은 디바이스 주소 또는 고유 레지스터를 SPI 통신으로 보낸 값을 리턴(return)한다. |
void MPU9250::MPU9250SelfTest(float * destination) | |
매개변수 | float 형 Self-test 응답 배열의 주소, 공장 조정값(trim)에서의 변화 비율을 나타낸다. |
설명 | 공장의 조정값과 그로부터 변경된 값을 퍼센티지로 계산하는 함수 |
void MPU9250::SelfTestPrint() | |
매개변수 | 매개변수 없음 |
설명 | 가속도센서와 자이로센서의 각 축에 대한 조정(trim)값을 시리얼 모니터에 보고한다. void MPU9250::SelfTestPrint() { Serial.print("x-axis self test: acceleration trim within : "); Serial.print(selfTest[0],1); Serial.println("% of factory value"); Serial.print("y-axis self test: acceleration trim within : "); Serial.print(selfTest[1],1); Serial.println("% of factory value"); Serial.print("z-axis self test: acceleration trim within : "); Serial.print(selfTest[2],1); Serial.println("% of factory value"); Serial.print("x-axis self test: gyration trim within : "); Serial.print(selfTest[3],1); Serial.println("% of factory value"); Serial.print("y-axis self test: gyration trim within : "); Serial.print(selfTest[4],1); Serial.println("% of factory value"); Serial.print("z-axis self test: gyration trim within : "); Serial.print(selfTest[5],1); Serial.println("% of factory value"); } |
void MPU9250::calibrateMPU9250(float * gyroBias, float * accelBias) | |
매개변수 | float형 배열의 주소, 자이로센서와 가속도센서의 바이어스(bias) 배열을 의미 |
설명 | 바이어스(bias) 레지스터를 읽어와 자이로센서와 가속도센서 교정(Calibrate) |
void MPU9250::initMPU9250() | |
매개변수 | 매개변수 없음 |
설명 | 가속도센서, 자이로센서, 온도센서 read 활성화 모드로 초기화 |
void MPU9250::initAK8963(float * destination) | |
매개변수 | float형 지자기센서 교정값이 저장된 배열의 주소 |
설명 | AK8963 ROM으로 부터 지자기센서 교정 |
GY9250.getAres(); | |
매개변수 | 2Gs:(00), 4Gs:(01), 8Gs:(10), and 16Gs:(11) |
설명 | 필요한 가속도센서 분해능을 선택하는 함수 |
GY9250.getGres(); | |
매개변수 | 250DPS:(00), 500DPS:(01), 1000DPS:(10), and 2000DPS:(11) |
설명 | 필요한 자이로센서 분해능을 선택하는 함수 |
GY9250.getMres(); | |
매개변수 | 14bit resolution:(0) and 16bit resolution:(1) |
설명 | 필요한 지자기센서 분해능을 선택하는 함수 |
void MPU9250::magCalMPU9250(float * bias_dest, float * scale_dest) | |
매개변수 | float형 지자기센서 bias 배열의 주소와 scale 배열의 주소값 |
설명 | 다음 요청을 4초 지연하고, 15초 동안 바이어스(bias)와 스케일(scale) 계산을 위한 데이터에 대한 보고를 시리얼 모니터에 출력한다. |
void MPU9250::AK8963Print() | |
매개변수 | 매개변수 없음 |
설명 | 지자기센서 바이어스(bias)와 스케일(scale)값을 시리얼 모니터에 출력 void MPU9250::AK8963Print() { Serial.println("AK8963 mag biases (mG)"); Serial.println(magBias[0]); Serial.println(magBias[1]); Serial.println(magBias[2]);
Serial.println("AK8963 mag scale (mG)"); Serial.println(magScale[0]); Serial.println(magScale[1]); Serial.println(magScale[2]); } |
void MPU9250::readAccelData(int16_t * destination) | |
매개변수 | int16_t형 가속도센서의 각 축의 정보를 가지고 있는 배열의 주소 |
설명 | 가속도센서 x, y, z 축 adc 값을 읽기 |
void MPU9250::readGyroData(int16_t * destination) | |
매개변수 | int16_t형 자이로센서의 각 축의 정보를 가지고 있는 배열의 주소 |
설명 | 자이로센서 x, y, z 축 adc 값을 읽기 |
void MPU9250::readMagData(int16_t * destination) | |
매개변수 | int16_t형 지자기센서의 각 축의 정보를 가지고 있는 배열의 주소 |
설명 | 지자기센서 x, y, z 축 adc 값을 읽기 |
void MPU9250::AccelPrint() void MPU9250::GyroPrint() void MPU9250::MagPrint() | |
매개변수 | 없음 |
설명 | 각각의 모든 축의 센서 값을 시리얼 모니터에 출력 void MPU9250::AccelPrint() { Serial.print(" ax = "); Serial.print(ax); Serial.print(" ay = "); Serial.print(ay); Serial.print(" az = "); Serial.print(az); } void MPU9250::GyroPrint() { Serial.print(" gx = "); Serial.print(gx); Serial.print(" gy = "); Serial.print(gy); Serial.print(" gz = "); Serial.print(gz); } void MPU9250::MagPrint() { Serial.print(" mx = "); Serial.print(mx); Serial.print(" my = "); Serial.print(my); Serial.print(" mz = "); Serial.print(mz); } |
참고자료
⦁MPU-9250 Product Specification Revision 1.1
⦁MPU-9250 Register Map and Descriptions Revision 1.4
⦁AK8963C - Asahi Kasei Microdevices DataSheet
⦁AK8963N - Asahi Kasei Microdevices DataSheet
⦁윤종호, 2015, 『데이터 통신』, 계백북스
⦁윤덕용, 2005, 『AVR ATmega128 마스터』, Ohm사
⦁웹사이트 Github의 sparkfun / MPU-9250_Breakout 자료 참고
'교육 자료 > Raduino' 카테고리의 다른 글
6. OLED 디스플레이를 이용한 움직이는 이미지 만들기 (0) | 2018.09.28 |
---|---|
5. OLED 디스플레이를 이용한 시계 만들기 (1) | 2018.09.28 |
3. I2C를 이용한 관성센서 제어 (0) | 2018.09.12 |
2. SPI를 이용한 관성센서 제어 (0) | 2018.09.12 |
1. SPI와 I2C를 이용한 관성센서 제어 (0) | 2018.09.11 |