본문 바로가기
DSP, MCU/STM32 (ARM Cortex-M)

STM32 ] 지자기 센서 HMC5883L 으로 방위각 측정하기 - 프로젝트 준비 과정 (2)

by eteo 2022. 7. 2.

 

 

HMC5883L 은 3축 마그네틱 감지센서 (Magnetometer) 로 나침반처럼 방위각을 알아낼 수 있어 Compass module 이라고 불린다. I2C 통신을 사용하여 데이터를 추출한다.

 

 

요즘에는 HMC5883L 모듈이 단종되어 QMC5883L 이라는 칩이 유통되고 있는데 QMC5883L 모듈은 I2C slave address 와 register address 가 달라서 다른 라이브러리를 써야 한다. 나는 HMC5883L 모듈을 사용하였다.

 

 

 

 

 

 

 

Specification

https://www.best-microcontroller-projects.com/hmc5883l.html

 

 

 

Datasheet

hmc5883l.pdf
0.75MB

 

 

 

참고.

지자기장(Magnetic field of the Earth) 은 지구의 내부로부터 태양풍과 만나는 곳까지 뻗어있는 자기장인데, 태양풍은 태양으로부터 방사되는 하전입자들의 흐름이다. 지구 표면에서의 규모 범위는 25에서 65μT(마이크로 테슬라)(= 0.25-0.65 가우스)까지이다. 대략적으로 회전 축에 대하여 10 도의 각도로 기울어진 자기 쌍극자의 필드이다(지구의 중심에 해당 각도로 배치된 막대 자석처럼). 그러나 지구의 외핵에서 용융된 철 합금의 움직임에 의해 생성되기 때문에 ,막대 자석의 자기장과는 달리 지구의 자기장은 오랜시간에 걸쳐서 변화한다.

전 세계 지구자기장의 크기는 25 μT에서 65 μT 정도이며, 한국의 경우 40 μT이다. 자기장은 비록 근원에서 멀어질수록 점점 약해지지만 무한하게 뻗어나간다. 지구의 자기장은 수만 킬로미터 정도 유효하게 퍼져 있어 자기권이라 불린다. 지자기의 일변화는 대한민국에서는 여름에 100 nT 정도다.

자북점은 이동하지만, 보통 나침반 탐색에 충분히 유용할정도로 매우 느리게 이동한다. 나침반의 자침은 지구 자기장 방향으로 배열되며 나침반의 N극은 자북극을 향한다. (위키백과)

 

 

 

 

 

배선

HMC5883L
VCC +3.3V
GND GND
SCL PB8 (I2C1)
SDA PB9 (I2C1)

 

I2C 핀의 GPIO 설정은 풀업으로 한다.

 

 

 

라이브러리 출처 :

https://github.com/DoanDuongVN/HMC5883L_STM32

https://github.com/jarzebski/Arduino-HMC5883L

 

 

 

위의 STM32 라이브러리를 머지하고

 

while 문 시작 전에 아래와 같이 셋업하고

  /* USER CODE BEGIN 2 */

  HMC5883L_setRange (HMC5883L_RANGE_1_3GA);
  HMC5883L_setMeasurementMode (HMC5883L_CONTINOUS);
  HMC5883L_setDataRate (HMC5883L_DATARATE_15HZ);
  HMC5883L_setSamples (HMC5883L_SAMPLES_1);
  HMC5883L_setOffset (0, 0);

  /* USER CODE END 2 */

 

 

 

while문에서 아래와 같이 값을 구해 UART로 출력한다.

 

 

  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  Vector mag = HMC5883L_readNormalize ();
	  printf ("XAxis %0.2f, YAxis %0.2f, ZAxis %0.2f \r\n", mag.XAxis, mag.YAxis, mag.ZAxis);

      // Calculate heading
	  float heading = atan2(mag.YAxis, mag.XAxis);
      
	  // Set declination angle on your location and fix heading
	  // You can find your declination on: http://magnetic-declination.com/
	  // (+) Positive or (-) for negative
	  // For Bytom / Poland declination angle is 4'26E (positive)
	  // Formula: (deg + (min / 60.0)) / (180 / M_PI);
	  float declinationAngle = (-8.0 + (50.0 / 60.0)) / (180 / M_PI);
	  heading += declinationAngle;
	  // Correct for heading < 0deg and heading > 360deg
	  if (heading < 0)
	  {
	  heading += 2 * M_PI;
	  }
	  if (heading > 2 * M_PI)
	  {
	  heading -= 2 * M_PI;
	  }
	  // Convert to degrees
	  float headingDegrees = heading * 180/M_PI; 


	  printf ("headingDegrees : %.0f\r\n", headingDegrees);


	  HAL_Delay(100);
	  /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

 

 

 

