'GY-273'에 해당되는 글 3건

  1. 2019.08.10 Hardware | Digital Compass - HMC5883L 사용기 - 3
  2. 2019.01.01 Hardware | Digital Compass - HMC5883L 사용기 - 2
  3. 2018.02.19 Hardware | Digitial Compass - HMC5883L 사용기 - 1

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

Hardware | Digital Compass - HMC5883L 사용기 - 2

|

이 글은 전편이 있습니다.


* Hardware | Digitial Compass - HMC5883L 사용기 - 1

http://chocoball.tistory.com/entry/Hardware-Digital-Compass-HMC5883L-1


위의 포스트에서는 HMC5883L 의 중국 버전인 QMC5883L 을 사용하는 분투기(?) 였고,

이번 글은 AliExpress 에서 정식 HMC5883L 을 파는 업자를 찾아서 구입후 사용해 보는 포스트 입니다.





1. 구매


그냥 저가의 HMC5883L 을 구입하면 아마도 QMC5883L 이 배달될 껍니다.

QMC5883L 은 대략 2 USD 언더로 구입할 수 있고, 정식 HMC5883L 은 3.5 USD 정도 합니다.


중국 판매자들도 조금의 양심은 있는지, 완전 짝퉁을 정식 부품과 동일하게 올려받지는 않는것 같아요.

이번에 구입한 판매 링크는 다음과 같습니다.


* GY-273 3V-5V HMC5883L Triple Axis Compass Magnetometer Sensor Module For Arduino Three Axis Magnetic Field Module

https://www.aliexpress.com/item/GY-273-3V-5V-HMC5883L-Triple-Axis-Compass-Magnetometer-Sensor-Module-For-Arduino-Three-Axis-Magnetic/32786802981.html



문제 없이 잘 도착했습니다.

두둥!!! 정말 이번에는 정품 chip 일까. 바로 확인해 봅니다.



오~!!! L883 이 찍혀 있군요. 정품 chip 입니다.



AliExpress 어플에서 보면 배송업자에게 구매자들이 질문하는 QnA 가 있는데, 그 질문들을 참고했습니다.

꽤나 많은 사람들이 진짜 "L883" 인지 문의하는 글들이 보입니다.



자세한 샷으로 확실하게 찍어 봅니다.



역시 pin header 는 스스로 납땜하라는 배려를 보여 줍니다.

이 취미는 이 맛에 하는거죠.



이 얼마나 고민하고 기다린 제품인지 모릅니다. 그래서 도착하자 마자 여러장 찍어 봤어요.





2. 회로


저번 QMC5883L 에서 했던 회로 구성과 완벽하게 같습니다.


  HMC5883L  | Arduino Nano
---------------------------
    VCC     |     3.3V
    GND     |     GND
    SCL     |     A5
    SDA     |     A4
---------------------------


저번 그림을 동일하게 사용해 주구요.



실제로 연결해 줍니다. 이것으로 준비는 끝.

I2C 로만 연결되니 다른 센서나 부품들 보다 확연히 단순합니다. 요즘 놀고있는 ESP8266 하려면 정말...


I2C detector 로 문제 없이 인식되는지 확인도 해봅니다.


#include "Wire.h"
#include "i2cdetect.h"
 
void setup() {
    Wire.begin();
    Serial.begin(9600);
    Serial.println("i2cdetect example\n");
    Serial.print("Scanning address range 0x03-0x77\n\n");
}
 
void loop() {
    i2cdetect(); // default range from 0x03 to 0x77
    delay(2000);
}


정식 chip 이라 전혀 문제 없이 인식 됩니다.

역시 돈이 최고인건가요... 싼거 쫒다가 힘들었던 저번 기억이 새록새록 생각납니다.



연결된 모습은 정말 간단하쥬?






3. sketch


저번 QMC5883L 에서 했던 회로 구성과 완벽하게 같습니다.

Arduino IDE 에서 가장 간단한 HMC5883L_compass 를 사용해 봅니다.


/*
  HMC5883L Triple Axis Digital Compass. Compass Example.
  Read more: http://www.jarzebski.pl/arduino/czujniki-i-sensory/3-osiowy-magnetometr-hmc5883l.html
  GIT: https://github.com/jarzebski/Arduino-HMC5883L
  Web: http://www.jarzebski.pl
  (c) 2014 by Korneliusz Jarzebski
*/

