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

Committer:
sameera0824
Date:
Mon Aug 15 19:17:10 2022 +0000
Revision:
0:e8ba98a758d0
Initial commit

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