Hardware | Digital Compass - HMC5883L 사용기 - 3

|

이 글은 전편 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

https://diydrones.com/profiles/blogs/advanced-hard-and-soft-iron-magnetometer-calibration-for-dummies



영점 조절을 위한 arduino code, Visual Studio 2010 C# 을 이용한 검증 어플 및 계산 어플까지 all set 를 혼자 만드신 분이죠.

위의 블로그에서 가져온 소스를 여기에 올려 놓습니다.


MagMaster.rar


위의 압축파일에 모든게 들어 있습니다만,

한가지 아쉬운 것은, 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

http://henrysbench.capnfatz.com/henrys-bench/arduino-sensors-and-input/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/



저는 이렇게 연결하고 윙윙 휘둘렀습니다.

그래서 몇 개씩 값이 튀기도 하고...



혹시... 혹시 나중에 기회가 되면, 그땐 위의 전문가들 처럼 해보고 싶네요.


And