├── LICENSE
├── README.md
├── examples
├── Example10_Mode1
│ └── Example10_Mode1.ino
├── Example1_BasicTiltLevelOffset
│ └── Example1_BasicTiltLevelOffset.ino
├── Example2_BasicTiltReading
│ └── Example2_BasicTiltReading.ino
├── Example3_BasicAccelerometerReading
│ └── Example3_BasicAccelerometerReading.ino
├── Example4_BasicTemperatureReading
│ └── Example4_BasicTemperatureReading.ino
├── Example5_RawDataReading
│ └── Example5_RawDataReading.ino
├── Example6_FastReadMode
│ └── Example6_FastReadMode.ino
├── Example7_FastReadModeContinuous
│ └── Example7_FastReadModeContinuous.ino
├── Example8_TwoSensors
│ └── Example8_TwoSensors.ino
└── Example9_AlternateSPI
│ └── Example9_AlternateSPI.ino
├── keywords.txt
├── library.properties
└── src
├── SCL3300.cpp
└── SCL3300.h
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Dave Armstrong
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SCL3300
2 |
3 |
4 | Arduino Library for Murata SCL3300 Inclinometer
5 |
6 | Version 3.3.1 - July 4, 2022
7 | Note: This is not a bug fix, nor a new feature release. The only change is adding the new Example10_Mode1 sketch, which is useful for more general tilt angle measurement needs.
8 |
9 | By David Armstrong
10 | https://github.com/DavidArmstrong/Arduino-SCL3300
11 | See MIT LICENSE.md file
12 |
13 |
14 | The Murata SCL3300 inclinometer sensor is a 3.3 volt device used to measure tilt in three axes simultaneously.
15 |
16 | Datasheet: https://www.murata.com/-/media/webrenewal/products/sensor/pdf/datasheet/datasheet_scl3300-d01.ashx?la=en-us
17 |
18 | Evaluation Board: https://www.murata.com/-/media/webrenewal/products/sensor/pdf/specification/pcbspec_scx3300.ashx?la=en-us
19 |
20 | Notes:
21 | 1) The SCL3300 inclinometer will require a bidrectional level shifter to interface the SPI pins to 5 volt devices, such as the Arduino Uno.
22 | 2) A pull-up resistor may be required on the Chip/Slave Select line of the SCL3300. A typical resistor value of 4.7k ohms should connect this pin to +3.3 volts.
23 | 3) Be sure to connect the SCL3300 DVIO pin to +3.3 volts as well. This pin powers the digital pins.
24 | 4) There is a small, but significant, library change starting with Version 3.0.0. This requires a one-line addition to any older sketches when using this updated SCL3300 library. All the example sketches have been updated to include the addtional code. (The backwards incompatibility is due to the improved error detection and handling design.)
25 |
26 | For an Arduino Uno, the default SPI pins are as follows:
27 | * SCK - Digital Pin 13
28 | * SDO - Digital Pin 12 (MISO)
29 | * SDI - Digital Pin 11 (MOSI)
30 | * CS - Digital Pin 10 (SS)
31 |
32 | For a SAMD-type Arduino, such as the Sparkfun Redboard Turbo or Arduino Zero, the default SPI pins are only available on the ICSP connector:
33 | * pin 22 (MISO)
34 | * pin 23 (MOSI)
35 | * pin 24 (SCK)
36 | * Chip/Slave Select uses digital Pin 10 as the default.
37 |
38 | ======================================
39 |
40 | Basic SCL3300 Library Functions:
41 |
42 | begin()
43 | This initializes the library and the SPI chip, and by default assigns the SPI Chip Select Pin to Digital Pin 10.
44 |
45 | begin(csPinNum)
46 | This variation allows you to choose a different pin as the SPI Chip Select Pin. Replace 'csPinNum' with your pin number.
47 |
48 | begin(altSpiPort, csPinNum)
49 | This allows using an alternate SPI port definition for communication to the SCL3300. Please see Example9_AlternateSPI.ino
50 |
51 | isConnected()
52 | Returns 'true' if the sensor is still responding as expected, and able to provide valid data. It does not collect a data set from the sensor.
53 |
54 | available()
55 | Reads the raw SCL3300 sensor data as a group so that all the data is consistent. Call this first before using the functions below. Starting with Version 3.0.0, this call should be the conditional in an 'if' statement, and an 'else' clause included to call reset() when available() returns false. (See the example sketches in the library.)
56 |
57 | getTiltLevelOffsetAngleX()
58 | Returns a double float of the tilt offset from level value in degrees for the X direction.
59 |
60 | getTiltLevelOffsetAngleY()
61 | Returns a double float of the tilt offset from level value in degrees for the Y direction.
62 |
63 | getTiltLevelOffsetAngleZ()
64 | Returns a double float of the tilt offset from level value in degrees for the Z direction.
65 |
66 | getCalculatedAngleX()
67 | Returns a double float of the tilt value in degrees (0-360) for the X direction.
68 |
69 | getCalculatedAngleY()
70 | Returns a double float of the tilt value in degrees (0-360) for the Y direction.
71 |
72 | getCalculatedAngleZ()
73 | Returns a double float of the tilt value in degrees (0-360) for the Z direction.
74 |
75 | getCalculatedAccelerometerX()
76 | Returns a double float of the accelerometer value in units of 'g' for the X direction.
77 |
78 | getCalculatedAccelerometerY()
79 | Returns a double float of the accelerometer value in units of 'g' for the Y direction.
80 |
81 | getCalculatedAccelerometerZ()
82 | Returns a double float of the accelerometer value in units of 'g' for the Z direction.
83 |
84 | getTemperatureCelsius()
85 | Returns a double float of the temperature in Celsius.
86 |
87 | getTemperatureFarenheit()
88 | Returns a double float of the temperature in Farenheit.
89 |
90 |
91 | Utility Functions available:
92 |
93 | reset()
94 | Does a software reset of the SCL3300 sensor.
95 |
96 | getSerialNumber()
97 | Returns a long integer of the device Serial Number set by the manufacturer.
98 |
99 | powerDownMode()
100 | Puts the sensor in a power down mode to reduce power usage.
101 |
102 | WakeMeUp()
103 | Revives sensor from being powered down, so that it can start to generate sensor data.
104 |
105 | setMode(modeNum)
106 | Sets the sensor mode to the number provided as modeNum. The default mode is '4'. Valid values are 1, 2, 3, and 4.
107 |
108 | setFastReadMode()
109 | 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.
110 |
111 | stopFastReadMode()
112 | This stops the Fast Read Mode in the library by closing the SPI connection that was open, and doing a reset of the SCL3300. 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.
113 |
--------------------------------------------------------------------------------
/examples/Example10_Mode1/Example10_Mode1.ino:
--------------------------------------------------------------------------------
1 | /* Read Tilt angles from Murata SCL3300 Inclinometer using Mode 1
2 | * Version 3.3.1 - July 4, 2022
3 | * Example10_Mode1
4 | *
5 | * Modes 3 and 4 (default for library) are designed to be used when the inclinometer
6 | * will be kept within +-10 degrees of level.
7 | * However, if the inclinometer might be used outside of that range, then
8 | * it is required that either Mode 1 or 2 be used instead.
9 | * This sketch demonstrates how to use Mode 1 when that is needed.
10 | */
11 |
12 | #include
13 | #include
14 |
15 | SCL3300 inclinometer;
16 | //Default SPI chip/slave select pin is D10
17 |
18 | // Need the following define for SAMD processors
19 | #if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL)
20 | #define Serial SERIAL_PORT_USBVIRTUAL
21 | #endif
22 |
23 | void setup() {
24 | Serial.begin(9600);
25 | delay(2000); //SAMD boards may need a long time to init SerialUSB
26 | Serial.println("Reading basic Tilt Level Offset values from SCL3300 Inclinometer");
27 | Serial.println("using Mode 1.");
28 |
29 | if (inclinometer.begin() == false) {
30 | Serial.println("Murata SCL3300 inclinometer not connected.");
31 | while(1); //Freeze
32 | } else {
33 | Serial.println("Murata SCL3300 inclinometer detected.");
34 | // Put this inclinometer into Mode 1, since we are using it to measure 0-90 Degree angles
35 | inclinometer.setMode(1);
36 | if (inclinometer.begin()) {
37 | Serial.println("Murata SCL3300 inclinometer now in Mode 1.");
38 | } else {
39 | Serial.println("Tube Murata SCL3300 inclinometer failed to transition to Mode 1.");
40 | while(1); //Freeze
41 | }
42 | }
43 | }
44 |
45 | void loop() {
46 | if (inclinometer.available()) { //Get next block of data from sensor
47 | Serial.print("X Tilt: ");
48 | Serial.print(inclinometer.getTiltLevelOffsetAngleX());
49 | Serial.print("\t");
50 | Serial.print("Y Tilt: ");
51 | Serial.print(inclinometer.getTiltLevelOffsetAngleY());
52 | Serial.print("\t");
53 | Serial.print("Z Tilt: ");
54 | Serial.println(inclinometer.getTiltLevelOffsetAngleZ());
55 | delay(100); //Allow a little time to see the output
56 | } else inclinometer.reset();
57 | }
58 |
--------------------------------------------------------------------------------
/examples/Example1_BasicTiltLevelOffset/Example1_BasicTiltLevelOffset.ino:
--------------------------------------------------------------------------------
1 | /* Read Tilt angles from Murata SCL3300 Inclinometer
2 | * Version 3.2.0 - September 3, 2021
3 | * Example1_BasicTiltLevelOffset
4 | */
5 |
6 | #include
7 | #include
8 |
9 | SCL3300 inclinometer;
10 | //Default SPI chip/slave select pin is D10
11 |
12 | // Need the following define for SAMD processors
13 | #if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL)
14 | #define Serial SERIAL_PORT_USBVIRTUAL
15 | #endif
16 |
17 | void setup() {
18 | Serial.begin(9600);
19 | delay(2000); //SAMD boards may need a long time to init SerialUSB
20 | Serial.println("Reading basic Tilt Level Offset values from SCL3300 Inclinometer");
21 |
22 | if (inclinometer.begin() == false) {
23 | Serial.println("Murata SCL3300 inclinometer not connected.");
24 | while(1); //Freeze
25 | }
26 | }
27 |
28 | void loop() {
29 | if (inclinometer.available()) { //Get next block of data from sensor
30 | Serial.print("X Tilt: ");
31 | Serial.print(inclinometer.getTiltLevelOffsetAngleX());
32 | Serial.print("\t");
33 | Serial.print("Y Tilt: ");
34 | Serial.print(inclinometer.getTiltLevelOffsetAngleY());
35 | Serial.print("\t");
36 | Serial.print("Z Tilt: ");
37 | Serial.println(inclinometer.getTiltLevelOffsetAngleZ());
38 | delay(100); //Allow a little time to see the output
39 | } else inclinometer.reset();
40 | }
41 |
--------------------------------------------------------------------------------
/examples/Example2_BasicTiltReading/Example2_BasicTiltReading.ino:
--------------------------------------------------------------------------------
1 | /* Read Tilt angles from Murata SCL3300 Inclinometer
2 | * Version 3.2.0 - September 3, 2021
3 | * Example2_BasicTiltReading
4 | */
5 |
6 | #include
7 | #include
8 |
9 | SCL3300 inclinometer;
10 | //Default SPI chip/slave select pin is D10
11 |
12 | // Need the following define for SAMD processors
13 | #if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL)
14 | #define Serial SERIAL_PORT_USBVIRTUAL
15 | #endif
16 |
17 | void setup() {
18 | Serial.begin(9600);
19 | delay(2000); //SAMD boards may need a long time to init SerialUSB
20 | Serial.println("Reading basic Tilt values from SCL3300 Inclinometer");
21 |
22 | if (inclinometer.begin() == false) {
23 | Serial.println("Murata SCL3300 inclinometer not connected.");
24 | while(1); //Freeze
25 | }
26 | }
27 |
28 | void loop() {
29 | if (inclinometer.available()) { //Get next block of data from sensor
30 | Serial.print("X Tilt: ");
31 | Serial.print(inclinometer.getCalculatedAngleX());
32 | Serial.print("\t");
33 | Serial.print("Y Tilt: ");
34 | Serial.print(inclinometer.getCalculatedAngleY());
35 | Serial.print("\t");
36 | Serial.print("Z Tilt: ");
37 | Serial.println(inclinometer.getCalculatedAngleZ());
38 | delay(250); //Allow a little time to see the output
39 | } else inclinometer.reset();
40 | }
41 |
--------------------------------------------------------------------------------
/examples/Example3_BasicAccelerometerReading/Example3_BasicAccelerometerReading.ino:
--------------------------------------------------------------------------------
1 | /* Read Accelerometer data from Murata SCL3300 Inclinometer
2 | * Version 3.2.0 - September 3, 2021
3 | * Example3_BasicAccelerometerReading
4 | */
5 |
6 | #include
7 | #include
8 |
9 | SCL3300 inclinometer;
10 | //Default SPI chip/slave select pin is D10
11 |
12 | // Need the following define for SAMD processors
13 | #if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL)
14 | #define Serial SERIAL_PORT_USBVIRTUAL
15 | #endif
16 |
17 | void setup() {
18 | Serial.begin(9600);
19 | delay(2000); //SAMD boards may need a long time to init SerialUSB
20 | Serial.println("Reading basic Accelerometer values from SCL3300 Inclinometer");
21 |
22 | if (inclinometer.begin() == false) {
23 | Serial.println("Murata SCL3300 inclinometer not connected.");
24 | while(1); //Freeze
25 | }
26 | }
27 |
28 | void loop() {
29 | if (inclinometer.available()) { //Get next block of data from sensor
30 | Serial.print("X Accelerometer: ");
31 | Serial.print(inclinometer.getCalculatedAccelerometerX());
32 | Serial.print("\t");
33 | Serial.print("Y Accelerometer: ");
34 | Serial.print(inclinometer.getCalculatedAccelerometerY());
35 | Serial.print("\t");
36 | Serial.print("Z Accelerometer: ");
37 | Serial.println(inclinometer.getCalculatedAccelerometerZ());
38 | delay(250); //Allow a little time to see the output
39 | } else inclinometer.reset();
40 | }
41 |
--------------------------------------------------------------------------------
/examples/Example4_BasicTemperatureReading/Example4_BasicTemperatureReading.ino:
--------------------------------------------------------------------------------
1 | /* Read Temperature Sensor from Murata SCL3300 Inclinometer
2 | * Version 3.2.0 - September 3, 2021
3 | * Example4_BasicTemperatureReading
4 | */
5 |
6 | #include
7 | #include
8 |
9 | SCL3300 inclinometer;
10 | //Default SPI chip/slave select pin is D10
11 |
12 | // Need the following define for SAMD processors
13 | #if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL)
14 | #define Serial SERIAL_PORT_USBVIRTUAL
15 | #endif
16 |
17 | void setup() {
18 | Serial.begin(9600);
19 | delay(2000); //SAMD boards may need a long time to init SerialUSB
20 | Serial.println("Reading basic Temperature values from SCL3300 Inclinometer");
21 |
22 | if (inclinometer.begin() == false) {
23 | Serial.println("Murata SCL3300 inclinometer not connected.");
24 | while(1); //Freeze
25 | }
26 | }
27 |
28 | void loop() {
29 | if (inclinometer.available()) { //Get next block of data from sensor
30 | Serial.print("Celsius Temperature: ");
31 | Serial.print(inclinometer.getCalculatedTemperatureCelsius());
32 | Serial.print("\t");
33 | Serial.print("Farenheit Temperature: ");
34 | Serial.println(inclinometer.getCalculatedTemperatureFarenheit());
35 | delay(250); //Allow a little time to see the output
36 | } else inclinometer.reset();
37 | }
38 |
--------------------------------------------------------------------------------
/examples/Example5_RawDataReading/Example5_RawDataReading.ino:
--------------------------------------------------------------------------------
1 | /* Read Raw sensor data from Murata SCL3300 Inclinometer
2 | * Version 3.2.0 - September 3, 2021
3 | * Example5_RawDataReading
4 | */
5 |
6 | #include
7 | #include
8 |
9 | SCL3300 inclinometer;
10 | //Default SPI chip/slave select pin is D10
11 |
12 | // Need the following define for SAMD processors
13 | #if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL)
14 | #define Serial SERIAL_PORT_USBVIRTUAL
15 | #endif
16 |
17 | void setup() {
18 | Serial.begin(9600);
19 | delay(2000); //SAMD boards may need a long time to init SerialUSB
20 | Serial.println("Reading Raw register values from SCL3300 Inclinometer");
21 |
22 | if (inclinometer.begin() == false) {
23 | Serial.println("Murata SCL3300 inclinometer not connected.");
24 | while(1); //Freeze
25 | }
26 | }
27 |
28 | void loop() {
29 | if (inclinometer.isConnected()) Serial.println("Inclinometer is still alive...");
30 | else Serial.println("Inclinometer error detected...");
31 |
32 | if (inclinometer.available()) { //Get next block of data from sensor
33 | Serial.print("Raw X Tilt: ");
34 | Serial.print(inclinometer.sclData.AngX);
35 | Serial.print("\t");
36 | Serial.print("Y Tilt: ");
37 | Serial.print(inclinometer.sclData.AngY);
38 | Serial.print("\t");
39 | Serial.print("Z Tilt: ");
40 | Serial.println(inclinometer.sclData.AngZ);
41 | Serial.print("Raw X Accel: ");
42 | Serial.print(inclinometer.sclData.AccX);
43 | Serial.print("\t");
44 | Serial.print("Y Accel: ");
45 | Serial.print(inclinometer.sclData.AccY);
46 | Serial.print("\t");
47 | Serial.print("Z Accel: ");
48 | Serial.println(inclinometer.sclData.AccZ);
49 | Serial.print("SCL3300 STO register: ");
50 | Serial.print((inclinometer.sclData.STO >> 8) & 0xff, HEX);
51 | Serial.print("\t");
52 | Serial.print("WHOAMI register: ");
53 | Serial.println(inclinometer.sclData.WHOAMI, HEX);
54 | Serial.print("Raw Temperature: ");
55 | Serial.println(inclinometer.sclData.TEMP);
56 | Serial.print("Serial Number Register: ");
57 | Serial.print(inclinometer.getSerialNumber());
58 | Serial.print("B33");
59 | Serial.print("\t");
60 | Serial.print("SL3300 Status Summary Register: ");
61 | Serial.println(inclinometer.sclData.StatusSum, HEX);
62 | delay(1000);
63 | } else inclinometer.reset();
64 | }
65 |
--------------------------------------------------------------------------------
/examples/Example6_FastReadMode/Example6_FastReadMode.ino:
--------------------------------------------------------------------------------
1 | /* Fast Read Sensor Mode for Murata SCL3300 Inclinometer
2 | * Version 3.2.0 - September 3, 2021
3 | * Example6_FastReadMode
4 | * Warning: Using Fast Read Mode in the library works by keeping the
5 | * SPI connection continuously open. This may or may not affect
6 | * the behavior of other hardware interactions, depending on the
7 | * sketch design. Fast Read Mode is considered an advanced use case,
8 | * and not recommended for the beginner.
9 | */
10 |
11 | #include
12 | #include
13 |
14 | SCL3300 inclinometer;
15 | //Default SPI chip/slave select pin is D10
16 |
17 | // Need the following define for SAMD processors
18 | #if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL)
19 | #define Serial SERIAL_PORT_USBVIRTUAL
20 | #endif
21 |
22 | int16_t AngX, AngY, AngZ, AccX, AccY, AccZ, STO, TEMP;
23 | uint16_t StatusSum, WHOAMI;
24 | long int n = 0;
25 | long int startmillis = 0;
26 |
27 | void setup() {
28 | Serial.begin(9600);
29 | delay(2000); //SAMD boards may need a long time to init SerialUSB
30 | Serial.println("Reading Raw register values from SCL3300 Inclinometer");
31 | Serial.println("We use FastReadMode in 1 second bursts.");
32 | if (inclinometer.begin() == false) {
33 | Serial.println("Murata SCL3300 inclinometer not connected.");
34 | while(1); //Freeze
35 | }
36 | }
37 |
38 | void loop() {
39 | n = 0;
40 | inclinometer.setFastReadMode();
41 | startmillis = millis();
42 | while (millis() - startmillis < 1000) {
43 | if (inclinometer.available()) { //Get next block of data from sensor
44 | n++;
45 | // Read raw binary data
46 | AngX = inclinometer.sclData.AngX;
47 | AngY = inclinometer.sclData.AngY;
48 | AngZ = inclinometer.sclData.AngZ;
49 | AccX = inclinometer.sclData.AccX;
50 | AccY = inclinometer.sclData.AccY;
51 | AccZ = inclinometer.sclData.AccZ;
52 | STO = inclinometer.sclData.STO;
53 | WHOAMI = inclinometer.sclData.WHOAMI;
54 | TEMP = inclinometer.sclData.TEMP;
55 | StatusSum = inclinometer.sclData.StatusSum;
56 | } else inclinometer.reset();
57 | }
58 | inclinometer.stopFastReadMode();
59 | Serial.print("Iterations per second: ");
60 | Serial.println(n);
61 | }
--------------------------------------------------------------------------------
/examples/Example7_FastReadModeContinuous/Example7_FastReadModeContinuous.ino:
--------------------------------------------------------------------------------
1 | /* Fast Read Sensor Mode for Murata SCL3300 Inclinometer
2 | * Version 3.2.0 - September 3, 2021
3 | * Example7_FastReadModeContinuous
4 | * Warning: Using Fast Read Mode in the library works by keeping the
5 | * SPI connection continuously open. This may or may not affect
6 | * the behavior of other hardware interactions, depending on the
7 | * sketch design. Fast Read Mode is considered an advanced use case,
8 | * and not recommended for the beginner.
9 | */
10 |
11 | #include
12 | #include
13 |
14 | SCL3300 inclinometer;
15 | //Default SPI chip/slave select pin is D10
16 |
17 | // Need the following define for SAMD processors
18 | #if defined (ARDUINO_ARCH_SAMD)
19 | #define Serial SerialUSB
20 | #endif
21 |
22 | int16_t AngX, AngY, AngZ, AccX, AccY, AccZ, STO, TEMP;
23 | uint16_t StatusSum, WHOAMI;
24 | long int n = 0;
25 | long int startmillis = 0;
26 |
27 | void setup() {
28 | Serial.begin(9600);
29 | delay(2000); //SAMD boards may need a long time to init SerialUSB
30 | Serial.println("Reading Raw register values from SCL3300 Inclinometer");
31 | Serial.println("We use FastReadMode continuously.");
32 | if (inclinometer.begin() == false) {
33 | Serial.println("Murata SCL3300 inclinometer not connected.");
34 | while(1); //Freeze
35 | }
36 | inclinometer.setFastReadMode();
37 | }
38 |
39 | void loop() {
40 | startmillis = millis();
41 | n = 0;
42 | while (millis() - startmillis < 1000) {
43 | if (inclinometer.available()) { //Get next block of data from sensor
44 | n++;
45 | // Read raw binary data
46 | AngX = inclinometer.sclData.AngX;
47 | AngY = inclinometer.sclData.AngY;
48 | AngZ = inclinometer.sclData.AngZ;
49 | AccX = inclinometer.sclData.AccX;
50 | AccY = inclinometer.sclData.AccY;
51 | AccZ = inclinometer.sclData.AccZ;
52 | STO = inclinometer.sclData.STO;
53 | WHOAMI = inclinometer.sclData.WHOAMI;
54 | TEMP = inclinometer.sclData.TEMP;
55 | StatusSum = inclinometer.sclData.StatusSum;
56 | } else inclinometer.reset();
57 | }
58 | Serial.print("Iterations per second: ");
59 | Serial.println(n);
60 | }
--------------------------------------------------------------------------------
/examples/Example8_TwoSensors/Example8_TwoSensors.ino:
--------------------------------------------------------------------------------
1 | /* Read Tilt angles from Two Murata SCL3300 Inclinometers
2 | * Version 3.2.0 - September 3, 2021
3 | * Example8_TwoSensors
4 | */
5 |
6 | #include
7 | #include
8 |
9 | SCL3300 inclinometerA, inclinometerB;
10 | //First SPI chip (A) select pin is D10
11 | //Second SPI chip (B) select pin is D9
12 |
13 | // Need the following define for SAMD processors
14 | #if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL)
15 | #define Serial SERIAL_PORT_USBVIRTUAL
16 | #endif
17 |
18 | void setup() {
19 | Serial.begin(9600);
20 | delay(2000); //SAMD boards may need a long time to init SerialUSB
21 | Serial.println("Reading basic Tilt Level Offset values from two SCL3300 Inclinometers");
22 |
23 | if (inclinometerA.begin(10) == false) {
24 | Serial.println("Murata SCL3300 inclinometer A not connected.");
25 | while(1); //Freeze
26 | }
27 | if (inclinometerB.begin(9) == false) {
28 | Serial.println("Murata SCL3300 inclinometer B not connected.");
29 | while(1); //Freeze
30 | }
31 | }
32 |
33 | void loop() {
34 | if (inclinometerA.available()) { //Get next block of data from sensor
35 | Serial.print("Dev A: X Tilt: ");
36 | Serial.print(inclinometerA.getTiltLevelOffsetAngleX());
37 | Serial.print("\t");
38 | Serial.print("Y Tilt: ");
39 | Serial.print(inclinometerA.getTiltLevelOffsetAngleY());
40 | Serial.print("\t");
41 | Serial.print("Z Tilt: ");
42 | Serial.println(inclinometerA.getTiltLevelOffsetAngleZ());
43 | } else inclinometerA.reset();
44 |
45 | if (inclinometerB.available()) { //Get next block of data from sensor
46 | Serial.print("Dev B: X Tilt: ");
47 | Serial.print(inclinometerB.getTiltLevelOffsetAngleX());
48 | Serial.print("\t");
49 | Serial.print("Y Tilt: ");
50 | Serial.print(inclinometerB.getTiltLevelOffsetAngleY());
51 | Serial.print("\t");
52 | Serial.print("Z Tilt: ");
53 | Serial.println(inclinometerB.getTiltLevelOffsetAngleZ());
54 | } else inclinometerB.reset();
55 | delay(100); //Allow a little time to see the output
56 | }
57 |
--------------------------------------------------------------------------------
/examples/Example9_AlternateSPI/Example9_AlternateSPI.ino:
--------------------------------------------------------------------------------
1 | /* Alternate SPI interface used to Read Tilt angles from Murata SCL3300 Inclinometer
2 | * Version 3.3.0 - September 13, 2021
3 | * Example9_AlternateSPI
4 | */
5 |
6 | #include
7 | #include
8 |
9 | SCL3300 inclinometer;
10 |
11 | // Need the following define for SAMD processors
12 | #if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL)
13 | #define Serial SERIAL_PORT_USBVIRTUAL
14 | #endif
15 |
16 | void setup() {
17 | Serial.begin(9600);
18 | delay(2000); //SAMD boards may need a long time to init SerialUSB
19 | Serial.println("Define a specific SPI interface for the SCL3300 Inclinometer");
20 |
21 | // Change the begin() parameters here, as needed, to reference the SPI
22 | // interface being used for the SCL3300 inclinometer.
23 | // The default Arduino interface is "SPI", and is shown here
24 | if (inclinometer.begin(SPI, 10) == false) {
25 | Serial.println("Murata SCL3300 inclinometer not connected.");
26 | while(1); //Freeze
27 | } else
28 | Serial.println("Murata SCL3300 inclinometer is connected.");
29 | }
30 |
31 | void loop() {
32 | if (inclinometer.isConnected()) {
33 | Serial.println("Inclinometer is still alive...");
34 | } else {
35 | Serial.println("Inclinometer error detected...");
36 | delay(1000);
37 | }
38 | if (inclinometer.available()) { //Get next block of data from sensor
39 | Serial.print("Raw X Tilt: ");
40 | Serial.print(inclinometer.sclData.AngX);
41 | Serial.print("\t");
42 | Serial.print("Y Tilt: ");
43 | Serial.print(inclinometer.sclData.AngY);
44 | Serial.print("\t");
45 | Serial.print("Z Tilt: ");
46 | Serial.println(inclinometer.sclData.AngZ);
47 | Serial.print("Raw X Accel: ");
48 | Serial.print(inclinometer.sclData.AccX);
49 | Serial.print("\t");
50 | Serial.print("Y Accel: ");
51 | Serial.print(inclinometer.sclData.AccY);
52 | Serial.print("\t");
53 | Serial.print("Z Accel: ");
54 | Serial.println(inclinometer.sclData.AccZ);
55 | Serial.print("SCL3300 STO register: ");
56 | Serial.print((inclinometer.sclData.STO >> 8) & 0xff, HEX);
57 | Serial.print("\t");
58 | Serial.print("WHOAMI register: ");
59 | Serial.println(inclinometer.sclData.WHOAMI, HEX);
60 | Serial.print("Raw Temperature: ");
61 | Serial.println(inclinometer.sclData.TEMP);
62 | Serial.print("Serial Number Register: ");
63 | Serial.print(inclinometer.getSerialNumber());
64 | Serial.print("B33");
65 | Serial.print("\t");
66 | Serial.print("SL3300 Status Summary Register: ");
67 | Serial.println(inclinometer.sclData.StatusSum, HEX);
68 | delay(1000);
69 | } else inclinometer.reset();
70 | }
71 |
--------------------------------------------------------------------------------
/keywords.txt:
--------------------------------------------------------------------------------
1 | ########################################################
2 | # Syntax Coloring Map for SCL3300 Inclinometer Library #
3 | ########################################################
4 |
5 | #######################################
6 | # Class
7 | #######################################
8 |
9 | SCL3300 KEYWORD1
10 |
11 | #######################################
12 | # Methods and Functions (KEYWORD2)
13 | #######################################
14 |
15 | begin KEYWORD2
16 | reset KEYWORD2
17 | setMode KEYWORD2
18 | isConnected KEYWORD2
19 | available KEYWORD2
20 | setFastReadMode KEYWORD2
21 | stopFastReadMode KEYWORD2
22 | getCalculatedAngleX KEYWORD2
23 | getCalculatedAngleY KEYWORD2
24 | getCalculatedAngleZ KEYWORD2
25 | getTiltLevelOffsetAngleX KEYWORD2
26 | getTiltLevelOffsetAngleY KEYWORD2
27 | getTiltLevelOffsetAngleZ KEYWORD2
28 | getCalculatedAccelerometerX KEYWORD2
29 | getCalculatedAccelerometerY KEYWORD2
30 | getCalculatedAccelerometerZ KEYWORD2
31 | ReadDataBlock KEYWORD2
32 | getErrFlag1 KEYWORD2
33 | getErrFlag2 KEYWORD2
34 | getSerialNumber KEYWORD2
35 | getCalculatedTemperatureCelsius KEYWORD2
36 | getCalculatedTemperatureFarenheit KEYWORD2
37 | angle KEYWORD2
38 | acceleration KEYWORD2
39 | powerDownMode KEYWORD2
40 | WakeUp KEYWORD2
41 |
42 |
43 | #######################################
44 | # Instances (KEYWORD2)
45 | #######################################
46 |
47 | #######################################
48 | # Constants (LITERAL1)
49 | #######################################
50 |
51 | SPI_MODE LITERAL1
52 |
--------------------------------------------------------------------------------
/library.properties:
--------------------------------------------------------------------------------
1 | name=SCL3300
2 | version=3.3.1
3 | author=David Armstrong
4 | maintainer=David Armstrong
5 | sentence=A library for SPI communication with the Murata SCL3300 Inclinometer sensor.
6 | paragraph=This sensor is a 3.3 volt device used to accurately measure tilt angles in three axes simultaneously.
7 | category=Sensors
8 | url=https://github.com/DavidArmstrong/SCL3300
9 | architectures=*
10 |
--------------------------------------------------------------------------------
/src/SCL3300.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | SCL3300.cpp
3 | SCL3300 Arduino Driver
4 | David Armstrong
5 | Version 3.3.0 - September 13, 2021
6 | https://github.com/DavidArmstrong/SCL3300
7 |
8 | Resources:
9 | Uses SPI.h for SPI operation
10 |
11 | Development environment specifics:
12 | Arduino IDE 1.8.15
13 |
14 | This code is released under the [MIT License](http://opensource.org/licenses/MIT).
15 | Please review the LICENSE.md file included with this example.
16 | Distributed as-is; no warranty is given.
17 |
18 | ******************************************************************************/
19 |
20 | // include this library's description file
21 | #include "SCL3300.h"
22 |
23 | // Public Methods //////////////////////////////////////////////////////////
24 | // Set the sensor mode to the number provided as modeNum.
25 | boolean SCL3300::setMode(int modeNum) {
26 | // Set Sensor mode - If not called, the default is mode 4, as set in header file
27 | // Only allowed values are: 1,2,3,4
28 | if (modeNum > 0 && modeNum < 5) {
29 | scl3300_mode = modeNum;
30 | if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
31 | transfer(modeCMD[scl3300_mode]); //Set mode on hardware
32 | if (!setFastRead) endTransmission(); //Let go of SPI port/bus
33 | if (crcerr || statuserr) {
34 | reset(); //Reset chip to fix the error state
35 | return false; //Let the caller know something went wrong
36 | } else return true; // Valid value, and chip was set to that mode
37 | } else
38 | return false; // Invalid value
39 | }
40 |
41 | // Current Version of begin() to initialize the library and the SCL3300
42 | boolean SCL3300::begin(void) {
43 | //This is the updated Version 3 begin function
44 | // Determine if we need to set up to use the default SPI interface, or some other one
45 | if (_spiPort == nullptr) _spiPort = &SPI;
46 |
47 | //Wait the required 1 ms before initializing the SCL3300 inclinomenter
48 | unsigned long startmillis = millis();
49 | while (millis() - startmillis < 1) ;
50 |
51 | initSPI(); // Initialize SPI Library
52 | if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
53 | //Write SW Reset command
54 | transfer(SwtchBnk0);
55 | transfer(SWreset);
56 | startmillis = millis();
57 | while (millis() - startmillis < 1) ;
58 | //Set measurement mode
59 | transfer(modeCMD[scl3300_mode]); //Set mode on hardware
60 | //We're good, so Enable angle outputs
61 | transfer(EnaAngOut);
62 | //The first response after reset is undefined and shall be discarded
63 | //wait 5 ms to stablize
64 | startmillis = millis();
65 | while (millis() - startmillis < 100) ;
66 |
67 | //Read Status to clear the status summary
68 | transfer(RdStatSum);
69 | transfer(RdStatSum); //Again, due to off-response protocol used
70 | transfer(RdStatSum); //And now we can get the real status
71 |
72 | //Read the WHOAMI register
73 | transfer(RdWHOAMI);
74 | //And again
75 | transfer(RdWHOAMI);
76 | if (!setFastRead) endTransmission(); //Let go of SPI port/bus
77 | //We now wait until the end of begin() to report if an error occurred
78 | if (crcerr || statuserr) return false;
79 | // Once everything is initialized, return a known expected value
80 | // The WHOAMI command should give an 8 bit value of 0xc1
81 | return (SCL3300_DATA == 0xc1); //Let the caller know if this worked
82 | }
83 |
84 | // Set up the SPI communication with the SCL3300 with provided Chip Select pin number, and provided SPI port
85 | boolean SCL3300::begin(SPIClass &spiPort, uint8_t csPin) {
86 | scl3300_csPin = csPin;
87 | _spiPort = &spiPort; //Grab the port the user wants us to use
88 | return begin();
89 | } // begin
90 |
91 | // Set up the SPI communication with the SCL3300 with provided Chip Select pin number
92 | boolean SCL3300::begin(uint8_t csPin) {
93 | scl3300_csPin = csPin;
94 | _spiPort = &SPI; // With this call, we do the default SPI interface
95 | return begin();
96 | } // begin
97 |
98 | //Check to validate that the sensor is still reachable and ready to provide data
99 | boolean SCL3300::isConnected() {
100 | if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
101 | transfer(SwtchBnk0);
102 | //Read the WHOAMI register
103 | transfer(RdWHOAMI);
104 | //And again
105 | transfer(RdWHOAMI);
106 | if (!setFastRead) endTransmission(); //Let go of SPI port/bus
107 | if (crcerr || statuserr) return false;
108 | // Once everything is initialized, return a known expected value
109 | // The WHOAMI command should give an 8 bit value of 0xc1
110 | return (SCL3300_DATA == 0xc1); //Let the caller know if this worked
111 | }
112 |
113 | //Read all the sensor data together to keep it consistent
114 | //This is required according to the datasheet
115 | boolean SCL3300::available(void) {
116 | //Version 3 of this function
117 | boolean errorflag = false;
118 | //Read all Sensor Data, as per Datasheet requirements
119 | if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
120 | transfer(SwtchBnk0);
121 | transfer(RdAccX);
122 | if (crcerr || statuserr) errorflag = true;
123 | transfer(RdAccY);
124 | if (crcerr || statuserr) errorflag = true;
125 | sclData.AccX = SCL3300_DATA;
126 | transfer(RdAccZ);
127 | if (crcerr || statuserr) errorflag = true;
128 | sclData.AccY = SCL3300_DATA;
129 | transfer(RdSTO);
130 | if (crcerr || statuserr) errorflag = true;
131 | sclData.AccZ = SCL3300_DATA;
132 | transfer(RdTemp);
133 | if (crcerr || statuserr) errorflag = true;
134 | sclData.STO = SCL3300_DATA;
135 | transfer(RdAngX);
136 | if (crcerr || statuserr) errorflag = true;
137 | sclData.TEMP = SCL3300_DATA;
138 | transfer(RdAngY);
139 | if (crcerr || statuserr) errorflag = true;
140 | sclData.AngX = SCL3300_DATA;
141 | transfer(RdAngZ);
142 | if (crcerr || statuserr) errorflag = true;
143 | sclData.AngY = SCL3300_DATA;
144 | transfer(RdStatSum);
145 | if (crcerr || statuserr) errorflag = true;
146 | sclData.AngZ = SCL3300_DATA;
147 | transfer(RdWHOAMI);
148 | if (crcerr || statuserr) errorflag = true;
149 | sclData.StatusSum = SCL3300_DATA;
150 | transfer(RdWHOAMI);
151 | if (crcerr || statuserr) errorflag = true;
152 | sclData.WHOAMI = SCL3300_DATA;
153 | if (!setFastRead) endTransmission(); //Let go of SPI port/bus
154 | if (errorflag) return false; //Inform caller that something went wrong
155 | // The WHOAMI command should give an 8 bit value of 0xc1
156 | return (SCL3300_DATA == 0xc1); //Let the caller know this worked
157 | }
158 |
159 | /* Set SCL3300 library into Fast Read Mode
160 | * Warning: Using Fast Read Mode in the library works by keeping the
161 | * SPI connection continuously open. This may or may not affect
162 | * the behavior of other hardware interactions, depending on the
163 | * sketch design. Fast Read Mode is considered an advanced use case,
164 | * and not recommended for the beginner.
165 | */
166 | void SCL3300::setFastReadMode() {
167 | setFastRead = true;
168 | beginTransmission(); //Set up this SPI port/bus
169 | begin(); //Re-init chip
170 | }
171 |
172 | /* Stop Fast Read Mode
173 | * Warning: Using Fast Read Mode in the library works by keeping the
174 | * SPI connection continuously open. This may or may not affect
175 | * the behavior of other hardware interactions, depending on the
176 | * sketch design. Fast Read Mode is considered an advanced use case,
177 | * and not recommended for the beginner.
178 | */
179 | void SCL3300::stopFastReadMode() {
180 | setFastRead = false;
181 | endTransmission(); //Close connection to SPI port/bus
182 | begin(); //Re-init chip
183 | }
184 |
185 | //Return the calculated X axis tilt angle in degrees
186 | double SCL3300::getCalculatedAngleX() {
187 | double tempX = angle(sclData.AngX);
188 | if (tempX < 0.) tempX += 360.;
189 | return tempX;
190 | }
191 |
192 | //Return the calculated Y axis tilt angle in degrees
193 | double SCL3300::getCalculatedAngleY() {
194 | double tempY = angle(sclData.AngY);
195 | if (tempY < 0.) tempY += 360.;
196 | return tempY;
197 | }
198 |
199 | //Return the calculated Z axis tilt angle in degrees
200 | double SCL3300::getCalculatedAngleZ() {
201 | double tempZ = angle(sclData.AngZ);
202 | if (tempZ < 0.) tempZ += 360.;
203 | return tempZ;
204 | }
205 |
206 | //Return the calculated X axis offset tilt angle in degrees
207 | double SCL3300::getTiltLevelOffsetAngleX() {
208 | return angle(sclData.AngX);
209 | }
210 |
211 | //Return the calculated Y axis offset tilt angle in degrees
212 | double SCL3300::getTiltLevelOffsetAngleY() {
213 | return angle(sclData.AngY);
214 | }
215 |
216 | //Return the calculated Z axis offset tilt angle in degrees
217 | double SCL3300::getTiltLevelOffsetAngleZ() {
218 | return angle(sclData.AngZ);
219 | }
220 |
221 | //Return the calculated X axis accelerometer value in units of 'g'
222 | double SCL3300::getCalculatedAccelerometerX(void) {
223 | return acceleration(sclData.AccX);
224 | }
225 |
226 | //Return the calculated Y axis accelerometer value in units of 'g'
227 | double SCL3300::getCalculatedAccelerometerY(void) {
228 | return acceleration(sclData.AccY);
229 | }
230 |
231 | //Return the calculated Z axis accelerometer value in units of 'g'
232 | double SCL3300::getCalculatedAccelerometerZ(void) {
233 | return acceleration(sclData.AccZ);
234 | }
235 |
236 | //Return value of Error Flag 1 register
237 | uint16_t SCL3300::getErrFlag1(void) {
238 | if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
239 | transfer(SwtchBnk0);
240 | transfer(RdErrFlg1);
241 | transfer(RdErrFlg1);
242 | if (!setFastRead) endTransmission(); //Let go of SPI port/bus
243 | //Since we are fetching the Error Flag 1 value, we want to return what we got
244 | //to the caller, regardless of whether or not there was an error
245 | //if (crcerr || statuserr) return ((uint16_t)(SCL3300_CMD) & 0xff); //check CRC and RS bits
246 | return SCL3300_DATA;
247 | }
248 |
249 | //Return value of Error Flag 2 register
250 | uint16_t SCL3300::getErrFlag2(void) {
251 | if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
252 | transfer(SwtchBnk0);
253 | transfer(RdErrFlg2);
254 | transfer(RdErrFlg2);
255 | if (!setFastRead) endTransmission(); //Let go of SPI port/bus
256 | //Since we are fetching the Error Flag 2 value, we want to return what we got
257 | //to the caller, regardless of whether or not there was an error
258 | //if (crcerr || statuserr) return ((uint16_t)(SCL3300_CMD) & 0xff); //check CRC and RS bits
259 | return SCL3300_DATA;
260 | }
261 |
262 | // Read the sensor Serial Number as created by the manufacturer
263 | unsigned long SCL3300::getSerialNumber(void) {
264 | //Return Device Serial number
265 | boolean errorflag = false;
266 | unsigned long serialNum = 0;
267 | if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
268 | transfer(SwtchBnk1);
269 | if (crcerr || statuserr) errorflag = true;
270 | transfer(RdSer1);
271 | if (crcerr || statuserr) errorflag = true;
272 | transfer(RdSer2);
273 | serialNum = SCL3300_DATA;
274 | if (crcerr || statuserr) errorflag = true;
275 | transfer(SwtchBnk0);
276 | serialNum = ((unsigned long)SCL3300_DATA << 16) | serialNum;
277 | if (!setFastRead) endTransmission(); //Let go of SPI port/bus
278 | //We wait until now to return an error code
279 | //In this case we send a 0 since a real serial number will never be 0
280 | if (crcerr || statuserr || errorflag) return 0;
281 | return serialNum;
282 | }
283 |
284 | // Place the sensor in a Powered Down mode to save power
285 | uint16_t SCL3300::powerDownMode(void) {
286 | //Software power down of sensor
287 | if (!setFastRead) beginTransmission(); //Set up this SPI port/bus
288 | transfer(SwtchBnk0);
289 | transfer(SetPwrDwn);
290 | endTransmission(); //Let go of SPI port/bus
291 | //Since an error is non-zero, we will return 0 if there was no error
292 | if (crcerr || statuserr) return (uint16_t)(SCL3300_CMD & 0xff); //check CRC and RS bits
293 | return 0;
294 | }
295 |
296 | // Revive the sensor from a power down mode so we can start getting data again
297 | uint16_t SCL3300::WakeMeUp(void) {
298 | //Software Wake Up of sensor
299 | beginTransmission(); //Set up this SPI port/bus
300 | transfer(WakeUp);
301 | if (!setFastRead) endTransmission(); //Let go of SPI port/bus
302 | //Since an error is non-zero, we will return 0 if there was no error
303 | if (crcerr || statuserr) return (uint16_t)(SCL3300_CMD & 0xff); //check CRC and RS bits
304 | return 0;
305 | }
306 |
307 | // Hardware reset of the sensor electronics
308 | uint16_t SCL3300::reset(void) {
309 | //Software reset of sensor
310 | //beginTransmission(); //Set up this SPI port/bus
311 | //transfer(SwtchBnk0);
312 | //transfer(SWreset);
313 | //endTransmission(); //Let go of SPI port/bus
314 | //we have to call begin() to set up the SCL3300 to the same state as before it was reset
315 | begin(); //Re-init chip
316 | //Since an error is non-zero, we will return 0 if there was no error
317 | if (crcerr || statuserr) return (uint16_t)(SCL3300_CMD & 0xff); //check CRC and RS bits
318 | return 0;
319 | }
320 |
321 | // Routine to get temperature in degrees Celsius
322 | double SCL3300::getCalculatedTemperatureCelsius(void) {
323 | // Return calculated temperature in degrees C
324 | double Temperature = -273. + (sclData.TEMP / 18.9);
325 | return Temperature;
326 | }
327 |
328 | // Routine to get temperature in degrees Farenheit
329 | double SCL3300::getCalculatedTemperatureFarenheit(void) {
330 | // Return calculated temperature in degrees F
331 | double Temperature = -273. + (sclData.TEMP / 18.9);
332 | Temperature = (Temperature * 9./5.) + 32.;
333 | return Temperature;
334 | }
335 |
336 | //Convert raw angle value to degrees tilt
337 | double SCL3300::angle(int16_t SCL3300_ANG) { //two's complement value expected
338 | // Return Angle in degrees
339 | double Angle = (SCL3300_ANG / 16384.) * 90.; // 16384 = 2^14
340 | return Angle;
341 | }
342 |
343 | //Convert raw accelerometer value to g's of acceleration
344 | double SCL3300::acceleration(int16_t SCL3300_ACC) { //two's complement value expected
345 | // Return acceleration in g
346 | if (scl3300_mode == 1) return (double)SCL3300_ACC / 6000.;
347 | if (scl3300_mode == 2) return (double)SCL3300_ACC / 3000.;
348 | if (scl3300_mode == 3) return (double)SCL3300_ACC / 12000.;
349 | if (scl3300_mode == 4) return (double)SCL3300_ACC / 12000.;
350 | return (double)SCL3300_ACC / 12000.; //Default should never be reached
351 | }
352 |
353 | //private functions for serial transmission
354 | // Begin SPI bus transmission to the device
355 | void SCL3300::beginTransmission() {
356 | _spiPort->beginTransaction(spiSettings);
357 | } //beginTransmission
358 |
359 | // End SPI bus transmission to the device
360 | void SCL3300::endTransmission() {
361 | // take the chip/slave select high to de-select:
362 | digitalWrite(scl3300_csPin, HIGH);
363 | _spiPort->endTransaction();
364 | unsigned long startmillis = millis();
365 | while (millis() - startmillis < 1) ; //wait a bit
366 | } //endTransmission
367 |
368 | //Initialize the Arduino SPI library for the SCL3300 hardware
369 | void SCL3300::initSPI() {
370 | //Initialize the Arduino SPI library for the SCL3300 hardware
371 | _spiPort->begin();
372 | // Maximum SPI frequency is 2 MHz - 4 MHz to achieve the best performance
373 | // initialize the chip select pin:
374 | pinMode(scl3300_csPin, OUTPUT);
375 | digitalWrite(scl3300_csPin, HIGH);
376 | // Data is read and written MSb first.
377 | // Data is captured on rising edge of clock (CPHA = 0)
378 | // Data is propagated on the falling edge (MISO line) of the SCK. (CPOL = 0)
379 | }
380 |
381 | // The following is taken directly from the Murata SCL3300 datasheet
382 | // Calculate CRC for 24 MSB's of the 32 bit dword
383 | // (8 LSB's are the CRC field and are not included in CRC calculation)
384 | uint8_t SCL3300::CalculateCRC(uint32_t Data)
385 | {
386 | uint8_t BitIndex;
387 | uint8_t BitValue;
388 | uint8_t SCL3300_CRC;
389 |
390 | SCL3300_CRC = 0xFF;
391 | for (BitIndex = 31; BitIndex > 7; BitIndex--) {
392 | BitValue = (uint8_t)((Data >> BitIndex) & 0x01);
393 | SCL3300_CRC = CRC8(BitValue, SCL3300_CRC);
394 | }
395 | SCL3300_CRC = (uint8_t)~SCL3300_CRC;
396 | return SCL3300_CRC;
397 | }
398 | uint8_t SCL3300::CRC8(uint8_t BitValue, uint8_t SCL3300_CRC)
399 | {
400 | uint8_t Temp;
401 | Temp = (uint8_t)(SCL3300_CRC & 0x80);
402 | if (BitValue == 0x01) {
403 | Temp ^= 0x80;
404 | }
405 | SCL3300_CRC <<= 1;
406 | if (Temp > 0) {
407 | SCL3300_CRC ^= 0x1D;
408 | }
409 | return SCL3300_CRC;
410 | }
411 |
412 | // Routine to transfer a 32-bit integer to the SCL3300, and return the 32-bit data read
413 | unsigned long SCL3300::transfer(unsigned long value) {
414 | FourByte dataorig;
415 | unsigned long startmicros;
416 |
417 | dataorig.bit32 = value; //Allow 32 bit value to be sent 8 bits at a time
418 | #ifdef debug_scl3300
419 | Serial_SCL.print(dataorig.bit32, HEX);
420 | Serial_SCL.print(" ");
421 | for (int j = 3; j >= 0; j--) {
422 | Serial_SCL.print(dataorig.bit8[j], HEX);
423 | Serial_SCL.print(" ");
424 | }
425 | #endif
426 | //Must allow at least 10 uSec between SPI transfers
427 | //The datasheet shows the CS line must be high during this time
428 | if (!setFastRead) startmicros = micros();
429 | //while ((micros() - startmicros < 10) && (micros() > 10)) ;
430 | if (!setFastRead) while ((micros() - startmicros < 10)) ;
431 |
432 | digitalWrite(scl3300_csPin, LOW); //Now chip select can be enabled for the full 32 bit xfer
433 | SCL3300_DATA = 0;
434 | for (int i = 3; i >= 0; i--) { //Xfers are done MSB first
435 | dataorig.bit8[i] = _spiPort->transfer(dataorig.bit8[i]);
436 | }
437 | SCL3300_DATA = dataorig.bit8[1] + (dataorig.bit8[2] << 8);
438 | SCL3300_CRC = dataorig.bit8[0];
439 | SCL3300_CMD = dataorig.bit8[3];
440 | digitalWrite(scl3300_csPin, HIGH); //And we are done
441 | #ifdef debug_scl3300
442 | for (int i = 3; i >= 0; i--) {
443 | Serial_SCL.print(" ");
444 | Serial_SCL.print(dataorig.bit8[i], HEX);
445 | }
446 | Serial_SCL.print(" ");
447 | #endif
448 | if (SCL3300_CRC == CalculateCRC(dataorig.bit32))
449 | crcerr = false;
450 | else
451 | crcerr = true;
452 | //check RS bits
453 | if ((SCL3300_CMD & 0x03) == 0x01)
454 | statuserr = false;
455 | else
456 | statuserr = true;
457 | #ifdef debug_scl3300
458 | Serial_SCL.print((SCL3300_CMD & 0x03));
459 | Serial_SCL.print(" ");
460 | Serial_SCL.print(SCL3300_DATA, HEX);
461 | Serial_SCL.print(" ");
462 | Serial_SCL.print(SCL3300_CRC, HEX);
463 | Serial_SCL.print(" ");
464 | Serial_SCL.print(CalculateCRC(dataorig.bit32), HEX);
465 | Serial_SCL.print(" ");
466 | Serial_SCL.println(crcerr);
467 | #endif
468 | return dataorig.bit32;
469 | }
470 |
--------------------------------------------------------------------------------
/src/SCL3300.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | SCL3300.h
3 | SCL3300 Arduino Library Header File
4 | David Armstrong
5 | Version 3.2.0 - September 3, 2021
6 | https://github.com/DavidArmstrong/SCL3300
7 |
8 | Resources:
9 | Uses SPI.h for SPI operation
10 |
11 | Development environment specifics:
12 | Arduino IDE 1.8.9, 1.8.11, 1.8.12, 1.8.13, 1.8.15
13 |
14 | This code is released under the [MIT License](http://opensource.org/licenses/MIT).
15 | Please review the LICENSE.md file included with this example.
16 | Distributed as-is; no warranty is given.
17 |
18 | This file prototypes the SCL3300 class, as implemented in SCL3300.cpp
19 |
20 | ******************************************************************************/
21 |
22 | // ensure this library description is only included once
23 | #ifndef __SCL3300_h
24 | #define __SCL3300_h
25 |
26 | // Uncomment the following line for debugging output
27 | //#define debug_scl3300
28 |
29 | // Need the following define for SAMD processors
30 | #if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL)
31 | #define Serial_SCL SERIAL_PORT_USBVIRTUAL
32 | #else
33 | #define Serial_SCL Serial
34 | #endif
35 |
36 | #include
37 |
38 | #if defined(ARDUINO) && ARDUINO >= 100
39 | #include "Arduino.h"
40 | #else
41 | #include "WProgram.h"
42 | #endif
43 |
44 | #include // SPI library is used for...SPI.
45 |
46 | #ifndef SCL3300_SPI_CLOCK
47 | #ifdef ARDUINO_ARCH_ESP32
48 | #define SCL3300_SPI_CLOCK 4000000
49 | #else
50 | #define SCL3300_SPI_CLOCK 4000000
51 | #endif
52 | #endif
53 |
54 | #ifndef SCL3300_SPI_MODE
55 | #define SCL3300_SPI_MODE SPI_MODE0
56 | #endif
57 |
58 | //Define allowed commands to SCL3300 inclinometer
59 | #define RdAccX 0x040000f7
60 | #define RdAccY 0x080000fd
61 | #define RdAccZ 0x0c0000fb
62 | #define RdSTO 0x100000e9
63 | #define EnaAngOut 0xb0001f6f
64 | #define RdAngX 0x240000c7
65 | #define RdAngY 0x280000cd
66 | #define RdAngZ 0x2c0000cb
67 | #define RdTemp 0x140000ef
68 | #define RdStatSum 0x180000e5
69 | #define RdErrFlg1 0x1c0000e3
70 | #define RdErrFlg2 0x200000c1
71 | #define RdCMD 0x340000df
72 | #define ChgMode1 0xb400001f
73 | #define ChgMode2 0xb4000102
74 | #define ChgMode3 0xb4000225
75 | #define ChgMode4 0xb4000338
76 | #define SetPwrDwn 0xb400046b
77 | #define WakeUp 0xb400001f
78 | #define SWreset 0xb4002098
79 | #define RdWHOAMI 0x40000091
80 | #define RdSer1 0x640000a7
81 | #define RdSer2 0x680000AD
82 | #define RdCurBank 0x7c0000b3
83 | #define SwtchBnk0 0xfc000073
84 | #define SwtchBnk1 0xfc00016e
85 |
86 | // Structure to hold raw sensor data
87 | // We need to populate all this every time we read a set of data
88 | struct SCL3300data {
89 | public:
90 | int16_t AccX;
91 | int16_t AccY;
92 | int16_t AccZ;
93 | int16_t STO;
94 | int16_t TEMP;
95 | int16_t AngX;
96 | int16_t AngY;
97 | int16_t AngZ;
98 | uint16_t StatusSum;
99 | uint16_t WHOAMI;
100 | };
101 |
102 | // SCL3300 library interface description
103 | class SCL3300 {
104 | // user-accessible "public" interface
105 | public:
106 | SPISettings spiSettings{SCL3300_SPI_CLOCK, MSBFIRST, SCL3300_SPI_MODE};
107 |
108 | SCL3300data sclData;
109 | boolean setMode(int mode);
110 | boolean begin(void);
111 | boolean begin(uint8_t csPin);
112 | boolean begin(SPIClass &spiPort, uint8_t csPin);
113 | //Functions to retrieve sensor data
114 | boolean isConnected();
115 | boolean available(void);
116 | void setFastReadMode();
117 | void stopFastReadMode();
118 | double getCalculatedAngleX(void);
119 | double getCalculatedAngleY(void);
120 | double getCalculatedAngleZ(void);
121 | double getTiltLevelOffsetAngleX(void);
122 | double getTiltLevelOffsetAngleY(void);
123 | double getTiltLevelOffsetAngleZ(void);
124 | double getCalculatedAccelerometerX(void);
125 | double getCalculatedAccelerometerY(void);
126 | double getCalculatedAccelerometerZ(void);
127 | uint16_t getErrFlag1(void);
128 | uint16_t getErrFlag2(void);
129 | unsigned long getSerialNumber(void);
130 | double getCalculatedTemperatureCelsius(void);
131 | double getCalculatedTemperatureFarenheit(void);
132 | double angle(int16_t SCL3300_ANG); //two's complement value expected
133 | double acceleration(int16_t SCL3300_ACC);
134 | bool crcerr, statuserr;
135 | uint16_t powerDownMode(void);
136 | uint16_t WakeMeUp(void);
137 | uint16_t reset(void);
138 |
139 | // library-accessible "private" interface
140 | private:
141 | SPIClass *_spiPort = NULL; //The generic connection to user's chosen spi hardware
142 |
143 | uint8_t scl3300_csPin = 10; // Default SPI chip select pin
144 | uint8_t scl3300_mode = 4; // Default inclinometer mode
145 | uint8_t SCL3300_CMD, SCL3300_CRC;
146 | uint16_t SCL3300_DATA;
147 | double Temperature, X_angle, Y_angle, Z_angle;
148 | bool setFastRead = false;
149 |
150 | void initSPI();
151 | void beginTransmission();
152 | void endTransmission();
153 | uint8_t CalculateCRC(uint32_t Data);
154 | uint8_t CRC8(uint8_t BitValue, uint8_t SCL3300_CRC);
155 | unsigned long transfer(unsigned long value);
156 |
157 | union FourByte {
158 | unsigned long bit32;
159 | unsigned int bit16[2];
160 | unsigned char bit8[4];
161 | };
162 | unsigned long modeCMD[5] = { 0, ChgMode1, ChgMode2, ChgMode3, ChgMode4 };
163 | };
164 | #endif
165 |
--------------------------------------------------------------------------------