├── .gitattributes ├── .gitignore ├── LICENSE.md ├── README.md ├── examples ├── ADCUsage │ └── ADCUsage.ino ├── FifoExample │ └── FifoExample.ino ├── FullSettingExample │ └── FullSettingExample.ino ├── IntUsage │ └── IntUsage.ino ├── LowLevelExample │ └── LowLevelExample.ino ├── MinimalistExample │ └── MinimalistExample.ino ├── MultiI2C │ └── MultiI2C.ino ├── MultiSPI │ └── MultiSPI.ino └── README.md ├── extras └── class diagrams.pdf ├── keywords.txt ├── library.properties └── src ├── SparkFunLIS3DH.cpp └── SparkFunLIS3DH.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 | -------------------------------------------------------------------------------- /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) 2015 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. 56 | 57 | 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SparkFun LIS3DH Arduino Library 2 | ======================================== 3 | 4 | ![LIS3DH Breakout](https://cdn.sparkfun.com//assets/parts/1/1/6/8/0/13963-02.jpg) 5 | 6 | [*LIS3DH Breakout (SEN-13963)*](https://www.sparkfun.com/products/13963) 7 | 8 | This is an arduino IDE library to control the LIS3DH. It can be configured to use I2C or SPI with 2 instances per I2C channel or any number of SPI instances. The top-level driver, class LIS3DH, contains an inner driver LIS3DHCore, a settings struct, and float-based math functions for conversion from raw to meaningful numbers. 9 | 10 | This has been tested with: 11 | 12 | * SparkFun RedBoard 13 | * SparkFun ESP32 Thing 14 | * Teensy 3.2 15 | 16 | Repository Contents 17 | ------------------- 18 | 19 | * **/examples** - Example sketches for the library (.ino). Run these from the Arduino IDE. 20 | * **/extras** - Contains class diagrams for the driver. Ignored by IDE. 21 | * **/src** - Source files for the library (.cpp, .h). 22 | * **keywords.txt** - Keywords from this library that will be highlighted in the Arduino IDE. 23 | * **library.properties** - General library properties for the Arduino package manager. 24 | 25 | Example Briefs 26 | -------------- 27 | 28 | * ADCUsage - Demonstrates analog in reads and has notes about temperature collection 29 | * FifoExample - Demonstrates using the built-in buffer to burst-collect data - **Good demonstration of settings** 30 | * FullSettingExample - Shows all settings, with non-used options commented out 31 | * IntUsage - shows configuration of interrupt bits 32 | * LowLevelExample - Demonstrates using only the core driver without math and settings overhead 33 | * MinimalistExample - The **easiest** configuration 34 | * MultiI2C - Using two LIS3DHs over I2C 35 | * MultiSPI - Using two LIS3DHs over SPI 36 | 37 | Documentation 38 | -------------- 39 | 40 | * **[Installing an Arduino Library Guide](https://learn.sparkfun.com/tutorials/installing-an-arduino-library)** - Basic information on how to install an Arduino library. 41 | * **[Product Repository](https://github.com/sparkfun/LIS3DH_Breakout)** - Main repository (including hardware files) for the LIS3DH Breakout. 42 | * **[Hookup Guide](https://learn.sparkfun.com/tutorials/lis3dh-hookup-guide)** - Basic hookup guide for the LIS3DH Breakout. 43 | 44 | Products that use this Library 45 | --------------------------------- 46 | 47 | * [SEN-13963](https://www.sparkfun.com/)- LIS3DH Breakout board 48 | 49 | Version History 50 | --------------- 51 | 52 | * [V 1.0.0](https://github.com/sparkfun/SparkFun_LIS3DH_Arduino_Library/releases/tag/V_1.0.0) -- Initial commit of Arduino 1.6-compatible library. 53 | * [V 1.0.2](https://github.com/sparkfun/SparkFun_LIS3DH_Arduino_Library/releases/tag/V_1.0.2) -- Added Teensy and ESP32 support. 54 | 55 | License Information 56 | ------------------- 57 | 58 | This product is _**open source**_! 59 | 60 | Please review the LICENSE.md file for license information. 61 | 62 | If you have any questions or concerns on licensing, please contact support@sparkfun.com. 63 | 64 | Distributed as-is; no warranty is given. 65 | 66 | - Your friends at SparkFun. 67 | 68 | -------------------------------------------------------------------------------- /examples/ADCUsage/ADCUsage.ino: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ADCUsage.ino 3 | 4 | Marshall Taylor @ SparkFun Electronics 5 | Nov 16, 2016 6 | https://github.com/sparkfun/LIS3DH_Breakout 7 | https://github.com/sparkfun/SparkFun_LIS3DH_Arduino_Library 8 | 9 | Description: 10 | ADC pin reading. 11 | 12 | This returns 10 bit values for the 3 analog in pins. The ADC works a little different 13 | than the arduino, in that the detectable range is centered around half-rail voltage and 14 | is not rail to rail. Connect a potentiometer between 3.3v and ground, and with the 15 | wiper connected to a pin. 16 | 17 | Also shown in this sketch is how the temperature is handled in the LIS3DH. 18 | When temperature is enabled, ADC3 can be read to determine the temperature change 19 | only, with a LSb worth 1 degree celsius. 20 | 21 | Resources: 22 | Uses Wire.h for i2c operation 23 | Uses SPI.h for SPI operation 24 | Either can be omitted if not used 25 | 26 | Development environment specifics: 27 | Arduino IDE 1.6.4 28 | Teensy loader 1.23 29 | 30 | Hardware connections: 31 | Connect I2C SDA line to A4 32 | Connect I2C SCL line to A5 33 | Connect GND and 3.3v power to the IMU 34 | 35 | This code is released under the [MIT License](http://opensource.org/licenses/MIT). 36 | 37 | Please review the LICENSE.md file included with this example. If you have any questions 38 | or concerns with licensing, please contact techsupport@sparkfun.com. 39 | 40 | Distributed as-is; no warranty is given. 41 | ******************************************************************************/ 42 | 43 | #include "SparkFunLIS3DH.h" 44 | #include "Wire.h" 45 | #include "SPI.h" 46 | 47 | LIS3DH myIMU; //Default constructor is I2C, addr 0x19. 48 | 49 | void setup() { 50 | // put your setup code here, to run once: 51 | Serial.begin(9600); 52 | delay(1000); //relax... 53 | Serial.println("Processor came out of reset.\n"); 54 | 55 | myIMU.settings.adcEnabled = 1; 56 | //Note: By also setting tempEnabled = 1, temperature data is available 57 | //on ADC3. Temperature *differences* can be read at a rate of 58 | //1 degree C per unit of ADC3 59 | myIMU.settings.tempEnabled = 0; 60 | myIMU.settings.accelSampleRate = 50; //Hz. Can be: 0,1,10,25,50,100,200,400,1600,5000 Hz 61 | myIMU.settings.accelRange = 2; //Max G force readable. Can be: 2, 4, 8, 16 62 | myIMU.settings.xAccelEnabled = 0; 63 | myIMU.settings.yAccelEnabled = 0; 64 | myIMU.settings.zAccelEnabled = 0; 65 | 66 | //Call .begin() to configure the IMU 67 | myIMU.begin(); 68 | 69 | } 70 | 71 | void loop() 72 | { 73 | //Get all parameters 74 | Serial.print("\nADC:\n"); 75 | Serial.print(" 1 = "); 76 | Serial.println(myIMU.read10bitADC1()); 77 | Serial.print(" 2 = "); 78 | Serial.println(myIMU.read10bitADC2()); 79 | Serial.print(" 3 = "); 80 | Serial.println(myIMU.read10bitADC3()); 81 | 82 | delay(300); 83 | } 84 | -------------------------------------------------------------------------------- /examples/FifoExample/FifoExample.ino: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | FifoExample.ino 3 | 4 | Marshall Taylor @ SparkFun Electronics 5 | Nov 16, 2016 6 | https://github.com/sparkfun/LIS3DH_Breakout 7 | https://github.com/sparkfun/SparkFun_LIS3DH_Arduino_Library 8 | 9 | Description: 10 | This sketch configures the FIFO, then only collects data when the watermark 11 | is passed. 12 | 13 | The data output to the serial monitor is in CSV (comma separated variables) format, and 14 | can be copy-pasted into a spreadsheet to make graphs. 15 | 16 | When doing math on profiles of acceleration, this is a good way to make sure the data 17 | samples occur regularly. 18 | 19 | Resources: 20 | Uses Wire.h for i2c operation 21 | Uses SPI.h for SPI operation 22 | Either can be omitted if not used 23 | 24 | Development environment specifics: 25 | Arduino IDE 1.6.4 26 | Teensy loader 1.23 27 | 28 | Hardware connections: 29 | Connect to SPI through a logic level converter (or to a 3.3v processor). 30 | Pin 10 is used as the chip select line. 31 | 32 | This code is released under the [MIT License](http://opensource.org/licenses/MIT). 33 | 34 | Please review the LICENSE.md file included with this example. If you have any questions 35 | or concerns with licensing, please contact techsupport@sparkfun.com. 36 | 37 | Distributed as-is; no warranty is given. 38 | ******************************************************************************/ 39 | 40 | #include "SparkFunLIS3DH.h" 41 | #include "Wire.h" 42 | #include "SPI.h" 43 | 44 | LIS3DH myIMU(SPI_MODE, 10); //Constructing with SPI interface information 45 | //LIS3DH myIMU(I2C_MODE, 0x19); //Alternate constructor for I2C 46 | 47 | uint32_t sampleNumber = 0; //Used to make CSV output row numbers 48 | 49 | void setup() { 50 | // put your setup code here, to run once: 51 | Serial.begin(9600); 52 | delay(1000); //relax... 53 | Serial.println("Processor came out of reset.\n"); 54 | 55 | myIMU.settings.adcEnabled = 0; 56 | //Note: By also setting tempEnabled = 1, temperature data is available 57 | //instead of ADC3 in. Temperature *differences* can be read at a rate of 58 | //1 degree C per unit of ADC3 data. 59 | myIMU.settings.tempEnabled = 0; 60 | myIMU.settings.accelSampleRate = 10; //Hz. Can be: 0,1,10,25,50,100,200,400,1600,5000 Hz 61 | myIMU.settings.accelRange = 2; //Max G force readable. Can be: 2, 4, 8, 16 62 | myIMU.settings.xAccelEnabled = 1; 63 | myIMU.settings.yAccelEnabled = 1; 64 | myIMU.settings.zAccelEnabled = 1; 65 | 66 | //FIFO control settings 67 | myIMU.settings.fifoEnabled = 1; 68 | myIMU.settings.fifoThreshold = 20; //Can be 0 to 32 69 | myIMU.settings.fifoMode = 1; //FIFO mode. 70 | //fifoMode can be: 71 | // 0 (Bypass mode, FIFO off) 72 | // 1 (FIFO mode) 73 | // 3 (FIFO until full) 74 | // 4 (FIFO when trigger) 75 | 76 | //Call .begin() to configure the IMU (except for the fifo) 77 | myIMU.begin(); 78 | 79 | Serial.print("Configuring FIFO with no error checking..."); 80 | myIMU.fifoBegin(); //Configure fifo 81 | Serial.print("Done!\n"); 82 | 83 | Serial.print("Clearing out the FIFO..."); 84 | myIMU.fifoClear(); 85 | Serial.print("Done!\n"); 86 | myIMU.fifoStartRec(); //cause fifo to start taking data (re-applies mode bits) 87 | 88 | } 89 | 90 | void loop() 91 | { 92 | //float temp; //This is to hold read data 93 | //uint16_t tempUnsigned; 94 | // 95 | while(( myIMU.fifoGetStatus() & 0x80 ) == 0) {}; //Wait for watermark 96 | 97 | //Now loop until FIFO is empty. 98 | //If having problems with the fifo not restarting after reading data, use the watermark 99 | //bits (b5 to b0) instead. 100 | //while(( myIMU.fifoGetStatus() & 0x1F ) > 2) //This checks that there is only a couple entries left 101 | while(( myIMU.fifoGetStatus() & 0x20 ) == 0) //This checks for the 'empty' flag 102 | { 103 | Serial.print(sampleNumber); 104 | Serial.print(","); 105 | Serial.print(myIMU.readFloatAccelX()); 106 | Serial.print(","); 107 | Serial.print(myIMU.readFloatAccelY()); 108 | Serial.print(","); 109 | Serial.print(myIMU.readFloatAccelZ()); 110 | Serial.println(); 111 | sampleNumber++; 112 | } 113 | 114 | } -------------------------------------------------------------------------------- /examples/FullSettingExample/FullSettingExample.ino: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | FullSettingExample.ino 3 | 4 | Marshall Taylor @ SparkFun Electronics 5 | Nov 16, 2016 6 | https://github.com/sparkfun/LIS3DH_Breakout 7 | https://github.com/sparkfun/SparkFun_LIS3DH_Arduino_Library 8 | 9 | Description: 10 | Most basic example of use. 11 | 12 | Example using the LSM6DS3 with settings applied within the begin() section. 13 | This sketch collects accelerometer data every second, then presents 14 | it on the serial monitor. 15 | 16 | Resources: 17 | Uses Wire.h for i2c operation 18 | Uses SPI.h for SPI operation 19 | Either can be omitted if not used 20 | 21 | Development environment specifics: 22 | Arduino IDE 1.6.4 23 | Teensy loader 1.23 24 | 25 | Hardware connections: 26 | Connect I2C SDA line to A4 27 | Connect I2C SCL line to A5 28 | Connect GND and 3.3v power to the IMU 29 | 30 | This code is released under the [MIT License](http://opensource.org/licenses/MIT). 31 | 32 | Please review the LICENSE.md file included with this example. If you have any questions 33 | or concerns with licensing, please contact techsupport@sparkfun.com. 34 | 35 | Distributed as-is; no warranty is given. 36 | ******************************************************************************/ 37 | 38 | #include "SparkFunLIS3DH.h" 39 | #include "Wire.h" 40 | #include "SPI.h" 41 | 42 | LIS3DH myIMU(I2C_MODE, 0x19); //Default constructor is I2C, addr 0x19. 43 | 44 | void setup() { 45 | // put your setup code here, to run once: 46 | Serial.begin(9600); 47 | delay(1000); //relax... 48 | Serial.println("Processor came out of reset.\n"); 49 | 50 | myIMU.settings.adcEnabled = 1; 51 | myIMU.settings.tempEnabled = 1; 52 | myIMU.settings.accelSampleRate = 50; //Hz. Can be: 0,1,10,25,50,100,200,400,1600,5000 Hz 53 | myIMU.settings.accelRange = 16; //Max G force readable. Can be: 2, 4, 8, 16 54 | myIMU.settings.xAccelEnabled = 1; 55 | myIMU.settings.yAccelEnabled = 1; 56 | myIMU.settings.zAccelEnabled = 1; 57 | 58 | //Call .begin() to configure the IMU 59 | myIMU.begin(); 60 | 61 | } 62 | 63 | 64 | void loop() 65 | { 66 | //Get all parameters 67 | Serial.print("\nAccelerometer:\n"); 68 | Serial.print(" X = "); 69 | Serial.println(myIMU.readFloatAccelX(), 4); 70 | Serial.print(" Y = "); 71 | Serial.println(myIMU.readFloatAccelY(), 4); 72 | Serial.print(" Z = "); 73 | Serial.println(myIMU.readFloatAccelZ(), 4); 74 | 75 | delay(1000); 76 | } 77 | -------------------------------------------------------------------------------- /examples/IntUsage/IntUsage.ino: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | IntUsage.ino 3 | 4 | Marshall Taylor @ SparkFun Electronics 5 | Nov 16, 2016 6 | https://github.com/sparkfun/LIS3DH_Breakout 7 | https://github.com/sparkfun/SparkFun_LIS3DH_Arduino_Library 8 | 9 | Description: 10 | Interrupt support for the LIS3DH is extremely flexible, so configuration must be left 11 | to the user. This sketch demonstrates how to make a interrupt configuration function. 12 | 13 | Use configIntterupts() as a template, then comment/uncomment desired options. 14 | See ST docs for information 15 | Doc ID 18198 (AN3308): LIS3DHpplication information 16 | Doc ID 17530: LIS3DH datasheet 17 | 18 | Resources: 19 | Uses Wire.h for i2c operation 20 | Uses SPI.h for SPI operation 21 | Either can be omitted if not used 22 | 23 | Development environment specifics: 24 | Arduino IDE 1.6.4 25 | Teensy loader 1.23 26 | 27 | Hardware connections: 28 | Connect I2C SDA line to A4 29 | Connect I2C SCL line to A5 30 | Connect GND and 3.3v power to the IMU 31 | 32 | This code is released under the [MIT License](http://opensource.org/licenses/MIT). 33 | 34 | Please review the LICENSE.md file included with this example. If you have any questions 35 | or concerns with licensing, please contact techsupport@sparkfun.com. 36 | 37 | Distributed as-is; no warranty is given. 38 | ******************************************************************************/ 39 | 40 | #include "SparkFunLIS3DH.h" 41 | #include "Wire.h" 42 | #include "SPI.h" 43 | 44 | LIS3DH myIMU(I2C_MODE, 0x19); //Default constructor is I2C, addr 0x19. 45 | 46 | void setup() { 47 | // put your setup code here, to run once: 48 | Serial.begin(9600); 49 | delay(1000); //relax... 50 | Serial.println("Processor came out of reset.\n"); 51 | 52 | //Accel sample rate and range effect interrupt time and threshold values!!! 53 | myIMU.settings.accelSampleRate = 50; //Hz. Can be: 0,1,10,25,50,100,200,400,1600,5000 Hz 54 | myIMU.settings.accelRange = 2; //Max G force readable. Can be: 2, 4, 8, 16 55 | 56 | myIMU.settings.adcEnabled = 0; 57 | myIMU.settings.tempEnabled = 0; 58 | myIMU.settings.xAccelEnabled = 1; 59 | myIMU.settings.yAccelEnabled = 1; 60 | myIMU.settings.zAccelEnabled = 1; 61 | 62 | //Call .begin() to configure the IMU 63 | myIMU.begin(); 64 | 65 | configIntterupts(); 66 | 67 | } 68 | 69 | 70 | void loop() 71 | { 72 | //Get all parameters 73 | //Serial.print("\nAccelerometer:\n"); 74 | //Serial.print(" X = "); 75 | //Serial.println(myIMU.readFloatAccelX(), 4); 76 | //Serial.print(" Y = "); 77 | //Serial.println(myIMU.readFloatAccelY(), 4); 78 | //Serial.print(" Z = "); 79 | //Serial.println(myIMU.readFloatAccelZ(), 4); 80 | 81 | uint8_t dataRead; 82 | 83 | Serial.print("LIS3DH_INT1_SRC: 0x"); 84 | myIMU.readRegister(&dataRead, LIS3DH_INT1_SRC);//cleared by reading 85 | Serial.println(dataRead, HEX); 86 | Serial.println("Decoded events:"); 87 | if(dataRead & 0x40) Serial.println("Interrupt Active"); 88 | if(dataRead & 0x20) Serial.println("Z high"); 89 | if(dataRead & 0x10) Serial.println("Z low"); 90 | if(dataRead & 0x08) Serial.println("Y high"); 91 | if(dataRead & 0x04) Serial.println("Y low"); 92 | if(dataRead & 0x02) Serial.println("X high"); 93 | if(dataRead & 0x01) Serial.println("X low"); 94 | Serial.println(); 95 | 96 | delay(1000); 97 | 98 | // Use this section to read back blocks of data from the LIS3DH for troubleshooting. 99 | // //Dump regs: 100 | // for( int i = LIS3DH_INT_COUNTER_REG; i <= LIS3DH_INT1_DURATION; i++) 101 | // { 102 | // Serial.print("0x"); 103 | // Serial.print(i,HEX); 104 | // Serial.print(": 0x"); 105 | // myIMU.readRegister(&dataRead, i); 106 | // Serial.println(dataRead, HEX); 107 | // } 108 | 109 | } 110 | 111 | void configIntterupts() 112 | { 113 | uint8_t dataToWrite = 0; 114 | 115 | //LIS3DH_INT1_CFG 116 | //dataToWrite |= 0x80;//AOI, 0 = OR 1 = AND 117 | //dataToWrite |= 0x40;//6D, 0 = interrupt source, 1 = 6 direction source 118 | //Set these to enable individual axes of generation source (or direction) 119 | // -- high and low are used generically 120 | //dataToWrite |= 0x20;//Z high 121 | //dataToWrite |= 0x10;//Z low 122 | dataToWrite |= 0x08;//Y high 123 | //dataToWrite |= 0x04;//Y low 124 | //dataToWrite |= 0x02;//X high 125 | //dataToWrite |= 0x01;//X low 126 | myIMU.writeRegister(LIS3DH_INT1_CFG, dataToWrite); 127 | 128 | //LIS3DH_INT1_THS 129 | dataToWrite = 0; 130 | //Provide 7 bit value, 0x7F always equals max range by accelRange setting 131 | dataToWrite |= 0x10; // 1/8 range 132 | myIMU.writeRegister(LIS3DH_INT1_THS, dataToWrite); 133 | 134 | //LIS3DH_INT1_DURATION 135 | dataToWrite = 0; 136 | //minimum duration of the interrupt 137 | //LSB equals 1/(sample rate) 138 | dataToWrite |= 0x01; // 1 * 1/50 s = 20ms 139 | myIMU.writeRegister(LIS3DH_INT1_DURATION, dataToWrite); 140 | 141 | //LIS3DH_CLICK_CFG 142 | dataToWrite = 0; 143 | //Set these to enable individual axes of generation source (or direction) 144 | // -- set = 1 to enable 145 | //dataToWrite |= 0x20;//Z double-click 146 | dataToWrite |= 0x10;//Z click 147 | //dataToWrite |= 0x08;//Y double-click 148 | dataToWrite |= 0x04;//Y click 149 | //dataToWrite |= 0x02;//X double-click 150 | dataToWrite |= 0x01;//X click 151 | myIMU.writeRegister(LIS3DH_CLICK_CFG, dataToWrite); 152 | 153 | //LIS3DH_CLICK_SRC 154 | dataToWrite = 0; 155 | //Set these to enable click behaviors (also read to check status) 156 | // -- set = 1 to enable 157 | //dataToWrite |= 0x20;//Enable double clicks 158 | dataToWrite |= 0x04;//Enable single clicks 159 | //dataToWrite |= 0x08;//sine (0 is positive, 1 is negative) 160 | dataToWrite |= 0x04;//Z click detect enabled 161 | dataToWrite |= 0x02;//Y click detect enabled 162 | dataToWrite |= 0x01;//X click detect enabled 163 | myIMU.writeRegister(LIS3DH_CLICK_SRC, dataToWrite); 164 | 165 | //LIS3DH_CLICK_THS 166 | dataToWrite = 0; 167 | //This sets the threshold where the click detection process is activated. 168 | //Provide 7 bit value, 0x7F always equals max range by accelRange setting 169 | dataToWrite |= 0x0A; // ~1/16 range 170 | myIMU.writeRegister(LIS3DH_CLICK_THS, dataToWrite); 171 | 172 | //LIS3DH_TIME_LIMIT 173 | dataToWrite = 0; 174 | //Time acceleration has to fall below threshold for a valid click. 175 | //LSB equals 1/(sample rate) 176 | dataToWrite |= 0x08; // 8 * 1/50 s = 160ms 177 | myIMU.writeRegister(LIS3DH_TIME_LIMIT, dataToWrite); 178 | 179 | //LIS3DH_TIME_LATENCY 180 | dataToWrite = 0; 181 | //hold-off time before allowing detection after click event 182 | //LSB equals 1/(sample rate) 183 | dataToWrite |= 0x08; // 4 * 1/50 s = 160ms 184 | myIMU.writeRegister(LIS3DH_TIME_LATENCY, dataToWrite); 185 | 186 | //LIS3DH_TIME_WINDOW 187 | dataToWrite = 0; 188 | //hold-off time before allowing detection after click event 189 | //LSB equals 1/(sample rate) 190 | dataToWrite |= 0x10; // 16 * 1/50 s = 320ms 191 | myIMU.writeRegister(LIS3DH_TIME_WINDOW, dataToWrite); 192 | 193 | //LIS3DH_CTRL_REG5 194 | //Int1 latch interrupt and 4D on int1 (preserve fifo en) 195 | myIMU.readRegister(&dataToWrite, LIS3DH_CTRL_REG5); 196 | dataToWrite &= 0xF3; //Clear bits of interest 197 | dataToWrite |= 0x08; //Latch interrupt (Cleared by reading int1_src) 198 | //dataToWrite |= 0x04; //Pipe 4D detection from 6D recognition to int1? 199 | myIMU.writeRegister(LIS3DH_CTRL_REG5, dataToWrite); 200 | 201 | //LIS3DH_CTRL_REG3 202 | //Choose source for pin 1 203 | dataToWrite = 0; 204 | //dataToWrite |= 0x80; //Click detect on pin 1 205 | dataToWrite |= 0x40; //AOI1 event (Generator 1 interrupt on pin 1) 206 | dataToWrite |= 0x20; //AOI2 event () 207 | //dataToWrite |= 0x10; //Data ready 208 | //dataToWrite |= 0x04; //FIFO watermark 209 | //dataToWrite |= 0x02; //FIFO overrun 210 | myIMU.writeRegister(LIS3DH_CTRL_REG3, dataToWrite); 211 | 212 | //LIS3DH_CTRL_REG6 213 | //Choose source for pin 2 and both pin output inversion state 214 | dataToWrite = 0; 215 | dataToWrite |= 0x80; //Click int on pin 2 216 | //dataToWrite |= 0x40; //Generator 1 interrupt on pin 2 217 | //dataToWrite |= 0x10; //boot status on pin 2 218 | //dataToWrite |= 0x02; //invert both outputs 219 | myIMU.writeRegister(LIS3DH_CTRL_REG6, dataToWrite); 220 | 221 | } -------------------------------------------------------------------------------- /examples/LowLevelExample/LowLevelExample.ino: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | LowLevelExample.ino 3 | 4 | Marshall Taylor @ SparkFun Electronics 5 | Nov 16, 2016 6 | https://github.com/sparkfun/LIS3DH_Breakout 7 | https://github.com/sparkfun/SparkFun_LIS3DH_Arduino_Library 8 | 9 | Description: 10 | Example using the LIS3DH with ONLY read and write methods. It's up to you to 11 | read the datasheets and get the sensor to behave as you will. 12 | 13 | This sketch saves a significant amount of memory because the settings and complex 14 | math (such as floating point variables) doesn't exist. The cost of saved memory is 15 | that the values are in 'counts', or raw data from the register. The user is 16 | responsible for converting these raw values into something meaningful. 17 | 18 | Use the register words from SparkFunLIS3DH.h to manually configure the IC. 19 | 20 | Resources: 21 | Uses Wire.h for i2c operation 22 | Uses SPI.h for SPI operation 23 | 24 | Development environment specifics: 25 | Arduino IDE 1.6.4 26 | Teensy loader 1.23 27 | 28 | Hardware connections: 29 | Connect I2C SDA line to A4 30 | Connect I2C SCL line to A5 31 | Connect GND and 3.3v power to the IMU 32 | 33 | This code is released under the [MIT License](http://opensource.org/licenses/MIT). 34 | 35 | Please review the LICENSE.md file included with this example. If you have any questions 36 | or concerns with licensing, please contact techsupport@sparkfun.com. 37 | 38 | Distributed as-is; no warranty is given. 39 | ******************************************************************************/ 40 | 41 | #include "SparkFunLIS3DH.h" 42 | #include "Wire.h" 43 | #include "SPI.h" 44 | 45 | uint16_t errorsAndWarnings = 0; 46 | 47 | LIS3DHCore myIMU( I2C_MODE, 0x19 ); 48 | //LIS3DHCore myIMU( SPI_MODE, 10 ); 49 | 50 | void setup() { 51 | // put your setup code here, to run once: 52 | Serial.begin(9600); 53 | delay(1000); //relax... 54 | Serial.println("Processor came out of reset.\n"); 55 | 56 | //Call .beginCore() to configure the IMU 57 | if( myIMU.beginCore() != 0 ) 58 | { 59 | Serial.print("Error at beginCore().\n"); 60 | } 61 | else 62 | { 63 | Serial.print("\nbeginCore() passed.\n"); 64 | } 65 | 66 | uint8_t dataToWrite = 0; //Temporary variable 67 | 68 | 69 | //Setup the accelerometer****************************** 70 | dataToWrite = 0; //Start Fresh! 71 | dataToWrite |= 0x4 << 4; //ODR of 50Hz 72 | dataToWrite |= 0x7; //Enable all axes 73 | 74 | //Now, write the patched together data 75 | errorsAndWarnings += myIMU.writeRegister(LIS3DH_CTRL_REG1, dataToWrite); 76 | 77 | dataToWrite = 0x80; 78 | errorsAndWarnings += myIMU.writeRegister(LIS3DH_CTRL_REG4, dataToWrite); 79 | 80 | dataToWrite = 0x80; //ADC enable 81 | errorsAndWarnings += myIMU.writeRegister(LIS3DH_TEMP_CFG_REG, dataToWrite); 82 | 83 | 84 | 85 | // //Test interrupt configuration profile on int1 86 | // { 87 | // dataToWrite = 0x40; //INT1 src 88 | // errorsAndWarnings += myIMU.writeRegister(LIS3DH_CTRL_REG3, dataToWrite); 89 | // dataToWrite = 0x08; //latch output int 90 | // errorsAndWarnings += myIMU.writeRegister(LIS3DH_CTRL_REG5, dataToWrite); 91 | // dataToWrite = 0x40; // 92 | // //errorsAndWarnings += myIMU.writeRegister(LIS3DH_REFERENCE, dataToWrite); 93 | // dataToWrite = 0x0A; //High X and high Y only 94 | // errorsAndWarnings += myIMU.writeRegister(LIS3DH_INT1_CFG, dataToWrite); 95 | // dataToWrite = 0x3F; // half amplitude? 96 | // errorsAndWarnings += myIMU.writeRegister(LIS3DH_INT1_THS, dataToWrite); 97 | // dataToWrite = 0x01; //duration? 98 | // errorsAndWarnings += myIMU.writeRegister(LIS3DH_INT1_DURATION, dataToWrite); 99 | // } 100 | 101 | 102 | //Test interrupt configuration profile on int2 103 | { 104 | dataToWrite = 0x40; //INT2 src 105 | errorsAndWarnings += myIMU.writeRegister(LIS3DH_CTRL_REG6, dataToWrite); 106 | dataToWrite = 0x08; //latch output int 107 | errorsAndWarnings += myIMU.writeRegister(LIS3DH_CTRL_REG5, dataToWrite); 108 | dataToWrite = 0x40; // 109 | //errorsAndWarnings += myIMU.writeRegister(LIS3DH_REFERENCE, dataToWrite); 110 | dataToWrite = 0x0A; //High X and high Y only 111 | errorsAndWarnings += myIMU.writeRegister(LIS3DH_INT1_CFG, dataToWrite); 112 | dataToWrite = 0x3F; // half amplitude? 113 | errorsAndWarnings += myIMU.writeRegister(LIS3DH_INT1_THS, dataToWrite); 114 | dataToWrite = 0x01; //duration? 115 | errorsAndWarnings += myIMU.writeRegister(LIS3DH_INT1_DURATION, dataToWrite); 116 | } 117 | 118 | //Get the ID: 119 | uint8_t readData = 0; 120 | Serial.print("\nReading LIS3DH_WHO_AM_I: 0x"); 121 | myIMU.readRegister(&readData, LIS3DH_WHO_AM_I); 122 | Serial.println(readData, HEX); 123 | 124 | } 125 | 126 | 127 | void loop() 128 | { 129 | int16_t temp; 130 | uint8_t temp2; 131 | 132 | uint8_t readData = 0; 133 | Serial.print("\nReading LIS3DH_WHO_AM_I: 0x"); 134 | myIMU.readRegister(&readData, LIS3DH_WHO_AM_I); 135 | Serial.println(readData, HEX); 136 | 137 | Serial.print("\nReading LIS3DH_STATUS_REG_AUX: 0x"); 138 | myIMU.readRegister(&readData, LIS3DH_STATUS_REG_AUX); 139 | Serial.println(readData, HEX); 140 | 141 | Serial.print("\nReading LIS3DH_INT1_SOURCE: 0x"); 142 | myIMU.readRegister(&readData, LIS3DH_INT1_SOURCE); 143 | Serial.println(readData, HEX); 144 | 145 | //Clear interrupts 146 | //errorsAndWarnings += myIMU.writeRegister(LIS3DH_INT1_SOURCE, 0x00); 147 | 148 | //Dump regs: 149 | for( int i = LIS3DH_STATUS_REG_AUX; i <= LIS3DH_INT1_DURATION; i++) 150 | { 151 | Serial.print("0x"); 152 | Serial.print(i,HEX); 153 | Serial.print(": 0x"); 154 | myIMU.readRegister(&readData, i); 155 | Serial.println(readData, HEX); 156 | } 157 | 158 | //Read a register into the temp variable. 159 | // if( myIMU.readRegister(&temp2, LIS3DH_OUT_Z_H) != 0 ) 160 | // { 161 | // errorsAndWarnings++; 162 | // } 163 | // Serial.println(temp2); 164 | 165 | //Get all parameters 166 | Serial.print("\nAccelerometer Counts:\n"); 167 | 168 | Serial.print(" X = "); 169 | //Read a register into the temp variable. 170 | if( myIMU.readRegisterInt16(&temp, LIS3DH_OUT_X_L) != 0 ) 171 | { 172 | errorsAndWarnings++; 173 | } 174 | Serial.println(temp); 175 | 176 | Serial.print(" Y = "); 177 | //Read a register into the temp variable. 178 | if( myIMU.readRegisterInt16(&temp, LIS3DH_OUT_Y_L) != 0 ) 179 | { 180 | errorsAndWarnings++; 181 | } 182 | Serial.println(temp); 183 | 184 | Serial.print(" Z = "); 185 | //Read a register into the temp variable. 186 | if( myIMU.readRegisterInt16(&temp, LIS3DH_OUT_Z_L) != 0 ) 187 | { 188 | errorsAndWarnings++; 189 | } 190 | Serial.println(temp); 191 | 192 | 193 | Serial.print("\nADC Counts:\n"); 194 | 195 | Serial.print(" ADC1 = "); 196 | //Read a register into the temp variable. 197 | if( myIMU.readRegisterInt16(&temp, LIS3DH_OUT_ADC1_L) != 0 ) 198 | { 199 | errorsAndWarnings++; 200 | } 201 | Serial.println(temp); 202 | 203 | Serial.print(" ADC2 = "); 204 | //Read a register into the temp variable. 205 | if( myIMU.readRegisterInt16(&temp, LIS3DH_OUT_ADC2_L) != 0 ) 206 | { 207 | errorsAndWarnings++; 208 | } 209 | Serial.println(temp); 210 | 211 | Serial.print(" ADC3 = "); 212 | //Read a register into the temp variable. 213 | if( myIMU.readRegisterInt16(&temp, LIS3DH_OUT_ADC3_L) != 0 ) 214 | { 215 | errorsAndWarnings++; 216 | } 217 | Serial.println(temp); 218 | 219 | 220 | Serial.println(); 221 | Serial.print("Total reported Errors and Warnings: "); 222 | Serial.println(errorsAndWarnings); 223 | 224 | 225 | delay(3000); 226 | } -------------------------------------------------------------------------------- /examples/MinimalistExample/MinimalistExample.ino: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | MinimalistExample.ino 3 | 4 | Marshall Taylor @ SparkFun Electronics 5 | Nov 16, 2016 6 | https://github.com/sparkfun/LIS3DH_Breakout 7 | https://github.com/sparkfun/SparkFun_LIS3DH_Arduino_Library 8 | 9 | Description: 10 | Most basic example of use. 11 | 12 | Example using the LIS3DH with basic settings. This sketch collects 13 | Accelerometer data every second, then presents it on the serial monitor. 14 | 15 | Resources: 16 | Uses Wire.h for i2c operation 17 | Uses SPI.h for SPI operation 18 | Either can be omitted if not used 19 | 20 | Development environment specifics: 21 | Arduino IDE 1.6.4 22 | Teensy loader 1.23 23 | 24 | Hardware connections: 25 | Connect I2C SDA line to A4 26 | Connect I2C SCL line to A5 27 | Connect GND and 3.3v power to the IMU 28 | 29 | This code is released under the [MIT License](http://opensource.org/licenses/MIT). 30 | 31 | Please review the LICENSE.md file included with this example. If you have any questions 32 | or concerns with licensing, please contact techsupport@sparkfun.com. 33 | 34 | Distributed as-is; no warranty is given. 35 | ******************************************************************************/ 36 | 37 | #include "SparkFunLIS3DH.h" 38 | #include "Wire.h" 39 | #include "SPI.h" 40 | 41 | LIS3DH myIMU; //Default constructor is I2C, addr 0x19. 42 | 43 | void setup() { 44 | // put your setup code here, to run once: 45 | Serial.begin(9600); 46 | delay(1000); //relax... 47 | Serial.println("Processor came out of reset.\n"); 48 | 49 | //Call .begin() to configure the IMU 50 | myIMU.begin(); 51 | 52 | } 53 | 54 | 55 | void loop() 56 | { 57 | //Get all parameters 58 | Serial.print("\nAccelerometer:\n"); 59 | Serial.print(" X = "); 60 | Serial.println(myIMU.readFloatAccelX(), 4); 61 | Serial.print(" Y = "); 62 | Serial.println(myIMU.readFloatAccelY(), 4); 63 | Serial.print(" Z = "); 64 | Serial.println(myIMU.readFloatAccelZ(), 4); 65 | 66 | delay(1000); 67 | } 68 | -------------------------------------------------------------------------------- /examples/MultiI2C/MultiI2C.ino: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | MultiI2C.ino 3 | 4 | Marshall Taylor @ SparkFun Electronics 5 | Nov 16, 2016 6 | https://github.com/sparkfun/LIS3DH_Breakout 7 | https://github.com/sparkfun/SparkFun_LIS3DH_Arduino_Library 8 | 9 | Description: 10 | Example using up to two LIS3DHs on the same I2C channel. If only one sensor 11 | is attached, this sketch reports failure on that channel and runs with the 12 | single sensor instead. 13 | 14 | Resources: 15 | Uses Wire.h for i2c operation 16 | Uses SPI.h for SPI operation 17 | Either can be omitted if not used 18 | 19 | Development environment specifics: 20 | Arduino IDE 1.6.4 21 | Teensy loader 1.23 22 | 23 | Hardware connections 24 | Connect I2C SDA line to A4 25 | Connect I2C SCL line to A5 26 | Connect GND and ***3.3v*** power to the IMU. The sensors are not 5v tolerant. 27 | 28 | (Multiple I2C devices use the same pins. Up to two LIS3DHs are allowed. Use 29 | the solder jumper to select address 0x19 (default) or 0x18) 30 | 31 | This code is released under the [MIT License](http://opensource.org/licenses/MIT). 32 | 33 | Please review the LICENSE.md file included with this example. If you have any questions 34 | or concerns with licensing, please contact techsupport@sparkfun.com. 35 | 36 | Distributed as-is; no warranty is given. 37 | ******************************************************************************/ 38 | 39 | #include "SparkFunLIS3DH.h" 40 | #include "Wire.h" 41 | #include "SPI.h" 42 | 43 | //Create two instances of the driver class 44 | LIS3DH SensorOne( I2C_MODE, 0x19 ); 45 | LIS3DH SensorTwo( I2C_MODE, 0x18 ); 46 | 47 | void setup() { 48 | // put your setup code here, to run once: 49 | Serial.begin(9600); 50 | delay(1000); //relax... 51 | Serial.println("Processor came out of reset.\n"); 52 | 53 | //Call .begin() to configure the IMUs 54 | if( SensorOne.begin() != 0 ) 55 | { 56 | Serial.println("Problem starting the sensor at 0x19."); 57 | } 58 | else 59 | { 60 | Serial.println("Sensor at 0x19 started."); 61 | } 62 | if( SensorTwo.begin() != 0 ) 63 | { 64 | Serial.println("Problem starting the sensor at 0x18."); 65 | } 66 | else 67 | { 68 | Serial.println("Sensor at 0x18 started."); 69 | } 70 | 71 | } 72 | 73 | 74 | void loop() 75 | { 76 | //Get all parameters 77 | Serial.print("\nAccelerometer:\n"); 78 | Serial.print(" X1 = "); 79 | Serial.println(SensorOne.readFloatAccelX(), 4); 80 | Serial.print(" Y1 = "); 81 | Serial.println(SensorOne.readFloatAccelY(), 4); 82 | Serial.print(" Z1 = "); 83 | Serial.println(SensorOne.readFloatAccelZ(), 4); 84 | Serial.print(" X2 = "); 85 | Serial.println(SensorTwo.readFloatAccelX(), 4); 86 | Serial.print(" Y2 = "); 87 | Serial.println(SensorTwo.readFloatAccelY(), 4); 88 | Serial.print(" Z2 = "); 89 | Serial.println(SensorTwo.readFloatAccelZ(), 4); 90 | 91 | Serial.print("\nSensorOne Bus Errors Reported:\n"); 92 | Serial.print(" All '1's = "); 93 | Serial.println(SensorOne.allOnesCounter); 94 | Serial.print(" Non-success = "); 95 | Serial.println(SensorOne.nonSuccessCounter); 96 | Serial.print("SensorTwo Bus Errors Reported:\n"); 97 | Serial.print(" All '1's = "); 98 | Serial.println(SensorTwo.allOnesCounter); 99 | Serial.print(" Non-success = "); 100 | Serial.println(SensorTwo.nonSuccessCounter); 101 | delay(1000); 102 | } 103 | -------------------------------------------------------------------------------- /examples/MultiSPI/MultiSPI.ino: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | MultiSPI.ino 3 | 4 | Marshall Taylor @ SparkFun Electronics 5 | Nov 16, 2016 6 | https://github.com/sparkfun/LIS3DH_Breakout 7 | https://github.com/sparkfun/SparkFun_LIS3DH_Arduino_Library 8 | 9 | Description: 10 | Example using up to two LIS3DHs on the same SPI channel, with different CS pins. 11 | If only one sensor is attached, this sketch reports failure on that channel and 12 | runs with the single sensor instead. 13 | 14 | Resources: 15 | Uses Wire.h for i2c operation 16 | Uses SPI.h for SPI operation 17 | Either can be omitted if not used 18 | 19 | Development environment specifics: 20 | Arduino IDE 1.6.4 21 | Teensy loader 1.23 22 | 23 | Hardware connections 24 | ***CAUTION -- SPI pins can not be connected directly to 5v IO*** 25 | 26 | Connect SDA/SDI lines to pin 11 through level shifters (MOSI) 27 | Connect SCL pin lines to pin 13 through level shifters (SCLK) 28 | Connect SDO/SA0 lines to pin 12 through level shifters (MISO) 29 | Connect CS to free pins through level shifters. This example uses 9 and 10. 30 | Connect GND and ***3.3v*** power to the IMU. The sensors are not 5v tolerant. 31 | 32 | (Multiple SPI devices share pins except for the Chip Select lines which 33 | are unique for each device on the bus.) 34 | 35 | This code is released under the [MIT License](http://opensource.org/licenses/MIT). 36 | 37 | Please review the LICENSE.md file included with this example. If you have any questions 38 | or concerns with licensing, please contact techsupport@sparkfun.com. 39 | 40 | Distributed as-is; no warranty is given. 41 | ******************************************************************************/ 42 | 43 | #include "SparkFunLIS3DH.h" 44 | #include "Wire.h" 45 | #include "SPI.h" 46 | 47 | //Create two instances of the driver class 48 | LIS3DH SensorOne( SPI_MODE, 10 ); 49 | LIS3DH SensorTwo( SPI_MODE, 9 ); 50 | 51 | 52 | void setup() { 53 | // put your setup code here, to run once: 54 | Serial.begin(9600); 55 | delay(1000); //relax... 56 | Serial.println("Processor came out of reset.\n"); 57 | 58 | //Call .begin() to configure the IMUs 59 | uint8_t returnData = 0; 60 | returnData = SensorOne.begin(); 61 | if(( returnData != 0x00 )&&( returnData != 0xFF )) 62 | { 63 | Serial.println("Problem starting the sensor with CS @ Pin 10."); 64 | } 65 | else 66 | { 67 | Serial.println("Sensor with CS @ Pin 10 started."); 68 | } 69 | returnData = SensorTwo.begin(); 70 | if(( returnData != 0x00 )&&( returnData != 0xFF )) 71 | { 72 | Serial.println("Problem starting the sensor with CS @ Pin 9."); 73 | } 74 | else 75 | { 76 | Serial.println("Sensor with CS @ Pin 9 started."); 77 | } 78 | 79 | } 80 | 81 | 82 | void loop() 83 | { 84 | //Get all parameters 85 | Serial.print("\nAccelerometer:\n"); 86 | Serial.print(" X1 = "); 87 | Serial.println(SensorOne.readFloatAccelX(), 4); 88 | Serial.print(" Y1 = "); 89 | Serial.println(SensorOne.readFloatAccelY(), 4); 90 | Serial.print(" Z1 = "); 91 | Serial.println(SensorOne.readFloatAccelZ(), 4); 92 | Serial.print(" X2 = "); 93 | Serial.println(SensorTwo.readFloatAccelX(), 4); 94 | Serial.print(" Y2 = "); 95 | Serial.println(SensorTwo.readFloatAccelY(), 4); 96 | Serial.print(" Z2 = "); 97 | Serial.println(SensorTwo.readFloatAccelZ(), 4); 98 | 99 | Serial.print("\nSensorOne Bus Errors Reported:\n"); 100 | Serial.print(" All '1's = "); 101 | Serial.println(SensorOne.allOnesCounter); 102 | Serial.print(" Non-success = "); 103 | Serial.println(SensorOne.nonSuccessCounter); 104 | Serial.print("SensorTwo Bus Errors Reported:\n"); 105 | Serial.print(" All '1's = "); 106 | Serial.println(SensorTwo.allOnesCounter); 107 | Serial.print(" Non-success = "); 108 | Serial.println(SensorTwo.nonSuccessCounter); 109 | delay(1000); 110 | } 111 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | SparkFun Arduino Examples 2 | ========================== 3 | 4 | Example Briefs 5 | -------------- 6 | 7 | * ADCUsage - Demonstrates analog in reads and has notes about temperature collection 8 | * FifoExample - Demonstrates using the built-in buffer to burst-collect data - **Good demonstration of settings** 9 | * FullSettingExample - Shows all settings, with non-used options commented out 10 | * IntUsage - shows configuration of interrupt bits 11 | * LowLevelExample - Demonstrates using only the core driver without math and settings overhead 12 | * MinimalistExample - The **easiest** configuration 13 | * MultiI2C - Using two LIS3DHs over I2C 14 | * MultiSPI - Using two LIS3DHs over SPI 15 | -------------------------------------------------------------------------------- /extras/class diagrams.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/SparkFun_LIS3DH_Arduino_Library/3ef63c4051ed393aab2c77dce59bf4a23f3f025e/extras/class diagrams.pdf -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ######################################################## 2 | # Syntax Coloring Map for SparkFun LSM6DS3 IMU Library # 3 | ######################################################## 4 | # Class 5 | ################################################################### 6 | 7 | LIS3DHCore KEYWORD1 8 | LIS3DH KEYWORD1 9 | 10 | ################################################################### 11 | # Methods and Functions 12 | ################################################################### 13 | 14 | beginCore KEYWORD2 15 | readRegisterRegion KEYWORD2 16 | readRegister KEYWORD2 17 | readRegisterInt16 KEYWORD2 18 | writeRegister KEYWORD2 19 | settings KEYWORD2 20 | allOnesCounter KEYWORD2 21 | begin KEYWORD2 22 | readRawAccelX KEYWORD2 23 | readRawAccelY KEYWORD2 24 | readRawAccelZ KEYWORD2 25 | readFloatAccelX KEYWORD2 26 | readFloatAccelY KEYWORD2 27 | readFloatAccelZ KEYWORD2 28 | read10bitADC1 KEYWORD2 29 | read10bitADC2 KEYWORD2 30 | read10bitADC3 KEYWORD2 31 | fifoBegin KEYWORD2 32 | fifoClear KEYWORD2 33 | fifoGetStatus KEYWORD2 34 | fifoStartRec KEYWORD2 35 | fifoEnd KEYWORD2 36 | calcAccel KEYWORD2 37 | 38 | ################################################################### 39 | # Constants 40 | ################################################################### 41 | 42 | I2C_MODE LITERAL1 43 | SPI_MODE LITERAL1 44 | IMU_SUCCESS LITERAL1 45 | IMU_HW_ERROR LITERAL1 46 | IMU_NOT_SUPPORTED LITERAL1 47 | IMU_GENERIC_ERROR LITERAL1 48 | IMU_OUT_OF_BOUNDS LITERAL1 49 | IMU_ALL_ONES_WARNING LITERAL1 50 | LIS3DH_STATUS_REG_AUX LITERAL1 51 | LIS3DH_OUT_ADC1_L LITERAL1 52 | LIS3DH_OUT_ADC1_H LITERAL1 53 | LIS3DH_OUT_ADC2_L LITERAL1 54 | LIS3DH_OUT_ADC2_H LITERAL1 55 | LIS3DH_OUT_ADC3_L LITERAL1 56 | LIS3DH_OUT_ADC3_H LITERAL1 57 | LIS3DH_WHO_AM_I LITERAL1 58 | LIS3DH_TEMP_CFG_REG LITERAL1 59 | LIS3DH_CTRL_REG1 LITERAL1 60 | LIS3DH_CTRL_REG2 LITERAL1 61 | LIS3DH_CTRL_REG3 LITERAL1 62 | LIS3DH_CTRL_REG4 LITERAL1 63 | LIS3DH_CTRL_REG5 LITERAL1 64 | LIS3DH_CTRL_REG6 LITERAL1 65 | LIS3DH_REFERENCE LITERAL1 66 | LIS3DH_STATUS_REG2 LITERAL1 67 | LIS3DH_OUT_X_L LITERAL1 68 | LIS3DH_OUT_X_H LITERAL1 69 | LIS3DH_OUT_Y_L LITERAL1 70 | LIS3DH_OUT_Y_H LITERAL1 71 | LIS3DH_OUT_Z_L LITERAL1 72 | LIS3DH_OUT_Z_H LITERAL1 73 | LIS3DH_FIFO_CTRL_REG LITERAL1 74 | LIS3DH_FIFO_SRC_REG LITERAL1 75 | LIS3DH_INT1_CFG LITERAL1 76 | LIS3DH_INT1_SRC LITERAL1 77 | LIS3DH_INT1_THS LITERAL1 78 | LIS3DH_INT1_DURATION LITERAL1 79 | LIS3DH_CLICK_CFG LITERAL1 80 | LIS3DH_CLICK_SRC LITERAL1 81 | LIS3DH_CLICK_THS LITERAL1 82 | LIS3DH_TIME_LIMIT LITERAL1 83 | LIS3DH_TIME_LATENCY LITERAL1 84 | LIS3DH_TIME_WINDOW LITERAL1 85 | 86 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=SparkFun LIS3DH Arduino Library 2 | version=1.0.3 3 | author=SparkFun Electronics 4 | maintainer=SparkFun Electronics 5 | sentence=A library to drive the STmicro LIS3DH by SPI or I2C. 6 | paragraph=Uno examples to drive by I2C or SPI, collect extra sensor inputs, and operate FIFO. Checkout the SparkFun LIS3DH Breakout for more information. 7 | category=Sensors 8 | url=https://github.com/sparkfun/SparkFun_LIS3DH_Arduino_Library 9 | architectures=* 10 | -------------------------------------------------------------------------------- /src/SparkFunLIS3DH.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | SparkFunLIS3DH.cpp 3 | LIS3DH Arduino and Teensy Driver 4 | 5 | Marshall Taylor @ SparkFun Electronics 6 | Nov 16, 2016 7 | https://github.com/sparkfun/LIS3DH_Breakout 8 | https://github.com/sparkfun/SparkFun_LIS3DH_Arduino_Library 9 | 10 | Resources: 11 | Uses Wire.h for i2c operation 12 | Uses SPI.h for SPI operation 13 | Either can be omitted if not used 14 | 15 | Development environment specifics: 16 | Arduino IDE 1.6.4 17 | Teensy loader 1.23 18 | 19 | This code is released under the [MIT License](http://opensource.org/licenses/MIT). 20 | 21 | Please review the LICENSE.md file included with this example. If you have any questions 22 | or concerns with licensing, please contact techsupport@sparkfun.com. 23 | 24 | Distributed as-is; no warranty is given. 25 | ******************************************************************************/ 26 | //Use VERBOSE_SERIAL to add debug serial to an existing Serial object. 27 | //Note: Use of VERBOSE_SERIAL adds delays surround RW ops, and should not be used 28 | //for functional testing. 29 | //#define VERBOSE_SERIAL 30 | 31 | //See SparkFunLIS3DH.h for additional topology notes. 32 | 33 | #include "SparkFunLIS3DH.h" 34 | #include "stdint.h" 35 | 36 | #include "Wire.h" 37 | #include "SPI.h" 38 | 39 | //****************************************************************************// 40 | // 41 | // LIS3DHCore functions. 42 | // 43 | // Construction arguments: 44 | // ( uint8_t busType, uint8_t inputArg ), 45 | // 46 | // where inputArg is address for I2C_MODE and chip select pin 47 | // number for SPI_MODE 48 | // 49 | // For SPI, construct LIS3DHCore myIMU(SPI_MODE, 10); 50 | // For I2C, construct LIS3DHCore myIMU(I2C_MODE, 0x6B); 51 | // 52 | // Default construction is I2C mode, address 0x6B. 53 | // 54 | //****************************************************************************// 55 | LIS3DHCore::LIS3DHCore( uint8_t busType, uint8_t inputArg ) : commInterface(I2C_MODE), I2CAddress(0x19), chipSelectPin(10) 56 | { 57 | commInterface = busType; 58 | if( commInterface == I2C_MODE ) 59 | { 60 | I2CAddress = inputArg; 61 | } 62 | if( commInterface == SPI_MODE ) 63 | { 64 | chipSelectPin = inputArg; 65 | } 66 | 67 | } 68 | 69 | status_t LIS3DHCore::beginCore(void) 70 | { 71 | status_t returnError = IMU_SUCCESS; 72 | 73 | switch (commInterface) { 74 | 75 | case I2C_MODE: 76 | Wire.begin(); 77 | break; 78 | 79 | case SPI_MODE: 80 | #if defined(ARDUINO_ARCH_ESP32) 81 | // initalize the chip select pins: 82 | pinMode(chipSelectPin, OUTPUT); 83 | digitalWrite(chipSelectPin, HIGH); 84 | SPI.begin(); 85 | SPI.setFrequency(1000000); 86 | // Data is read and written MSb first. 87 | SPI.setBitOrder(SPI_MSBFIRST); 88 | // Like the standard arduino/teensy comment below, mode0 seems wrong according to standards 89 | // but conforms to the timing diagrams when used for the ESP32 90 | SPI.setDataMode(SPI_MODE0); 91 | 92 | #elif defined(__MK20DX256__) 93 | // initalize the chip select pins: 94 | pinMode(chipSelectPin, OUTPUT); 95 | digitalWrite(chipSelectPin, HIGH); 96 | // start the SPI library: 97 | SPI.begin(); 98 | // Maximum SPI frequency is 10MHz, could divide by 2 here: 99 | SPI.setClockDivider(SPI_CLOCK_DIV4); 100 | // Data is read and written MSb first. 101 | SPI.setBitOrder(MSBFIRST); 102 | // Data is captured on rising edge of clock (CPHA = 0) 103 | // Base value of the clock is HIGH (CPOL = 1) 104 | 105 | // MODE0 for Teensy 3.1 operation 106 | SPI.setDataMode(SPI_MODE0); 107 | #else 108 | // probably __AVR__ 109 | // initalize the chip select pins: 110 | pinMode(chipSelectPin, OUTPUT); 111 | digitalWrite(chipSelectPin, HIGH); 112 | // start the SPI library: 113 | SPI.begin(); 114 | // Maximum SPI frequency is 10MHz, could divide by 2 here: 115 | SPI.setClockDivider(SPI_CLOCK_DIV4); 116 | // Data is read and written MSb first. 117 | SPI.setBitOrder(MSBFIRST); 118 | // Data is captured on rising edge of clock (CPHA = 0) 119 | // Base value of the clock is HIGH (CPOL = 1) 120 | 121 | // MODE3 for 328p operation 122 | SPI.setDataMode(SPI_MODE3); 123 | 124 | #endif 125 | break; 126 | default: 127 | break; 128 | } 129 | 130 | //Spin for a few ms 131 | volatile uint8_t temp = 0; 132 | for( uint16_t i = 0; i < 10000; i++ ) 133 | { 134 | temp++; 135 | } 136 | 137 | //Check the ID register to determine if the operation was a success. 138 | uint8_t readCheck; 139 | readRegister(&readCheck, LIS3DH_WHO_AM_I); 140 | if( readCheck != 0x33 ) 141 | { 142 | returnError = IMU_HW_ERROR; 143 | } 144 | 145 | return returnError; 146 | 147 | } 148 | 149 | //****************************************************************************// 150 | // 151 | // ReadRegisterRegion 152 | // 153 | // Parameters: 154 | // *outputPointer -- Pass &variable (base address of) to save read data to 155 | // offset -- register to read 156 | // length -- number of bytes to read 157 | // 158 | // Note: Does not know if the target memory space is an array or not, or 159 | // if there is the array is big enough. if the variable passed is only 160 | // two bytes long and 3 bytes are requested, this will over-write some 161 | // other memory! 162 | // 163 | //****************************************************************************// 164 | status_t LIS3DHCore::readRegisterRegion(uint8_t *outputPointer , uint8_t offset, uint8_t length) 165 | { 166 | status_t returnError = IMU_SUCCESS; 167 | 168 | //define pointer that will point to the external space 169 | uint8_t i = 0; 170 | uint8_t c = 0; 171 | uint8_t tempFFCounter = 0; 172 | 173 | switch (commInterface) { 174 | 175 | case I2C_MODE: 176 | Wire.beginTransmission(I2CAddress); 177 | offset |= 0x80; //turn auto-increment bit on, bit 7 for I2C 178 | Wire.write(offset); 179 | if( Wire.endTransmission() != 0 ) 180 | { 181 | returnError = IMU_HW_ERROR; 182 | } 183 | else //OK, all worked, keep going 184 | { 185 | // request 6 bytes from slave device 186 | Wire.requestFrom(I2CAddress, length); 187 | while ( (Wire.available()) && (i < length)) // slave may send less than requested 188 | { 189 | c = Wire.read(); // receive a byte as character 190 | *outputPointer = c; 191 | outputPointer++; 192 | i++; 193 | } 194 | } 195 | break; 196 | 197 | case SPI_MODE: 198 | // take the chip select low to select the device: 199 | digitalWrite(chipSelectPin, LOW); 200 | // send the device the register you want to read: 201 | SPI.transfer(offset | 0x80 | 0x40); //Ored with "read request" bit and "auto increment" bit 202 | while ( i < length ) // slave may send less than requested 203 | { 204 | c = SPI.transfer(0x00); // receive a byte as character 205 | if( c == 0xFF ) 206 | { 207 | //May have problem 208 | tempFFCounter++; 209 | } 210 | *outputPointer = c; 211 | outputPointer++; 212 | i++; 213 | } 214 | if( tempFFCounter == i ) 215 | { 216 | //Ok, we've recieved all ones, report 217 | returnError = IMU_ALL_ONES_WARNING; 218 | } 219 | // take the chip select high to de-select: 220 | digitalWrite(chipSelectPin, HIGH); 221 | break; 222 | 223 | default: 224 | break; 225 | } 226 | 227 | return returnError; 228 | } 229 | 230 | //****************************************************************************// 231 | // 232 | // ReadRegister 233 | // 234 | // Parameters: 235 | // *outputPointer -- Pass &variable (address of) to save read data to 236 | // offset -- register to read 237 | // 238 | //****************************************************************************// 239 | status_t LIS3DHCore::readRegister(uint8_t* outputPointer, uint8_t offset) { 240 | //Return value 241 | uint8_t result; 242 | uint8_t numBytes = 1; 243 | status_t returnError = IMU_SUCCESS; 244 | 245 | switch (commInterface) { 246 | 247 | case I2C_MODE: 248 | Wire.beginTransmission(I2CAddress); 249 | Wire.write(offset); 250 | if( Wire.endTransmission() != 0 ) 251 | { 252 | returnError = IMU_HW_ERROR; 253 | } 254 | Wire.requestFrom(I2CAddress, numBytes); 255 | while ( Wire.available() ) // slave may send less than requested 256 | { 257 | result = Wire.read(); // receive a byte as a proper uint8_t 258 | } 259 | break; 260 | 261 | case SPI_MODE: 262 | // take the chip select low to select the device: 263 | digitalWrite(chipSelectPin, LOW); 264 | // send the device the register you want to read: 265 | SPI.transfer(offset | 0x80); //Ored with "read request" bit 266 | // send a value of 0 to read the first byte returned: 267 | result = SPI.transfer(0x00); 268 | // take the chip select high to de-select: 269 | digitalWrite(chipSelectPin, HIGH); 270 | 271 | if( result == 0xFF ) 272 | { 273 | //we've recieved all ones, report 274 | returnError = IMU_ALL_ONES_WARNING; 275 | } 276 | break; 277 | 278 | default: 279 | break; 280 | } 281 | 282 | *outputPointer = result; 283 | return returnError; 284 | } 285 | 286 | //****************************************************************************// 287 | // 288 | // readRegisterInt16 289 | // 290 | // Parameters: 291 | // *outputPointer -- Pass &variable (base address of) to save read data to 292 | // offset -- register to read 293 | // 294 | //****************************************************************************// 295 | status_t LIS3DHCore::readRegisterInt16( int16_t* outputPointer, uint8_t offset ) 296 | { 297 | { 298 | //offset |= 0x80; //turn auto-increment bit on 299 | uint8_t myBuffer[2]; 300 | status_t returnError = readRegisterRegion(myBuffer, offset, 2); //Does memory transfer 301 | int16_t output = (int16_t)myBuffer[0] | int16_t(myBuffer[1] << 8); 302 | *outputPointer = output; 303 | return returnError; 304 | } 305 | 306 | } 307 | 308 | //****************************************************************************// 309 | // 310 | // writeRegister 311 | // 312 | // Parameters: 313 | // offset -- register to write 314 | // dataToWrite -- 8 bit data to write to register 315 | // 316 | //****************************************************************************// 317 | status_t LIS3DHCore::writeRegister(uint8_t offset, uint8_t dataToWrite) { 318 | status_t returnError = IMU_SUCCESS; 319 | switch (commInterface) { 320 | case I2C_MODE: 321 | //Write the byte 322 | Wire.beginTransmission(I2CAddress); 323 | Wire.write(offset); 324 | Wire.write(dataToWrite); 325 | if( Wire.endTransmission() != 0 ) 326 | { 327 | returnError = IMU_HW_ERROR; 328 | } 329 | break; 330 | 331 | case SPI_MODE: 332 | // take the chip select low to select the device: 333 | digitalWrite(chipSelectPin, LOW); 334 | // send the device the register you want to read: 335 | SPI.transfer(offset); 336 | // send a value of 0 to read the first byte returned: 337 | SPI.transfer(dataToWrite); 338 | // decrement the number of bytes left to read: 339 | // take the chip select high to de-select: 340 | digitalWrite(chipSelectPin, HIGH); 341 | break; 342 | 343 | //No way to check error on this write (Except to read back but that's not reliable) 344 | 345 | default: 346 | break; 347 | } 348 | 349 | return returnError; 350 | } 351 | 352 | //****************************************************************************// 353 | // 354 | // Main user class -- wrapper for the core class + maths 355 | // 356 | // Construct with same rules as the core ( uint8_t busType, uint8_t inputArg ) 357 | // 358 | //****************************************************************************// 359 | LIS3DH::LIS3DH( uint8_t busType, uint8_t inputArg ) : LIS3DHCore( busType, inputArg ) 360 | { 361 | //Construct with these default settings 362 | //ADC stuff 363 | settings.adcEnabled = 1; 364 | 365 | //Temperature settings 366 | settings.tempEnabled = 1; 367 | 368 | //Accelerometer settings 369 | settings.accelSampleRate = 50; //Hz. Can be: 0,1,10,25,50,100,200,400,1600,5000 Hz 370 | settings.accelRange = 2; //Max G force readable. Can be: 2, 4, 8, 16 371 | 372 | settings.xAccelEnabled = 1; 373 | settings.yAccelEnabled = 1; 374 | settings.zAccelEnabled = 1; 375 | 376 | //FIFO control settings 377 | settings.fifoEnabled = 0; 378 | settings.fifoThreshold = 20; //Can be 0 to 32 379 | settings.fifoMode = 0; //FIFO mode. 380 | 381 | allOnesCounter = 0; 382 | nonSuccessCounter = 0; 383 | 384 | } 385 | 386 | //****************************************************************************// 387 | // 388 | // Begin 389 | // 390 | // This starts the lower level begin, then applies settings 391 | // 392 | //****************************************************************************// 393 | status_t LIS3DH::begin( void ) 394 | { 395 | //Begin the inherited core. This gets the physical wires connected 396 | status_t returnError = beginCore(); 397 | 398 | applySettings(); 399 | 400 | return returnError; 401 | } 402 | 403 | //****************************************************************************// 404 | // 405 | // Configuration section 406 | // 407 | // This uses the stored SensorSettings to start the IMU 408 | // Use statements such as "myIMU.settings.commInterface = SPI_MODE;" or 409 | // "myIMU.settings.accelEnabled = 1;" to configure before calling .begin(); 410 | // 411 | //****************************************************************************// 412 | void LIS3DH::applySettings( void ) 413 | { 414 | uint8_t dataToWrite = 0; //Temporary variable 415 | 416 | //Build TEMP_CFG_REG 417 | dataToWrite = 0; //Start Fresh! 418 | dataToWrite = ((settings.tempEnabled & 0x01) << 6) | ((settings.adcEnabled & 0x01) << 7); 419 | //Now, write the patched together data 420 | #ifdef VERBOSE_SERIAL 421 | Serial.print("LIS3DH_TEMP_CFG_REG: 0x"); 422 | Serial.println(dataToWrite, HEX); 423 | #endif 424 | writeRegister(LIS3DH_TEMP_CFG_REG, dataToWrite); 425 | 426 | //Build CTRL_REG1 427 | dataToWrite = 0; //Start Fresh! 428 | // Convert ODR 429 | switch(settings.accelSampleRate) 430 | { 431 | case 1: 432 | dataToWrite |= (0x01 << 4); 433 | break; 434 | case 10: 435 | dataToWrite |= (0x02 << 4); 436 | break; 437 | case 25: 438 | dataToWrite |= (0x03 << 4); 439 | break; 440 | case 50: 441 | dataToWrite |= (0x04 << 4); 442 | break; 443 | case 100: 444 | dataToWrite |= (0x05 << 4); 445 | break; 446 | case 200: 447 | dataToWrite |= (0x06 << 4); 448 | break; 449 | default: 450 | case 400: 451 | dataToWrite |= (0x07 << 4); 452 | break; 453 | case 1600: 454 | dataToWrite |= (0x08 << 4); 455 | break; 456 | case 5000: 457 | dataToWrite |= (0x09 << 4); 458 | break; 459 | } 460 | 461 | dataToWrite |= (settings.zAccelEnabled & 0x01) << 2; 462 | dataToWrite |= (settings.yAccelEnabled & 0x01) << 1; 463 | dataToWrite |= (settings.xAccelEnabled & 0x01); 464 | //Now, write the patched together data 465 | #ifdef VERBOSE_SERIAL 466 | Serial.print("LIS3DH_CTRL_REG1: 0x"); 467 | Serial.println(dataToWrite, HEX); 468 | #endif 469 | writeRegister(LIS3DH_CTRL_REG1, dataToWrite); 470 | 471 | //Build CTRL_REG4 472 | dataToWrite = 0; //Start Fresh! 473 | // Convert scaling 474 | switch(settings.accelRange) 475 | { 476 | case 2: 477 | dataToWrite |= (0x00 << 4); 478 | break; 479 | case 4: 480 | dataToWrite |= (0x01 << 4); 481 | break; 482 | case 8: 483 | dataToWrite |= (0x02 << 4); 484 | break; 485 | default: 486 | case 16: 487 | dataToWrite |= (0x03 << 4); 488 | break; 489 | } 490 | dataToWrite |= 0x80; //set block update 491 | dataToWrite |= 0x08; //set high resolution 492 | #ifdef VERBOSE_SERIAL 493 | Serial.print("LIS3DH_CTRL_REG4: 0x"); 494 | Serial.println(dataToWrite, HEX); 495 | #endif 496 | //Now, write the patched together data 497 | writeRegister(LIS3DH_CTRL_REG4, dataToWrite); 498 | 499 | } 500 | //****************************************************************************// 501 | // 502 | // Accelerometer section 503 | // 504 | //****************************************************************************// 505 | int16_t LIS3DH::readRawAccelX( void ) 506 | { 507 | int16_t output; 508 | status_t errorLevel = readRegisterInt16( &output, LIS3DH_OUT_X_L ); 509 | if( errorLevel != IMU_SUCCESS ) 510 | { 511 | if( errorLevel == IMU_ALL_ONES_WARNING ) 512 | { 513 | allOnesCounter++; 514 | } 515 | else 516 | { 517 | nonSuccessCounter++; 518 | } 519 | } 520 | return output; 521 | } 522 | float LIS3DH::readFloatAccelX( void ) 523 | { 524 | float output = calcAccel(readRawAccelX()); 525 | return output; 526 | } 527 | 528 | int16_t LIS3DH::readRawAccelY( void ) 529 | { 530 | int16_t output; 531 | status_t errorLevel = readRegisterInt16( &output, LIS3DH_OUT_Y_L ); 532 | if( errorLevel != IMU_SUCCESS ) 533 | { 534 | if( errorLevel == IMU_ALL_ONES_WARNING ) 535 | { 536 | allOnesCounter++; 537 | } 538 | else 539 | { 540 | nonSuccessCounter++; 541 | } 542 | } 543 | return output; 544 | } 545 | 546 | float LIS3DH::readFloatAccelY( void ) 547 | { 548 | float output = calcAccel(readRawAccelY()); 549 | return output; 550 | } 551 | 552 | int16_t LIS3DH::readRawAccelZ( void ) 553 | { 554 | int16_t output; 555 | status_t errorLevel = readRegisterInt16( &output, LIS3DH_OUT_Z_L ); 556 | if( errorLevel != IMU_SUCCESS ) 557 | { 558 | if( errorLevel == IMU_ALL_ONES_WARNING ) 559 | { 560 | allOnesCounter++; 561 | } 562 | else 563 | { 564 | nonSuccessCounter++; 565 | } 566 | } 567 | return output; 568 | 569 | } 570 | 571 | float LIS3DH::readFloatAccelZ( void ) 572 | { 573 | float output = calcAccel(readRawAccelZ()); 574 | return output; 575 | } 576 | 577 | float LIS3DH::calcAccel( int16_t input ) 578 | { 579 | float output; 580 | switch(settings.accelRange) 581 | { 582 | case 2: 583 | output = (float)input / 15987; 584 | break; 585 | case 4: 586 | output = (float)input / 7840; 587 | break; 588 | case 8: 589 | output = (float)input / 3883; 590 | break; 591 | case 16: 592 | output = (float)input / 1280; 593 | break; 594 | default: 595 | output = 0; 596 | break; 597 | } 598 | return output; 599 | } 600 | 601 | //****************************************************************************// 602 | // 603 | // Accelerometer section 604 | // 605 | //****************************************************************************// 606 | uint16_t LIS3DH::read10bitADC1( void ) 607 | { 608 | int16_t intTemp; 609 | uint16_t uintTemp; 610 | readRegisterInt16( &intTemp, LIS3DH_OUT_ADC1_L ); 611 | intTemp = 0 - intTemp; 612 | uintTemp = intTemp + 32768; 613 | return uintTemp >> 6; 614 | } 615 | 616 | uint16_t LIS3DH::read10bitADC2( void ) 617 | { 618 | int16_t intTemp; 619 | uint16_t uintTemp; 620 | readRegisterInt16( &intTemp, LIS3DH_OUT_ADC2_L ); 621 | intTemp = 0 - intTemp; 622 | uintTemp = intTemp + 32768; 623 | return uintTemp >> 6; 624 | } 625 | 626 | uint16_t LIS3DH::read10bitADC3( void ) 627 | { 628 | int16_t intTemp; 629 | uint16_t uintTemp; 630 | readRegisterInt16( &intTemp, LIS3DH_OUT_ADC3_L ); 631 | intTemp = 0 - intTemp; 632 | uintTemp = intTemp + 32768; 633 | return uintTemp >> 6; 634 | } 635 | 636 | //****************************************************************************// 637 | // 638 | // FIFO section 639 | // 640 | //****************************************************************************// 641 | void LIS3DH::fifoBegin( void ) 642 | { 643 | uint8_t dataToWrite = 0; //Temporary variable 644 | 645 | //Build LIS3DH_FIFO_CTRL_REG 646 | readRegister( &dataToWrite, LIS3DH_FIFO_CTRL_REG ); //Start with existing data 647 | dataToWrite &= 0x20;//clear all but bit 5 648 | dataToWrite |= (settings.fifoMode & 0x03) << 6; //apply mode 649 | dataToWrite |= (settings.fifoThreshold & 0x1F); //apply threshold 650 | //Now, write the patched together data 651 | #ifdef VERBOSE_SERIAL 652 | Serial.print("LIS3DH_FIFO_CTRL_REG: 0x"); 653 | Serial.println(dataToWrite, HEX); 654 | #endif 655 | writeRegister(LIS3DH_FIFO_CTRL_REG, dataToWrite); 656 | 657 | //Build CTRL_REG5 658 | readRegister( &dataToWrite, LIS3DH_CTRL_REG5 ); //Start with existing data 659 | dataToWrite &= 0xBF;//clear bit 6 660 | dataToWrite |= (settings.fifoEnabled & 0x01) << 6; 661 | //Now, write the patched together data 662 | #ifdef VERBOSE_SERIAL 663 | Serial.print("LIS3DH_CTRL_REG5: 0x"); 664 | Serial.println(dataToWrite, HEX); 665 | #endif 666 | writeRegister(LIS3DH_CTRL_REG5, dataToWrite); 667 | } 668 | 669 | void LIS3DH::fifoClear( void ) { 670 | //Drain the fifo data and dump it 671 | while( (fifoGetStatus() & 0x20 ) == 0 ) { 672 | readRawAccelX(); 673 | readRawAccelY(); 674 | readRawAccelZ(); 675 | } 676 | } 677 | 678 | void LIS3DH::fifoStartRec( void ) 679 | { 680 | uint8_t dataToWrite = 0; //Temporary variable 681 | 682 | //Turn off... 683 | readRegister( &dataToWrite, LIS3DH_FIFO_CTRL_REG ); //Start with existing data 684 | dataToWrite &= 0x3F;//clear mode 685 | #ifdef VERBOSE_SERIAL 686 | Serial.print("LIS3DH_FIFO_CTRL_REG: 0x"); 687 | Serial.println(dataToWrite, HEX); 688 | #endif 689 | writeRegister(LIS3DH_FIFO_CTRL_REG, dataToWrite); 690 | // ... then back on again 691 | readRegister( &dataToWrite, LIS3DH_FIFO_CTRL_REG ); //Start with existing data 692 | dataToWrite &= 0x3F;//clear mode 693 | dataToWrite |= (settings.fifoMode & 0x03) << 6; //apply mode 694 | //Now, write the patched together data 695 | #ifdef VERBOSE_SERIAL 696 | Serial.print("LIS3DH_FIFO_CTRL_REG: 0x"); 697 | Serial.println(dataToWrite, HEX); 698 | #endif 699 | writeRegister(LIS3DH_FIFO_CTRL_REG, dataToWrite); 700 | } 701 | 702 | uint8_t LIS3DH::fifoGetStatus( void ) 703 | { 704 | //Return some data on the state of the fifo 705 | uint8_t tempReadByte = 0; 706 | readRegister(&tempReadByte, LIS3DH_FIFO_SRC_REG); 707 | #ifdef VERBOSE_SERIAL 708 | Serial.print("LIS3DH_FIFO_SRC_REG: 0x"); 709 | Serial.println(tempReadByte, HEX); 710 | #endif 711 | return tempReadByte; 712 | } 713 | 714 | void LIS3DH::fifoEnd( void ) 715 | { 716 | uint8_t dataToWrite = 0; //Temporary variable 717 | 718 | //Turn off... 719 | readRegister( &dataToWrite, LIS3DH_FIFO_CTRL_REG ); //Start with existing data 720 | dataToWrite &= 0x3F;//clear mode 721 | #ifdef VERBOSE_SERIAL 722 | Serial.print("LIS3DH_FIFO_CTRL_REG: 0x"); 723 | Serial.println(dataToWrite, HEX); 724 | #endif 725 | writeRegister(LIS3DH_FIFO_CTRL_REG, dataToWrite); 726 | } 727 | 728 | -------------------------------------------------------------------------------- /src/SparkFunLIS3DH.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | SparkFunLIS3DH.h 3 | LIS3DH Arduino and Teensy Driver 4 | 5 | Marshall Taylor @ SparkFun Electronics 6 | Nov 16, 2016 7 | https://github.com/sparkfun/LIS3DH_Breakout 8 | https://github.com/sparkfun/SparkFun_LIS3DH_Arduino_Library 9 | 10 | Resources: 11 | Uses Wire.h for i2c operation 12 | Uses SPI.h for SPI operation 13 | Either can be omitted if not used 14 | 15 | Development environment specifics: 16 | Arduino IDE 1.6.4 17 | Teensy loader 1.23 18 | 19 | This code is released under the [MIT License](http://opensource.org/licenses/MIT). 20 | 21 | Please review the LICENSE.md file included with this example. If you have any questions 22 | or concerns with licensing, please contact techsupport@sparkfun.com. 23 | 24 | Distributed as-is; no warranty is given. 25 | ******************************************************************************/ 26 | 27 | #ifndef __LIS3DH_IMU_H__ 28 | #define __LIS3DH_IMU_H__ 29 | 30 | #include "stdint.h" 31 | 32 | //values for commInterface 33 | #define I2C_MODE 0 34 | #define SPI_MODE 1 35 | 36 | // Return values 37 | typedef enum 38 | { 39 | IMU_SUCCESS, 40 | IMU_HW_ERROR, 41 | IMU_NOT_SUPPORTED, 42 | IMU_GENERIC_ERROR, 43 | IMU_OUT_OF_BOUNDS, 44 | IMU_ALL_ONES_WARNING, 45 | //... 46 | } status_t; 47 | 48 | //This is the core operational class of the driver. 49 | // LIS3DHCore contains only read and write operations towards the IMU. 50 | // To use the higher level functions, use the class LIS3DH which inherits 51 | // this class. 52 | 53 | class LIS3DHCore 54 | { 55 | public: 56 | LIS3DHCore( uint8_t ); 57 | LIS3DHCore( uint8_t, uint8_t ); 58 | ~LIS3DHCore() = default; 59 | 60 | status_t beginCore( void ); 61 | 62 | //The following utilities read and write to the IMU 63 | 64 | //ReadRegisterRegion takes a uint8 array address as input and reads 65 | // a chunk of memory into that array. 66 | status_t readRegisterRegion(uint8_t*, uint8_t, uint8_t ); 67 | 68 | //readRegister reads one 8-bit register 69 | status_t readRegister(uint8_t*, uint8_t); 70 | 71 | //Reads two 8-bit regs, LSByte then MSByte order, and concatenates them. 72 | // Acts as a 16-bit read operation 73 | status_t readRegisterInt16(int16_t*, uint8_t offset ); 74 | 75 | //Writes an 8-bit byte; 76 | status_t writeRegister(uint8_t, uint8_t); 77 | 78 | private: 79 | //Communication stuff 80 | uint8_t commInterface; 81 | uint8_t I2CAddress; 82 | uint8_t chipSelectPin; 83 | }; 84 | 85 | //This struct holds the settings the driver uses to do calculations 86 | struct SensorSettings 87 | { 88 | public: 89 | //ADC and Temperature settings 90 | uint8_t adcEnabled; 91 | uint8_t tempEnabled; 92 | 93 | //Accelerometer settings 94 | uint16_t accelSampleRate; //Hz. Can be: 0,1,10,25,50,100,200,400,1600,5000 Hz 95 | uint8_t accelRange; //Max G force readable. Can be: 2, 4, 8, 16 96 | 97 | uint8_t xAccelEnabled; 98 | uint8_t yAccelEnabled; 99 | uint8_t zAccelEnabled; 100 | 101 | //Fifo settings 102 | uint8_t fifoEnabled; 103 | uint8_t fifoMode; //can be 0x0,0x1,0x2,0x3 104 | uint8_t fifoThreshold; 105 | }; 106 | 107 | 108 | //This is the highest level class of the driver. 109 | // 110 | // class LIS3DH inherits the core and makes use of the beginCore() 111 | //method through it's own begin() method. It also contains the 112 | //settings struct to hold user settings. 113 | 114 | class LIS3DH : public LIS3DHCore 115 | { 116 | public: 117 | //IMU settings 118 | SensorSettings settings; 119 | 120 | //Error checking 121 | uint16_t allOnesCounter; 122 | uint16_t nonSuccessCounter; 123 | 124 | //Constructor generates default SensorSettings. 125 | //(over-ride after construction if desired) 126 | LIS3DH( uint8_t busType = I2C_MODE, uint8_t inputArg = 0x19 ); 127 | //~LIS3DH() = default; 128 | 129 | //Call to apply SensorSettings 130 | status_t begin( void ); 131 | void applySettings( void ); 132 | 133 | //Returns the raw bits from the sensor cast as 16-bit signed integers 134 | int16_t readRawAccelX( void ); 135 | int16_t readRawAccelY( void ); 136 | int16_t readRawAccelZ( void ); 137 | 138 | //Returns the values as floats. Inside, this calls readRaw___(); 139 | float readFloatAccelX( void ); 140 | float readFloatAccelY( void ); 141 | float readFloatAccelZ( void ); 142 | 143 | //ADC related calls 144 | uint16_t read10bitADC1( void ); 145 | uint16_t read10bitADC2( void ); 146 | uint16_t read10bitADC3( void ); 147 | 148 | //FIFO stuff 149 | void fifoBegin( void ); 150 | void fifoClear( void ); 151 | uint8_t fifoGetStatus( void ); 152 | void fifoStartRec(); 153 | void fifoEnd( void ); 154 | 155 | float calcAccel( int16_t ); 156 | 157 | private: 158 | 159 | }; 160 | 161 | //Device Registers 162 | #define LIS3DH_STATUS_REG_AUX 0x07 163 | #define LIS3DH_OUT_ADC1_L 0x08 164 | #define LIS3DH_OUT_ADC1_H 0x09 165 | #define LIS3DH_OUT_ADC2_L 0x0A 166 | #define LIS3DH_OUT_ADC2_H 0x0B 167 | #define LIS3DH_OUT_ADC3_L 0x0C 168 | #define LIS3DH_OUT_ADC3_H 0x0D 169 | #define LIS3DH_INT_COUNTER_REG 0x0E 170 | #define LIS3DH_WHO_AM_I 0x0F 171 | 172 | #define LIS3DH_TEMP_CFG_REG 0x1F 173 | #define LIS3DH_CTRL_REG1 0x20 174 | #define LIS3DH_CTRL_REG2 0x21 175 | #define LIS3DH_CTRL_REG3 0x22 176 | #define LIS3DH_CTRL_REG4 0x23 177 | #define LIS3DH_CTRL_REG5 0x24 178 | #define LIS3DH_CTRL_REG6 0x25 179 | #define LIS3DH_REFERENCE 0x26 180 | #define LIS3DH_STATUS_REG2 0x27 181 | #define LIS3DH_OUT_X_L 0x28 182 | #define LIS3DH_OUT_X_H 0x29 183 | #define LIS3DH_OUT_Y_L 0x2A 184 | #define LIS3DH_OUT_Y_H 0x2B 185 | #define LIS3DH_OUT_Z_L 0x2C 186 | #define LIS3DH_OUT_Z_H 0x2D 187 | #define LIS3DH_FIFO_CTRL_REG 0x2E 188 | #define LIS3DH_FIFO_SRC_REG 0x2F 189 | #define LIS3DH_INT1_CFG 0x30 190 | #define LIS3DH_INT1_SRC 0x31 191 | #define LIS3DH_INT1_THS 0x32 192 | #define LIS3DH_INT1_DURATION 0x33 193 | 194 | #define LIS3DH_CLICK_CFG 0x38 195 | #define LIS3DH_CLICK_SRC 0x39 196 | #define LIS3DH_CLICK_THS 0x3A 197 | #define LIS3DH_TIME_LIMIT 0x3B 198 | #define LIS3DH_TIME_LATENCY 0x3C 199 | #define LIS3DH_TIME_WINDOW 0x3D 200 | 201 | #endif // End of __LIS3DH_IMU_H__ definition check 202 | --------------------------------------------------------------------------------