여기서 heading 은 0에서 2π 사이의 값을 가지는 라디안 단위이고 heading 에 *(180/π) 를 곱해서 도° 로 변환해준다.

 

 

 

 

사용전 설정 방법

 

0. 측정시 주변에 자성을 띄는 방해요인에 노출되지 않도록 한다.

 

1. 자편각 보정하기

 

지자기 센서를 통해 측정되는 값은 진북이 아닌 자북이다.

 

자북(Magnetic North)이란 나침반의 N극이 가리키는 북쪽으로 캐나다 북쪽 허드스만 부근에 위치한 천연자력지대를 가리키며, 해마다 조금씩 이동하고 있다.

 

진북(True North)은 언제나 변하지 않는 북쪽으로 북극성의 방향을 뜻한다.

 

도북(Grid North)은 지도상의 북쪽으로 지도 세로선 위쪽을 말한다.

 

진북과 자북의 차이는 자편각이라고 하며, 지자기 센서에서 측정되는 북쪽은 자북이므로 진북을 알아내기 위해서는 자편각 값 만큼 보정해주어야 한다.

 

 

 

 

아래 사이트에서 지역별 자편각을 확인할 수 있다.

https://www.magnetic-declination.com/

 

 

 

위도와 경도가 나오고

Magnetic Declination은 Negative로 도분초 표기법을 써서 -8도 50분 이라고 읽는다. 따라서 아래와 같은 코드로 보정해주었다.

float declinationAngle = (-8.0 + (50.0 / 60.0)) / (180 / M_PI);
heading += declinationAngle;

 

 

 

 

 

2. Calibration 하기

 

Calibration은 센서를 사용하기 전 초기값을 교정해주는 작업을 말한다.

 

아래와 같은 코드로 x, y축 값만 출력되게끔 한다.

printf ("%0.2f, %0.2f\r\n", mag.XAxis, mag.YAxis);

 

 

 

마치 이런식으로 빙글빙글 돌려준다. 바닥에 두고 할 필요는 없고 바닥과 수평을 유지한상태에서 왔다갔다 360도 돌리면 된다.

 

 

출력된 값을 모두 복사해서

 

 

엑셀에 붙여넣기 한다.

 

 

쉼표 구분기호로 셀을 분리시킨다.

 

 

 

삽입 - 차트 - 분산형

 

 

 

 

원형이 그려지는데 x축으로 40만큼, y축으로 -200만큼 치우친 것이 확인됐다.

 

이 값만큼 오프셋을 조정해주어야 한다.

 

 

 

내가 사용하는 라이브러리는

 

while문 시작 전 지자기센서 셋업시 오프셋을 설정하고,

실시간으로 x, y, z 축 값을 반환하는 함수를 살펴보면 해당 오프셋만큼 빼주고 있다.

 

 

 

 

 

따라서 셋업 코드를 아래와 같이 설정한 뒤

 

HMC5883L_setOffset (40, -200);

 

 

다시 측정해 봤을 때 원점을 기준으로 원이 그려지는 것을 확인하였다.

 

 

 

 

 

 

 

 

 

지자기센서의 x축 화살표가 그려진 방향을 북쪽으로 향하게 하고 측정했을 때 UART 출력화면을 보면 360~0의 근사치가 나온다.

 

 

 

 

 

x축 화살표를 핸드폰과 동일한 방향으로 두고 실시간 값 측정했을 때 핸드폰의 방향센서와 비슷한 값이 출력된다.

 

 

 

 

 

 

 

 

+

위의 코드는 테스트용이고 실제 사용할 때는 아래처럼 사용했다.

라이브러리 파일에 calculateHeading이라는 함수를 만들어 필요한 문구를 넣어두고 HAL_Delay를 쓰지않고 sysTick 차이를 사용해서 실행되게 끔 했다.

70ms 의 간격으로 실행되게끔 한것은 위에서 셋업한 센서의 측정주파수가 15Hz(디폴트값)이기 때문이다.

while (1)
{
	current_tick = HAL_GetTick();
	if(current_tick - start_tick >= 70){
	    calculateHeading();
        start_tick = current_tick;
    }
}
HMC5883L_setDataRate (HMC5883L_DATARATE_15HZ);