SCL3300 sensor 3-axis inclinometer with angle output and digital SPI interface

Committer:
metronix
Date:
Mon Sep 05 15:56:44 2022 +0000
Revision:
1:52b1117c65ea
Parent:
0:e8ba98a758d0
modified scl3300 Library test program

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sameera0824 0:e8ba98a758d0 1 /******************************************************************************
sameera0824 0:e8ba98a758d0 2 SCL3300.cpp
sameera0824 0:e8ba98a758d0 3 David Armstrong
sameera0824 0:e8ba98a758d0 4 Version 3.3.0 - September 13, 2021
sameera0824 0:e8ba98a758d0 5 https://github.com/DavidArmstrong/SCL3300
sameera0824 0:e8ba98a758d0 6
metronix 1:52b1117c65ea 7 MODIFIDER BY METRONICA (METRONIX)
metronix 1:52b1117c65ea 8
sameera0824 0:e8ba98a758d0 9 Resources:
sameera0824 0:e8ba98a758d0 10 Uses SPI.h for SPI operation
sameera0824 0:e8ba98a758d0 11
sameera0824 0:e8ba98a758d0 12 Development environment specifics:
metronix 1:52b1117c65ea 13 MBED OS
sameera0824 0:e8ba98a758d0 14
sameera0824 0:e8ba98a758d0 15 This code is released under the [MIT License](http://opensource.org/licenses/MIT).
sameera0824 0:e8ba98a758d0 16 Please review the LICENSE.md file included with this example.
sameera0824 0:e8ba98a758d0 17 Distributed as-is; no warranty is given.
sameera0824 0:e8ba98a758d0 18
metronix 1:52b1117c65ea 19
sameera0824 0:e8ba98a758d0 20 ******************************************************************************/
sameera0824 0:e8ba98a758d0 21
sameera0824 0:e8ba98a758d0 22 // include this library's description file
sameera0824 0:e8ba98a758d0 23 #include "SCL3300.h"
sameera0824 0:e8ba98a758d0 24
metronix 1:52b1117c65ea 25 SCL3300::SCL3300(PinName mosi, PinName miso, PinName sclk, PinName scl3300_csPin) : _spi(mosi, miso, sclk), _scl3300_csPin(scl3300_csPin) {
metronix 1:52b1117c65ea 26 _scl3300_csPin = 1;
metronix 1:52b1117c65ea 27
metronix 1:52b1117c65ea 28 // Set default to and 4MHz for data transfer
metronix 1:52b1117c65ea 29 _transfer_sck = 4000000;
metronix 1:52b1117c65ea 30
metronix 1:52b1117c65ea 31 modeCMD[0] = 0;
metronix 1:52b1117c65ea 32 modeCMD[1] = ChgMode1;
metronix 1:52b1117c65ea 33 modeCMD[2] = ChgMode2;
metronix 1:52b1117c65ea 34 modeCMD[3] = ChgMode3;
metronix 1:52b1117c65ea 35 modeCMD[4] = ChgMode4;
metronix 1:52b1117c65ea 36
metronix 1:52b1117c65ea 37 scl3300_mode=4;
metronix 1:52b1117c65ea 38 }
metronix 1:52b1117c65ea 39
metronix 1:52b1117c65ea 40
sameera0824 0:e8ba98a758d0 41 // Public Methods //////////////////////////////////////////////////////////
sameera0824 0:e8ba98a758d0 42 // Set the sensor mode to the number provided as modeNum.
metronix 1:52b1117c65ea 43 bool SCL3300::setMode(int modeNum) {
sameera0824 0:e8ba98a758d0 44 // Set Sensor mode - If not called, the default is mode 4, as set in header file
sameera0824 0:e8ba98a758d0 45 // Only allowed values are: 1,2,3,4
sameera0824 0:e8ba98a758d0 46 if (modeNum > 0 && modeNum < 5) {
sameera0824 0:e8ba98a758d0 47 scl3300_mode = modeNum;
sameera0824 0:e8ba98a758d0 48 if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
sameera0824 0:e8ba98a758d0 49 transfer(modeCMD[scl3300_mode]); //Set mode on hardware
sameera0824 0:e8ba98a758d0 50 if (!setFastRead) endTransmission(); //Let go of SPI port/bus
sameera0824 0:e8ba98a758d0 51 if (crcerr || statuserr) {
sameera0824 0:e8ba98a758d0 52 reset(); //Reset chip to fix the error state
sameera0824 0:e8ba98a758d0 53 return false; //Let the caller know something went wrong
sameera0824 0:e8ba98a758d0 54 } else return true; // Valid value, and chip was set to that mode
sameera0824 0:e8ba98a758d0 55 } else
sameera0824 0:e8ba98a758d0 56 return false; // Invalid value
sameera0824 0:e8ba98a758d0 57 }
sameera0824 0:e8ba98a758d0 58
sameera0824 0:e8ba98a758d0 59 // Current Version of begin() to initialize the library and the SCL3300
metronix 1:52b1117c65ea 60 bool SCL3300::begin(void) {
sameera0824 0:e8ba98a758d0 61 //This is the updated Version 3 begin function
metronix 1:52b1117c65ea 62
sameera0824 0:e8ba98a758d0 63 //Wait the required 1 ms before initializing the SCL3300 inclinomenter
metronix 1:52b1117c65ea 64 timer2.start();
metronix 1:52b1117c65ea 65 unsigned long startmillis = timer2.read_ms();
metronix 1:52b1117c65ea 66 while (timer2.read_ms() - startmillis < 1) ;
metronix 1:52b1117c65ea 67 timer2.stop();
sameera0824 0:e8ba98a758d0 68
sameera0824 0:e8ba98a758d0 69 initSPI(); // Initialize SPI Library
sameera0824 0:e8ba98a758d0 70 if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
sameera0824 0:e8ba98a758d0 71 //Write SW Reset command
sameera0824 0:e8ba98a758d0 72 transfer(SwtchBnk0);
sameera0824 0:e8ba98a758d0 73 transfer(SWreset);
metronix 1:52b1117c65ea 74 timer2.start();
metronix 1:52b1117c65ea 75 startmillis = timer2.read_ms();
metronix 1:52b1117c65ea 76 while (timer2.read_ms() - startmillis < 1) ;
metronix 1:52b1117c65ea 77 timer2.stop();
sameera0824 0:e8ba98a758d0 78 //Set measurement mode
sameera0824 0:e8ba98a758d0 79 transfer(modeCMD[scl3300_mode]); //Set mode on hardware
sameera0824 0:e8ba98a758d0 80 //We're good, so Enable angle outputs
sameera0824 0:e8ba98a758d0 81 transfer(EnaAngOut);
sameera0824 0:e8ba98a758d0 82 //The first response after reset is undefined and shall be discarded
sameera0824 0:e8ba98a758d0 83 //wait 5 ms to stablize
metronix 1:52b1117c65ea 84 timer2.start();
metronix 1:52b1117c65ea 85 startmillis = timer2.read_ms();
metronix 1:52b1117c65ea 86 while (timer2.read_ms() - startmillis < 100) ;
metronix 1:52b1117c65ea 87 timer2.stop();
sameera0824 0:e8ba98a758d0 88
sameera0824 0:e8ba98a758d0 89 //Read Status to clear the status summary
sameera0824 0:e8ba98a758d0 90 transfer(RdStatSum);
sameera0824 0:e8ba98a758d0 91 transfer(RdStatSum); //Again, due to off-response protocol used
sameera0824 0:e8ba98a758d0 92 transfer(RdStatSum); //And now we can get the real status
sameera0824 0:e8ba98a758d0 93
sameera0824 0:e8ba98a758d0 94 //Read the WHOAMI register
sameera0824 0:e8ba98a758d0 95 transfer(RdWHOAMI);
sameera0824 0:e8ba98a758d0 96 //And again
sameera0824 0:e8ba98a758d0 97 transfer(RdWHOAMI);
sameera0824 0:e8ba98a758d0 98 if (!setFastRead) endTransmission(); //Let go of SPI port/bus
sameera0824 0:e8ba98a758d0 99 //We now wait until the end of begin() to report if an error occurred
sameera0824 0:e8ba98a758d0 100 if (crcerr || statuserr) return false;
sameera0824 0:e8ba98a758d0 101 // Once everything is initialized, return a known expected value
sameera0824 0:e8ba98a758d0 102 // The WHOAMI command should give an 8 bit value of 0xc1
sameera0824 0:e8ba98a758d0 103 return (SCL3300_DATA == 0xc1); //Let the caller know if this worked
sameera0824 0:e8ba98a758d0 104 }
sameera0824 0:e8ba98a758d0 105
sameera0824 0:e8ba98a758d0 106
sameera0824 0:e8ba98a758d0 107 //Check to validate that the sensor is still reachable and ready to provide data
metronix 1:52b1117c65ea 108 bool SCL3300::isConnected() {
sameera0824 0:e8ba98a758d0 109 if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
sameera0824 0:e8ba98a758d0 110 transfer(SwtchBnk0);
sameera0824 0:e8ba98a758d0 111 //Read the WHOAMI register
sameera0824 0:e8ba98a758d0 112 transfer(RdWHOAMI);
sameera0824 0:e8ba98a758d0 113 //And again
sameera0824 0:e8ba98a758d0 114 transfer(RdWHOAMI);
sameera0824 0:e8ba98a758d0 115 if (!setFastRead) endTransmission(); //Let go of SPI port/bus
sameera0824 0:e8ba98a758d0 116 if (crcerr || statuserr) return false;
sameera0824 0:e8ba98a758d0 117 // Once everything is initialized, return a known expected value
sameera0824 0:e8ba98a758d0 118 // The WHOAMI command should give an 8 bit value of 0xc1
sameera0824 0:e8ba98a758d0 119 return (SCL3300_DATA == 0xc1); //Let the caller know if this worked
sameera0824 0:e8ba98a758d0 120 }
sameera0824 0:e8ba98a758d0 121
sameera0824 0:e8ba98a758d0 122 //Read all the sensor data together to keep it consistent
sameera0824 0:e8ba98a758d0 123 //This is required according to the datasheet
metronix 1:52b1117c65ea 124 bool SCL3300::available(void) {
sameera0824 0:e8ba98a758d0 125 //Version 3 of this function
metronix 1:52b1117c65ea 126 bool errorflag = false;
sameera0824 0:e8ba98a758d0 127 //Read all Sensor Data, as per Datasheet requirements
sameera0824 0:e8ba98a758d0 128 if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
sameera0824 0:e8ba98a758d0 129 transfer(SwtchBnk0);
sameera0824 0:e8ba98a758d0 130 transfer(RdAccX);
sameera0824 0:e8ba98a758d0 131 if (crcerr || statuserr) errorflag = true;
sameera0824 0:e8ba98a758d0 132 transfer(RdAccY);
sameera0824 0:e8ba98a758d0 133 if (crcerr || statuserr) errorflag = true;
sameera0824 0:e8ba98a758d0 134 sclData.AccX = SCL3300_DATA;
sameera0824 0:e8ba98a758d0 135 transfer(RdAccZ);
sameera0824 0:e8ba98a758d0 136 if (crcerr || statuserr) errorflag = true;
sameera0824 0:e8ba98a758d0 137 sclData.AccY = SCL3300_DATA;
sameera0824 0:e8ba98a758d0 138 transfer(RdSTO);
sameera0824 0:e8ba98a758d0 139 if (crcerr || statuserr) errorflag = true;
sameera0824 0:e8ba98a758d0 140 sclData.AccZ = SCL3300_DATA;
sameera0824 0:e8ba98a758d0 141 transfer(RdTemp);
sameera0824 0:e8ba98a758d0 142 if (crcerr || statuserr) errorflag = true;
sameera0824 0:e8ba98a758d0 143 sclData.STO = SCL3300_DATA;
sameera0824 0:e8ba98a758d0 144 transfer(RdAngX);
sameera0824 0:e8ba98a758d0 145 if (crcerr || statuserr) errorflag = true;
sameera0824 0:e8ba98a758d0 146 sclData.TEMP = SCL3300_DATA;
sameera0824 0:e8ba98a758d0 147 transfer(RdAngY);
sameera0824 0:e8ba98a758d0 148 if (crcerr || statuserr) errorflag = true;
sameera0824 0:e8ba98a758d0 149 sclData.AngX = SCL3300_DATA;
sameera0824 0:e8ba98a758d0 150 transfer(RdAngZ);
sameera0824 0:e8ba98a758d0 151 if (crcerr || statuserr) errorflag = true;
sameera0824 0:e8ba98a758d0 152 sclData.AngY = SCL3300_DATA;
sameera0824 0:e8ba98a758d0 153 transfer(RdStatSum);
sameera0824 0:e8ba98a758d0 154 if (crcerr || statuserr) errorflag = true;
sameera0824 0:e8ba98a758d0 155 sclData.AngZ = SCL3300_DATA;
sameera0824 0:e8ba98a758d0 156 transfer(RdWHOAMI);
sameera0824 0:e8ba98a758d0 157 if (crcerr || statuserr) errorflag = true;
sameera0824 0:e8ba98a758d0 158 sclData.StatusSum = SCL3300_DATA;
sameera0824 0:e8ba98a758d0 159 transfer(RdWHOAMI);
sameera0824 0:e8ba98a758d0 160 if (crcerr || statuserr) errorflag = true;
sameera0824 0:e8ba98a758d0 161 sclData.WHOAMI = SCL3300_DATA;
sameera0824 0:e8ba98a758d0 162 if (!setFastRead) endTransmission(); //Let go of SPI port/bus
sameera0824 0:e8ba98a758d0 163 if (errorflag) return false; //Inform caller that something went wrong
sameera0824 0:e8ba98a758d0 164 // The WHOAMI command should give an 8 bit value of 0xc1
sameera0824 0:e8ba98a758d0 165 return (SCL3300_DATA == 0xc1); //Let the caller know this worked
sameera0824 0:e8ba98a758d0 166 }
sameera0824 0:e8ba98a758d0 167
sameera0824 0:e8ba98a758d0 168 /* Set SCL3300 library into Fast Read Mode
sameera0824 0:e8ba98a758d0 169 * Warning: Using Fast Read Mode in the library works by keeping the
sameera0824 0:e8ba98a758d0 170 * SPI connection continuously open. This may or may not affect
sameera0824 0:e8ba98a758d0 171 * the behavior of other hardware interactions, depending on the
sameera0824 0:e8ba98a758d0 172 * sketch design. Fast Read Mode is considered an advanced use case,
sameera0824 0:e8ba98a758d0 173 * and not recommended for the beginner.
sameera0824 0:e8ba98a758d0 174 */
sameera0824 0:e8ba98a758d0 175 void SCL3300::setFastReadMode() {
sameera0824 0:e8ba98a758d0 176 setFastRead = true;
sameera0824 0:e8ba98a758d0 177 beginTransmission(); //Set up this SPI port/bus
sameera0824 0:e8ba98a758d0 178 begin(); //Re-init chip
sameera0824 0:e8ba98a758d0 179 }
sameera0824 0:e8ba98a758d0 180
sameera0824 0:e8ba98a758d0 181 /* Stop Fast Read Mode
sameera0824 0:e8ba98a758d0 182 * Warning: Using Fast Read Mode in the library works by keeping the
sameera0824 0:e8ba98a758d0 183 * SPI connection continuously open. This may or may not affect
sameera0824 0:e8ba98a758d0 184 * the behavior of other hardware interactions, depending on the
sameera0824 0:e8ba98a758d0 185 * sketch design. Fast Read Mode is considered an advanced use case,
sameera0824 0:e8ba98a758d0 186 * and not recommended for the beginner.
sameera0824 0:e8ba98a758d0 187 */
sameera0824 0:e8ba98a758d0 188 void SCL3300::stopFastReadMode() {
sameera0824 0:e8ba98a758d0 189 setFastRead = false;
sameera0824 0:e8ba98a758d0 190 endTransmission(); //Close connection to SPI port/bus
sameera0824 0:e8ba98a758d0 191 begin(); //Re-init chip
sameera0824 0:e8ba98a758d0 192 }
sameera0824 0:e8ba98a758d0 193
sameera0824 0:e8ba98a758d0 194 //Return the calculated X axis tilt angle in degrees
sameera0824 0:e8ba98a758d0 195 double SCL3300::getCalculatedAngleX() {
sameera0824 0:e8ba98a758d0 196 double tempX = angle(sclData.AngX);
sameera0824 0:e8ba98a758d0 197 if (tempX < 0.) tempX += 360.;
sameera0824 0:e8ba98a758d0 198 return tempX;
sameera0824 0:e8ba98a758d0 199 }
sameera0824 0:e8ba98a758d0 200
sameera0824 0:e8ba98a758d0 201 //Return the calculated Y axis tilt angle in degrees
sameera0824 0:e8ba98a758d0 202 double SCL3300::getCalculatedAngleY() {
sameera0824 0:e8ba98a758d0 203 double tempY = angle(sclData.AngY);
sameera0824 0:e8ba98a758d0 204 if (tempY < 0.) tempY += 360.;
sameera0824 0:e8ba98a758d0 205 return tempY;
sameera0824 0:e8ba98a758d0 206 }
sameera0824 0:e8ba98a758d0 207
sameera0824 0:e8ba98a758d0 208 //Return the calculated Z axis tilt angle in degrees
sameera0824 0:e8ba98a758d0 209 double SCL3300::getCalculatedAngleZ() {
sameera0824 0:e8ba98a758d0 210 double tempZ = angle(sclData.AngZ);
sameera0824 0:e8ba98a758d0 211 if (tempZ < 0.) tempZ += 360.;
sameera0824 0:e8ba98a758d0 212 return tempZ;
sameera0824 0:e8ba98a758d0 213 }
sameera0824 0:e8ba98a758d0 214
sameera0824 0:e8ba98a758d0 215 //Return the calculated X axis offset tilt angle in degrees
sameera0824 0:e8ba98a758d0 216 double SCL3300::getTiltLevelOffsetAngleX() {
sameera0824 0:e8ba98a758d0 217 return angle(sclData.AngX);
sameera0824 0:e8ba98a758d0 218 }
sameera0824 0:e8ba98a758d0 219
sameera0824 0:e8ba98a758d0 220 //Return the calculated Y axis offset tilt angle in degrees
sameera0824 0:e8ba98a758d0 221 double SCL3300::getTiltLevelOffsetAngleY() {
sameera0824 0:e8ba98a758d0 222 return angle(sclData.AngY);
sameera0824 0:e8ba98a758d0 223 }
sameera0824 0:e8ba98a758d0 224
sameera0824 0:e8ba98a758d0 225 //Return the calculated Z axis offset tilt angle in degrees
sameera0824 0:e8ba98a758d0 226 double SCL3300::getTiltLevelOffsetAngleZ() {
sameera0824 0:e8ba98a758d0 227 return angle(sclData.AngZ);
sameera0824 0:e8ba98a758d0 228 }
sameera0824 0:e8ba98a758d0 229
sameera0824 0:e8ba98a758d0 230 //Return the calculated X axis accelerometer value in units of 'g'
sameera0824 0:e8ba98a758d0 231 double SCL3300::getCalculatedAccelerometerX(void) {
sameera0824 0:e8ba98a758d0 232 return acceleration(sclData.AccX);
sameera0824 0:e8ba98a758d0 233 }
sameera0824 0:e8ba98a758d0 234
sameera0824 0:e8ba98a758d0 235 //Return the calculated Y axis accelerometer value in units of 'g'
sameera0824 0:e8ba98a758d0 236 double SCL3300::getCalculatedAccelerometerY(void) {
sameera0824 0:e8ba98a758d0 237 return acceleration(sclData.AccY);
sameera0824 0:e8ba98a758d0 238 }
sameera0824 0:e8ba98a758d0 239
sameera0824 0:e8ba98a758d0 240 //Return the calculated Z axis accelerometer value in units of 'g'
sameera0824 0:e8ba98a758d0 241 double SCL3300::getCalculatedAccelerometerZ(void) {
sameera0824 0:e8ba98a758d0 242 return acceleration(sclData.AccZ);
sameera0824 0:e8ba98a758d0 243 }
sameera0824 0:e8ba98a758d0 244
sameera0824 0:e8ba98a758d0 245 //Return value of Error Flag 1 register
sameera0824 0:e8ba98a758d0 246 uint16_t SCL3300::getErrFlag1(void) {
sameera0824 0:e8ba98a758d0 247 if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
sameera0824 0:e8ba98a758d0 248 transfer(SwtchBnk0);
sameera0824 0:e8ba98a758d0 249 transfer(RdErrFlg1);
sameera0824 0:e8ba98a758d0 250 transfer(RdErrFlg1);
sameera0824 0:e8ba98a758d0 251 if (!setFastRead) endTransmission(); //Let go of SPI port/bus
sameera0824 0:e8ba98a758d0 252 //Since we are fetching the Error Flag 1 value, we want to return what we got
sameera0824 0:e8ba98a758d0 253 //to the caller, regardless of whether or not there was an error
sameera0824 0:e8ba98a758d0 254 //if (crcerr || statuserr) return ((uint16_t)(SCL3300_CMD) & 0xff); //check CRC and RS bits
sameera0824 0:e8ba98a758d0 255 return SCL3300_DATA;
sameera0824 0:e8ba98a758d0 256 }
sameera0824 0:e8ba98a758d0 257
sameera0824 0:e8ba98a758d0 258 //Return value of Error Flag 2 register
sameera0824 0:e8ba98a758d0 259 uint16_t SCL3300::getErrFlag2(void) {
sameera0824 0:e8ba98a758d0 260 if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
sameera0824 0:e8ba98a758d0 261 transfer(SwtchBnk0);
sameera0824 0:e8ba98a758d0 262 transfer(RdErrFlg2);
sameera0824 0:e8ba98a758d0 263 transfer(RdErrFlg2);
sameera0824 0:e8ba98a758d0 264 if (!setFastRead) endTransmission(); //Let go of SPI port/bus
sameera0824 0:e8ba98a758d0 265 //Since we are fetching the Error Flag 2 value, we want to return what we got
sameera0824 0:e8ba98a758d0 266 //to the caller, regardless of whether or not there was an error
sameera0824 0:e8ba98a758d0 267 //if (crcerr || statuserr) return ((uint16_t)(SCL3300_CMD) & 0xff); //check CRC and RS bits
sameera0824 0:e8ba98a758d0 268 return SCL3300_DATA;
sameera0824 0:e8ba98a758d0 269 }
sameera0824 0:e8ba98a758d0 270
sameera0824 0:e8ba98a758d0 271 // Read the sensor Serial Number as created by the manufacturer
sameera0824 0:e8ba98a758d0 272 unsigned long SCL3300::getSerialNumber(void) {
sameera0824 0:e8ba98a758d0 273 //Return Device Serial number
metronix 1:52b1117c65ea 274 bool errorflag = false;
sameera0824 0:e8ba98a758d0 275 unsigned long serialNum = 0;
sameera0824 0:e8ba98a758d0 276 if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
sameera0824 0:e8ba98a758d0 277 transfer(SwtchBnk1);
sameera0824 0:e8ba98a758d0 278 if (crcerr || statuserr) errorflag = true;
sameera0824 0:e8ba98a758d0 279 transfer(RdSer1);
sameera0824 0:e8ba98a758d0 280 if (crcerr || statuserr) errorflag = true;
sameera0824 0:e8ba98a758d0 281 transfer(RdSer2);
sameera0824 0:e8ba98a758d0 282 serialNum = SCL3300_DATA;
sameera0824 0:e8ba98a758d0 283 if (crcerr || statuserr) errorflag = true;
sameera0824 0:e8ba98a758d0 284 transfer(SwtchBnk0);
sameera0824 0:e8ba98a758d0 285 serialNum = ((unsigned long)SCL3300_DATA << 16) | serialNum;
sameera0824 0:e8ba98a758d0 286 if (!setFastRead) endTransmission(); //Let go of SPI port/bus
sameera0824 0:e8ba98a758d0 287 //We wait until now to return an error code
sameera0824 0:e8ba98a758d0 288 //In this case we send a 0 since a real serial number will never be 0
sameera0824 0:e8ba98a758d0 289 if (crcerr || statuserr || errorflag) return 0;
sameera0824 0:e8ba98a758d0 290 return serialNum;
sameera0824 0:e8ba98a758d0 291 }
sameera0824 0:e8ba98a758d0 292
sameera0824 0:e8ba98a758d0 293 // Place the sensor in a Powered Down mode to save power
sameera0824 0:e8ba98a758d0 294 uint16_t SCL3300::powerDownMode(void) {
sameera0824 0:e8ba98a758d0 295 //Software power down of sensor
sameera0824 0:e8ba98a758d0 296 if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
sameera0824 0:e8ba98a758d0 297 transfer(SwtchBnk0);
sameera0824 0:e8ba98a758d0 298 transfer(SetPwrDwn);
sameera0824 0:e8ba98a758d0 299 endTransmission(); //Let go of SPI port/bus
sameera0824 0:e8ba98a758d0 300 //Since an error is non-zero, we will return 0 if there was no error
sameera0824 0:e8ba98a758d0 301 if (crcerr || statuserr) return (uint16_t)(SCL3300_CMD & 0xff); //check CRC and RS bits
sameera0824 0:e8ba98a758d0 302 return 0;
sameera0824 0:e8ba98a758d0 303 }
sameera0824 0:e8ba98a758d0 304
sameera0824 0:e8ba98a758d0 305 // Revive the sensor from a power down mode so we can start getting data again
sameera0824 0:e8ba98a758d0 306 uint16_t SCL3300::WakeMeUp(void) {
sameera0824 0:e8ba98a758d0 307 //Software Wake Up of sensor
sameera0824 0:e8ba98a758d0 308 beginTransmission(); //Set up this SPI port/bus
sameera0824 0:e8ba98a758d0 309 transfer(WakeUp);
sameera0824 0:e8ba98a758d0 310 if (!setFastRead) endTransmission(); //Let go of SPI port/bus
sameera0824 0:e8ba98a758d0 311 //Since an error is non-zero, we will return 0 if there was no error
sameera0824 0:e8ba98a758d0 312 if (crcerr || statuserr) return (uint16_t)(SCL3300_CMD & 0xff); //check CRC and RS bits
sameera0824 0:e8ba98a758d0 313 return 0;
sameera0824 0:e8ba98a758d0 314 }
sameera0824 0:e8ba98a758d0 315
sameera0824 0:e8ba98a758d0 316 // Hardware reset of the sensor electronics
sameera0824 0:e8ba98a758d0 317 uint16_t SCL3300::reset(void) {
sameera0824 0:e8ba98a758d0 318 //Software reset of sensor
sameera0824 0:e8ba98a758d0 319 //beginTransmission(); //Set up this SPI port/bus
sameera0824 0:e8ba98a758d0 320 //transfer(SwtchBnk0);
sameera0824 0:e8ba98a758d0 321 //transfer(SWreset);
sameera0824 0:e8ba98a758d0 322 //endTransmission(); //Let go of SPI port/bus
sameera0824 0:e8ba98a758d0 323 //we have to call begin() to set up the SCL3300 to the same state as before it was reset
sameera0824 0:e8ba98a758d0 324 begin(); //Re-init chip
sameera0824 0:e8ba98a758d0 325 //Since an error is non-zero, we will return 0 if there was no error
sameera0824 0:e8ba98a758d0 326 if (crcerr || statuserr) return (uint16_t)(SCL3300_CMD & 0xff); //check CRC and RS bits
sameera0824 0:e8ba98a758d0 327 return 0;
sameera0824 0:e8ba98a758d0 328 }
sameera0824 0:e8ba98a758d0 329
sameera0824 0:e8ba98a758d0 330 // Routine to get temperature in degrees Celsius
sameera0824 0:e8ba98a758d0 331 double SCL3300::getCalculatedTemperatureCelsius(void) {
sameera0824 0:e8ba98a758d0 332 // Return calculated temperature in degrees C
sameera0824 0:e8ba98a758d0 333 double Temperature = -273. + (sclData.TEMP / 18.9);
sameera0824 0:e8ba98a758d0 334 return Temperature;
sameera0824 0:e8ba98a758d0 335 }
sameera0824 0:e8ba98a758d0 336
sameera0824 0:e8ba98a758d0 337 // Routine to get temperature in degrees Farenheit
sameera0824 0:e8ba98a758d0 338 double SCL3300::getCalculatedTemperatureFarenheit(void) {
sameera0824 0:e8ba98a758d0 339 // Return calculated temperature in degrees F
sameera0824 0:e8ba98a758d0 340 double Temperature = -273. + (sclData.TEMP / 18.9);
sameera0824 0:e8ba98a758d0 341 Temperature = (Temperature * 9./5.) + 32.;
sameera0824 0:e8ba98a758d0 342 return Temperature;
sameera0824 0:e8ba98a758d0 343 }
sameera0824 0:e8ba98a758d0 344
sameera0824 0:e8ba98a758d0 345 //Convert raw angle value to degrees tilt
sameera0824 0:e8ba98a758d0 346 double SCL3300::angle(int16_t SCL3300_ANG) { //two's complement value expected
sameera0824 0:e8ba98a758d0 347 // Return Angle in degrees
sameera0824 0:e8ba98a758d0 348 double Angle = (SCL3300_ANG / 16384.) * 90.; // 16384 = 2^14
sameera0824 0:e8ba98a758d0 349 return Angle;
sameera0824 0:e8ba98a758d0 350 }
sameera0824 0:e8ba98a758d0 351
sameera0824 0:e8ba98a758d0 352 //Convert raw accelerometer value to g's of acceleration
sameera0824 0:e8ba98a758d0 353 double SCL3300::acceleration(int16_t SCL3300_ACC) { //two's complement value expected
sameera0824 0:e8ba98a758d0 354 // Return acceleration in g
sameera0824 0:e8ba98a758d0 355 if (scl3300_mode == 1) return (double)SCL3300_ACC / 6000.;
sameera0824 0:e8ba98a758d0 356 if (scl3300_mode == 2) return (double)SCL3300_ACC / 3000.;
sameera0824 0:e8ba98a758d0 357 if (scl3300_mode == 3) return (double)SCL3300_ACC / 12000.;
sameera0824 0:e8ba98a758d0 358 if (scl3300_mode == 4) return (double)SCL3300_ACC / 12000.;
sameera0824 0:e8ba98a758d0 359 return (double)SCL3300_ACC / 12000.; //Default should never be reached
sameera0824 0:e8ba98a758d0 360 }
sameera0824 0:e8ba98a758d0 361
sameera0824 0:e8ba98a758d0 362 //private functions for serial transmission
sameera0824 0:e8ba98a758d0 363 // Begin SPI bus transmission to the device
sameera0824 0:e8ba98a758d0 364 void SCL3300::beginTransmission() {
metronix 1:52b1117c65ea 365 _scl3300_csPin=0;
sameera0824 0:e8ba98a758d0 366 } //beginTransmission
sameera0824 0:e8ba98a758d0 367
sameera0824 0:e8ba98a758d0 368 // End SPI bus transmission to the device
sameera0824 0:e8ba98a758d0 369 void SCL3300::endTransmission() {
sameera0824 0:e8ba98a758d0 370 // take the chip/slave select high to de-select:
metronix 1:52b1117c65ea 371 _scl3300_csPin=1;
metronix 1:52b1117c65ea 372 timer2.start();
metronix 1:52b1117c65ea 373 unsigned long startmillis = timer2.read_ms();
metronix 1:52b1117c65ea 374 while (timer2.read_ms() - startmillis < 1) ; //wait a bit
metronix 1:52b1117c65ea 375 timer2.stop();
sameera0824 0:e8ba98a758d0 376 } //endTransmission
sameera0824 0:e8ba98a758d0 377
sameera0824 0:e8ba98a758d0 378 //Initialize the Arduino SPI library for the SCL3300 hardware
sameera0824 0:e8ba98a758d0 379 void SCL3300::initSPI() {
sameera0824 0:e8ba98a758d0 380 //Initialize the Arduino SPI library for the SCL3300 hardware
metronix 1:52b1117c65ea 381 _spi.frequency(_transfer_sck);
sameera0824 0:e8ba98a758d0 382 // Maximum SPI frequency is 2 MHz - 4 MHz to achieve the best performance
sameera0824 0:e8ba98a758d0 383 // initialize the chip select pin:
metronix 1:52b1117c65ea 384 _scl3300_csPin=1;
sameera0824 0:e8ba98a758d0 385 // Data is read and written MSb first.
sameera0824 0:e8ba98a758d0 386 // Data is captured on rising edge of clock (CPHA = 0)
sameera0824 0:e8ba98a758d0 387 // Data is propagated on the falling edge (MISO line) of the SCK. (CPOL = 0)
sameera0824 0:e8ba98a758d0 388 }
sameera0824 0:e8ba98a758d0 389
sameera0824 0:e8ba98a758d0 390 // The following is taken directly from the Murata SCL3300 datasheet
sameera0824 0:e8ba98a758d0 391 // Calculate CRC for 24 MSB's of the 32 bit dword
sameera0824 0:e8ba98a758d0 392 // (8 LSB's are the CRC field and are not included in CRC calculation)
sameera0824 0:e8ba98a758d0 393 uint8_t SCL3300::CalculateCRC(uint32_t Data)
sameera0824 0:e8ba98a758d0 394 {
sameera0824 0:e8ba98a758d0 395 uint8_t BitIndex;
sameera0824 0:e8ba98a758d0 396 uint8_t BitValue;
sameera0824 0:e8ba98a758d0 397 uint8_t SCL3300_CRC;
sameera0824 0:e8ba98a758d0 398
sameera0824 0:e8ba98a758d0 399 SCL3300_CRC = 0xFF;
sameera0824 0:e8ba98a758d0 400 for (BitIndex = 31; BitIndex > 7; BitIndex--) {
sameera0824 0:e8ba98a758d0 401 BitValue = (uint8_t)((Data >> BitIndex) & 0x01);
sameera0824 0:e8ba98a758d0 402 SCL3300_CRC = CRC8(BitValue, SCL3300_CRC);
sameera0824 0:e8ba98a758d0 403 }
sameera0824 0:e8ba98a758d0 404 SCL3300_CRC = (uint8_t)~SCL3300_CRC;
sameera0824 0:e8ba98a758d0 405 return SCL3300_CRC;
sameera0824 0:e8ba98a758d0 406 }
sameera0824 0:e8ba98a758d0 407 uint8_t SCL3300::CRC8(uint8_t BitValue, uint8_t SCL3300_CRC)
sameera0824 0:e8ba98a758d0 408 {
sameera0824 0:e8ba98a758d0 409 uint8_t Temp;
sameera0824 0:e8ba98a758d0 410 Temp = (uint8_t)(SCL3300_CRC & 0x80);
sameera0824 0:e8ba98a758d0 411 if (BitValue == 0x01) {
sameera0824 0:e8ba98a758d0 412 Temp ^= 0x80;
sameera0824 0:e8ba98a758d0 413 }
sameera0824 0:e8ba98a758d0 414 SCL3300_CRC <<= 1;
sameera0824 0:e8ba98a758d0 415 if (Temp > 0) {
sameera0824 0:e8ba98a758d0 416 SCL3300_CRC ^= 0x1D;
sameera0824 0:e8ba98a758d0 417 }
sameera0824 0:e8ba98a758d0 418 return SCL3300_CRC;
sameera0824 0:e8ba98a758d0 419 }
sameera0824 0:e8ba98a758d0 420
sameera0824 0:e8ba98a758d0 421 // Routine to transfer a 32-bit integer to the SCL3300, and return the 32-bit data read
sameera0824 0:e8ba98a758d0 422 unsigned long SCL3300::transfer(unsigned long value) {
sameera0824 0:e8ba98a758d0 423 FourByte dataorig;
sameera0824 0:e8ba98a758d0 424 unsigned long startmicros;
sameera0824 0:e8ba98a758d0 425
sameera0824 0:e8ba98a758d0 426 dataorig.bit32 = value; //Allow 32 bit value to be sent 8 bits at a time
sameera0824 0:e8ba98a758d0 427 #ifdef debug_scl3300
metronix 1:52b1117c65ea 428 _spi.print(dataorig.bit32, HEX);
metronix 1:52b1117c65ea 429 _spi.print(" ");
sameera0824 0:e8ba98a758d0 430 for (int j = 3; j >= 0; j--) {
metronix 1:52b1117c65ea 431 _spi.print(dataorig.bit8[j], HEX);
metronix 1:52b1117c65ea 432 _spi.print(" ");
sameera0824 0:e8ba98a758d0 433 }
sameera0824 0:e8ba98a758d0 434 #endif
sameera0824 0:e8ba98a758d0 435 //Must allow at least 10 uSec between SPI transfers
sameera0824 0:e8ba98a758d0 436 //The datasheet shows the CS line must be high during this time
metronix 1:52b1117c65ea 437 timer1.start();
metronix 1:52b1117c65ea 438 if (!setFastRead) startmicros = timer1.read_us();
sameera0824 0:e8ba98a758d0 439 //while ((micros() - startmicros < 10) && (micros() > 10)) ;
metronix 1:52b1117c65ea 440 if (!setFastRead) while ((timer1.read_us() - startmicros < 10)) ;
metronix 1:52b1117c65ea 441 timer1.stop();
metronix 1:52b1117c65ea 442 _scl3300_csPin=0; //Now chip select can be enabled for the full 32 bit xfer
sameera0824 0:e8ba98a758d0 443 SCL3300_DATA = 0;
sameera0824 0:e8ba98a758d0 444 for (int i = 3; i >= 0; i--) { //Xfers are done MSB first
metronix 1:52b1117c65ea 445 dataorig.bit8[i] = transfer(dataorig.bit8[i]);
sameera0824 0:e8ba98a758d0 446 }
sameera0824 0:e8ba98a758d0 447 SCL3300_DATA = dataorig.bit8[1] + (dataorig.bit8[2] << 8);
sameera0824 0:e8ba98a758d0 448 SCL3300_CRC = dataorig.bit8[0];
sameera0824 0:e8ba98a758d0 449 SCL3300_CMD = dataorig.bit8[3];
metronix 1:52b1117c65ea 450 _scl3300_csPin=1; //And we are done
sameera0824 0:e8ba98a758d0 451 #ifdef debug_scl3300
sameera0824 0:e8ba98a758d0 452 for (int i = 3; i >= 0; i--) {
metronix 1:52b1117c65ea 453 _spi.print(" ");
metronix 1:52b1117c65ea 454 _spi.print(dataorig.bit8[i], HEX);
sameera0824 0:e8ba98a758d0 455 }
metronix 1:52b1117c65ea 456 _spi.print(" ");
sameera0824 0:e8ba98a758d0 457 #endif
sameera0824 0:e8ba98a758d0 458 if (SCL3300_CRC == CalculateCRC(dataorig.bit32))
sameera0824 0:e8ba98a758d0 459 crcerr = false;
sameera0824 0:e8ba98a758d0 460 else
sameera0824 0:e8ba98a758d0 461 crcerr = true;
sameera0824 0:e8ba98a758d0 462 //check RS bits
sameera0824 0:e8ba98a758d0 463 if ((SCL3300_CMD & 0x03) == 0x01)
sameera0824 0:e8ba98a758d0 464 statuserr = false;
sameera0824 0:e8ba98a758d0 465 else
sameera0824 0:e8ba98a758d0 466 statuserr = true;
sameera0824 0:e8ba98a758d0 467 #ifdef debug_scl3300
metronix 1:52b1117c65ea 468 _spi.print((SCL3300_CMD & 0x03));
metronix 1:52b1117c65ea 469 _spi.print(" ");
metronix 1:52b1117c65ea 470 _spi.print(SCL3300_DATA, HEX);
metronix 1:52b1117c65ea 471 _spi.print(" ");
metronix 1:52b1117c65ea 472 _spi.print(SCL3300_CRC, HEX);
metronix 1:52b1117c65ea 473 _spi.print(" ");
metronix 1:52b1117c65ea 474 _spi.print(CalculateCRC(dataorig.bit32), HEX);
metronix 1:52b1117c65ea 475 _spi.print(" ");
metronix 1:52b1117c65ea 476 _spi.println(crcerr);
sameera0824 0:e8ba98a758d0 477 #endif
sameera0824 0:e8ba98a758d0 478 return dataorig.bit32;
sameera0824 0:e8ba98a758d0 479 }