Friday, April 24, 2015

Arduino Nano + GY-271 (Digital Compass module) + OLED

This example show a Arduino Nano, connect with GY-271 Digital Compass module and 0.96" 128x64 OLED via a common I2C bus. GY-271 is a Digital Compass module using HMC5883L, a 3-Axis Digital Compass IC. The reading from GY-271 (x, y, abd z) is display on the OLED. Arduino Nano communicate with GY-271 via I2C bus using Wire library. Arduino Nano communicate with 0.96" 128x64 OLED via the same I2C bus, using u8glib library. I'm not sure is it 100% compatible to use both Wire and u8glib libraries, both share the common I2C bus. Anyway in this example it work.


Connection:
VCC of GY-271, OLED and Arduino Nano connect together.
GND of GY-271, OLED and Arduino Nano connect together.
SCL of GY-271 and OLED connect to A5 of Arduino Nano.
SDA of GY-271 and OLED connect to A4 of Arduino Nano.
DRDY of GY-271 no connection.
(In the following Fritzing drawing, the HMC5883 breakout not exactly my GY-271 module, just to show the connect of SCL and SDA.)


Nano_OLED_Compass.ino
#include "U8glib.h"
#include <Wire.h> //I2C Arduino Library

#define address 0x1E //0011110b, I2C 7bit address of HMC5883

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);

int x,y,z; //triple axis data

char bufferX [20];
char bufferY [20];
char bufferZ [20];

void draw(void) {
  u8g.setFont(u8g_font_unifont);
  u8g.drawStr( 0, 20, bufferX);
  u8g.drawStr( 0, 40, bufferY);
  u8g.drawStr( 0, 60, bufferZ);

}

void setup(void) {
  x = 0;
  y = 0;
  z = 0;
  
  Wire.begin();
  
  //Put the HMC5883 IC into the correct operating mode
  Wire.beginTransmission(address); //open communication with HMC5883
  Wire.write(0x02); //select mode register
  Wire.write(0x00); //continuous measurement mode
  Wire.endTransmission();

}

void loop(void) {
  //Tell the HMC5883 where to begin reading data
  Wire.beginTransmission(address);
  Wire.write(0x03); //select register 3, X MSB register
  Wire.endTransmission();
  
 
 //Read data from each axis, 2 registers per axis
  Wire.requestFrom(address, 6);
  if(6<=Wire.available()){
    x = Wire.read()<<8; //X msb
    x |= Wire.read(); //X lsb
    z = Wire.read()<<8; //Z msb
    z |= Wire.read(); //Z lsb
    y = Wire.read()<<8; //Y msb
    y |= Wire.read(); //Y lsb
  }
  
  sprintf(bufferX, "x : %d", x);
  sprintf(bufferY, "y : %d", y);
  sprintf(bufferZ, "z : %d", z);

  u8g.firstPage();  
  do {
    draw();
  } while( u8g.nextPage() );
  
  delay(100);
}



Then I tried to find the bearing by calling atan2((double)y, (double)x) * 180/M_PI, but get a very big error without calibration. Finally I found a library with auto calibration, read next: HMC5883L library with calibration, for Arduino.

About 3-Axis Digital Compass IC HMC5883L:



- 3-Axis Digital Compass IC HMC5883L
- Application Note – AN226 Honeywell HMC5883L/HMC5983 3-Axis Digital Compass IC Pin Configuration for I2C Communication

1 comment: