이 글은 전편 2개가 있습니다.
* Hardware | Digitial Compass - HMC5883L 사용기 - 1
- https://chocoball.tistory.com/entry/Hardware-Digital-Compass-HMC5883L-1
* Hardware | Digital Compass - HMC5883L 사용기 - 2
- https://chocoball.tistory.com/entry/Hardware-Digital-Compass-HMC5883L-2
1. Why calibration?
이 HMC5883L 이나, 기타 digital compass 는 영점조정이 필요합니다.
Calibration 을 하기 전은 정확성에 있어서 사용할 수 있는 물건이 아니라고도 할 정도 입니다.
또한 지구상에서 내가 어디에 있느냐에 따라 자력의 방향과 세기가 달라지므로, 공장에서 만들어 졌던 들,
이 영점 조정은 꼭 필요하게 된다는 이야기가 됩니다.
현재 위치하고 있는 지리적 장소에 따라 변하는 자력을 계산해 주는 사이트도 있습니다.
* NCEI Geomagnetic Calculators
- https://www.ngdc.noaa.gov/geomag/calculators/magcalc.shtml
2. Yury Matselenak
아래 그림처럼 직각 육면체 (박스) 를 이용하여 영점 조정한 사람이 있습니다.
* Advanced hard and soft iron magnetometer calibration for dummies
영점 조절을 위한 arduino code, Visual Studio 2010 C# 을 이용한 검증 어플 및 계산 어플까지 all set 를 혼자 만드신 분이죠.
위의 블로그에서 가져온 소스를 여기에 올려 놓습니다.
위의 압축파일에 모든게 들어 있습니다만,
한가지 아쉬운 것은, 2014년에 만들어진 코드라, 최신 Arduino IDE 에서는 제대로 동작하지 않습니다.
동작만 한다면, 이 분이 안내하고 만들어진 프로그램을 사용하여 영점 조정이 가능하나, 그러지 못했네요.
시간이 생기면 소스를 분석하고, geomagnetic 에 대해 공부하여 소스 개선을 좀 해주고 싶으나, 현재 그럴 여유는 없습니다.
Yuri 아저씨의 방식을 잠깐 설명해 보면, HMC5883L 센서는, PCB에 프린팅 된 XYZ 축의 모양에 따라 다음과 같은 축을 가집니다.
이 센서를 가지고 다음과 같이, 북쪽을 0도로 정하고 3차원 공간에서 XYZ 값을 가져오면, 틀어진 중심점을 알 수 있으니,
측정시에 그 틀어진 만큼을 빼주거나 더해주면 된다는 이론 입니다.
모두 12가지를 측정하여, 그 값들을 가지고 틀어진 중심점을 구하는 방식 입니다.
3. Sequential Quadratic Programming
측정된 값을 가지고 SQP (Sequential Quadratic Programming) 을 통해 최적의 영점을 잡아주는 방식도 있습니다.
(보다 기술적인 것은 잘 모름)
본 방식은, 아래 블로그에서 소개되었습니다.
* 電子コンパスHMC5883Lのキャリブレーションに挑戦
- http://tomoto335.hatenablog.com/entry/arduino/HMC5883L
결과적으로 SQP 를 실행해야 하는데, 이를 Octave (상용 MatLab 의 GNU 버전) 을 통해서 답을 구할 수 있다고 하네요.
Yuri 아저씨 방식이 안되니, 이 방식으로 진행해 봅니다.
4. Octave
SQP 계산을 위해, 일단 Octave 를 설치해 봅니다.
* GNU Octave
- https://www.gnu.org/software/octave/
사용하는 OS 에 맞게 다운로드 하구요.
인스톨 실행파일을 실행 시킵니다.
나에게 맞게 설정하구요.
저는 바탕화면이 지저분하게 되는게 싫어서 "Install for all users" 만 선택했습니다.
BLAS library 는 뭔지 모르니 그냥 OpenBLAS 로 놔뒀습니다.
Windows 10을 새로 깔았더니만 JRE 가 없네요. Octave 는 JRE 가 필요하다 합니다. 깔아 줍니다.
자 이제 다음으로 넘어갑니다.
5. 연결
우선 arduino 와 HML5883L 을 다음과 같이 연결합니다.
HMC5883L | Arduino Nano ------------------------- VCC | 5V GND | GND SCL | A5 SDA | A4 -------------------------
그리고 I2CScanner / I2Cdetect 를 이요하여 address 0x1E 를 통해서 잘 인식 되었는지 확인합니다.
0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- 1e -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
Hardware 준비는 끝났으니, arduino source 준비로 넘어갑니다.
6. 값을 입력받자
HMC5883L 을 구동시켜 주는 몇 가지 Library 들을 확인해 봤는데, Adafruit 에서 만든 Unified library 가 가장 짱인 것 같습니다.
OS 를 싹 밀었더니만 예전 library 가 다 날라갔네요. 깔끔하게 다시 설치해 줍니다.
바로 실행하면, Octave 에서 계산을 방해하는 문자들이 들어가니 아래와 같이 단순한게 XYZ 값만 입력받게 합니다.
#include "Wire.h" #include "Adafruit_Sensor.h" #include "Adafruit_HMC5883_U.h" /* Assign a unique ID to this sensor at the same time */ Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345); void setup(void) { Serial.begin(9600); /* Initialise the sensor */ if(!mag.begin()) { /* There was a problem detecting the HMC5883 ... check your connections */ Serial.println("Ooops, no HMC5883 detected ... Check your wiring!"); while(1); } } void loop(void) { /* Get a new sensor event */ sensors_event_t event; mag.getEvent(&event); /* Display the results (magnetic vector values are in micro-Tesla (uT)) */ Serial.print(event.magnetic.x); Serial.print(","); Serial.print(event.magnetic.y); Serial.print(","); Serial.println(event.magnetic.z); }
그러면 다음과 같은 결과들을 얻을 수 있습니다.
... -21.82,-9.36,-41.94 -16.45,-8.73,-47.24 -16.45,-8.73,-47.24 -16.45,-8.73,-47.24 -9.64,-6.91,-51.43 -9.64,-6.91,-51.43 -9.64,-6.91,-51.43 -3.55,-4.00,-53.27 -3.55,-4.00,-53.27 -3.55,-4.00,-53.27 2.55,-1.27,-54.18 ...
Serial Monitor 의 값들을 카피하여 txt 파일로 하나 만들어 놓습니다. 이게 Octave 에서 사용될 소스 값입니다.
참고로 Yuri 아저씨가 만들어 주신 MagMaster 프로그램 중에, MagViewer 라는게 있습니다.
실행시키면, 입력받을 Serial Port 를 물어보는데, arduino 와 연결된 port 를 지정하면 값들을 읽어와서 3차원 공간에 뿌려 줍니다.
훗, 확실히 틀어져 있군요.
동영상으로도 올려 봅니다. Graph Fetish 인지라, 이런거 보면 사족을 못 씁니다.
마우스로 요리조리 움직일 수 있어서 3차원 공간에서 어떻게 값들이 찍히는지 실시간으로 알 수 있습니다.
7. 영접을 찾아 보자
이제 Octave 에서 SQP 를 시켜 볼 차례 입니다.
Serial Monitor 에서 받은 값들을 파일로 만든 다음, Octave 내에서 아래 command 를 실행 시킵니다.
global points points = csvread("HMC5883L_org_uncal.txt"); scatter3(points(:,1), points(:,2), points(:,3));
느낌이 예전 GNU Plot 을 사용하는 것이랑 매우 비슷하네요. Command 도 비슷하고.
짜잔~! 3차원으로 찍힌 그림을 그려줍니다. 이는 아까 MegViewer 로 본 모습이기도 합니다.
값들이 모두 입력 되었으니, 틀어진 값을 찾기 위해 SQP 해 봅니다.
function retval = sphere_errors(p, x) retval = sqrt( (p(:,1).-x(1)).^2+(p(:,2).-x(2)).^2+(p(:,3).-x(3)).^2).-x(4) endfunction function retval = sphere_error(x) global points retval = sum(sphere_errors(points, x).^2) endfunction x0 = [mean(points(:,1)), mean(points(:,2)), mean(points(:,3)), 100] result = sqp(x0, @sphere_error)
그러면 한참만에 아래 값들이 도출됩니다. 모든 값들에 대해 mash 형태로 계산을 하다 보니, 꽤 시간이 걸립니다.
계산에 의하면, 중심점은 (12.1, -5.9, -7.2) 반경 47.85 라고 나옵니다.
이 값들이 지금까지 찾았던 영점값 되겠습니다.
8. 영접값 적용하여 확인
이제 다시 arduino source 로 돌아와, 위에서 구한 값들을 입력받는 source 에 반영해 줍니다.
중심점이 벗어나 있으니, 그만큼 가감해서, 입력 받을 때, 자동으로 계산되게 해주면 됩니다.
MegViewer 를 통해 어떻게 변했나 확인해 볼까요?
오호이~. 적용이 되어서 둥그런 원 모양과 중심축에 붙어서 값들이 표현되었습니다.
이게 calibration 의 힘이란 말인가... (대박)
9. Further More
사실 저는 이 결과가 썩 마음에 들지 않습니다.
일단, 값을 입력받는 방식 차제를 아래 그림들 처럼 고정된 상태에서 선의 걸리적 거림 없이,
6면체의 각 면과 같이 회전하면서 값들을 받아야, 입력값을 신뢰할 수 있을 것 같았습니다.
* Arduino GY-273 HMC5883L Magnetometer Compass Tutorial
위와 같이 하려면, 아래 장치 처럼, 무선모듈을 추가해야 하고, 배터리로 구동시켜야 합니다.
* Tutorial: How to calibrate a compass (and accelerometer) with Arduino
- https://thecavepearlproject.org/2015/05/22/calibrating-any-compass-or-accelerometer-for-arduino/
저는 이렇게 연결하고 윙윙 휘둘렀습니다.
그래서 몇 개씩 값이 튀기도 하고...
혹시... 혹시 나중에 기회가 되면, 그땐 위의 전문가들 처럼 해보고 싶네요.
'Hardware' 카테고리의 다른 글
Hardware | ZP07-MP901 공기질 측정 센서 (0) | 2019.08.13 |
---|---|
Hardware | ADS1115 16bit 4채널 ADC 를 사용해 보자 (6) | 2019.08.12 |
Hardware | Arduino 를 DIY 해보자 - 2 (0) | 2019.08.04 |
Hardware | 납땜 주변 용품 (0) | 2019.08.02 |
Hardware | bluetooth 모듈 HC-06 / HC-05 사용해 보기 - 1 (0) | 2019.07.07 |