3 Axis Compass Sensor
O Watch Sensor Kit includes the Honeywell HMC5883 chip which is a 3 axis digital compass chip that can be used to make a digital compass. This chip uses magnetoresistance sensors.
Here is an example to demo this sensor. This is based on the compass example from TinyCircuits.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
/* * Compass demo for O Watch * This demo shows the heading or magnetic direction your are pointing O Watch * O Watch needs to be help parallel to the ground and away from any magnetic materials * * Based on TinyCompass demo by Tony Batey * https://www.hackster.io/tbatey_tiny-circuits/tinycompass-32de65 * * This example is in the public domain * http://theowatch.com * */ #include <TinyScreen.h> //TinyScreen Library #include <Wire.h> //Communication with sensor board via I2C #include <SPI.h> //Communication with OLED TinyScreen display = TinyScreen(TinyScreenPlus); //Declare the variables for use in the program int x, y, z; int x_max=-10000; // Starting values for hard iron calibration int y_max=-10000; // We want these values to be extreme in the int x_min=10000; // opposite direction so it calibrates nicely int y_min=10000; #define HMC5883_I2CADDR 0x1E //Set the address for the compass void setup() { Wire.begin(); display.begin(); display.setFlip(1); display.setFont(liberationSans_10ptFontInfo); display.fontColor(TS_8b_White,TS_8b_Black); display.setFont(liberationSans_12ptFontInfo); display.setCursor(20,15); HMC5883nit(); //initialize the compass //Draw an arrow pointing top display.drawLine(5,20,10,10,TS_8b_White); display.drawLine(10,40,10,10,TS_8b_White); display.drawLine(15,20,10,10,TS_8b_White); } void loop() { ReadMyCompass(); if(x > x_max) //Find values of hard iron distortion x_max = x; //This will store the max and min values if(y >y_max) //of the magnetic field around you y_max = y; if(y<y_min) y_min = y; if(x<x_min) x_min = x; int xoffset= (x_max+x_min)/2; int yoffset= (y_max+y_min)/2; int x_scale = x-xoffset; // Math to compensate for hard int y_scale = y-yoffset; // iron distortions // Heading in radians float heading = atan2(x_scale,y_scale); //Heading between 0 and 6.3 radians if(heading < 0) heading += 2*PI; if(heading>2*PI) heading -= 2*PI; //Conversion to degrees int Degrees = heading * 180/M_PI; display.setCursor(25,10); Degrees = Degrees-90; //Adjust 90 degrees because the sensor is pointing right if (Degrees < 0) Degrees=Degrees+360; if(Degrees<30 || Degrees> 330) display.print("N "); if(Degrees >= 30 && Degrees< 60) display.print("NE "); if(Degrees >= 60 && Degrees< 120) display.print("E "); //East and West flipped here because the compass is upside down if(Degrees >= 120 && Degrees< 150) display.print("SE "); if(Degrees >= 150 && Degrees< 210) display.print("S "); if(Degrees >= 210 && Degrees< 240) display.print("SW "); if(Degrees >= 240 && Degrees< 300) display.print("W "); //East and West flipped here because the compass is upside down if(Degrees >= 300 && Degrees< 330) display.print("NW "); display.setCursor(25,30); display.print(Degrees); //Display the heading in degrees display.print(" "); delay(100); display.clearWindow(25,10,55,50); } void HMC5883nit() { //Put the HMC5883 into operating mode Wire.beginTransmission(HMC5883_I2CADDR); Wire.write(byte(0x02)); // Mode register Wire.write(byte(0x00)); // Continuous measurement mode Wire.endTransmission(); } void ReadMyCompass() { Wire.beginTransmission(HMC5883_I2CADDR); Wire.write(byte(0x03)); // Send request to X MSB register Wire.endTransmission(); Wire.requestFrom(HMC5883_I2CADDR, 6); // Request 6 bytes; 2 bytes per axis if(Wire.available() <=6) // If 6 bytes available { x = (int16_t)(Wire.read() << 8 | Wire.read()); z = (int16_t)(Wire.read() << 8 | Wire.read()); y = (int16_t)(Wire.read() << 8 | Wire.read()); } } |
You can copy paste this code to the Arduino IDE and load to the O Watch to see it work.
After uploading the code, you need to calibrate it by rotating the O Watch 3 times each on x, y, and z axis as shown in the TinyCircuits example. Calibration us required every time you power on or upload the compass program.
Few things to note.
- The compass sensor is pointing to the right i.e. towards the buttons on the right if you’re wearing the O Watch on your left wrist. Therefore the heading values are shifted down by 90 to show the results pointing ahead.
- The compass sensor sits upside down in the O Watch. Therefore you need to swap the results of East and West to display the heading correctly.
Adafruit also has a HMC5883 Library if you’d like to give that a try.