#include "Wire.h"
#include "HMC5883L.h"

HMC5883L compass;

void setup() {
	Serial.begin(9600);
	
	// Initialize Initialize HMC5883L
	Serial.println("Initialize HMC5883L");
	while (!compass.begin()) {
		Serial.println("Could not find a valid HMC5883L sensor, check wiring!");
		delay(500);
	}
	
	// Set measurement range
	compass.setRange(HMC5883L_RANGE_1_3GA);
	
	// Set measurement mode
	compass.setMeasurementMode(HMC5883L_CONTINOUS);
	
	// Set data rate
	compass.setDataRate(HMC5883L_DATARATE_30HZ);
	
	// Set number of samples averaged
	compass.setSamples(HMC5883L_SAMPLES_8);
	
	// Set calibration offset. See HMC5883L_calibration.ino
	compass.setOffset(0, 0);
}

void loop() {
	Vector norm = compass.readNormalize();
	
	// Calculate heading
	float heading = atan2(norm.YAxis, norm.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 = (4.0 + (26.0 / 60.0)) / (180 / M_PI);
	heading += declinationAngle;
	
	// Correct for heading < 0deg and heading > 360deg
	if (heading < 0) {
		heading += 2 * PI;
	}
	
	if (heading > 2 * PI) {
		heading -= 2 * PI;
	}
	
	// Convert to degrees
	float headingDegrees = heading * 180/M_PI; 
	
	// Output
	Serial.print(" Heading = ");
	Serial.print(heading);
	Serial.print(" Degress = ");
	Serial.print(headingDegrees);
	Serial.println();
	
	delay(100);
}


예전에 삽질한게 무엇? 이라고 말하듯 바로 실행됩니다.







4. Processing


Processing 이라는 어플은 센서로부터 오는 신호를 시각적으로 실시간 표현해 주는 어플 입니다.


* Processing



이 Processing 을 이용하여 실시간으로 공간 데이터를 시각적으로 표현하고자 합니다.

순서는 다음과 같습니다.


- Arduino 에 Processing 과 연동하기 위한 sketch 를 업로드 한다

- Processing 을 띄워, Arduino 와 연동용으로 만든 Processing sketch 를 실행한다


고맙게도 processing 과 연동해주는 소스를 jarzebski 라는 분이 만들었습니다.


* jarzebski/Arduino-HMC5883L

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

Arduino-HMC5883L-master.zip


위 zip 파일을 풀어서 "Arduino > libraries" 에 풀어줍니다.

그러면 아래와 같이 HMC5883L_processing 이라는 sketch 를 찾을 수 있습니다. Arduino 에 업로드 해 줍니다.


File > Examples > HMC5883L > HMC5883L_processing



이제 Processing을 실행시켜서, 아까 다운로드 받은 소스 안에 Processing 이라는 폴더를 찾아 봅니다.

그 안에 "HMC5883L_processing.pde" 파일이 아래 경로에 있습니다.


Arduino > libraries > HMC5883L > Processing > HMC5883L_processing > HMC5883L_processing.pde


Processing 에서 위의 파일을 로드해 줍니다.



그냥 실행시키면 그냥 까만 화면이 나옵니다.

소스에서 Serial.list 부분과 baud rate 를 바꿔줘야 합니다.


우선 Serial.list 는 Arduino IDE 에서 봤을 때, 위에서부터 몇번째 COM port 를 선택했냐에 따라서 바꿔 주면 됩니다.

저의 PC 는 COM6 에 연결되어 있으니, Serial.list 의 두번째가 됩니다.

Array 로 표현되어 있으니, 대괄호 안이 0 --> 1 으로 바뀌어야 하겠습니다. Serial.list()[1] 처럼요.



추가로 baud rate 를 115200 으로 맞춥니다.

이는 아래 그림처럼 arduino 에 올린 sketch 에서도 바꿔서 맞춰줘야 합니다.



요즘은 ESP8266 도 그렇고, Arduino Nano 의 세로운 Bootloader 도 그렇고, 기본 baud rate 를 115200 으로 통일되는 것 같아요.

이 Processing 과 Arduino sketch 도 baud rate 부분은 모두 115200 으로 통일해 줍니다.


여기까지 무사히 왔다면 문제 없이 Processing 에서 구동될 것입니다.



짜잔~~!!! 잘 연동되어서 digital compass 역할을 실시간으로 보여주고 있습니다.

동영상 갑니다.






FIN


좀 멀리 돌아온 감이 있지만, 마무리가 잘 되어 기분이 좋네요.

2019년 1월 1일 이른 아침부터 준비하여 글 올리는 것도 나름 뿌듯합니다.


이 HMC5883L 이라는 물건이 calibration - 영점 조정 을 하지 않으면 쓸수 있는 물건이 아니라고 합니다.

언제가 될 지 모르겠지만, 다음에는 HMC5883L 의 calibration 에 대해서 다뤄보겠습니다.


And

Hardware | Digitial Compass - HMC5883L 사용기 - 1

|

1. 시작하기


지구의 자력을 측정할 수 있는 digital compass 센서가 있다는 소문을 들었습니다.


센서 내부에 코일을 감은 자석에 +/- 극을 지속적으로 변화시켜,

자기장의 변화에 따른 저항을 측정하는 방식으로 방위를 파악한다고 합니다.



* Magnetoresistance

https://en.wikipedia.org/wiki/Magnetoresistance



지표를 기준으로 기울기까지 파악할 수 있습니다.

X/Y 로만 측정하면 방위를 측정할 수 있겠죠.



지구는 위의 그림처럼 자기작을 가지고 있습니다.

위의 그림의 출처는 다음에 있는 블로그를 참조하였습니다.


* Arduino: simple compass with HMC5883L + Library

http://bluelemonlabs.blogspot.kr/2013/08/arduino-simple-compass-with-hmc5883l.html


정확히는 "Anisotropic Magnetoresistance" 현상을 이용한 것이라고 합니다.

더 자세히 알고싶으시면 구글링~.





2. 센서 구입


이런 현상을 이용하여 digital compass 를 쉽게 만들 수 있는 센서를 구입하지 않는 이유를 찾을 수 없었습니다.


* GY-273 3V-5V HMC5883L Triple Axis Compass Magnetometer Sensor Module Three Axis Magnetic Field Module For Arduino

https://ko.aliexpress.com/item/GY-273-3V-5V-HMC5883L-Triple-Axis-Compass-Magnetometer-Sensor-Module-Three-Axis-Magnetic-Field-Module/32826264150.html



센서류 치고는 좀 비싸지만 그렇게 많이는 아니여서 망설임 없이 구입합니다.

(이게 나중에 화근이 됩니다)





3. 도착


무난하게 도착하였습니다.



뽁뽁이 봉지에 잘 넣어서 왔으며, 전자파 방지 비닐에 싸아서 왔습니다.



Header pin 은 납땜되지 않은 채로 왔습니다.

아무래도 운송시 휠수도 있고, 튀어나온 곳으로 힘을 받을 수 있으니까요.



중국 제조사의 이름은 GY-273 인듯 합니다.





4. Layout


Pinout 정보는 다음과 같습니다.


  HMC5883L  | Arduino Nano
---------------------------
    VCC     |     3.3V
    GND     |     GND
    SCL     |     A5
    SDA     |     A4
---------------------------


회로 배선은 다음과 같습니다.



실제 배선은 다음과 같습니다.






5. WTF


순서상으론 이 부분에서 소스를 보여줘야 하나, 다음과 같이 정상적으로 구동이 되지 않는 화면을 먼저 보여드립니다.



Arduino 자체가 망가졌나 해서, 가지고 있던 다른 Arduino Nano 클론 및 Arduino Micro 도 사용해 봤습니다.



가능한 모든 방법을 동원해 봤습니다.

그래도 안되더군요.


정말 가끔 있는 breakout 보드가 망가졌나 했습니다.


한가지 의심스러운 것은 HMC5883L breakout 보드의 I2C address 가, 보통 sample sketch 에서는 "0x1E" 으로 표현되어 있는데,

제가 구입한 보드는 "0x0D" 라고 표시되는 것이였습니다.


뭐, 중국 카피품일 경우, 이 address 가 다르게 나오는 경우가 있어, sketch 에서 변경만 하고 실행했더랬습니다.



위에서 3c 는 OLED 를 같이 접속시켜 확인한 결과 입니다.

문제 없이 "0d" 부분에 연결이 되어 있다고 뜹니다.


인터넷에서 가능한 다른 sample sketch 를 구해서 해봤으나 실패했습니다.





6. i2c scanner


혹여 i2c scanner 의 문제인가 하고, 다른 i2c scanner 도 구해서 해봤으나, 결과는 같았습니다.


// --------------------------------------
// i2c_scanner
//
// Version 1
//    This program (or code that looks like it)
//    can be found in many places.
//    For example on the Arduino.cc forum.
//    The original author is not known.
// Version 2, Juni 2012, Using Arduino 1.0.1
//     Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26  2013
//    V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
//    by Arduino.cc user Krodal.
//    Changes by louarnold removed.
//    Scanning addresses changed from 0...127 to 1...119,
//    according to the i2c scanner by Nick Gammon
//    http://www.gammon.com.au/forum/?id=10896
// Version 5, March 28, 2013
//    As version 4, but address scans now to 127.
//    A sensor seems to use address 120.
// 
//
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
//

#include "Wire.h"

void setup() {
	Wire.begin();
	
	Serial.begin(9600);
	Serial.println("\nI2C Scanner");
}

void loop() {
	byte error, address;
	int nDevices;
	
	Serial.println("Scanning...");
	
	nDevices = 0;
	
	for(address = 1; address < 127; address++ ) {
		// The i2c_scanner uses the return value of
		// the Write.endTransmisstion to see if
		// a device did acknowledge to the address.
		
		Wire.beginTransmission(address);
		error = Wire.endTransmission();
		
		if (error == 0) {
			Serial.print("I2C device found at address 0x");
			if (address<16) Serial.print("0");
			Serial.print(address,HEX);
			Serial.println("  !");
			
			nDevices++;
		} else if (error==4) {
			Serial.print("Unknow error at address 0x");
			if (address<16) Serial.print("0");
			Serial.println(address,HEX);
		}
	}
	
	if (nDevices == 0) Serial.println("No I2C devices found\n");
	else Serial.println("done\n");
	
	delay(5000);           // wait 5 seconds for next scan
}


결과는 다음과 같이 동일하게 "0x0D" 라고 명확하게 표시됩니다.



참고로 앞으론 이 i2c scanner 도 사용해봐야겠네요.
연결된 I2C 부품을 깔끔하게 HEX address 를 표현해 줍니다.





7.  QMC5883L


진심으로 보드가 고장난 것이라 생각하고 재구매를 생각하고 있었습니다.


그러다가 다음과 같은 블로그 글을 읽게 됩니다.

결론은 HMC5883L 이 모두 동일한게 아니라 중국발 QMC5883L 이라는 제품이 있고, 전혀 동일하지 않다는 내용입니다.

허거걱 !!!


* Problem with HMC5883L magnetometer

https://www.reddit.com/r/AskElectronics/comments/5xo3md/problem_with_hmc5883l_magnetometer/



* PROBLEMS WITH GY-271 MAGNETOMETER (HMC5883L != QMC5883L)

http://www.esp8266.com/viewtopic.php?f=13&t=15445


Chip 자체가 다르고 identical 하지 않다고 하니, 한번 살펴 봅니다.



사진으로는 잘 모르겠으나, 일반적인 HMC5883L 과는 다른 마킹임에는 틀림 없어 보입니다.

구매 사이트에서 사진을 퍼와 봤습니다.



완전히 다르네요. "DA 5883 6014" 라고 되어 있습니다.

Sparkfun 에서의 HMC5883L 의 제품은 다음 그림과 같습니다. "L883 2105" 라고 되어 있습니다.


* Sparkfun

https://www.sparkfun.com/products/retired/10494



AliExpress 의 구매 사이트를 더 뒤져 보니 다음과 같은 문구를 발견했습니다.

"Note: It is Domestic Chip HMC5883, the program is not compatible ...."



아놔...


어떤 사이트에는 "Bad Sensor" 라고도 올려져 있습니다.



위의 사진을 보면 정말 main chip 만 다를 뿐, 완벽하게 동일한 구성품과 회로도 입니다.


* HMC5883L(Or QMC5883L) Electronic Compass

http://wiki.epalsite.com/index.php?title=HMC5883L(Or_QMC5883L)_Electronic_Compass


QMC5883L 의 Datasheet 는 다음과 같습니다.

QMC5883L-Datasheet-1.0.pdf





8. Sketch


cpp 및 h 파일은 다음 사이트에서 가져 왔습니다.

arduino/library/ 디렉토리에 "QMC5883L" 이라고 만들고, 그 안에 cpp 와 h 파일을 넣었습니다.


* HMC5883L Compass Module Comunicating but all zero's for x,y,z

https://forum.arduino.cc/index.php?topic=482179.0


Library 소스를 보면 address 가 이미 "0x0D" 라고 박혀 있네요.


QMC5883L 의 sample sketch 를 옮겨 봅니다.


/*
QMC5883L_Example.ino - Example sketch for integration with an QMC5883L triple axis magnetometer.
Copyright (C) 2017 Andy Barnard based on an original for the QMC5883L by Love Electronics (C) 2011

This program is free software: you can redistribute it and/or modify
it under the terms of the version 3 GNU General Public License as
published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

See .

*/

// Reference the I2C Library
#include "Wire.h"
// Reference the QMC5883L Compass Library
#include "QMC5883L.h"

// configure the compass as reqiured
#define OSR 0b00               // over sampling rate set to 512. 0b01 is 256, 0b10 is 128 and 0b11 is 64
#define RNG 0b00               // Full Scale set to +/- 2 Gauss, 0b01 is +/- 8.
#define ODR 0b00               // output data rate set to 10Hz, 0b01 is 50Hz, 0b10 is 100Hz, 0b11 is 200Hz
#define MODE 0b01              // continuous measurement mode, 0b00 is standby
#define CR2 0b00000000          // control register 2: disable soft reset and pointer rollover, interrupt pin not enabled
#define RESETPERIOD 0b00000001  // datasheet recommends this be 1, not sure why!

// Store our compass as a variable.
QMC5883L compass;
// Record any errors that may occur in the compass.
int error = 0;

// Out setup routine, here we will configure the microcontroller and compass.
void setup() {
	// Initialize the serial port.
	Serial.begin(9600);
	
	Serial.println("Starting the I2C interface.");
	Wire.begin(); // Start the I2C interface.
	TWBR = 12;    //Set the I2C clock speed to 400kHz - only works with Arduino UNO
	
	Serial.println("Constructing new QMC5883L");
	compass = QMC5883L(); // Construct a new HMC5883 compass.
	
	// Check that a device responds at the compass address - don't continue if it doesn't - 
	do {
		delay(100);
		Wire.beginTransmission(QMC5883L_Address);
		error = Wire.endTransmission();
		if (error) Serial.println("Can't find compass - is it connected and powered up?");
	} while (error);
	
	// configure the control registers using static settings above
	// compass autoranges, but starts in the mode given
	compass.dataRegister.OSR_RNG_ODR_MODE = (OSR << 6) |(RNG << 4)  | (ODR <<2) |  MODE;
	compass.dataRegister.CR2_INT_ENABLE = CR2;
	compass.dataRegister.SET_RESET_PERIOD = RESETPERIOD;
	
	Serial.println("Configuring QMC5883L - OSR 512, range +/-2 Gauss, ODR 10, Continuous");
	error = compass.Configure(compass.dataRegister); // use static settings from above - can access register data directly if required..
	if (error != 0) // If there is an error, print it out, although no way to get error with this sensor....
	Serial.println(compass.GetErrorText(error));
}

// Our main program loop.
void loop() {
	// Retrive the raw values from the compass (not scaled).
	MagnetometerRaw raw = compass.ReadRawAxis(&compass.dataRegister);
	// Retrived the scaled values from the compass (scaled to the configured scale).
	MagnetometerScaled scaled = compass.ReadScaledAxis(&compass.dataRegister);
	
	// Values are accessed like so:
	int MilliGauss_OnThe_XAxis = scaled.XAxis;     // (or YAxis, or ZAxis)
	
	// Calculate heading when the magnetometer is level, then correct for signs of axis.
	// heading (degrees): 0 = +X, 90 = +Y, 180 = -X, 270 = -Y
	float heading = atan2(scaled.YAxis, scaled.XAxis);
	
	// Once you have your heading, you must then add your 'Declination Angle', which is the 'Error' of the magnetic field in your location.
	// Find yours here: http://www.magnetic-declination.com/
	// Example is: 2� 37' W, which is 2.617 Degrees, or (which we need) 0.0456752665 radians, I will use 0.0457
	// If you cannot find your Declination, comment out these two lines, your compass will be slightly off.
	// float declinationAngle = 0.0457;
	
	float declinationAngle = 0;
	heading += declinationAngle;
	
	// Correct for when signs are reversed.
	if (heading < 0)
		heading += 2*PI;
	
	// Check for wrap due to addition of declination.
	if (heading > 2*PI)
		heading -= 2*PI;
	
	// Convert radians to degrees for readability.
	float headingDegrees = heading * 180/M_PI;
	
	// Output the data via the serial port.
	Output(raw, scaled, heading, headingDegrees);
	
	// Normally we would either:
	// 1. delay the application by 100ms to allow the loop to run at 10Hz (default bandwidth for the QMC5883L)
	// 2. poll the dataready flag in the dataRegister.OVL_DRDY register
	// 3. set the interrupt flat and set a hardware interrupt on the DRDY pin 
	// The first of these options is the easiest.
	delay(100);
}

// Output the data down the serial port.
void Output(MagnetometerRaw raw, MagnetometerScaled scaled, float heading, float headingDegrees)
{
   Serial.print("Raw (X,Y,Z): (");
   Serial.print(raw.XAxis);
   Serial.print(", ");   
   Serial.print(raw.YAxis);
   Serial.print(", ");   
   Serial.print(raw.ZAxis);
   
   Serial.print(")\tScaled (X,Y,Z): (");
   Serial.print(scaled.XAxis, 4);
   Serial.print(", ");   
   Serial.print(scaled.YAxis, 4);
   Serial.print(", ");   
   Serial.print(scaled.ZAxis, 4);
   Serial.println(")");

 
   Serial.print("Magnitude (0.25 to 0.6 on Earth surface): ");
   Serial.print(sqrt(scaled.XAxis * scaled.XAxis + scaled.YAxis * scaled.YAxis + scaled.ZAxis * scaled.ZAxis));
   Serial.print(" Heading: ");
   Serial.print(headingDegrees);
   Serial.print(" Bearing: ");
   Serial.print(bearingDegrees(headingDegrees));
   Serial.println(" (Degrees)");
}

  // Cacluate bearing from heading.
  // bearing 0 = Y pointing North, 90 = Y pointing E, 180 = Y pointing S, 270 = Y pointing W
  float bearingDegrees(float headingDegrees) {
     
     float bearing = 450 - headingDegrees;
     if (bearing >= 360)
     {
      bearing -= 360;
     }
     return bearing;
  }





9. 결과


QMC5883L 이라고 안 이상, 그 뒤는 문제 없이 구동까지 확인할 수 있었습니다.






FIN


여기까지 걸린 시간은 대략 이틀.

구매 사이트에 처음부터 QMC5883L 이라고 표기했으면 이렇게까지 고민하지 않았을 터인데.

역시 알아서 쓰라는 AliExpress 와 대륙의 기상이 느껴집니다.


인터넷을 보면 QMC5883L 에 대해서는 꽤나 여러가지 시도가 있습니다.

사실 접근 address 및 쓰고 읽는 부분만 다를 뿐, 구동 방식은 같다고 합니다.


* QMC5883L Electronic Compass

http://wiki.epalsite.com/index.php?title=QMC5883L_Electronic_Compass



Mecha 라는 ID 를 사용하시는 분이 만든 library 도 있습니다.


* Arduino lib for QMC5883

https://github.com/mechasolution/Mecha_QMC5883L


QMC5883L 임을 안 이상, 다음에는 좀더 철저하게 사용해 보도록 하겠습니다.

And
prev | 1 | next