December 2022
The code uses a level crossing algorithm, monitoring conditions during transport and recording data for all sensors to the micro SD card when:
When any of the above thresholds are exceeded, all sensor data is recorded to the micro SD card. The acceleration and gyroscope data is sampled as quickly as possible. Every one second, the max, min, and avg is calculated for each of the three acceleration and gyroscope axis. Follosing that, the tilt (pitch, roll, yaw) is calculated, and the temperature assessed relative to the 32 °F BS 105 °F thresholds.
The sketch below was run for seven days with the level crossing being manually exceeded once or more per day in order to cause the data including the 4400 mAh Lithium Ion battery voltage to be recorded. I estimate the battery life at 80% discharge to be 95 hours for four days.
/*
M4 Express ATSAMD51 Cortex M4 microcontroller
9DOF IMU - Adafruit ISM330DHCX + LIS3MDL FeatherWing
Datalogger + RTC FeatherWing
Adafruit Sensirion SHT40 Temperature & Humidity Sensor
SparkFun Qwiic / Stemma QT FeatherWing (for SHT40)
Li 4400 mAh 3.7 V battery
Monitors conditions during transport and records to mSD card:
3-axis maximum acceleration exceeding 0.25 G
Tilt exceeding 18 degrees
Temperature when it is < 32 °F or > 105 °F
When any of the above thresholds are exceeded, all sensor data is
recorded to the micro SD card.
The acceleration and gyroscope data is sampled as quickly as possible.
Every one second, the max, min, and avg is calculated for each of the
three acceleration and gyroscope axis. Follosing that, the tilt
(pitch, roll, yaw) is calculated, and the temperature assessed relative
to the 32 °F BS 105 °F thresholds.
9 DOF IMU - Accelerometer / Gyroscope / Magnetometer
Before using this sketch, you must calibrate the sensors using:
sensor_calib_zero-offset_imu_accel_gyro_mag.ino
and then update the following with the results:
xyzReading accelOffset = {0.0, 0.0, 0.0};
xyzReading gyroOffset = {0.0, 0.0, 0.0};
xyzReading magHardIronOffset = {0.0, 0.0, 0.0};
xyzReading magSoftIronScale = {0.0, 0.0, 0.0};
*/
const byte pin_built_in_led = 13;
void blinkERR(byte ledPIN){
// S-O-S
const int S = 150, O = 300;
for(int i = 3; i>0; i--){
digitalWrite(ledPIN, HIGH);
delay(S);
digitalWrite(ledPIN, LOW);
delay(S);
}
delay(200);
for(int i = 3; i>0; i--){
digitalWrite(ledPIN, HIGH);
delay(O);
digitalWrite(ledPIN, LOW);
delay(O);
}
delay(200);
for(int i = 3; i>0; i--){
digitalWrite(ledPIN, HIGH);
delay(S);
digitalWrite(ledPIN, LOW);
delay(S);
}
delay(200);
} // blinkERR()
/////////////////////////////////////////////////////////////////////////
// SHT40 temperature & humidity sensor
// Install library "Adafruit SHT4X"
// Typical read duration is 11 ms
#include "Adafruit_SHT4x.h"
Adafruit_SHT4x sht4 = Adafruit_SHT4x();
/////////////////////////////////////////////////////////////////////////
// SD
// NOTE: Typical SD write & flush takes 20 to 30 ms
// Arduino standard SD library
#include <SPI.h>
#include <SD.h>
// 'chip/secondary select' (SS) (also called CS)
// M4 Express ATSAMD51 Cortex M4 pin 10
const int SDchipSelect = 10;
File sdfile;
/////////////////////////////////////////////////////////////////////////
// Adafruit LSM6DS (ISM330DHCX) + LIS3MDL
//Install these libraries:
// Adafruit_Sensor
// Adafruit LSM6DS LSM6DSOX, ISM330DHCX, LSM6DSO32, LSM6DS33
// https://github.com/adafruit/Adafruit_LSM6DS
// Adafruit LIS3MDL https://github.com/adafruit/Adafruit_LIS3MDL
#include <Adafruit_LIS3MDL.h> // magnetometer
Adafruit_LIS3MDL magn;
//For LIS3MDL: Examples -> Adafruit LIS3MDL -> lis3mdl_demo
// LSM6DS library for accel, gyro, temp
// See library folder 'Adafruit_LSM6DS' for include options, and https://learn.adafruit.com/lsm6dsox-and-ism330dhc-6-dof-imu?view=all
#include <Adafruit_ISM330DHCX.h>
Adafruit_ISM330DHCX imu;
//For ISM330DHCX: File -> Examples -> Adafruit LSM6DS -> adafruit_ism330dhcx_test
#include <Wire.h>
#include <Adafruit_Sensor.h>
#define MAGNETOMETER_EXISTS true
unsigned long samples = 0;
float degPerSec(float radPerSec) {
// Ref: 0.006 rad/s = 0.35 deg/s
float f = radPerSec * 180.0 / M_PI;
return f;
}
struct xyzReading {
float x;
float y;
float z;
};
xyzReading accelMax = {0.0, 0.0, 0.0};
xyzReading accelMin = {0.0, 0.0, 0.0};
xyzReading accelAvg = {0.0, 0.0, 0.0};
// Update accelOffset by running: 'sensor_calib_zero-offset_imu_accel_gyro_mag.ino'
xyzReading accelOffset = {0.076220, 0.194032, 0.038702};
xyzReading accelZero = {0.0, 0.0, 9.80665};
xyzReading gyroMax = {0.0, 0.0, 0.0};
xyzReading gyroMin = {0.0, 0.0, 0.0};
xyzReading gyroAvg = {0.0, 0.0, 0.0};
// Update gyroOffset by running: 'sensor_calib_zero-offset_imu_accel_gyro_mag.ino'
xyzReading gyroOffset = {-0.005534, 0.008544, 0.008752};
xyzReading gyroZero = {0.0, 0.0, 0.0};
#if MAGNETOMETER_EXISTS
// corrections below in micro-Tesla (uT)
xyzReading magHardIronOffset = {-1.3666, -5.5759, 2.3239};
xyzReading magSoftIronScale = {0.9859, 0.9723, 1.0448};
// If you have the magnetic declination to correct for the difference between
// magnetic north and geographic north, then revise the next line to reflect
// that offset.
float mag_decl = 0.0;
float magnetometerHeading(float raw_mag_x, float raw_mag_y) {
// raw_mag_x and raw_mag_y in micro-Tesla (uT)
// If mag_decl = 0.0, then returns the magnetic heading in degrees,
// otherwise the geographic heading in degrees.
// Calculate angle for heading, assuming the magnetometer is parallel
// to the ground and +Y points toward the magnetic heading of interest.
//float heading = -1 * (atan2(raw_mag_x, raw_mag_y) * 180.0) / M_PI;
// Calculate angle for heading, assuming the magnetometer is parallel
// to the ground and +X points toward the magnetic heading of interest.
float heading = -1 * (atan2(raw_mag_y, raw_mag_x) * 180.0) / M_PI;
// Apply any magnetic declination to get the geographic heading
heading += mag_decl;
// Convert heading to 0..360 degrees
if (heading < 0) {
heading += 360.0;
}
return heading;
} // magnetometerHeading()
#endif
struct LevelCrossLowHiAbs {
float a_x_hi;
float a_y_hi;
float a_z_hi;
float r_hi;
float p_hi;
float t_lo;
float t_hi;
};
// +/-0.25 G (2.5 m/s^2) threshold for acceleration,
// +/-18 deg threshold for tilt,
// < 32 °F and > 105 ° F threshold for temperature
LevelCrossLowHiAbs level_cross = {
{2.5},
{2.5},
{12.3},
{18.0},
{18.0},
{32.0},
{105.0},
};
void sampleData() {
// Continuously sample data as fast as loop() will allow.
// Record the data to accelMax, accelMin, accelAvg
// (using the offset correction), and also update 'samples'.
// See also TimerA().
// Below varies by library.
sensors_event_t a; // m/s^2
sensors_event_t g; // rad/s
sensors_event_t t; // °C
sensors_event_t m; // micro-Tesla (uT)
imu.getEvent(&a, &g, &t);
// sensors_event_t accel, mag, gyro, temp, dist, lux, press, RH, I, V
//sensors_event_t a, m, g;
//gyro.getEvent(&g);
//accelmagn.getEvent(&a, &m);
accelAvg.x += a.acceleration.x + accelOffset.x;
accelAvg.y += a.acceleration.y + accelOffset.y;
accelAvg.z += a.acceleration.z + accelOffset.z;
gyroAvg.x += g.gyro.x + gyroOffset.x;
gyroAvg.y += g.gyro.y + gyroOffset.y;
gyroAvg.z += g.gyro.z + gyroOffset.z;
if (samples == 0) {
accelMax.x = a.acceleration.x + accelOffset.x;
accelMax.y = a.acceleration.y + accelOffset.y;
accelMax.z = a.acceleration.z + accelOffset.z;
gyroMax.x = g.gyro.x + gyroOffset.x;
gyroMax.y = g.gyro.y + gyroOffset.y;
gyroMax.z = g.gyro.z + gyroOffset.z;
accelMin.x = a.acceleration.x + accelOffset.x;
accelMin.y = a.acceleration.y + accelOffset.y;
accelMin.z = a.acceleration.z + accelOffset.z;
gyroMin.x = g.gyro.x + gyroOffset.x;
gyroMin.y = g.gyro.y + gyroOffset.y;
gyroMin.z = g.gyro.z + gyroOffset.z;
} else {
accelMax.x = max(a.acceleration.x + accelOffset.x, accelMax.x);
accelMax.y = max(a.acceleration.y + accelOffset.x, accelMax.y);
accelMax.z = max(a.acceleration.z + accelOffset.z, accelMax.z);
gyroMax.x = max(g.gyro.x + gyroOffset.x, gyroMax.x);
gyroMax.y = max(g.gyro.y + gyroOffset.y, gyroMax.y);
gyroMax.z = max(g.gyro.z + gyroOffset.z, gyroMax.z);
accelMin.x = min(a.acceleration.x + accelOffset.x, accelMin.x);
accelMin.y = min(a.acceleration.y + accelOffset.y, accelMin.y);
accelMin.z = min(a.acceleration.z + accelOffset.z, accelMin.z);
gyroMin.x = min(g.gyro.x + gyroOffset.x, gyroMin.x);
gyroMin.y = min(g.gyro.y + gyroOffset.y, gyroMin.y);
gyroMin.z = min(g.gyro.z + gyroOffset.z, gyroMin.z);
}
samples++;
} // sampleData()
//////////////////////////////////////////////////////////////////////////////
// TimerA
// 1000000 us = 1000 ms = 1 sec = 1 Hz
const unsigned long timerAinterval = 1000;
unsigned long timerAlap = millis(); // timer
void timerA() {
// Timer A
if (timerAlap > millis()) timerAlap = millis();
if (millis() - timerAlap > timerAinterval) {
accelAvg.x = accelAvg.x / samples;
accelAvg.y = accelAvg.y / samples;
accelAvg.z = accelAvg.z / samples;
gyroAvg.x = gyroAvg.x / samples;
gyroAvg.y = gyroAvg.y / samples;
gyroAvg.z = gyroAvg.z / samples;
// Below varies by library.
sensors_event_t a; // m/s^2
sensors_event_t g; // rad/s
sensors_event_t t; // °C
sensors_event_t m; // micro-Tesla (uT)
imu.getEvent(&a, &g, &t);
magn.getEvent(&m);
// Determine if the sensor is at rest...
if ((accelAvg.z > accelZero.z*0.95 && accelAvg.z < accelZero.z*1.05) || fabs(accelMax.x)-fabs(accelMin.x) < 1.0 || fabs(accelMax.y)-fabs(accelMin.y) < 1.0 ) {
// Sensor is not in motion and is in the standard orientation (+z = 9.81 m/s^2)
// atan2() returns a value in the range of -PI to +PI radians (+/- 180 deg)
double roll = atan2(-1*accelAvg.x ,(sqrt((pow(accelAvg.y,2)) + (pow(accelAvg.z,2))))); // radians
double pitch = atan2 (accelAvg.y ,(sqrt((pow(accelAvg.x,2)) + (pow(accelAvg.z,2))))); // radians
// Convert roll & pitch to degrees. +/- 0..180
roll *= 180.0 / M_PI;
pitch *= 180.0 / M_PI;
// SHT40 read takes 3 ms
sensors_event_t humidity, temp;
sht4.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
float t = temp.temperature*9.0/5.0+32.0;
float rh = humidity.relative_humidity;
#if MAGNETOMETER_EXISTS
float Yh = ((m.magnetic.y - magHardIronOffset.y) * magSoftIronScale.y * cos(roll)) - ((m.magnetic.z - magHardIronOffset.z) * magSoftIronScale.z * sin(roll));
float Xh = ((m.magnetic.x - magHardIronOffset.x) * magSoftIronScale.x * cos(pitch))+((m.magnetic.y - magHardIronOffset.y) * magSoftIronScale.y * sin(roll)*sin(pitch)) + ((m.magnetic.z - magHardIronOffset.z) * magSoftIronScale.z * cos(roll) * sin(pitch));
double yaw = atan2(Yh, Xh) * 180.0 / M_PI; // degrees 0 to 360
// Check for level crosssing..
if (fabs(accelMax.x) > level_cross.a_x_hi || fabs(accelMax.y) > level_cross.a_y_hi || fabs(accelMax.z) > level_cross.a_z_hi || fabs(roll) > level_cross.r_hi || fabs(pitch) > level_cross.p_hi || fabs(t) > level_cross.t_hi || t < level_cross.t_lo) {
digitalWrite(pin_built_in_led, HIGH);
//One or more level cross thresholds exceeded.
Serial.print("\t"); Serial.print(accelAvg.x,2); Serial.print("\t"); Serial.print(accelAvg.y,2); Serial.print("\t"); Serial.print(accelAvg.z,2); Serial.print("\t\t");
Serial.print(roll,2); Serial.print("\t"); Serial.print(pitch,2); Serial.print("\t"); Serial.print(yaw,2); Serial.print("\t\t");
Serial.print(magnetometerHeading((m.magnetic.x - magHardIronOffset.x) * magSoftIronScale.x, (m.magnetic.y - magHardIronOffset.y) * magSoftIronScale.y),1); Serial.print("\t\t");
Serial.print(t,2); Serial.print("\t"); Serial.print(rh,2); Serial.println("\t\t");
Serial.println("");
// Write the data to the SD card.
sdfile.print(millis()); sdfile.print(";");
sdfile.print(accelAvg.x,3); sdfile.print(";");
sdfile.print(accelAvg.y,3); sdfile.print(";");
sdfile.print(accelAvg.z,3); sdfile.print(";");
sdfile.print(roll,3); sdfile.print(";");
sdfile.print(pitch,3); sdfile.print(";");
sdfile.print(yaw,3); sdfile.print(";");
sdfile.print(magnetometerHeading((m.magnetic.x - magHardIronOffset.x) * magSoftIronScale.x, (m.magnetic.y - magHardIronOffset.y) * magSoftIronScale.y),1); sdfile.print(";");
sdfile.print(t,1); sdfile.print(";");
sdfile.print(rh,1); sdfile.println(";");
// Execute a flush() to insure it is written since no sdfile.close() will be issued.
sdfile.flush();
digitalWrite(pin_built_in_led, LOW);
}
#endif
} else {
Serial.println("\tSensor in motion");
} // sensor motion detection
accelAvg.x = 0; accelAvg.y = 0; accelAvg.z = 0;
accelMin.x = 0; accelMin.y = 0; accelMin.z = 0;
accelMax.x = 0; accelMax.y = 0; accelMax.z = 0;
gyroAvg.x = 0; gyroAvg.y = 0; gyroAvg.z = 0;
gyroMin.x = 0; gyroMin.y = 0; gyroMin.z = 0;
gyroMax.x = 0; gyroMax.y = 0; gyroMax.z = 0;
samples = 0;
timerAlap = millis(); // reset the timer
}
} // timerA()
/////////////////////////////////////////////////////////////////////////
void setup() {
pinMode(pin_built_in_led, OUTPUT);
digitalWrite(pin_built_in_led, LOW);
Serial.begin(115200);
while (!Serial) {
digitalWrite(pin_built_in_led, HIGH);
delay(1);
digitalWrite(pin_built_in_led, LOW);
}
Serial.println("\nSerial ready\n");
//////////////////////////////////////////////////////////////////////////////
// micro SD card AF P/N 254
if (!SD.begin(SDchipSelect)) {
Serial.println("SD card failed, or not present");
while (1) {
blinkERR(pin_built_in_led);
}
}
Serial.println("SD card initialized.");
// Create a filename reference to a file that doesn't exist 'ANALOG00.TXT'..'ANALOG99.TXT'
char filename[15];
strcpy(filename, "/ANALOG00.TXT");
for (uint8_t i = 0; i < 100; i++) {
filename[7] = '0' + i/10;
filename[8] = '0' + i%10;
// create if does not exist, do not open existing, write, sync after write
if (SD.exists(filename)){
Serial.print("File '");
Serial.print(filename);
Serial.println("' already exists");
} else {
Serial.print("New file will be '");
Serial.print(filename);
Serial.println("'");
break;
}
}
// Open file on SD Card for writing
sdfile = SD.open(filename, FILE_WRITE);
if (! sdfile) {
Serial.print("ERROR - unable to create '");
Serial.print(filename); Serial.println("'");
while (1);
}
Serial.println("");
#if MAGNETOMETER_EXISTS
sdfile.println("m/s^2\tX\tY\tZ\t\tRoll\tPitch\tYaw deg\t\tMagnetic deg\t\tTemp F\t\tRH %");
#else
sdfile.println("m/s^2\tX\tY\tZ\t\tRoll\tPitch\t\tTemp F\t\tRH %");
#endif
// Execute a flush() to insure it is written since no sdfile.close() will be issued.
sdfile.flush();
//////////////////////////////////////////////////////////////////////////////
// SHT40 temperature & humidity sensor
Serial.println("\nAdafruit SHT4x temperature & humidity sensor initialization..");
// Warning: If SHT40 initialization fails, power cycle of device required.
if (! sht4.begin()) {
Serial.println("SHT4x sensor initialization error!");
while (1) blinkERR(pin_built_in_led);
}
Serial.print("SHT4x sensor serial number 0x");
Serial.println(sht4.readSerial(), HEX);
// Set the sensor precision (higher precision = longer read time)
sht4.setPrecision(SHT4X_LOW_PRECISION);
switch (sht4.getPrecision()) {
case SHT4X_HIGH_PRECISION:
Serial.println("High precision");
break;
case SHT4X_MED_PRECISION:
Serial.println("Med precision");
break;
case SHT4X_LOW_PRECISION:
Serial.println("Low precision");
break;
}
// Set the heater. Higher heat = longer read times and more power consumption.
sht4.setHeater(SHT4X_NO_HEATER);
switch (sht4.getHeater()) {
case SHT4X_NO_HEATER:
Serial.println("No heater");
break;
case SHT4X_HIGH_HEATER_1S:
Serial.println("High heat for 1 second");
break;
case SHT4X_HIGH_HEATER_100MS:
Serial.println("High heat for 0.1 second");
break;
case SHT4X_MED_HEATER_1S:
Serial.println("Medium heat for 1 second");
break;
case SHT4X_MED_HEATER_100MS:
Serial.println("Medium heat for 0.1 second");
break;
case SHT4X_LOW_HEATER_1S:
Serial.println("Low heat for 1 second");
break;
case SHT4X_LOW_HEATER_100MS:
Serial.println("Low heat for 0.1 second");
break;
}
Serial.println("");
//////////////////////////////////////////////////////////////////////////////
// Adafruit LSM6DS (ISM330DHCX) + LIS3MDL (modify based on the sensor being used)
// Initialize
Serial.println("LSM6DS (ISM330DHCX) initialization...");
delay(2000);
while (!imu.begin_I2C()) {
Serial.println("LSM6DS (ISM330DHCX) initialization failure");
blinkERR(pin_built_in_led);
delay(1000);
}
Serial.println("LSM6DS (ISM330DHCX) initialized");
imu.setAccelRange(LSM6DS_ACCEL_RANGE_16_G);
Serial.print("Accelerometer range set to: ");
switch (imu.getAccelRange()) {
case LSM6DS_ACCEL_RANGE_2_G:
Serial.println("+-2G");
break;
case LSM6DS_ACCEL_RANGE_4_G:
Serial.println("+-4G");
break;
case LSM6DS_ACCEL_RANGE_8_G:
Serial.println("+-8G");
break;
case LSM6DS_ACCEL_RANGE_16_G:
Serial.println("+-16G");
break;
}
// imu.setGyroRange(LSM6DS_GYRO_RANGE_250_DPS);
Serial.print("Gyro range set to: ");
switch (imu.getGyroRange()) {
case LSM6DS_GYRO_RANGE_125_DPS:
Serial.println("125 degrees/s");
break;
case LSM6DS_GYRO_RANGE_250_DPS:
Serial.println("250 degrees/s");
break;
case LSM6DS_GYRO_RANGE_500_DPS:
Serial.println("500 degrees/s");
break;
case LSM6DS_GYRO_RANGE_1000_DPS:
Serial.println("1000 degrees/s");
break;
case LSM6DS_GYRO_RANGE_2000_DPS:
Serial.println("2000 degrees/s");
break;
case ISM330DHCX_GYRO_RANGE_4000_DPS:
Serial.println("4000 degrees/s");
break;
}
imu.setAccelDataRate(LSM6DS_RATE_104_HZ);
Serial.print("Accelerometer data rate set to: ");
switch (imu.getAccelDataRate()) {
case LSM6DS_RATE_SHUTDOWN:
Serial.println("0 Hz");
break;
case LSM6DS_RATE_12_5_HZ:
Serial.println("12.5 Hz");
break;
case LSM6DS_RATE_26_HZ:
Serial.println("26 Hz");
break;
case LSM6DS_RATE_52_HZ:
Serial.println("52 Hz");
break;
case LSM6DS_RATE_104_HZ:
Serial.println("104 Hz");
break;
case LSM6DS_RATE_208_HZ:
Serial.println("208 Hz");
break;
case LSM6DS_RATE_416_HZ:
Serial.println("416 Hz");
break;
case LSM6DS_RATE_833_HZ:
Serial.println("833 Hz");
break;
case LSM6DS_RATE_1_66K_HZ:
Serial.println("1.66 KHz");
break;
case LSM6DS_RATE_3_33K_HZ:
Serial.println("3.33 KHz");
break;
case LSM6DS_RATE_6_66K_HZ:
Serial.println("6.66 KHz");
break;
}
imu.setGyroDataRate(LSM6DS_RATE_104_HZ);
Serial.print("Gyro data rate set to: ");
switch (imu.getGyroDataRate()) {
case LSM6DS_RATE_SHUTDOWN:
Serial.println("0 Hz");
break;
case LSM6DS_RATE_12_5_HZ:
Serial.println("12.5 Hz");
break;
case LSM6DS_RATE_26_HZ:
Serial.println("26 Hz");
break;
case LSM6DS_RATE_52_HZ:
Serial.println("52 Hz");
break;
case LSM6DS_RATE_104_HZ:
Serial.println("104 Hz");
break;
case LSM6DS_RATE_208_HZ:
Serial.println("208 Hz");
break;
case LSM6DS_RATE_416_HZ:
Serial.println("416 Hz");
break;
case LSM6DS_RATE_833_HZ:
Serial.println("833 Hz");
break;
case LSM6DS_RATE_1_66K_HZ:
Serial.println("1.66 KHz");
break;
case LSM6DS_RATE_3_33K_HZ:
Serial.println("3.33 KHz");
break;
case LSM6DS_RATE_6_66K_HZ:
Serial.println("6.66 KHz");
break;
}
imu.configInt1(false, false, true); // accelerometer DRDY on INT1
imu.configInt2(false, true, false); // gyro DRDY on INT2
// Adafruit LIS3MDL magnetometer
if (!magn.begin_I2C()) {
Serial.println("LIS3MDL initialization failure");
while (1) blinkERR(pin_built_in_led);
}
Serial.println("LIS3MDL initialized");
magn.setPerformanceMode(LIS3MDL_MEDIUMMODE);
Serial.print("Performance mode set to: ");
switch (magn.getPerformanceMode()) {
case LIS3MDL_LOWPOWERMODE: Serial.println("Low"); break;
case LIS3MDL_MEDIUMMODE: Serial.println("Medium"); break;
case LIS3MDL_HIGHMODE: Serial.println("High"); break;
case LIS3MDL_ULTRAHIGHMODE: Serial.println("Ultra-High"); break;
}
magn.setOperationMode(LIS3MDL_CONTINUOUSMODE);
Serial.print("Operation mode set to: ");
// Single shot mode will complete conversion and go into power down
switch (magn.getOperationMode()) {
case LIS3MDL_CONTINUOUSMODE: Serial.println("Continuous"); break;
case LIS3MDL_SINGLEMODE: Serial.println("Single mode"); break;
case LIS3MDL_POWERDOWNMODE: Serial.println("Power-down"); break;
}
magn.setDataRate(LIS3MDL_DATARATE_155_HZ);
// You can check the datarate by looking at the frequency of the DRDY pin
Serial.print("Data rate set to: ");
switch (magn.getDataRate()) {
case LIS3MDL_DATARATE_0_625_HZ: Serial.println("0.625 Hz"); break;
case LIS3MDL_DATARATE_1_25_HZ: Serial.println("1.25 Hz"); break;
case LIS3MDL_DATARATE_2_5_HZ: Serial.println("2.5 Hz"); break;
case LIS3MDL_DATARATE_5_HZ: Serial.println("5 Hz"); break;
case LIS3MDL_DATARATE_10_HZ: Serial.println("10 Hz"); break;
case LIS3MDL_DATARATE_20_HZ: Serial.println("20 Hz"); break;
case LIS3MDL_DATARATE_40_HZ: Serial.println("40 Hz"); break;
case LIS3MDL_DATARATE_80_HZ: Serial.println("80 Hz"); break;
case LIS3MDL_DATARATE_155_HZ: Serial.println("155 Hz"); break;
case LIS3MDL_DATARATE_300_HZ: Serial.println("300 Hz"); break;
case LIS3MDL_DATARATE_560_HZ: Serial.println("560 Hz"); break;
case LIS3MDL_DATARATE_1000_HZ: Serial.println("1000 Hz"); break;
}
magn.setRange(LIS3MDL_RANGE_4_GAUSS);
Serial.print("Range set to: ");
switch (magn.getRange()) {
case LIS3MDL_RANGE_4_GAUSS: Serial.println("+-4 gauss"); break;
case LIS3MDL_RANGE_8_GAUSS: Serial.println("+-8 gauss"); break;
case LIS3MDL_RANGE_12_GAUSS: Serial.println("+-12 gauss"); break;
case LIS3MDL_RANGE_16_GAUSS: Serial.println("+-16 gauss"); break;
}
magn.setIntThreshold(500);
magn.configInterrupt(false, false, true, // enable z axis
true, // polarity
false, // don't latch
true); // enabled!
//////////////////////////////////////////////////////////////////////////////
Serial.println("\nSetup complete\n");
timerAlap = millis(); // reset the timer
samples = 0;
randomSeed(millis());
Serial.println("\nSetup complete\n");
#if MAGNETOMETER_EXISTS
Serial.println("m/s^2\tX\tY\tZ\t\tRoll\tPitch\tYaw deg\t\tMag deg\t\tTemp F\tRH %");
#else
Serial.println("m/s^2\tX\tY\tZ\t\tRoll\tPitch\t\tTemp F\tRH %");
#endif
} // setup()
void loop() {
sampleData();
timerA();
} // loop()
Do you need help developing or customizing a IoT product for your needs? Send me an email requesting a free one hour phone / web share consultation.
The information presented on this website is for the author's use only. Use of this information by anyone other than the author is offered as guidelines and non-professional advice only. No liability is assumed by the author or this web site.