본문 바로가기

Hardware/Arduino and Friends

GY86에 있는 지자기 센서 HMC5883L 사용하기

최근 GY86이라는 모듈에 있는 자이로+가속도센서인 MPU6050을 테스트[바로가기]해 보았었는데요. GY86에는 MPU6050뿐만 아니라 HMC5883L이라는 지자기 센서가 함께 포함되어 있습니다. 이 센서가 좀 힘든게 MPU6050에 slave로 연결되어 있어서 I2C 통신에 익숙하지 않으시면 다루기가 쉽지 않더라구요. 그러나 뭐... 인터넷에서는 자신의 소중한 경험을 공유하시는 많은 분들이 계시죠~^^

과객이라는 멋진 이름을 사용하시는 분께서 운영하시는 블로그에 GY86 모듈의 사용법[바로가기]이 올라있더라구요~ 그래서 이분의 글중에 일부를 따라하게 되었습니다.~^^

이 분의 글에 보면 위 말처럼 코드에서 수행해야하는 절차가 잘 정리되어 있지만~ 저처럼 잘 모르는 사람들이 따라할려면 역시 코드도 보아야죠~

일단 그 전에 [바로가기]에 가서 HMC5883L 라이브러리를 받습니다. 그리고...

아.. 저 화면에서 파일을 받아서...

아두이노 폴더의 라이브러리 폴더에 복사해 두면 됩니다. 이전에 했던 MPU6050 라이브러리도 보이네요^^ 그리고... 과객님의 코드 중에서...

// 출처 : http://blog.naver.com/PostView.nhn?blogId=msyang59&logNo=220108266726

#include "I2Cdev.h"
#include "MPU6050.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include <Wire.h>
#endif
 
#define HMC5883L_DEFAULT_ADDRESS    0x1E
#define HMC5883L_RA_DATAX_H         0x03
#define HMC5883L_RA_DATAZ_H         0x05
#define HMC5883L_RA_DATAY_H         0x07

MPU6050 mpu;

int16_t ax, ay, az;
int16_t gx, gy, gz;
int16_t mx, my, mz;
 
float heading;
 
void setup() {
  // I2C 버스를 사용하기 위하여 Wire.begin()를 실행합니다.
  #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    Wire.begin();
    TWBR = 12; // 400kHz I2C clock (200kHz if CPU is 8MHz)
 
  #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
    Fastwire::setup(400, true);
  #endif
   
  Serial.begin(115200);
  
  mpu.initialize();
  mpu.setI2CMasterModeEnabled(0);
  mpu.setI2CBypassEnabled(1);
 
  Wire.beginTransmission(HMC5883L_DEFAULT_ADDRESS);
  Wire.write(0x02); 
  Wire.write(0x00);  // 연속 읽기 모드로 설정
  Wire.endTransmission();
  delay(5);
 
  Wire.beginTransmission(HMC5883L_DEFAULT_ADDRESS);
  Wire.write(0x00);
  Wire.write(B00011000);  // 75Hz
  Wire.endTransmission();
  delay(5);
 
  mpu.setI2CBypassEnabled(0);
 
  // X 축 WORD 
  /* 0x80은 7번째 비트를 1로 만듭니다. MPU6050 데이터 자료에 읽기 모드
   * 설정은 '1'로 쓰기 모드 설정은 '0'로 하여야 한다고 나와 있습니다. */
  mpu.setSlaveAddress(0, HMC5883L_DEFAULT_ADDRESS | 0x80);
  mpu.setSlaveRegister(0, HMC5883L_RA_DATAX_H);
  mpu.setSlaveEnabled(0, true);
  mpu.setSlaveWordByteSwap(0, false);
  mpu.setSlaveWriteMode(0, false);
  mpu.setSlaveWordGroupOffset(0, false);
  mpu.setSlaveDataLength(0, 2);
 
  // Y 축 WORD
  mpu.setSlaveAddress(1, HMC5883L_DEFAULT_ADDRESS | 0x80);
  mpu.setSlaveRegister(1, HMC5883L_RA_DATAY_H);
  mpu.setSlaveEnabled(1, true);
  mpu.setSlaveWordByteSwap(1, false);
  mpu.setSlaveWriteMode(1, false);
  mpu.setSlaveWordGroupOffset(1, false);
  mpu.setSlaveDataLength(1, 2);
 
  // Z 축 WORD
  mpu.setSlaveAddress(2, HMC5883L_DEFAULT_ADDRESS | 0x80);
  mpu.setSlaveRegister(2, HMC5883L_RA_DATAZ_H);
  mpu.setSlaveEnabled(2, true);
  mpu.setSlaveWordByteSwap(2, false);
  mpu.setSlaveWriteMode(2, false);
  mpu.setSlaveWordGroupOffset(2, false);
  mpu.setSlaveDataLength(2, 2);
 
  // HMC5883L은 MPU6050을 통하여 읽을 수 있어, 마스터 모드를 ON합니다
  mpu.setI2CMasterModeEnabled(1);

  delay(1000);
}
 
void loop() {
  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  
  // MPU6050을 통하여 HMC5883L 지자기 센서 데이터 값을 읽어 들입니다
  mx=mpu.getExternalSensorWord(0);
  my=mpu.getExternalSensorWord(2);
  mz=mpu.getExternalSensorWord(4);

  heading = atan2(my, mx);
  if(heading < 0) heading += 2 * M_PI;
 
  // Serial.print(ax); Serial.print("\t");
  // Serial.print(ay); Serial.print("\t");
  // Serial.print(az); Serial.print("\t");
  Serial.print(mx); Serial.print("\t");
  Serial.print(my); Serial.print("\t");
  Serial.print(mz); Serial.print("\n");
  // Serial.print(heading); Serial.print("\n");
}

이렇게 살짝 바꾸었습니다. 전 그냥 지자기 센서 값의 출력만 보고 싶었거든요~^^

주석처리한 걸 풀면 다른 값도 볼수 있습니다만.. 전 지자기 값만~^^

그래서 시리얼 모니터에 연결해보면 값이 잘 나오네요~~^^

결선은 지난번 MPU6050을 테스트하던 것과 동일하게, Vcc는 5V에... SCL, SDA는 각각 아두이노에 동일핀에 연결했습니다.^^

반응형