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

Files at this revision

API Documentation at this revision

Comitter:
sameera0824
Date:
Mon Aug 15 19:17:10 2022 +0000
Commit message:
Initial commit

Changed in this revision

SCL3300.cpp Show annotated file Show diff for this revision Revisions of this file
SCL3300.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r e8ba98a758d0 SCL3300.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SCL3300.cpp	Mon Aug 15 19:17:10 2022 +0000
@@ -0,0 +1,469 @@
+/******************************************************************************
+SCL3300.cpp
+SCL3300 Arduino Driver
+David Armstrong
+Version 3.3.0 - September 13, 2021
+https://github.com/DavidArmstrong/SCL3300
+
+Resources:
+Uses SPI.h for SPI operation
+
+Development environment specifics:
+Arduino IDE 1.8.15
+
+This code is released under the [MIT License](http://opensource.org/licenses/MIT).
+Please review the LICENSE.md file included with this example.
+Distributed as-is; no warranty is given.
+
+******************************************************************************/
+
+// include this library's description file
+#include "SCL3300.h"
+
+// Public Methods //////////////////////////////////////////////////////////
+// Set the sensor mode to the number provided as modeNum.
+boolean SCL3300::setMode(int modeNum) {
+  // Set Sensor mode - If not called, the default is mode 4, as set in header file
+  // Only allowed values are: 1,2,3,4
+  if (modeNum > 0 && modeNum < 5) {
+    scl3300_mode = modeNum;
+    if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
+    transfer(modeCMD[scl3300_mode]); //Set mode on hardware
+    if (!setFastRead) endTransmission(); //Let go of SPI port/bus
+    if (crcerr || statuserr) {
+      reset(); //Reset chip to fix the error state
+      return false;  //Let the caller know something went wrong
+    } else return true; // Valid value, and chip was set to that mode
+  } else
+    return false; // Invalid value
+}
+
+// Current Version of begin() to initialize the library and the SCL3300
+boolean SCL3300::begin(void) {
+  //This is the updated Version 3 begin function
+  // Determine if we need to set up to use the default SPI interface, or some other one
+  if (_spiPort == nullptr) _spiPort = &SPI;
+  
+  //Wait the required 1 ms before initializing the SCL3300 inclinomenter
+  unsigned long startmillis = millis();
+  while (millis() - startmillis < 1) ;
+  
+  initSPI();    // Initialize SPI Library
+  if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
+  //Write SW Reset command
+  transfer(SwtchBnk0);
+  transfer(SWreset);
+  startmillis = millis();
+  while (millis() - startmillis < 1) ;
+  //Set measurement mode
+  transfer(modeCMD[scl3300_mode]); //Set mode on hardware
+  //We're good, so Enable angle outputs
+  transfer(EnaAngOut);
+  //The first response after reset is undefined and shall be discarded
+  //wait 5 ms to stablize
+  startmillis = millis();
+  while (millis() - startmillis < 100) ;
+
+  //Read Status to clear the status summary
+  transfer(RdStatSum);
+  transfer(RdStatSum); //Again, due to off-response protocol used
+  transfer(RdStatSum); //And now we can get the real status
+  
+  //Read the WHOAMI register
+  transfer(RdWHOAMI);
+  //And again
+  transfer(RdWHOAMI);
+  if (!setFastRead) endTransmission(); //Let go of SPI port/bus
+  //We now wait until the end of begin() to report if an error occurred
+  if (crcerr || statuserr) return false;
+  // Once everything is initialized, return a known expected value
+  // The WHOAMI command should give an 8 bit value of 0xc1
+  return (SCL3300_DATA == 0xc1); //Let the caller know if this worked
+}
+
+// Set up the SPI communication with the SCL3300 with provided Chip Select pin number, and provided SPI port
+boolean SCL3300::begin(SPIClass &spiPort, uint8_t csPin) {
+  scl3300_csPin = csPin;
+  _spiPort = &spiPort; //Grab the port the user wants us to use
+  return begin();
+} // begin
+
+// Set up the SPI communication with the SCL3300 with provided Chip Select pin number
+boolean SCL3300::begin(uint8_t csPin) {
+  scl3300_csPin = csPin;
+  _spiPort = &SPI; // With this call, we do the default SPI interface
+  return begin();
+} // begin
+
+//Check to validate that the sensor is still reachable and ready to provide data
+boolean SCL3300::isConnected() {
+  if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
+  transfer(SwtchBnk0);
+  //Read the WHOAMI register
+  transfer(RdWHOAMI);
+  //And again
+  transfer(RdWHOAMI);
+  if (!setFastRead) endTransmission(); //Let go of SPI port/bus
+  if (crcerr || statuserr) return false;
+  // Once everything is initialized, return a known expected value
+  // The WHOAMI command should give an 8 bit value of 0xc1
+  return (SCL3300_DATA == 0xc1); //Let the caller know if this worked
+}
+
+//Read all the sensor data together to keep it consistent
+//This is required according to the datasheet
+boolean SCL3300::available(void) {
+  //Version 3 of this function
+  boolean errorflag = false;
+  //Read all Sensor Data, as per Datasheet requirements
+  if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
+  transfer(SwtchBnk0);
+  transfer(RdAccX);
+  if (crcerr || statuserr) errorflag = true;
+  transfer(RdAccY);
+  if (crcerr || statuserr) errorflag = true;
+  sclData.AccX = SCL3300_DATA;
+  transfer(RdAccZ);
+  if (crcerr || statuserr) errorflag = true;
+  sclData.AccY = SCL3300_DATA;
+  transfer(RdSTO);
+  if (crcerr || statuserr) errorflag = true;
+  sclData.AccZ = SCL3300_DATA;
+  transfer(RdTemp);
+  if (crcerr || statuserr) errorflag = true;
+  sclData.STO = SCL3300_DATA;
+  transfer(RdAngX);
+  if (crcerr || statuserr) errorflag = true;
+  sclData.TEMP = SCL3300_DATA;
+  transfer(RdAngY);
+  if (crcerr || statuserr) errorflag = true;
+  sclData.AngX = SCL3300_DATA;
+  transfer(RdAngZ);
+  if (crcerr || statuserr) errorflag = true;
+  sclData.AngY = SCL3300_DATA;
+  transfer(RdStatSum);
+  if (crcerr || statuserr) errorflag = true;
+  sclData.AngZ = SCL3300_DATA;
+  transfer(RdWHOAMI);
+  if (crcerr || statuserr) errorflag = true;
+  sclData.StatusSum = SCL3300_DATA;
+  transfer(RdWHOAMI);
+  if (crcerr || statuserr) errorflag = true;
+  sclData.WHOAMI = SCL3300_DATA;
+  if (!setFastRead) endTransmission(); //Let go of SPI port/bus
+  if (errorflag) return false; //Inform caller that something went wrong
+  // The WHOAMI command should give an 8 bit value of 0xc1
+  return (SCL3300_DATA == 0xc1); //Let the caller know this worked
+}
+
+/* Set SCL3300 library into Fast Read Mode
+ * Warning: Using Fast Read Mode in the library works by keeping the
+ *          SPI connection continuously open.  This may or may not affect
+ *          the behavior of other hardware interactions, depending on the
+ *          sketch design.  Fast Read Mode is considered an advanced use case,
+ *          and not recommended for the beginner.
+*/
+void SCL3300::setFastReadMode() {
+  setFastRead = true;
+  beginTransmission(); //Set up this SPI port/bus
+  begin(); //Re-init chip
+}
+
+/* Stop Fast Read Mode
+ * Warning: Using Fast Read Mode in the library works by keeping the
+ *          SPI connection continuously open.  This may or may not affect
+ *          the behavior of other hardware interactions, depending on the
+ *          sketch design.  Fast Read Mode is considered an advanced use case,
+ *          and not recommended for the beginner.
+*/
+void SCL3300::stopFastReadMode() {
+  setFastRead = false;
+  endTransmission();  //Close connection to SPI port/bus
+  begin(); //Re-init chip
+}
+
+//Return the calculated X axis tilt angle in degrees
+double SCL3300::getCalculatedAngleX() {
+  double tempX = angle(sclData.AngX);
+  if (tempX < 0.) tempX += 360.;
+  return tempX;
+}
+
+//Return the calculated Y axis tilt angle in degrees
+double SCL3300::getCalculatedAngleY() {
+  double tempY = angle(sclData.AngY);
+  if (tempY < 0.) tempY += 360.;
+  return tempY;
+}
+
+//Return the calculated Z axis tilt angle in degrees
+double SCL3300::getCalculatedAngleZ() {
+  double tempZ = angle(sclData.AngZ);
+  if (tempZ < 0.) tempZ += 360.;
+  return tempZ;
+}
+
+//Return the calculated X axis offset tilt angle in degrees
+double SCL3300::getTiltLevelOffsetAngleX() {
+  return angle(sclData.AngX);
+}
+
+//Return the calculated Y axis offset tilt angle in degrees
+double SCL3300::getTiltLevelOffsetAngleY() {
+  return angle(sclData.AngY);
+}
+
+//Return the calculated Z axis offset tilt angle in degrees
+double SCL3300::getTiltLevelOffsetAngleZ() {
+  return angle(sclData.AngZ);
+}
+
+//Return the calculated X axis accelerometer value in units of 'g'
+double SCL3300::getCalculatedAccelerometerX(void) {
+  return acceleration(sclData.AccX);
+}
+
+//Return the calculated Y axis accelerometer value in units of 'g'
+double SCL3300::getCalculatedAccelerometerY(void) {
+  return acceleration(sclData.AccY);
+}
+
+//Return the calculated Z axis accelerometer value in units of 'g'
+double SCL3300::getCalculatedAccelerometerZ(void) {
+  return acceleration(sclData.AccZ);
+}
+
+//Return value of Error Flag 1 register
+uint16_t SCL3300::getErrFlag1(void) {
+  if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
+  transfer(SwtchBnk0);
+  transfer(RdErrFlg1);
+  transfer(RdErrFlg1);
+  if (!setFastRead) endTransmission(); //Let go of SPI port/bus
+  //Since we are fetching the Error Flag 1 value, we want to return what we got
+  //to the caller, regardless of whether or not there was an error
+  //if (crcerr || statuserr) return ((uint16_t)(SCL3300_CMD) & 0xff); //check CRC and RS bits
+  return SCL3300_DATA;
+}
+
+//Return value of Error Flag 2 register
+uint16_t SCL3300::getErrFlag2(void) {
+  if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
+  transfer(SwtchBnk0);
+  transfer(RdErrFlg2);
+  transfer(RdErrFlg2);
+  if (!setFastRead) endTransmission(); //Let go of SPI port/bus
+  //Since we are fetching the Error Flag 2 value, we want to return what we got
+  //to the caller, regardless of whether or not there was an error
+  //if (crcerr || statuserr) return ((uint16_t)(SCL3300_CMD) & 0xff); //check CRC and RS bits
+  return SCL3300_DATA;
+}
+
+// Read the sensor Serial Number as created by the manufacturer
+unsigned long SCL3300::getSerialNumber(void) {
+  //Return Device Serial number
+  boolean errorflag = false;
+  unsigned long serialNum = 0;
+  if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
+  transfer(SwtchBnk1);
+  if (crcerr || statuserr) errorflag = true;
+  transfer(RdSer1);
+  if (crcerr || statuserr) errorflag = true;
+  transfer(RdSer2);
+  serialNum = SCL3300_DATA;
+  if (crcerr || statuserr) errorflag = true;
+  transfer(SwtchBnk0);
+  serialNum = ((unsigned long)SCL3300_DATA << 16) | serialNum;
+  if (!setFastRead) endTransmission(); //Let go of SPI port/bus
+  //We wait until now to return an error code
+  //In this case we send a 0 since a real serial number will never be 0
+  if (crcerr || statuserr || errorflag) return 0;
+  return serialNum;
+}
+
+// Place the sensor in a Powered Down mode to save power
+uint16_t SCL3300::powerDownMode(void) {
+  //Software power down of sensor
+  if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
+  transfer(SwtchBnk0);
+  transfer(SetPwrDwn);
+  endTransmission(); //Let go of SPI port/bus
+  //Since an error is non-zero, we will return 0 if there was no error
+  if (crcerr || statuserr) return (uint16_t)(SCL3300_CMD & 0xff); //check CRC and RS bits
+  return 0;
+}
+
+// Revive the sensor from a power down mode so we can start getting data again
+uint16_t SCL3300::WakeMeUp(void) {
+  //Software Wake Up of sensor
+  beginTransmission(); //Set up this SPI port/bus
+  transfer(WakeUp);
+  if (!setFastRead) endTransmission(); //Let go of SPI port/bus
+  //Since an error is non-zero, we will return 0 if there was no error
+  if (crcerr || statuserr) return (uint16_t)(SCL3300_CMD & 0xff); //check CRC and RS bits
+  return 0;
+}
+
+// Hardware reset of the sensor electronics
+uint16_t SCL3300::reset(void) {
+  //Software reset of sensor
+  //beginTransmission(); //Set up this SPI port/bus
+  //transfer(SwtchBnk0);
+  //transfer(SWreset);
+  //endTransmission(); //Let go of SPI port/bus
+  //we have to call begin() to set up the SCL3300 to the same state as before it was reset
+  begin(); //Re-init chip
+  //Since an error is non-zero, we will return 0 if there was no error
+  if (crcerr || statuserr) return (uint16_t)(SCL3300_CMD & 0xff); //check CRC and RS bits
+  return 0;
+}
+
+// Routine to get temperature in degrees Celsius
+double SCL3300::getCalculatedTemperatureCelsius(void) {
+  // Return calculated temperature in degrees C
+  double Temperature = -273. + (sclData.TEMP / 18.9);
+  return Temperature;
+}
+
+// Routine to get temperature in degrees Farenheit
+double SCL3300::getCalculatedTemperatureFarenheit(void) {
+  // Return calculated temperature in degrees F
+  double Temperature = -273. + (sclData.TEMP / 18.9);
+  Temperature = (Temperature * 9./5.) + 32.;
+  return Temperature;
+}
+
+//Convert raw angle value to degrees tilt
+double SCL3300::angle(int16_t SCL3300_ANG) { //two's complement value expected
+  // Return Angle in degrees
+  double Angle = (SCL3300_ANG / 16384.) * 90.; // 16384 = 2^14
+  return Angle;
+}
+ 
+ //Convert raw accelerometer value to g's of acceleration
+double SCL3300::acceleration(int16_t SCL3300_ACC) { //two's complement value expected
+  // Return acceleration in g
+  if (scl3300_mode == 1) return (double)SCL3300_ACC / 6000.;
+  if (scl3300_mode == 2) return (double)SCL3300_ACC / 3000.;
+  if (scl3300_mode == 3) return (double)SCL3300_ACC / 12000.;
+  if (scl3300_mode == 4) return (double)SCL3300_ACC / 12000.;
+  return (double)SCL3300_ACC / 12000.; //Default should never be reached
+}
+
+//private functions for serial transmission
+// Begin SPI bus transmission to the device
+void SCL3300::beginTransmission() {
+  _spiPort->beginTransaction(spiSettings);
+} //beginTransmission
+
+// End SPI bus transmission to the device
+void SCL3300::endTransmission() {
+  // take the chip/slave select high to de-select:
+  digitalWrite(scl3300_csPin, HIGH);
+  _spiPort->endTransaction();
+  unsigned long startmillis = millis();
+  while (millis() - startmillis < 1) ; //wait a bit
+} //endTransmission
+
+//Initialize the Arduino SPI library for the SCL3300 hardware
+void SCL3300::initSPI() {
+  //Initialize the Arduino SPI library for the SCL3300 hardware
+  _spiPort->begin();
+  // Maximum SPI frequency is 2 MHz - 4 MHz to achieve the best performance
+  // initialize the chip select pin:
+  pinMode(scl3300_csPin, OUTPUT);
+  digitalWrite(scl3300_csPin, HIGH);
+  // Data is read and written MSb first.
+  // Data is captured on rising edge of clock (CPHA = 0)
+  // Data is propagated on the falling edge (MISO line) of the SCK. (CPOL = 0)
+}
+
+// The following is taken directly from the Murata SCL3300 datasheet
+// Calculate CRC for 24 MSB's of the 32 bit dword
+// (8 LSB's are the CRC field and are not included in CRC calculation)
+uint8_t SCL3300::CalculateCRC(uint32_t Data)
+{
+uint8_t BitIndex;
+uint8_t BitValue;
+uint8_t SCL3300_CRC;
+
+SCL3300_CRC = 0xFF;
+for (BitIndex = 31; BitIndex > 7; BitIndex--) {
+  BitValue = (uint8_t)((Data >> BitIndex) & 0x01);
+  SCL3300_CRC = CRC8(BitValue, SCL3300_CRC);
+}
+SCL3300_CRC = (uint8_t)~SCL3300_CRC;
+return SCL3300_CRC;
+}
+uint8_t SCL3300::CRC8(uint8_t BitValue, uint8_t SCL3300_CRC)
+{
+  uint8_t Temp;
+  Temp = (uint8_t)(SCL3300_CRC & 0x80);
+  if (BitValue == 0x01) {
+    Temp ^= 0x80;
+  }
+  SCL3300_CRC <<= 1;
+  if (Temp > 0) {
+    SCL3300_CRC ^= 0x1D;
+  }
+  return SCL3300_CRC;
+}
+
+// Routine to transfer a 32-bit integer to the SCL3300, and return the 32-bit data read
+unsigned long SCL3300::transfer(unsigned long value) {
+  FourByte dataorig;
+  unsigned long startmicros;
+  
+  dataorig.bit32 = value; //Allow 32 bit value to be sent 8 bits at a time
+  #ifdef debug_scl3300
+  Serial_SCL.print(dataorig.bit32, HEX);
+  Serial_SCL.print(" ");
+  for (int j = 3; j >= 0; j--) {
+    Serial_SCL.print(dataorig.bit8[j], HEX);
+    Serial_SCL.print(" ");
+  }
+  #endif
+  //Must allow at least 10 uSec between SPI transfers
+  //The datasheet shows the CS line must be high during this time
+  if (!setFastRead) startmicros = micros();
+  //while ((micros() - startmicros < 10) && (micros() > 10)) ;
+  if (!setFastRead) while ((micros() - startmicros < 10)) ;
+  
+  digitalWrite(scl3300_csPin, LOW); //Now chip select can be enabled for the full 32 bit xfer
+  SCL3300_DATA = 0;
+  for (int i = 3; i >= 0; i--) { //Xfers are done MSB first
+    dataorig.bit8[i] = _spiPort->transfer(dataorig.bit8[i]);
+  }
+  SCL3300_DATA = dataorig.bit8[1] + (dataorig.bit8[2] << 8);
+  SCL3300_CRC = dataorig.bit8[0];
+  SCL3300_CMD = dataorig.bit8[3];
+  digitalWrite(scl3300_csPin, HIGH); //And we are done
+  #ifdef debug_scl3300
+  for (int i = 3; i >= 0; i--) {
+    Serial_SCL.print(" ");
+    Serial_SCL.print(dataorig.bit8[i], HEX);
+  }
+  Serial_SCL.print("  ");
+  #endif
+  if (SCL3300_CRC == CalculateCRC(dataorig.bit32))
+    crcerr = false;
+  else
+    crcerr = true;
+  //check RS bits
+  if ((SCL3300_CMD & 0x03) == 0x01)
+    statuserr = false;
+  else
+    statuserr = true;
+  #ifdef debug_scl3300
+  Serial_SCL.print((SCL3300_CMD & 0x03));
+  Serial_SCL.print(" ");
+  Serial_SCL.print(SCL3300_DATA, HEX);
+  Serial_SCL.print(" ");
+  Serial_SCL.print(SCL3300_CRC, HEX);
+  Serial_SCL.print(" ");
+  Serial_SCL.print(CalculateCRC(dataorig.bit32), HEX);
+  Serial_SCL.print(" ");
+  Serial_SCL.println(crcerr);
+  #endif
+  return dataorig.bit32;
+}
diff -r 000000000000 -r e8ba98a758d0 SCL3300.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SCL3300.h	Mon Aug 15 19:17:10 2022 +0000
@@ -0,0 +1,164 @@
+/******************************************************************************
+SCL3300.h
+SCL3300 Arduino Library Header File
+David Armstrong
+Version 3.2.0 - September 3, 2021
+https://github.com/DavidArmstrong/SCL3300
+
+Resources:
+Uses SPI.h for SPI operation
+
+Development environment specifics:
+Arduino IDE 1.8.9, 1.8.11, 1.8.12, 1.8.13, 1.8.15
+
+This code is released under the [MIT License](http://opensource.org/licenses/MIT).
+Please review the LICENSE.md file included with this example.
+Distributed as-is; no warranty is given.
+
+This file prototypes the SCL3300 class, as implemented in SCL3300.cpp
+
+******************************************************************************/
+
+// ensure this library description is only included once
+#ifndef __SCL3300_h
+#define __SCL3300_h
+
+// Uncomment the following line for debugging output
+//#define debug_scl3300
+
+// Need the following define for SAMD processors
+#if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL)
+  #define Serial_SCL SERIAL_PORT_USBVIRTUAL
+#else
+  #define Serial_SCL Serial
+#endif
+
+#include <stdint.h>
+
+#if defined(ARDUINO) && ARDUINO >= 100
+  #include "Arduino.h"
+#else
+  #include "WProgram.h"
+#endif
+
+#include <SPI.h>  // SPI library is used for...SPI.
+
+#ifndef SCL3300_SPI_CLOCK
+#ifdef ARDUINO_ARCH_ESP32
+#define SCL3300_SPI_CLOCK 4000000
+#else
+#define SCL3300_SPI_CLOCK 4000000
+#endif
+#endif
+
+#ifndef SCL3300_SPI_MODE
+#define SCL3300_SPI_MODE SPI_MODE0
+#endif
+
+//Define allowed commands to SCL3300 inclinometer
+#define RdAccX      0x040000f7
+#define RdAccY      0x080000fd
+#define RdAccZ      0x0c0000fb
+#define RdSTO       0x100000e9
+#define EnaAngOut   0xb0001f6f
+#define RdAngX      0x240000c7
+#define RdAngY      0x280000cd
+#define RdAngZ      0x2c0000cb
+#define RdTemp      0x140000ef
+#define RdStatSum   0x180000e5
+#define RdErrFlg1   0x1c0000e3
+#define RdErrFlg2   0x200000c1
+#define RdCMD       0x340000df
+#define ChgMode1    0xb400001f
+#define ChgMode2    0xb4000102
+#define ChgMode3    0xb4000225
+#define ChgMode4    0xb4000338
+#define SetPwrDwn   0xb400046b
+#define WakeUp      0xb400001f
+#define SWreset     0xb4002098
+#define RdWHOAMI    0x40000091
+#define RdSer1      0x640000a7
+#define RdSer2      0x680000AD
+#define RdCurBank   0x7c0000b3
+#define SwtchBnk0   0xfc000073
+#define SwtchBnk1   0xfc00016e
+
+// Structure to hold raw sensor data
+// We need to populate all this every time we read a set of data
+struct SCL3300data {
+  public:
+    int16_t AccX;
+    int16_t AccY;
+    int16_t AccZ;
+    int16_t STO;
+    int16_t TEMP;
+    int16_t AngX;
+    int16_t AngY;
+    int16_t AngZ;
+    uint16_t StatusSum;
+    uint16_t WHOAMI;
+};
+
+// SCL3300 library interface description
+class SCL3300 {
+  // user-accessible "public" interface
+  public:
+    SPISettings spiSettings{SCL3300_SPI_CLOCK, MSBFIRST, SCL3300_SPI_MODE};
+    
+    SCL3300data sclData;
+    boolean setMode(int mode);
+    boolean begin(void);
+    boolean begin(uint8_t csPin);
+    boolean begin(SPIClass &spiPort, uint8_t csPin);
+    //Functions to retrieve sensor data
+    boolean isConnected();
+    boolean available(void);
+    void setFastReadMode();
+    void stopFastReadMode();
+    double getCalculatedAngleX(void);
+    double getCalculatedAngleY(void);
+    double getCalculatedAngleZ(void);
+    double getTiltLevelOffsetAngleX(void);
+    double getTiltLevelOffsetAngleY(void);
+    double getTiltLevelOffsetAngleZ(void);
+    double getCalculatedAccelerometerX(void);
+    double getCalculatedAccelerometerY(void);
+    double getCalculatedAccelerometerZ(void);
+    uint16_t getErrFlag1(void);
+    uint16_t getErrFlag2(void);
+    unsigned long getSerialNumber(void);
+    double getCalculatedTemperatureCelsius(void);
+    double getCalculatedTemperatureFarenheit(void);
+    double angle(int16_t SCL3300_ANG); //two's complement value expected
+    double acceleration(int16_t SCL3300_ACC);
+    bool crcerr, statuserr;
+    uint16_t powerDownMode(void);
+    uint16_t WakeMeUp(void);
+    uint16_t reset(void);
+    
+  // library-accessible "private" interface
+  private:
+    SPIClass *_spiPort = NULL;  //The generic connection to user's chosen spi hardware
+
+    uint8_t scl3300_csPin = 10; // Default SPI chip select pin
+    uint8_t scl3300_mode = 4; // Default inclinometer mode
+    uint8_t SCL3300_CMD, SCL3300_CRC;
+    uint16_t SCL3300_DATA;
+    double Temperature, X_angle, Y_angle, Z_angle;
+    bool setFastRead = false;
+    
+    void initSPI();
+    void beginTransmission();
+    void endTransmission();
+    uint8_t CalculateCRC(uint32_t Data);
+    uint8_t CRC8(uint8_t BitValue, uint8_t SCL3300_CRC);
+    unsigned long transfer(unsigned long value);
+
+    union FourByte {
+      unsigned long bit32;
+      unsigned int bit16[2];
+      unsigned char bit8[4];
+    };
+    unsigned long modeCMD[5]  = { 0, ChgMode1, ChgMode2, ChgMode3, ChgMode4 };
+};
+#endif