├── .gitattributes ├── .gitignore ├── LICENSE.md ├── README.md ├── examples ├── SparkFun_DigitalCompass │ ├── Processing │ │ └── uViewImageConverter │ │ │ ├── data │ │ │ ├── spriteMono.png │ │ │ └── uview_t.png │ │ │ └── uViewImageConverter.pde │ └── SparkFun_DigitalCompass.ino ├── SparkFun_MAG3110_Basic │ └── SparkFun_MAG3110_Basic.ino ├── SparkFun_MAG3110_Calibrated │ └── SparkFun_MAG3110_Calibrated.ino ├── SparkFun_MAG3110_Magnitude │ └── SparkFun_MAG3110_Magnitude.ino ├── SparkFun_MAG3110_Other │ └── SparkFun_MAG3110_Other.ino └── SparkFun_MAG3110_Triggered │ └── SparkFun_MAG3110_Triggered.ino ├── extras └── MAG3110_v9.2.pdf ├── keywords.txt ├── library.properties └── src ├── SparkFun_MAG3110.cpp └── SparkFun_MAG3110.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## SparkFun Useful stuff 3 | ################# 4 | 5 | ## AVR Development 6 | *.eep 7 | *.elf 8 | *.lst 9 | *.lss 10 | *.sym 11 | *.d 12 | *.o 13 | *.srec 14 | *.map 15 | 16 | ## Notepad++ backup files 17 | *.bak 18 | 19 | ## BOM files 20 | *bom* 21 | 22 | ################# 23 | ## Eclipse 24 | ################# 25 | 26 | *.pydevproject 27 | .project 28 | .metadata 29 | bin/ 30 | tmp/ 31 | *.tmp 32 | *.bak 33 | *.swp 34 | *~.nib 35 | local.properties 36 | .classpath 37 | .settings/ 38 | .loadpath 39 | 40 | # External tool builders 41 | .externalToolBuilders/ 42 | 43 | # Locally stored "Eclipse launch configurations" 44 | *.launch 45 | 46 | # CDT-specific 47 | .cproject 48 | 49 | # PDT-specific 50 | .buildpath 51 | 52 | 53 | ############# 54 | ## Eagle 55 | ############# 56 | 57 | # Ignore the board and schematic backup files 58 | *.b#? 59 | *.s#? 60 | 61 | 62 | ################# 63 | ## Visual Studio 64 | ################# 65 | 66 | ## Ignore Visual Studio temporary files, build results, and 67 | ## files generated by popular Visual Studio add-ons. 68 | 69 | # User-specific files 70 | *.suo 71 | *.user 72 | *.sln.docstates 73 | 74 | # Build results 75 | [Dd]ebug/ 76 | [Rr]elease/ 77 | *_i.c 78 | *_p.c 79 | *.ilk 80 | *.meta 81 | *.obj 82 | *.pch 83 | *.pdb 84 | *.pgc 85 | *.pgd 86 | *.rsp 87 | *.sbr 88 | *.tlb 89 | *.tli 90 | *.tlh 91 | *.tmp 92 | *.vspscc 93 | .builds 94 | *.dotCover 95 | 96 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 97 | #packages/ 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opensdf 104 | *.sdf 105 | 106 | # Visual Studio profiler 107 | *.psess 108 | *.vsp 109 | 110 | # ReSharper is a .NET coding add-in 111 | _ReSharper* 112 | 113 | # Installshield output folder 114 | [Ee]xpress 115 | 116 | # DocProject is a documentation generator add-in 117 | DocProject/buildhelp/ 118 | DocProject/Help/*.HxT 119 | DocProject/Help/*.HxC 120 | DocProject/Help/*.hhc 121 | DocProject/Help/*.hhk 122 | DocProject/Help/*.hhp 123 | DocProject/Help/Html2 124 | DocProject/Help/html 125 | 126 | # Click-Once directory 127 | publish 128 | 129 | # Others 130 | [Bb]in 131 | [Oo]bj 132 | sql 133 | TestResults 134 | *.Cache 135 | ClientBin 136 | stylecop.* 137 | ~$* 138 | *.dbmdl 139 | Generated_Code #added for RIA/Silverlight projects 140 | 141 | # Backup & report files from converting an old project file to a newer 142 | # Visual Studio version. Backup files are not needed, because we have git ;-) 143 | _UpgradeReport_Files/ 144 | Backup*/ 145 | UpgradeLog*.XML 146 | 147 | 148 | ############ 149 | ## Windows 150 | ############ 151 | 152 | # Windows image file caches 153 | Thumbs.db 154 | 155 | # Folder config file 156 | Desktop.ini 157 | 158 | 159 | ############# 160 | ## Python 161 | ############# 162 | 163 | *.py[co] 164 | 165 | # Packages 166 | *.egg 167 | *.egg-info 168 | dist 169 | build 170 | eggs 171 | parts 172 | bin 173 | var 174 | sdist 175 | develop-eggs 176 | .installed.cfg 177 | 178 | # Installer logs 179 | pip-log.txt 180 | 181 | # Unit test / coverage reports 182 | .coverage 183 | .tox 184 | 185 | #Translations 186 | *.mo 187 | 188 | #Mr Developer 189 | .mr.developer.cfg 190 | 191 | # Mac crap 192 | .DS_Store 193 | 194 | ############# 195 | ## Misc 196 | ############# 197 | Misc/ 198 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | SparkFun License Information 2 | ============================ 3 | 4 | SparkFun uses two different licenses for our files — one for hardware and one for code. 5 | 6 | Hardware 7 | --------- 8 | 9 | **SparkFun hardware is released under [Creative Commons Share-alike 4.0 International](http://creativecommons.org/licenses/by-sa/4.0/).** 10 | 11 | Note: This is a human-readable summary of (and not a substitute for) the [license](http://creativecommons.org/licenses/by-sa/4.0/legalcode). 12 | 13 | You are free to: 14 | 15 | Share — copy and redistribute the material in any medium or format 16 | Adapt — remix, transform, and build upon the material 17 | for any purpose, even commercially. 18 | The licensor cannot revoke these freedoms as long as you follow the license terms. 19 | Under the following terms: 20 | 21 | Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 22 | ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. 23 | No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 24 | Notices: 25 | 26 | You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation. 27 | No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. 28 | 29 | 30 | Code 31 | -------- 32 | 33 | **SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT).** 34 | 35 | The MIT License (MIT) 36 | 37 | Copyright (c) 2016 SparkFun Electronics 38 | 39 | Permission is hereby granted, free of charge, to any person obtaining a copy 40 | of this software and associated documentation files (the "Software"), to deal 41 | in the Software without restriction, including without limitation the rights 42 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 43 | copies of the Software, and to permit persons to whom the Software is 44 | furnished to do so, subject to the following conditions: 45 | 46 | The above copyright notice and this permission notice shall be included in all 47 | copies or substantial portions of the Software. 48 | 49 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 50 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 51 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 52 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 53 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 54 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 55 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SparkFun MAG3110 Breakout Board Arduino Library 2 | ============================================ 3 | Arduino Library for the SparkFun Triple Axis Magnetometer Breakout - MAG3110 4 | 5 | This library makes it easy for you to get started with the MAG3110 breakout board. It also has commands included for more advanced users that want to squeeze even more functionality out of the MAG3110. 6 | 7 | You will also be able to calibrate the MAG3110 whenever necessary as shown in the example. 8 | 9 | SparkFun MAG3110 Arduino Library 10 | ======================================== 11 | 12 | [![SparkFun MAG3110](https://cdn.sparkfun.com//assets/parts/9/3/9/8/12670-01.jpg)](https://www.sparkfun.com/products/12670) 13 | 14 | [*SparkFun Triple Axis Magnetometer Breakout - MAG3110*](https://www.sparkfun.com/products/12670) 15 | 16 | Freescale’s MAG3110 is a small, low-power, digital 3-axis magnetometer. The device can be used in conjunction with a 3-axis accelerometer to produce orientation independent accurate compass heading information. It features a standard I2C serial interface output and smart embedded functions. It’s also a tiny QFN package which isn’t very easy to play with so here is our easy to use breakout board. This board breaks out all of the pins for the MAG3110 to a standard 0.1" header and also supplies the necessary filtering capacitors so that you can easily use it in your next navigation project. 17 | 18 | This library includes functions that allow you to read your heading to magnetic north. Data from this is output on the range of -180 degrees to +180 degrees. 19 | 20 | 21 | Repository Contents 22 | ------------------- 23 | 24 | * **/examples** - Example sketches for the library (.ino). Run these from the Arduino IDE. 25 | * **/src** - Source files for the library (.cpp, .h). 26 | * **library.properties** - General library properties for the Arduino package manager. 27 | 28 | 29 | Documentation 30 | -------------- 31 | 32 | * **[Installing an Arduino Library Guide](https://learn.sparkfun.com/tutorials/installing-an-arduino-library)** - Basic information on how to install an Arduino library. 33 | * **[Product Repository](https://github.com/sparkfun/MAG3110_Breakout_Board)** - Main repository (including hardware files). 34 | * **[Hookup Guide](https://learn.sparkfun.com/tutorials/mag3110-magnetometer-hookup-guide-)** - Basic hookup guide. 35 | 36 | Products that use this Library 37 | --------------------------------- 38 | 39 | * [SparkFun Triple Axis Magnetometer Breakout - MAG3110 - SEN-12670 ](https://www.sparkfun.com/products/12670)- MAG3110 is a small, low-power, digital 3-axis magnetometer. The device can be used in conjunction with a 3-axis accelerometer to produce orientation independent accurate compass heading information. It features a standard I2C serial interface output and smart embedded functions. It’s also a tiny QFN package which isn’t very easy to play with so here is our easy to use breakout board. This board breaks out all of the pins for the MAG3110 to a standard 0.1" header and also supplies the necessary filtering capacitors so that you can easily use it in your next navigation project. 40 | 41 | Version History 42 | --------------- 43 | 44 | * [1.0.3](https://github.com/sparkfun/SparkFun_MAG3110_Breakout_Board_Arduino_Library/releases/tag/V_1.0.3) - Move Wire.begin() and unnecessary wait after Wire.requestFrom() 45 | * [1.0.2](https://github.com/sparkfun/SparkFun_MAG3110_Breakout_Board_Arduino_Library/releases/tag/V_1.0.2) - Update library properties version 46 | * [1.0.1](https://github.com/sparkfun/SparkFun_MAG3110_Breakout_Board_Arduino_Library/releases/tag/V_1.0.1) - Keyword Fix 47 | * [1.0.0](https://github.com/sparkfun/SparkFun_MAG3110_Breakout_Board_Arduino_Library/releases/tag/V_1.0.0) - Initial release of the Triple Axis Accelerometer Breakout - MAG3110 SparkFun Library. 48 | 49 | License Information 50 | ------------------- 51 | 52 | This product is _**open source**_! 53 | 54 | Please review the LICENSE.md file for license information. 55 | 56 | If you have any questions or concerns on licensing, please contact techsupport@sparkfun.com. 57 | 58 | Distributed as-is; no warranty is given. 59 | 60 | - Your friends at SparkFun. And George the contract author :) 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /examples/SparkFun_DigitalCompass/Processing/uViewImageConverter/data/spriteMono.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/SparkFun_MAG3110_Breakout_Board_Arduino_Library/ea89f4ce5a5b17dfa22475b013081f7683685f3f/examples/SparkFun_DigitalCompass/Processing/uViewImageConverter/data/spriteMono.png -------------------------------------------------------------------------------- /examples/SparkFun_DigitalCompass/Processing/uViewImageConverter/data/uview_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/SparkFun_MAG3110_Breakout_Board_Arduino_Library/ea89f4ce5a5b17dfa22475b013081f7683685f3f/examples/SparkFun_DigitalCompass/Processing/uViewImageConverter/data/uview_t.png -------------------------------------------------------------------------------- /examples/SparkFun_DigitalCompass/Processing/uViewImageConverter/uViewImageConverter.pde: -------------------------------------------------------------------------------- 1 | import drop.*; 2 | import test.*; 3 | 4 | PImage uView; 5 | PImage sprite; 6 | SDrop drop; 7 | 8 | PrintWriter output; 9 | 10 | color darkScreen = color(23, 20, 29); 11 | 12 | int offset = 7; 13 | 14 | void setup() { 15 | //size(96,97); 16 | size(110, 110); 17 | uView = loadImage("uview_t.png"); 18 | drop = new SDrop(this); 19 | } 20 | 21 | //Displays the image 22 | void draw() { 23 | clear(); 24 | background(100, 100, 120); 25 | image(uView, 0 + offset, 0 + offset); 26 | fill(darkScreen); 27 | noStroke(); 28 | rect(16 + offset, 17 + offset, 64, 48); 29 | if(sprite != null) 30 | { 31 | //center the image 32 | int xPos = 48 - (sprite.width/2) + offset; 33 | int yPos = 41 - (sprite.height/2) + offset; 34 | image(sprite, xPos, yPos); 35 | } 36 | } 37 | 38 | //Occurs when a file is dropped into the window 39 | void dropEvent(DropEvent de) 40 | { 41 | //Load the sprite 42 | if(de.isImage()) { 43 | //Can't use de.loadImage() for this part 44 | //The drag and drop library has a strange bug where 45 | //the width and height are always 4 46 | String filePath = de.filePath(); 47 | sprite = loadImage(filePath); 48 | 49 | if(sprite.width > 64 || sprite.height > 48) //The sprite is too big 50 | { 51 | println("Sprite will not fit on microview screen! Cannot load sprite."); 52 | sprite = null; 53 | } 54 | else 55 | { 56 | //Get the filename 57 | int index = 0; 58 | for(int j = 0; j < filePath.length(); j++) 59 | { 60 | if(filePath.charAt(j) == '\\') //The backslash character in filepaths 61 | index = j; //We will find the last backslash 62 | } 63 | 64 | //This should give the filename without the file extension... 65 | //It might not work with weird file paths that have periods in them 66 | String fileName = filePath.substring(index+1, filePath.indexOf('.')); 67 | 68 | //Now it's time to format the image and make sure it displays properly 69 | sprite.loadPixels(); 70 | 71 | //Create an empty image buffer 72 | int arrayHeight = sprite.height/8; 73 | if(sprite.height % 8 > 0) //If the height is not evenly divisible by 8, then add 1 more row 74 | arrayHeight++; 75 | byte[][] buffer = new byte[sprite.width][arrayHeight]; 76 | 77 | //println(sprite.width); 78 | //println(arrayHeight); 79 | 80 | //In this loop we format the image to look like a microview sprite 81 | //We also take care of formatting the hex code for the image 82 | int dimensions = sprite.width*sprite.height; 83 | for(int i = 0; i < dimensions; i++) 84 | { 85 | if(sprite.pixels[i] == color(0, 0, 0)) //If the pixel is black 86 | { 87 | sprite.pixels[i] = color(22,208,255); //Make it monochrome blue 88 | //And mark it as a 1 in our array 89 | //See http://microview.io/Font/creating-fonts-for-microview.html 90 | //This will show you how the microview display buffer is arranged 91 | int y = i / sprite.width; 92 | int x = i - (y*sprite.width); 93 | 94 | buffer[x][y/8] |= (0x01 << y%8); 95 | } 96 | else //if the pixel is not black, make it black 97 | { 98 | sprite.pixels[i] = darkScreen; 99 | } 100 | } 101 | 102 | //Now we finish by writing the hex to a file for use with the microView 103 | for(int k = 0; k < arrayHeight; k++) 104 | { 105 | println("//Row " + k); 106 | for(int l = 0; l < sprite.width; l++) 107 | { 108 | print("0x" + hex(buffer[l][k]) + ","); 109 | } 110 | println(""); 111 | println("//----------"); 112 | } 113 | 114 | sprite.updatePixels(); 115 | } 116 | } 117 | } -------------------------------------------------------------------------------- /examples/SparkFun_DigitalCompass/SparkFun_DigitalCompass.ino: -------------------------------------------------------------------------------- 1 | /* ********************************************* 2 | SparkFun_DigitalCompass 3 | Triple Axis Magnetometer Breakout - MAG3110 4 | Digital Compass Example 5 | 6 | Utilizing Sparkfun's MAG3110 Library 7 | and MicroView! 8 | 9 | George B. on behalf of SparkFun Electronics 10 | Created: Sep 22, 2016 11 | Updated: n/a 12 | 13 | Development Environment Specifics: 14 | Arduino 1.6.7 15 | 16 | Hardware Specifications: 17 | SparkFun MAG3110 18 | Bi-directional Logic Level Converter 19 | Arduino Micro 20 | 21 | This code is beerware; if you see me (or any other SparkFun employee) at the 22 | local, and you've found our code helpful, please buy us a round! 23 | Distributed as-is; no warranty is given. 24 | * *********************************************/ 25 | 26 | #include 27 | #include 28 | 29 | 30 | //This allows us to store the bitmaps in program memory 31 | //We have 32kB of program memory as opposed to only 2kB of dynamic memory 32 | //See https://www.arduino.cc/en/Reference/PROGMEM 33 | //Use the keyword PROGMEM to store that variable in program memory 34 | #include 35 | 36 | #define SCREEN_BUFFER_SIZE 384 //The buffer is 384 bytes in length 37 | 38 | //All of these are the bitmaps for the compass needle positions 39 | const uint8_t PROGMEM compass_0[] = { 40 | //Row 0 41 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x04, 0x18, 0x20, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 42 | //---------- 43 | //Row 1 44 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFC, 0xFC, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 45 | //---------- 46 | //Row 2 47 | 0x00, 0x60, 0x80, 0x00, 0x80, 0x60, 0x80, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x20, 0x20, 0x20, 0x00, 48 | //---------- 49 | //Row 3 50 | 0x00, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x3C, 0xC0, 0x00, 0x00, 0x80, 0x7C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x09, 0x09, 0x09, 0x00, 51 | //---------- 52 | //Row 4 53 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x38, 0x38, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 54 | //---------- 55 | //Row 5 56 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 57 | //---------- 58 | 59 | }; 60 | 61 | const uint8_t PROGMEM compass_30[] = { 62 | //Row 0 63 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x04, 0x18, 0x20, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 64 | //---------- 65 | //Row 1 66 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xF8, 0xF0, 0xE0, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 67 | //---------- 68 | //Row 2 69 | 0x00, 0x60, 0x80, 0x00, 0x80, 0x60, 0x80, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x78, 0x78, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x20, 0x20, 0x20, 0x00, 70 | //---------- 71 | //Row 3 72 | 0x00, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0F, 0x0D, 0x38, 0x70, 0xE0, 0xC0, 0x87, 0x7E, 0xF8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x09, 0x09, 0x09, 0x00, 73 | //---------- 74 | //Row 4 75 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x06, 0x0F, 0x1F, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 76 | //---------- 77 | //Row 5 78 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 79 | //---------- 80 | 81 | }; 82 | 83 | const uint8_t PROGMEM compass_60[] = { 84 | //Row 0 85 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x04, 0x18, 0x20, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 86 | //---------- 87 | //Row 1 88 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 89 | //---------- 90 | //Row 2 91 | 0x00, 0x60, 0x80, 0x00, 0x80, 0x60, 0x80, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x07, 0x1F, 0x1E, 0x3F, 0xFE, 0xFE, 0xFC, 0xFE, 0xFC, 0xF8, 0xF8, 0xF8, 0xF8, 0x30, 0xF0, 0xE0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x20, 0x20, 0x20, 0x00, 92 | //---------- 93 | //Row 3 94 | 0x00, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x07, 0x0F, 0x0F, 0x1B, 0x0C, 0x18, 0x18, 0x30, 0x19, 0x31, 0x77, 0x6F, 0xEC, 0x78, 0xF8, 0xE0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x09, 0x09, 0x09, 0x00, 95 | //---------- 96 | //Row 4 97 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 98 | //---------- 99 | //Row 5 100 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 101 | //---------- 102 | 103 | }; 104 | 105 | const uint8_t PROGMEM compass_90[] = { 106 | //Row 0 107 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x04, 0x18, 0x20, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 108 | //---------- 109 | //Row 1 110 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 111 | //---------- 112 | //Row 2 113 | 0x00, 0x60, 0x80, 0x00, 0x80, 0x60, 0x80, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xE0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF0, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x20, 0x20, 0x20, 0x00, 114 | //---------- 115 | //Row 3 116 | 0x00, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0F, 0x0F, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x09, 0x09, 0x09, 0x00, 117 | //---------- 118 | //Row 4 119 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 120 | //---------- 121 | //Row 5 122 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 123 | //---------- 124 | 125 | }; 126 | 127 | const uint8_t PROGMEM compass_120[] = { 128 | //Row 0 129 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x04, 0x18, 0x20, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 130 | //---------- 131 | //Row 1 132 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 133 | //---------- 134 | //Row 2 135 | 0x00, 0x60, 0x80, 0x00, 0x80, 0x60, 0x80, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xE0, 0xF0, 0xF0, 0xD8, 0x30, 0x18, 0x18, 0x0C, 0x8E, 0xEC, 0xEE, 0x76, 0x37, 0x1E, 0x1F, 0x07, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x20, 0x20, 0x20, 0x00, 136 | //---------- 137 | //Row 3 138 | 0x00, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xE0, 0xF8, 0x78, 0xFC, 0x7F, 0x7F, 0x3F, 0x7F, 0x3F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0C, 0x0F, 0x07, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x09, 0x09, 0x09, 0x00, 139 | //---------- 140 | //Row 4 141 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 142 | //---------- 143 | //Row 5 144 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 145 | //---------- 146 | 147 | }; 148 | 149 | const uint8_t PROGMEM compass_150[] = { 150 | //Row 0 151 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x04, 0x18, 0x20, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 152 | //---------- 153 | //Row 1 154 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x60, 0xF8, 0xF8, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 155 | //---------- 156 | //Row 2 157 | 0x00, 0x60, 0x80, 0x00, 0x80, 0x60, 0x80, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xB0, 0xBC, 0x0F, 0x03, 0x83, 0xE9, 0x7E, 0x17, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x20, 0x20, 0x20, 0x00, 158 | //---------- 159 | //Row 3 160 | 0x00, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x1E, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x09, 0x09, 0x09, 0x00, 161 | //---------- 162 | //Row 4 163 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x1F, 0x1F, 0x07, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 164 | //---------- 165 | //Row 5 166 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 167 | //---------- 168 | 169 | }; 170 | 171 | const uint8_t PROGMEM compass_180[] = { 172 | //Row 0 173 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x04, 0x18, 0x20, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 174 | //---------- 175 | //Row 1 176 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x1C, 0x1C, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 177 | //---------- 178 | //Row 2 179 | 0x00, 0x60, 0x80, 0x00, 0x80, 0x60, 0x80, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x3E, 0x01, 0x00, 0x00, 0x03, 0x3C, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x20, 0x20, 0x20, 0x00, 180 | //---------- 181 | //Row 3 182 | 0x00, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x09, 0x09, 0x09, 0x00, 183 | //---------- 184 | //Row 4 185 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x3F, 0x3F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 186 | //---------- 187 | //Row 5 188 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 189 | //---------- 190 | 191 | }; 192 | 193 | const uint8_t PROGMEM compass_210[] = { 194 | //Row 0 195 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x04, 0x18, 0x20, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 196 | //---------- 197 | //Row 1 198 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xF8, 0xF8, 0x60, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 199 | //---------- 200 | //Row 2 201 | 0x00, 0x60, 0x80, 0x00, 0x80, 0x60, 0x80, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x1F, 0x7E, 0xE1, 0x87, 0x07, 0x0E, 0xBC, 0xB0, 0xF0, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x20, 0x20, 0x20, 0x00, 202 | //---------- 203 | //Row 3 204 | 0x00, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x1E, 0x1F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x09, 0x09, 0x09, 0x00, 205 | //---------- 206 | //Row 4 207 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x07, 0x1F, 0x1F, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 208 | //---------- 209 | //Row 5 210 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 211 | //---------- 212 | 213 | }; 214 | 215 | const uint8_t PROGMEM compass_240[] = { 216 | //Row 0 217 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x04, 0x18, 0x20, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 218 | //---------- 219 | //Row 1 220 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 221 | //---------- 222 | //Row 2 223 | 0x00, 0x60, 0x80, 0x00, 0x80, 0x60, 0x80, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x07, 0x1F, 0x1E, 0x37, 0xF6, 0xEE, 0x8C, 0x98, 0x0C, 0x18, 0x18, 0x30, 0xD8, 0xF0, 0xF0, 0xE0, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x20, 0x20, 0x20, 0x00, 224 | //---------- 225 | //Row 3 226 | 0x00, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x07, 0x0F, 0x0C, 0x1F, 0x1F, 0x1F, 0x1F, 0x3F, 0x7F, 0x3F, 0x7F, 0x7F, 0xFC, 0x78, 0xF8, 0xE0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x09, 0x09, 0x09, 0x00, 227 | //---------- 228 | //Row 4 229 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 230 | //---------- 231 | //Row 5 232 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 233 | //---------- 234 | 235 | }; 236 | 237 | const uint8_t PROGMEM compass_270[] = { 238 | //Row 0 239 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x04, 0x18, 0x20, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 240 | //---------- 241 | //Row 1 242 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 243 | //---------- 244 | //Row 2 245 | 0x00, 0x60, 0x80, 0x00, 0x80, 0x60, 0x80, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xE0, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x20, 0x20, 0x20, 0x00, 246 | //---------- 247 | //Row 3 248 | 0x00, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x07, 0x07, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x09, 0x09, 0x09, 0x00, 249 | //---------- 250 | //Row 4 251 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 252 | //---------- 253 | //Row 5 254 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 255 | //---------- 256 | 257 | }; 258 | 259 | const uint8_t PROGMEM compass_300[] = { 260 | //Row 0 261 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x04, 0x18, 0x20, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 262 | //---------- 263 | //Row 1 264 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 265 | //---------- 266 | //Row 2 267 | 0x00, 0x60, 0x80, 0x00, 0x80, 0x60, 0x80, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xE0, 0xF0, 0x30, 0xF8, 0xF8, 0xF8, 0xF8, 0xFC, 0xFE, 0xFC, 0xFE, 0xFE, 0x3F, 0x1E, 0x1F, 0x07, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x20, 0x20, 0x20, 0x00, 268 | //---------- 269 | //Row 3 270 | 0x00, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xE0, 0xF8, 0x78, 0xEC, 0x6E, 0x77, 0x37, 0x71, 0x30, 0x18, 0x18, 0x0C, 0x1B, 0x0F, 0x0F, 0x07, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x09, 0x09, 0x09, 0x00, 271 | //---------- 272 | //Row 4 273 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 274 | //---------- 275 | //Row 5 276 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 277 | //---------- 278 | 279 | }; 280 | 281 | const uint8_t PROGMEM compass_330[] = { 282 | //Row 0 283 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x04, 0x18, 0x20, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 284 | //---------- 285 | //Row 1 286 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xE0, 0xF8, 0xF8, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 287 | //---------- 288 | //Row 2 289 | 0x00, 0x60, 0x80, 0x00, 0x80, 0x60, 0x80, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x78, 0xF8, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x20, 0x20, 0x20, 0x00, 290 | //---------- 291 | //Row 3 292 | 0x00, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x03, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE8, 0x7E, 0x97, 0xC1, 0xC0, 0xF0, 0x3D, 0x0D, 0x0F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x09, 0x09, 0x09, 0x00, 293 | //---------- 294 | //Row 4 295 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x1F, 0x1F, 0x06, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 296 | //---------- 297 | //Row 5 298 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 299 | //---------- 300 | 301 | }; 302 | 303 | //Calibration screen sprites 304 | const uint8_t PROGMEM calibration_0[] = { 305 | //Row 0 306 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x29, 0x29, 0x19, 0x00, 0x7C, 0x24, 0x24, 0x18, 0x00, 0x3D, 0x00, 0x3C, 0x04, 0x3C, 0x80, 0x80, 0x80, 0x80, 0x00, 0x21, 0x25, 0x3F, 0x00, 0x00, 0x3E, 0x25, 0x25, 0x18, 0x00, 0x3F, 0x21, 0x23, 0x1C, 0x00, 0x02, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 307 | //---------- 308 | //Row 1 309 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xF0, 0x78, 0x38, 0x1C, 0x0E, 0x06, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x06, 0x0E, 0x1C, 0x38, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 310 | //---------- 311 | //Row 2 312 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xC0, 0xC0, 0xFE, 0xFF, 0xE3, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x18, 0x1C, 0x3E, 0xFF, 0xFF, 0x1C, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 313 | //---------- 314 | //Row 3 315 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x43, 0xE1, 0xC1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x7C, 0x3F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 316 | //---------- 317 | //Row 4 318 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x01, 0x83, 0x07, 0x0E, 0xCC, 0x1C, 0x1C, 0x18, 0x18, 0x18, 0x38, 0x38, 0x38, 0x38, 0x18, 0x1C, 0x1C, 0x0C, 0x0E, 0x07, 0x03, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 319 | //---------- 320 | //Row 5 321 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x20, 0x11, 0x00, 0x00, 0x10, 0x2A, 0x2A, 0x3C, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3F, 0x22, 0x22, 0x1C, 0x00, 0x00, 0x3E, 0x04, 0x02, 0x00, 0x10, 0x2A, 0x2A, 0x3C, 0x00, 0x02, 0x1F, 0x22, 0x22, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x02, 0x02, 0x3C, 0x00, 0x00, 0x1C, 0xA2, 0xA2, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 322 | //---------- 323 | 324 | }; 325 | 326 | const uint8_t PROGMEM calibration_1[] = { 327 | //Row 0 328 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x29, 0x29, 0x19, 0x00, 0x7C, 0x24, 0x24, 0x18, 0x00, 0x3D, 0x00, 0x3C, 0x04, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x25, 0x3F, 0x00, 0x00, 0x3E, 0x25, 0x25, 0x18, 0x00, 0x3F, 0x21, 0x23, 0x1C, 0x00, 0x02, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 329 | //---------- 330 | //Row 1 331 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 332 | //---------- 333 | //Row 2 334 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 335 | //---------- 336 | //Row 3 337 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 338 | //---------- 339 | //Row 4 340 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 341 | //---------- 342 | //Row 5 343 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x20, 0x11, 0x00, 0x00, 0x10, 0x2A, 0x2A, 0x3C, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3F, 0x22, 0x22, 0x1C, 0x00, 0x00, 0x3E, 0x04, 0x02, 0x00, 0x10, 0x2A, 0x2A, 0x3C, 0x00, 0x02, 0x1F, 0x22, 0x22, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x02, 0x02, 0x3C, 0x00, 0x00, 0x1C, 0xA2, 0xA2, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 344 | //---------- 345 | 346 | }; 347 | 348 | const uint8_t* const PROGMEM compass[] = {compass_0, compass_30, compass_60, compass_90, 349 | compass_120, compass_150, compass_180, compass_210, 350 | compass_240, compass_270, compass_300, compass_330 351 | }; 352 | 353 | const uint8_t* const PROGMEM calibrate[] = { calibration_0, calibration_1 }; 354 | 355 | uint8_t spriteBuffer [SCREEN_BUFFER_SIZE]; //Will hold the bitmap data loaded from program memory 356 | 357 | MAG3110 mag = MAG3110(); 358 | 359 | void setup() { 360 | 361 | //Set up the microview 362 | //Display Sparkfun logo (preloaded into display memory) 363 | //And display MAG3110 demo text 364 | uView.begin(); 365 | uView.clear(ALL); 366 | uView.display(); 367 | delay(1400); 368 | uView.clear(PAGE); 369 | uView.print("MAG3110"); 370 | uView.setCursor(0, 10); 371 | uView.print("Demo"); 372 | uView.display(); 373 | delay(1500); 374 | uView.clear(PAGE); 375 | 376 | //Start communications 377 | 378 | Serial.begin(9600); 379 | 380 | Wire.begin(); //setup I2C bus 381 | Wire.setClock(400000); // I2C fast mode, 400kHz 382 | 383 | //Initialize the MAG3110 384 | mag.initialize(); 385 | //Start calibration 386 | mag.enterCalMode(); 387 | } 388 | 389 | //Loads a sprite from program memory into the display buffer 390 | //You must use special functions to load data from program memory 391 | //See http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html 392 | //For more information 393 | void loadSpriteFromPMem(const void* sprite) { 394 | memcpy_P(spriteBuffer, (byte*)pgm_read_word(sprite), SCREEN_BUFFER_SIZE); 395 | memcpy(uView.getScreenBuffer(), &spriteBuffer, SCREEN_BUFFER_SIZE); 396 | } 397 | 398 | int i = 0; 399 | int animationTimer = millis(); 400 | bool calibrationDone = false; 401 | void loop() { 402 | 403 | //If we're in calibration mode 404 | if (mag.isCalibrating()) 405 | { 406 | //Display the calibration screen 407 | if (millis() - animationTimer > 500) 408 | { 409 | i ^= 0x01; //Toggles on and off 410 | 411 | animationTimer = millis(); 412 | 413 | uView.clear(PAGE); 414 | //Make the calibration mode screen "blink" 415 | //This simply toggles which sprite is shown 416 | loadSpriteFromPMem(&(calibrate[i])); 417 | uView.display(); 418 | 419 | mag.calibrate(); 420 | } 421 | } 422 | 423 | 424 | //If we have just exited calibration mode 425 | if (mag.isCalibrated() && !calibrationDone) 426 | { 427 | uView.clear(PAGE); 428 | uView.print("Ok"); 429 | uView.display(); 430 | Serial.println("Exiting calibration mode"); 431 | 432 | delay(3000); 433 | calibrationDone = true; 434 | } 435 | 436 | if (mag.isCalibrated()) 437 | { 438 | //This used to cycle through all the compass sprites 439 | //if (i >11) 440 | //i = 0; 441 | 442 | //Make sure the top edge of the microview is pointed the same way as the x-axis of the MAG3110 unit 443 | //As in this case, you may need to add an offset to get the proper angle 444 | //In my circuit, the x-axis of the MAG3110 was 90 CW of the front of my microview, so I add 90 degrees 445 | //The other code makes the heading pertain to 0 to 360 degrees instead of +- 180 446 | int heading = (int)mag.readHeading() + 90; 447 | 448 | if (heading < 0) //If the heading is negative (ranges from -1 to -180) 449 | heading *= -1; //Negate the heading 450 | else if (heading > 0) 451 | heading = 360 - heading; 452 | 453 | int spriteNum = 0; 454 | 455 | //These if statements select the proper compass needle sprite 456 | if (heading < 15 && heading > 0 || heading > 345) //Between 0 and 15 or above 345 degrees 457 | { 458 | spriteNum = 0; 459 | } 460 | else if (heading >= 15 && heading < 45) //Between 15 and 45 461 | { 462 | spriteNum = 1; 463 | } 464 | else if (heading >= 45 && heading < 75) 465 | { 466 | spriteNum = 2; 467 | } 468 | else if (heading >= 75 && heading < 105) 469 | { 470 | spriteNum = 3; 471 | } 472 | else if (heading >= 105 && heading < 135) 473 | { 474 | spriteNum = 4; 475 | } 476 | else if (heading >= 135 && heading < 165) 477 | { 478 | spriteNum = 5; 479 | } 480 | else if (heading >= 165 && heading < 195) 481 | { 482 | spriteNum = 6; 483 | } 484 | else if (heading >= 195 && heading < 225) 485 | { 486 | spriteNum = 7; 487 | } 488 | else if (heading >= 225 && heading < 255) 489 | { 490 | spriteNum = 8; 491 | } 492 | else if (heading >= 255 && heading < 285) 493 | { 494 | spriteNum = 9; 495 | } 496 | else if (heading >= 285 && heading < 315) 497 | { 498 | spriteNum = 10; 499 | } 500 | else if (heading >= 315 && heading < 345) 501 | { 502 | spriteNum = 11; 503 | } 504 | 505 | //Load and display compass 506 | uView.clear(PAGE); 507 | loadSpriteFromPMem(&(compass[spriteNum])); 508 | uView.setCursor(0, 40); 509 | uView.print(heading); 510 | uView.display(); 511 | delay(100); 512 | } 513 | } 514 | 515 | -------------------------------------------------------------------------------- /examples/SparkFun_MAG3110_Basic/SparkFun_MAG3110_Basic.ino: -------------------------------------------------------------------------------- 1 | /* ********************************************* 2 | * SparkFun_MAG3110_Basic 3 | * Triple Axis Magnetometer Breakout - MAG3110 4 | * Hook Up Guide Example 5 | * 6 | * Utilizing Sparkfun's MAG3110 Library 7 | * A basic sketch that reads x y and z readings 8 | * from the MAG3110 sensor 9 | * 10 | * George B. on behalf of SparkFun Electronics 11 | * Created: Sep 22, 2016 12 | * Updated: n/a 13 | * 14 | * Development Environment Specifics: 15 | * Arduino 1.6.7 16 | * 17 | * Hardware Specifications: 18 | * SparkFun MAG3110 19 | * Bi-directional Logic Level Converter 20 | * Arduino Micro 21 | * 22 | * This code is beerware; if you see me (or any other SparkFun employee) at the 23 | * local, and you've found our code helpful, please buy us a round! 24 | * Distributed as-is; no warranty is given. 25 | * *********************************************/ 26 | 27 | #include 28 | 29 | MAG3110 mag = MAG3110(); //Instantiate MAG3110 30 | 31 | void setup() { 32 | 33 | Serial.begin(9600); 34 | 35 | Wire.begin(); //setup I2C bus 36 | Wire.setClock(400000); // I2C fast mode, 400kHz 37 | 38 | mag.initialize(); //Initializes the mag sensor 39 | mag.start(); //Puts the sensor in active mode 40 | } 41 | 42 | void loop() { 43 | 44 | int x, y, z; 45 | //Only read data when it's ready 46 | if(mag.dataReady()) { 47 | //Read the data 48 | mag.readMag(&x, &y, &z); 49 | 50 | Serial.print("X: "); 51 | Serial.print(x); 52 | Serial.print(", Y: "); 53 | Serial.print(y); 54 | Serial.print(", Z: "); 55 | Serial.println(z); 56 | 57 | Serial.println("--------"); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /examples/SparkFun_MAG3110_Calibrated/SparkFun_MAG3110_Calibrated.ino: -------------------------------------------------------------------------------- 1 | /* ********************************************* 2 | * SparkFun_MAG3110_Calibrated 3 | * Triple Axis Magnetometer Breakout - MAG3110 4 | * Hook Up Guide Example 5 | * 6 | * Utilizing Sparkfun's MAG3110 Library 7 | * Shows how to use the built-in calibration 8 | * This allows you to get a heading 9 | * 10 | * Note: Calibration only works with a level 11 | * sensor orientation and uses only x and y axes 12 | * 13 | * To calibrate, spin the sensor around 360 degrees 14 | * It should exit calibration mode after 5-10 seconds 15 | * 16 | * Heading is in the range of +-180 degrees 17 | * With 0 meaning the x-axis is facing magnetic north 18 | * 19 | * George B. on behalf of SparkFun Electronics 20 | * Created: Sep 22, 2016 21 | * Updated: n/a 22 | * 23 | * Development Environment Specifics: 24 | * Arduino 1.6.7 25 | * 26 | * Hardware Specifications: 27 | * SparkFun MAG3110 28 | * Bi-directional Logic Level Converter 29 | * Arduino Micro 30 | * 31 | * This code is beerware; if you see me (or any other SparkFun employee) at the 32 | * local, and you've found our code helpful, please buy us a round! 33 | * Distributed as-is; no warranty is given. 34 | * *********************************************/ 35 | 36 | #include 37 | 38 | MAG3110 mag = MAG3110(); //Instantiate MAG3110 39 | 40 | void setup() { 41 | 42 | Serial.begin(9600); 43 | 44 | Wire.begin(); //setup I2C bus 45 | Wire.setClock(400000); // I2C fast mode, 400kHz 46 | 47 | mag.initialize(); //Initialize the MAG3110 48 | } 49 | 50 | void loop() { 51 | 52 | int x, y, z; 53 | 54 | if(!mag.isCalibrated()) //If we're not calibrated 55 | { 56 | if(!mag.isCalibrating()) //And we're not currently calibrating 57 | { 58 | Serial.println("Entering calibration mode"); 59 | mag.enterCalMode(); //This sets the output data rate to the highest possible and puts the mag sensor in active mode 60 | } 61 | else 62 | { 63 | //Must call every loop while calibrating to collect calibration data 64 | //This will automatically exit calibration 65 | //You can terminate calibration early by calling mag.exitCalMode(); 66 | mag.calibrate(); 67 | } 68 | } 69 | else 70 | { 71 | Serial.println("Calibrated!"); 72 | } 73 | mag.readMag(&x, &y, &z); 74 | 75 | Serial.print("X: "); 76 | Serial.print(x); 77 | Serial.print(", Y: "); 78 | Serial.print(y); 79 | Serial.print(", Z: "); 80 | Serial.println(z); 81 | 82 | Serial.print("Heading: "); 83 | Serial.println(mag.readHeading()); 84 | 85 | Serial.println("--------"); 86 | 87 | delay(100); 88 | } 89 | -------------------------------------------------------------------------------- /examples/SparkFun_MAG3110_Magnitude/SparkFun_MAG3110_Magnitude.ino: -------------------------------------------------------------------------------- 1 | /* ********************************************* 2 | * SparkFun_MAG3110_Calibrated 3 | * Triple Axis Magnetometer Breakout - MAG3110 4 | * Hook Up Guide Example 5 | * 6 | * Utilizing Sparkfun's MAG3110 Library 7 | * This allows you to see the magnitude of 8 | * magnetic fields around the sensor 9 | * 10 | * You can see interference from power electronics 11 | * IE: a microwave 12 | * Or put a fridge magnet nearby to see the spikes. 13 | * 14 | * Use Tools->Serial Plotter to visualize the data 15 | * 16 | * George B. on behalf of SparkFun Electronics 17 | * Created: Sep 22, 2016 18 | * Updated: n/a 19 | * 20 | * Development Environment Specifics: 21 | * Arduino 1.6.7 22 | * 23 | * Hardware Specifications: 24 | * SparkFun MAG3110 25 | * Bi-directional Logic Level Converter 26 | * Arduino Micro 27 | * 28 | * This code is beerware; if you see me (or any other SparkFun employee) at the 29 | * local, and you've found our code helpful, please buy us a round! 30 | * Distributed as-is; no warranty is given. 31 | * *********************************************/ 32 | 33 | #include 34 | 35 | MAG3110 mag = MAG3110(); //Instantiate MAG3110 36 | 37 | void setup() { 38 | 39 | Serial.begin(9600); 40 | 41 | Wire.begin(); //setup I2C bus 42 | Wire.setClock(400000); // I2C fast mode, 400kHz 43 | 44 | mag.initialize(); //Initialize the MAG3110 45 | } 46 | 47 | void loop() { 48 | 49 | int x, y, z; 50 | 51 | if(!mag.isCalibrated()) //If we're not calibrated 52 | { 53 | if(!mag.isCalibrating()) //And we're not currently calibrating 54 | { 55 | Serial.println("Entering calibration mode"); 56 | mag.enterCalMode(); //This sets the output data rate to the highest possible and puts the mag sensor in active mode 57 | } 58 | else 59 | { 60 | //Must call every loop while calibrating to collect calibration data 61 | //This will automatically exit calibration 62 | //You can terminate calibration early by calling mag.exitCalMode(); 63 | mag.calibrate(); 64 | } 65 | } 66 | else //We are calibrated 67 | { 68 | mag.readMag(&x, &y, &z); 69 | float magnitude = sqrt(pow(x*mag.x_scale, 2) + pow(y*mag.y_scale, 2)); //x_scale and y_scale are set by calibration! Do not modify them! 70 | Serial.println(magnitude); 71 | } 72 | delay(20); 73 | } 74 | -------------------------------------------------------------------------------- /examples/SparkFun_MAG3110_Other/SparkFun_MAG3110_Other.ino: -------------------------------------------------------------------------------- 1 | /* ********************************************* 2 | * SparkFun_MAG3110_Other 3 | * Triple Axis Magnetometer Breakout - MAG3110 4 | * Hook Up Guide Example 5 | * 6 | * Utilizing Sparkfun's MAG3110 Library 7 | * 8 | * This sketch shows you some of the library's 9 | * more obscure functionality 10 | * 11 | * Read the comments to learn more 12 | * 13 | * George B. on behalf of SparkFun Electronics 14 | * Created: Sep 22, 2016 15 | * Updated: n/a 16 | * 17 | * Development Environment Specifics: 18 | * Arduino 1.6.7 19 | * 20 | * Hardware Specifications: 21 | * SparkFun MAG3110 22 | * Bi-directional Logic Level Converter 23 | * Arduino Micro 24 | * 25 | * This code is beerware; if you see me (or any other SparkFun employee) at the 26 | * local, and you've found our code helpful, please buy us a round! 27 | * Distributed as-is; no warranty is given. 28 | * *********************************************/ 29 | 30 | #include 31 | 32 | MAG3110 mag = MAG3110(); //Instantiate MAG3110 33 | 34 | void setup() { 35 | 36 | Serial.begin(9600); 37 | 38 | Wire.begin(); //setup I2C bus 39 | Wire.setClock(400000); // I2C fast mode, 400kHz 40 | 41 | mag.initialize(); 42 | //This line makes the output data rate a lot slower 43 | //Output Data Rate = 1.25Hz 44 | //Oversampling Ratio = 32 45 | //This means it takes 32 samples and averages the results 46 | if(!mag.error) //You can use this to check if there was an error during initialization. 47 | { 48 | mag.setDR_OS(MAG3110_DR_OS_1_25_32); 49 | mag.start(); 50 | } 51 | 52 | //You can set your own offsets without calibration 53 | //mag.setOffset(MAG3110_X_AXIS, -100); 54 | //mag.setOffset(MAG3110_Y_AXIS, 300); 55 | //mag.setOffset(MAG3110_Z_AXIS, -300); 56 | 57 | //You can read the sensor's offset by calling: 58 | //int offset = mag.readOffset(MAG3110_X_AXIS); 59 | 60 | //You can obtain system information by calling any of the following: 61 | //mag.isActive(); //Tells you whether the mag sensor is active or in standby 62 | //mag.isRaw(); //Tells you if the mag sensor is outputting raw data or not 63 | //mag.isCalibrated(); //Tells you if the mag sensor has been calibrated 64 | //mag.isCalibrating(); //Tells you if the mag sensor is currently being calibrated 65 | //uint8_t mode = mag.getSysMode(); //Reads the SYSMOD register. See the datasheet for more information 66 | 67 | //This will reset the sensor to default values 68 | //It sets the offsets to 0, flags it as uncalibrated, and sets the device to standby mode 69 | //The Output Data Rate and Oversampling ratio will also be set to 80 and 16 respectively (see datasheet) 70 | //mag.reset(); 71 | 72 | //This will disable the use of user offsets 73 | //User offsets are enabled by default but are initialized to 0 74 | //mag.rawData(true); 75 | } 76 | 77 | void loop() { 78 | 79 | float xf, yf, zf; 80 | //Only read data when it's ready 81 | if(mag.error) 82 | Serial.println("Could not connect to MAG3110 Sensor!"); 83 | if(mag.dataReady()) { 84 | mag.readMicroTeslas(&xf, &yf, &zf); //This divides the values by 10 to get the reading in microTeslas 85 | 86 | Serial.print("X: "); 87 | Serial.print(xf); 88 | Serial.print(", Y: "); 89 | Serial.print(yf); 90 | Serial.print(", Z: "); 91 | Serial.println(zf); 92 | 93 | Serial.println("--------"); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /examples/SparkFun_MAG3110_Triggered/SparkFun_MAG3110_Triggered.ino: -------------------------------------------------------------------------------- 1 | /* ********************************************* 2 | * SparkFun_MAG3110_Triggered 3 | * Triple Axis Magnetometer Breakout - MAG3110 4 | * Hook Up Guide Example 5 | * 6 | * Utilizing Sparkfun's MAG3110 Library 7 | * A sketch showing how to use triggered 8 | * (one-shot) readings on the MAG3110 9 | * 10 | * This saves power but may affect the accuracy of the data 11 | * See the datasheet for more information 12 | * 13 | * George B. on behalf of SparkFun Electronics 14 | * Created: Sep 22, 2016 15 | * Updated: n/a 16 | * 17 | * Development Environment Specifics: 18 | * Arduino 1.6.7 19 | * 20 | * Hardware Specifications: 21 | * SparkFun MAG3110 22 | * Bi-directional Logic Level Converter 23 | * Arduino Micro 24 | * 25 | * This code is beerware; if you see me (or any other SparkFun employee) at the 26 | * local, and you've found our code helpful, please buy us a round! 27 | * Distributed as-is; no warranty is given. 28 | * *********************************************/ 29 | 30 | #include 31 | 32 | MAG3110 mag = MAG3110(); //Instantiate MAG3110 33 | 34 | void setup() { 35 | 36 | Serial.begin(9600); 37 | 38 | Wire.begin(); //setup I2C bus 39 | Wire.setClock(400000); // I2C fast mode, 400kHz 40 | 41 | mag.initialize(); //Initializes the mag sensor 42 | //When initialized, the sensor will be in standby 43 | } 44 | 45 | int timeStamp = 0; 46 | void loop() { 47 | 48 | //Trigger a measurement every 2 seconds 49 | if(millis() - timeStamp > 2000) 50 | { 51 | timeStamp = millis(); 52 | mag.triggerMeasurement(); 53 | } 54 | 55 | int x, y, z; 56 | //Only read data when it's ready 57 | if(mag.dataReady()) { 58 | //Read the data 59 | mag.readMag(&x, &y, &z); 60 | 61 | Serial.print("X: "); 62 | Serial.print(x); 63 | Serial.print(", Y: "); 64 | Serial.print(y); 65 | Serial.print(", Z: "); 66 | Serial.println(z); 67 | 68 | Serial.println("--------"); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /extras/MAG3110_v9.2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/SparkFun_MAG3110_Breakout_Board_Arduino_Library/ea89f4ce5a5b17dfa22475b013081f7683685f3f/extras/MAG3110_v9.2.pdf -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For MAG3110 3 | ####################################### 4 | 5 | ####################################### 6 | # Library (KEYWORD1) 7 | ####################################### 8 | 9 | MAG3110 KEYWORD1 10 | SparkFunMAG3110 KEYWORD1 11 | 12 | ####################################### 13 | # Datatypes (KEYWORD1) 14 | ####################################### 15 | 16 | #Nothing here yet 17 | 18 | ####################################### 19 | # Methods and Functions (KEYWORD2) 20 | ####################################### 21 | 22 | initialize KEYWORD2 23 | readRegister KEYWORD2 24 | writeRegister KEYWORD2 25 | dataReady KEYWORD2 26 | readMag KEYWORD2 27 | readMicroTeslas KEYWORD2 28 | readHeading KEYWORD2 29 | setDR_OS KEYWORD2 30 | triggerMeasurement KEYWORD2 31 | rawData KEYWORD2 32 | setOffset KEYWORD2 33 | readOffset KEYWORD2 34 | start KEYWORD2 35 | enterStandby KEYWORD2 36 | exitStandby KEYWORD2 37 | isActive KEYWORD2 38 | isRaw KEYWORD2 39 | isCalibrated KEYWORD2 40 | isCalibrating KEYWORD2 41 | getSysMode KEYWORD2 42 | enterCalMode KEYWORD2 43 | calibrate KEYWORD2 44 | exitCalMode KEYWORD2 45 | reset KEYWORD2 46 | 47 | scale_x KEYWORD2 48 | scale_y KEYWORD2 49 | 50 | ####################################### 51 | # Constants (LITERAL1) 52 | ####################################### 53 | 54 | MAG3110_I2C_ADDRESS LITERAL1 55 | 56 | ///////////////////////////////////////// 57 | // MAG3110 Magnetometer Registers // 58 | ///////////////////////////////////////// 59 | MAG3110_DR_STATUS LITERAL1 60 | MAG3110_OUT_X_MSB LITERAL1 61 | MAG3110_OUT_X_LSB LITERAL1 62 | MAG3110_OUT_Y_MSB LITERAL1 63 | MAG3110_OUT_Y_LSB LITERAL1 64 | MAG3110_OUT_Z_MSB LITERAL1 65 | MAG3110_OUT_Z_LSB LITERAL1 66 | MAG3110_WHO_AM_I LITERAL1 67 | MAG3110_SYSMOD LITERAL1 68 | MAG3110_OFF_X_MSB LITERAL1 69 | MAG3110_OFF_X_LSB LITERAL1 70 | MAG3110_OFF_Y_MSB LITERAL1 71 | MAG3110_OFF_Y_LSB LITERAL1 72 | MAG3110_OFF_Z_MSB LITERAL1 73 | MAG3110_OFF_Z_LSB LITERAL1 74 | MAG3110_DIE_TEMP LITERAL1 75 | MAG3110_CTRL_REG1 LITERAL1 76 | MAG3110_CTRL_REG2 LITERAL1 77 | 78 | MAG3110_WHO_AM_I_RSP LITERAL1 79 | 80 | MAG3110_DR_OS_80_16 LITERAL1 81 | MAG3110_DR_OS_40_32 LITERAL1 82 | MAG3110_DR_OS_20_64 LITERAL1 83 | MAG3110_DR_OS_10_128 LITERAL1 84 | MAG3110_DR_OS_40_16 LITERAL1 85 | MAG3110_DR_OS_20_32 LITERAL1 86 | MAG3110_DR_OS_10_64 LITERAL1 87 | MAG3110_DR_OS_5_128 LITERAL1 88 | MAG3110_DR_OS_20_16 LITERAL1 89 | MAG3110_DR_OS_10_32 LITERAL1 90 | MAG3110_DR_OS_5_64 LITERAL1 91 | MAG3110_DR_OS_2_5_128 LITERAL1 92 | MAG3110_DR_OS_10_16 LITERAL1 93 | MAG3110_DR_OS_5_32 LITERAL1 94 | MAG3110_DR_OS_2_5_64 LITERAL1 95 | MAG3110_DR_OS_1_25_128 LITERAL1 96 | MAG3110_DR_OS_5_16 LITERAL1 97 | MAG3110_DR_OS_2_5_32 LITERAL1 98 | MAG3110_DR_OS_1_25_64 LITERAL1 99 | MAG3110_DR_OS_0_63_128 LITERAL1 100 | MAG3110_DR_OS_2_5_16 LITERAL1 101 | MAG3110_DR_OS_1_25_32 LITERAL1 102 | MAG3110_DR_OS_0_63_64 LITERAL1 103 | MAG3110_DR_OS_0_31_128 LITERAL1 104 | MAG3110_DR_OS_1_25_16 LITERAL1 105 | MAG3110_DR_OS_0_63_32 LITERAL1 106 | MAG3110_DR_OS_0_31_64 LITERAL1 107 | MAG3110_DR_OS_0_16_128 LITERAL1 108 | MAG3110_DR_OS_0_63_16 LITERAL1 109 | MAG3110_DR_OS_0_31_32 LITERAL1 110 | MAG3110_DR_OS_0_16_64 LITERAL1 111 | MAG3110_DR_OS_0_08_128 LITERAL1 112 | 113 | MAG3110_FAST_READ LITERAL1 114 | MAG3110_TRIGGER_MEASUREMENT LITERAL1 115 | MAG3110_ACTIVE_MODE LITERAL1 116 | MAG3110_STANDBY_MODE LITERAL1 117 | 118 | MAG3110_AUTO_MRST_EN LITERAL1 119 | MAG3110_RAW_MODE LITERAL1 120 | MAG3110_NORMAL_MODE LITERAL1 121 | MAG3110_MAG_RST LITERAL1 122 | 123 | MAG3110_SYSMOD_STANDBY LITERAL1 124 | MAG3110_SYSMOD_ACTIVE_RAW LITERAL1 125 | MAG3110_SYSMOD_ACTIVE LITERAL1 126 | 127 | MAG3110_X_AXIS LITERAL1 128 | MAG3110_Y_AXIS LITERAL1 129 | MAG3110_Z_AXIS LITERAL1 130 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=SparkFun MAG3110 Magnetometer Breakout Arduino Library 2 | version=1.0.3 3 | author=George B. for SparkFun Electronics 4 | maintainer=SparkFun Electronics 5 | sentence=This library makes it easy for you to get started with the MAG3110 breakout board. (https://www.sparkfun.com/products/12670) 6 | paragraph=This library makes it easy for you to get started with the MAG3110 breakout board. It also has commands included for more advanced users that want to squeeze even more functionality out of the MAG3110. 7 | category=Other 8 | url=https://github.com/sparkfun/SparkFun_MAG3110_Breakout_Board_Arduino_Library 9 | architectures=avr 10 | -------------------------------------------------------------------------------- /src/SparkFun_MAG3110.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | MAG3110.cpp 3 | SFE_MAG3110 Library 4 | George Beckstein contracting for SparkFun Electronics 5 | Original Creation Date: 9/11/2016 6 | 7 | This file defines the MAG3110 class methods, etc 8 | 9 | Development environment specifics: 10 | IDE: Arduino 1.6.7 11 | Hardware Platform: Arduino Uno 12 | MAG3110 Breakout Version 1 13 | 14 | This code is beerware; if you see me (or any other SparkFun employee) at the 15 | local, and you've found our code helpful, please buy us a round! 16 | 17 | Distributed as-is; no warranty is given. 18 | ******************************************************************************/ 19 | 20 | #include "Arduino.h" 21 | #include "SparkFun_MAG3110.h" 22 | #include 23 | #include 24 | 25 | #define CALIBRATION_TIMEOUT 5000 //timeout in milliseconds 26 | #define DEG_PER_RAD (180.0/3.14159265358979) 27 | 28 | MAG3110::MAG3110() { 29 | 30 | //Just some random initial values 31 | x_offset = 0; 32 | y_offset = 0; 33 | 34 | x_scale = 0.0f; 35 | y_scale = 0.0f; 36 | } 37 | 38 | bool MAG3110::initialize() { 39 | 40 | if(readRegister(MAG3110_WHO_AM_I) != MAG3110_WHO_AM_I_RSP){ //Could not find MAG3110 41 | //Serial.println("Could not find MAG3110 connected!"); 42 | return false; 43 | } 44 | else //Successfully initialized 45 | { 46 | //Initial values 47 | reset(); 48 | return true; 49 | } 50 | } 51 | 52 | uint8_t MAG3110::readRegister(uint8_t address){ 53 | uint8_t output; 54 | 55 | Wire.beginTransmission(MAG3110_I2C_ADDRESS); 56 | Wire.write(address); 57 | Wire.endTransmission(); 58 | 59 | delayMicroseconds(2); 60 | 61 | Wire.requestFrom(MAG3110_I2C_ADDRESS, 1); 62 | while(Wire.available()) 63 | { 64 | output = Wire.read(); 65 | } 66 | 67 | return output; 68 | } 69 | 70 | void MAG3110::writeRegister(uint8_t address, uint8_t value){ 71 | Wire.beginTransmission(MAG3110_I2C_ADDRESS); 72 | Wire.write(address); 73 | Wire.write(value); 74 | Wire.endTransmission(); 75 | } 76 | 77 | bool MAG3110::dataReady() { 78 | return ((readRegister(MAG3110_DR_STATUS) & 0x8) >> 3); 79 | } 80 | 81 | void MAG3110::readMag(int* x, int* y, int* z){ 82 | 83 | // Start readout at X MSB address 84 | Wire.beginTransmission(MAG3110_I2C_ADDRESS); 85 | Wire.write(MAG3110_OUT_X_MSB); 86 | Wire.endTransmission(); 87 | 88 | delayMicroseconds(2); 89 | 90 | // Read out data using multiple byte read mode 91 | Wire.requestFrom(MAG3110_I2C_ADDRESS, 6); 92 | 93 | // Combine registers 94 | uint16_t values[3]; 95 | for(uint8_t idx = 0; idx <= 2; idx++) 96 | { 97 | values[idx] = Wire.read() << 8; // MSB 98 | values[idx] |= Wire.read(); // LSB 99 | } 100 | 101 | // Put data into referenced variables 102 | *x = (int) values[0]; 103 | *y = (int) values[1]; 104 | *z = (int) values[2]; 105 | 106 | } 107 | 108 | void MAG3110::readMicroTeslas(float* x, float* y, float* z){ 109 | 110 | // Using internal read function 111 | int x_int, y_int, z_int; 112 | readMag(&x_int, &y_int, &z_int); 113 | 114 | //Read each axis and scale to Teslas 115 | *x = (float) x_int * 0.1f; 116 | *y = (float) y_int * 0.1f; 117 | *z = (float) z_int * 0.1f; 118 | 119 | } 120 | 121 | //Note: Must be calibrated to use readHeading!!! 122 | float MAG3110::readHeading(){ 123 | 124 | int x, y, z; 125 | readMag(&x, &y, &z); 126 | 127 | float xf = (float) x * 1.0f; 128 | float yf = (float) y * 1.0f; 129 | 130 | //Calculate the heading 131 | return (atan2(-y*y_scale, x*x_scale) * DEG_PER_RAD); 132 | } 133 | 134 | void MAG3110::setDR_OS(uint8_t DROS){ 135 | bool wasActive = activeMode; 136 | 137 | if(activeMode) 138 | enterStandby(); //Must be in standby to modify CTRL_REG1 139 | 140 | //If we attempt to write to CTRL_REG1 right after going into standby 141 | //It might fail to modify the other bits 142 | delay(100); 143 | 144 | //Get the current control register 145 | uint8_t current = readRegister(MAG3110_CTRL_REG1) & 0x07; //And chop off the 5 MSB 146 | writeRegister(MAG3110_CTRL_REG1, (current | DROS)); //Write back the register with new DR_OS set 147 | 148 | delay(100); 149 | 150 | //Start sampling again if we were before 151 | if(wasActive) 152 | exitStandby(); 153 | } 154 | 155 | void MAG3110::triggerMeasurement(){ 156 | 157 | uint8_t current = readRegister(MAG3110_CTRL_REG1); 158 | writeRegister(MAG3110_CTRL_REG1, (current | 0x02)); 159 | } 160 | 161 | //Note that AUTO_MRST_EN will always read back as 0 162 | //Therefore we must explicitly set this bit every time we modify CTRL_REG2 163 | void MAG3110::rawData(bool raw){ 164 | if(raw) //Turn on raw (non-user corrected) mode 165 | { 166 | rawMode = true; 167 | writeRegister(MAG3110_CTRL_REG2, MAG3110_AUTO_MRST_EN | (0x01 << 5) ); 168 | } 169 | else //Turn off raw mode 170 | { 171 | rawMode = false; 172 | writeRegister(MAG3110_CTRL_REG2, MAG3110_AUTO_MRST_EN & ~(0x01 << 5)); 173 | } 174 | } 175 | 176 | //If you look at the datasheet, the offset registers are kind of strange 177 | //The offset is stored in the most significant 15 bits. 178 | //Bit 0 of the LSB register is always 0 for some reason... 179 | //So we have to left shift the values by 1 180 | //Ask me how confused I was... 181 | void MAG3110::setOffset(uint8_t axis, int offset){ 182 | 183 | offset = offset << 1; 184 | 185 | uint8_t msbAddress = axis + 8; 186 | uint8_t lsbAddress = msbAddress + 1; 187 | 188 | writeRegister(msbAddress, (uint8_t)((offset >> 8) & 0xFF)); 189 | 190 | delay(15); 191 | 192 | writeRegister(lsbAddress, (uint8_t) offset & 0xFF); 193 | } 194 | 195 | //See above 196 | int MAG3110::readOffset(uint8_t axis){ 197 | return (readAxis(axis+8)) >> 1; 198 | } 199 | 200 | void MAG3110::start() { 201 | exitStandby(); 202 | } 203 | 204 | void MAG3110::enterStandby(){ 205 | activeMode = false; 206 | uint8_t current = readRegister(MAG3110_CTRL_REG1); 207 | //Clear bits 0 and 1 to enter low power standby mode 208 | writeRegister(MAG3110_CTRL_REG1, (current & ~(0x3))); 209 | } 210 | 211 | void MAG3110::exitStandby(){ 212 | activeMode = true; 213 | uint8_t current = readRegister(MAG3110_CTRL_REG1); 214 | writeRegister(MAG3110_CTRL_REG1, (current | MAG3110_ACTIVE_MODE)); 215 | 216 | } 217 | 218 | bool MAG3110::isActive() { 219 | return activeMode; 220 | } 221 | 222 | bool MAG3110::isRaw() { 223 | return rawMode; 224 | } 225 | 226 | bool MAG3110::isCalibrated() { 227 | return calibrated; 228 | } 229 | 230 | bool MAG3110::isCalibrating() { 231 | return calibrationMode; 232 | } 233 | 234 | uint8_t MAG3110::getSysMode() { 235 | return readRegister(MAG3110_SYSMOD); 236 | } 237 | 238 | void MAG3110::enterCalMode(){ 239 | calibrationMode = true; 240 | //Starting values for calibration 241 | x_min = 32767; 242 | x_max = 0x8000; 243 | 244 | y_min = 32767; 245 | y_max = 0x8000; 246 | 247 | //Read raw readings for calibration 248 | rawData(true); 249 | 250 | calibrated = false; 251 | 252 | //Set to active mode, highest DROS for continous readings 253 | setDR_OS(MAG3110_DR_OS_80_16); 254 | if(!activeMode) 255 | start(); 256 | } 257 | 258 | void MAG3110::calibrate(){ 259 | int x, y, z; 260 | readMag(&x, &y, &z); 261 | 262 | bool changed = false; //Keep track of if a min/max is updated 263 | if(x < x_min) 264 | { 265 | x_min = x; 266 | changed = true; 267 | } 268 | if(x > x_max) 269 | { 270 | x_max = x; 271 | changed = true; 272 | } 273 | if(y < y_min) 274 | { 275 | y_min = y; 276 | changed = true; 277 | } 278 | if(y > y_max) 279 | { 280 | y_max = y; 281 | changed = true; 282 | } 283 | 284 | if(changed) 285 | timeLastChange = millis(); //Reset timeout counter 286 | 287 | if(millis() > 5000 && millis() - timeLastChange > CALIBRATION_TIMEOUT) //If the timeout has been reached, exit calibration 288 | exitCalMode(); 289 | } 290 | 291 | void MAG3110::exitCalMode(){ 292 | //Calculate offsets 293 | x_offset = (x_min + x_max)/2; 294 | 295 | y_offset = (y_min + y_max)/2; 296 | 297 | x_scale = 1.0/(x_max - x_min); 298 | y_scale = 1.0/(y_max - y_min); 299 | 300 | setOffset(MAG3110_X_AXIS, x_offset); 301 | //Set the offsets 302 | setOffset(MAG3110_Y_AXIS, y_offset); 303 | 304 | //Use the offsets (set to normal mode) 305 | rawData(false); 306 | 307 | calibrationMode = false; 308 | calibrated = true; 309 | 310 | //Enter standby and wait 311 | //enterStandby(); 312 | } 313 | 314 | void MAG3110::reset() { 315 | enterStandby(); 316 | writeRegister(MAG3110_CTRL_REG1, 0x00); //Set everything to 0 317 | writeRegister(MAG3110_CTRL_REG2, 0x80); //Enable Auto Mag Reset, non-raw mode 318 | 319 | calibrationMode = false; 320 | activeMode = false; 321 | rawMode = false; 322 | calibrated = false; 323 | 324 | setOffset(MAG3110_X_AXIS, 0); 325 | setOffset(MAG3110_Y_AXIS, 0); 326 | setOffset(MAG3110_Z_AXIS, 0); 327 | } 328 | 329 | //This is private because you must read each axis for the data ready bit to be cleared 330 | //It may be confusing for casual users 331 | int MAG3110::readAxis(uint8_t axis){ 332 | uint8_t lsbAddress, msbAddress; 333 | uint8_t lsb, msb; 334 | 335 | msbAddress = axis; 336 | lsbAddress = axis+1; 337 | 338 | msb = readRegister(msbAddress); 339 | 340 | delayMicroseconds(2); //needs at least 1.3us free time between start and stop 341 | 342 | lsb = readRegister(lsbAddress); 343 | 344 | int16_t out = (lsb | (msb << 8)); //concatenate the MSB and LSB; 345 | return (int)out; 346 | } -------------------------------------------------------------------------------- /src/SparkFun_MAG3110.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | MAG3110.h 3 | SFE_MAG3110 Library - MAG3110 Register Map 4 | George Beckstein contracting for SparkFun Electronics 5 | Original Creation Date: 9/11/2016 6 | 7 | This file declares the MAG3110 class and registers 8 | 9 | Development environment specifics: 10 | IDE: Arduino 1.6.7 11 | Hardware Platform: Arduino Uno 12 | MAG3110 Breakout Version 1 13 | 14 | This code is beerware; if you see me (or any other SparkFun employee) at the 15 | local, and you've found our code helpful, please buy us a round! 16 | 17 | Distributed as-is; no warranty is given. 18 | ******************************************************************************/ 19 | 20 | #ifndef SFE_MAG3110_h 21 | #define SFE_MAG3110_h 22 | 23 | #include "Arduino.h" 24 | #include "Wire.h" 25 | 26 | ///////////////////////////////////////// 27 | // MAG3110 I2C Address // 28 | ///////////////////////////////////////// 29 | 30 | #define MAG3110_I2C_ADDRESS 0x0E 31 | 32 | ///////////////////////////////////////// 33 | // MAG3110 Magnetometer Registers // 34 | ///////////////////////////////////////// 35 | #define MAG3110_DR_STATUS 0x00 36 | #define MAG3110_OUT_X_MSB 0x01 37 | #define MAG3110_OUT_X_LSB 0x02 38 | #define MAG3110_OUT_Y_MSB 0x03 39 | #define MAG3110_OUT_Y_LSB 0x04 40 | #define MAG3110_OUT_Z_MSB 0x05 41 | #define MAG3110_OUT_Z_LSB 0x06 42 | #define MAG3110_WHO_AM_I 0x07 43 | #define MAG3110_SYSMOD 0x08 44 | #define MAG3110_OFF_X_MSB 0x09 45 | #define MAG3110_OFF_X_LSB 0x0A 46 | #define MAG3110_OFF_Y_MSB 0x0B 47 | #define MAG3110_OFF_Y_LSB 0x0C 48 | #define MAG3110_OFF_Z_MSB 0x0D 49 | #define MAG3110_OFF_Z_LSB 0x0E 50 | #define MAG3110_DIE_TEMP 0x0F 51 | #define MAG3110_CTRL_REG1 0x10 52 | #define MAG3110_CTRL_REG2 0x11 53 | 54 | //////////////////////////////// 55 | // MAG3110 WHO_AM_I Response // 56 | //////////////////////////////// 57 | #define MAG3110_WHO_AM_I_RSP 0xC4 58 | 59 | ///////////////////////////////////////// 60 | // MAG3110 Commands and Settings // 61 | ///////////////////////////////////////// 62 | 63 | //CTRL_REG1 Settings 64 | //Output Data Rate/Oversample Settings 65 | //DR_OS_80_16 -> Output Data Rate = 80Hz, Oversampling Ratio = 16 66 | 67 | #define MAG3110_DR_OS_80_16 0x00 68 | #define MAG3110_DR_OS_40_32 0x08 69 | #define MAG3110_DR_OS_20_64 0x10 70 | #define MAG3110_DR_OS_10_128 0x18 71 | #define MAG3110_DR_OS_40_16 0x20 72 | #define MAG3110_DR_OS_20_32 0x28 73 | #define MAG3110_DR_OS_10_64 0x30 74 | #define MAG3110_DR_OS_5_128 0x38 75 | #define MAG3110_DR_OS_20_16 0x40 76 | #define MAG3110_DR_OS_10_32 0x48 77 | #define MAG3110_DR_OS_5_64 0x50 78 | #define MAG3110_DR_OS_2_5_128 0x58 79 | #define MAG3110_DR_OS_10_16 0x60 80 | #define MAG3110_DR_OS_5_32 0x68 81 | #define MAG3110_DR_OS_2_5_64 0x70 82 | #define MAG3110_DR_OS_1_25_128 0x78 83 | #define MAG3110_DR_OS_5_16 0x80 84 | #define MAG3110_DR_OS_2_5_32 0x88 85 | #define MAG3110_DR_OS_1_25_64 0x90 86 | #define MAG3110_DR_OS_0_63_128 0x98 87 | #define MAG3110_DR_OS_2_5_16 0xA0 88 | #define MAG3110_DR_OS_1_25_32 0xA8 89 | #define MAG3110_DR_OS_0_63_64 0xB0 90 | #define MAG3110_DR_OS_0_31_128 0xB8 91 | #define MAG3110_DR_OS_1_25_16 0xC0 92 | #define MAG3110_DR_OS_0_63_32 0xC8 93 | #define MAG3110_DR_OS_0_31_64 0xD0 94 | #define MAG3110_DR_OS_0_16_128 0xD8 95 | #define MAG3110_DR_OS_0_63_16 0xE0 96 | #define MAG3110_DR_OS_0_31_32 0xE8 97 | #define MAG3110_DR_OS_0_16_64 0xF0 98 | #define MAG3110_DR_OS_0_08_128 0xF8 99 | 100 | //Other CTRL_REG1 Settings 101 | #define MAG3110_FAST_READ 0x04 102 | #define MAG3110_TRIGGER_MEASUREMENT 0x02 103 | #define MAG3110_ACTIVE_MODE 0x01 104 | #define MAG3110_STANDBY_MODE 0x00 105 | 106 | //CTRL_REG2 Settings 107 | #define MAG3110_AUTO_MRST_EN 0x80 108 | #define MAG3110_RAW_MODE 0x20 109 | #define MAG3110_NORMAL_MODE 0x00 110 | #define MAG3110_MAG_RST 0x10 111 | 112 | //SYSMOD Readings 113 | #define MAG3110_SYSMOD_STANDBY 0x00 114 | #define MAG3110_SYSMOD_ACTIVE_RAW 0x01 115 | #define MAG3110_SYSMOD_ACTIVE 0x02 116 | 117 | #define MAG3110_X_AXIS 1 118 | #define MAG3110_Y_AXIS 3 119 | #define MAG3110_Z_AXIS 5 120 | 121 | class MAG3110 122 | { 123 | public: 124 | MAG3110(); 125 | 126 | bool initialize(); 127 | 128 | //Public methods 129 | uint8_t readRegister(uint8_t address); 130 | void writeRegister(uint8_t address, uint8_t value); 131 | 132 | bool dataReady(); 133 | 134 | void readMag(int* x, int* y, int* z); 135 | void readMicroTeslas(float* x, float* y, float* z); 136 | float readHeading(); 137 | 138 | void setDR_OS(uint8_t DROS); 139 | void triggerMeasurement(); 140 | void rawData(bool raw); 141 | 142 | void setOffset(uint8_t axis, int offset); 143 | int readOffset(uint8_t axis); 144 | 145 | void start(); 146 | void enterStandby(); 147 | void exitStandby(); 148 | 149 | bool isActive(); 150 | bool isRaw(); 151 | bool isCalibrated(); 152 | bool isCalibrating(); 153 | uint8_t getSysMode(); 154 | 155 | void enterCalMode(); 156 | void calibrate(); 157 | void exitCalMode(); 158 | 159 | void reset(); 160 | 161 | bool error; 162 | 163 | float x_scale; 164 | float y_scale; 165 | 166 | bool calibrated; 167 | 168 | private: 169 | 170 | //Private variables 171 | int x_offset; 172 | int y_offset; 173 | 174 | 175 | 176 | int x_min; 177 | int x_max; 178 | 179 | int y_min; 180 | int y_max; 181 | 182 | int timeLastChange; 183 | 184 | bool calibrationMode; 185 | bool activeMode; 186 | bool rawMode; 187 | 188 | int readAxis(uint8_t axis); 189 | }; 190 | 191 | #endif --------------------------------------------------------------------------------