LIS3DH 3-axes accelerometer driver added (#546)

This commit is contained in:
Gunar Schorcht 2018-01-20 13:01:38 +01:00 committed by Ruslan V. Uss
parent 812794f7d9
commit a4de9dd4f1
9 changed files with 3665 additions and 0 deletions

3
examples/lis3dh/Makefile Normal file
View file

@ -0,0 +1,3 @@
PROGRAM=LIS3DH
EXTRA_COMPONENTS = extras/i2c extras/lis3dh
include ../../common.mk

View file

@ -0,0 +1,367 @@
/**
* Simple example with one sensor connected to I2C or SPI. It demonstrates the
* different approaches to fetch the data. Either one of the interrupt signals
* is used or new data are fetched periodically.
*
* Harware configuration:
*
* I2C
*
* +-----------------+ +----------+
* | ESP8266 / ESP32 | | LIS3DH |
* | | | |
* | GPIO 14 (SCL) ----> SCL |
* | GPIO 13 (SDA) <---> SDA |
* | GPIO 5 <---- INT1 |
* +-----------------+ +----------+
*
* SPI
*
* +-----------------+ +----------+ +-----------------+ +----------+
* | ESP8266 | | LIS3DH | | ESP32 | | LIS3DH |
* | | | | | | | |
* | GPIO 14 (SCK) ----> SCK | | GPIO 16 (SCK) ----> SCK |
* | GPIO 13 (MOSI)----> SDI | | GPIO 17 (MOSI)----> SDI |
* | GPIO 12 (MISO)<---- SDO | | GPIO 18 (MISO)<---- SDO |
* | GPIO 2 (CS) ----> CS | | GPIO 19 (CS) ----> CS |
* | GPIO 5 <---- INT1 | | GPIO 5 <---- INT1 |
* +-----------------+ +---------+ +-----------------+ +----------+
*/
/* -- use following constants to define the example mode ----------- */
// #define SPI_USED // SPI interface is used, otherwise I2C
// #define FIFO_MODE // multiple sample read mode
// #define INT_DATA // data interrupts used (data ready and FIFO status)
// #define INT_EVENT // inertial event interrupts used (wake-up, free fall or 6D/4D orientation)
// #define INT_CLICK // click detection interrupts used
#if defined(INT_DATA) || defined(INT_EVENT) || defined(INT_CLICK)
#define INT_USED
#endif
/* -- includes ----------------------------------------------------- */
#include "lis3dh.h"
/** -- platform dependent definitions ------------------------------ */
#ifdef ESP_PLATFORM // ESP32 (ESP-IDF)
// user task stack depth for ESP32
#define TASK_STACK_DEPTH 2048
// SPI interface definitions for ESP32
#define SPI_BUS HSPI_HOST
#define SPI_SCK_GPIO 16
#define SPI_MOSI_GPIO 17
#define SPI_MISO_GPIO 18
#define SPI_CS_GPIO 19
#else // ESP8266 (esp-open-rtos)
// user task stack depth for ESP8266
#define TASK_STACK_DEPTH 256
// SPI interface definitions for ESP8266
#define SPI_BUS 1
#define SPI_SCK_GPIO 14
#define SPI_MOSI_GPIO 13
#define SPI_MISO_GPIO 12
#define SPI_CS_GPIO 2 // GPIO 15, the default CS of SPI bus 1, can't be used
#endif // ESP_PLATFORM
// I2C interface defintions for ESP32 and ESP8266
#define I2C_BUS 0
#define I2C_SCL_PIN 14
#define I2C_SDA_PIN 13
#define I2C_FREQ I2C_FREQ_100K
// interrupt GPIOs defintions for ESP8266 and ESP32
#define INT1_PIN 5
#define INT2_PIN 4
/* -- user tasks --------------------------------------------------- */
static lis3dh_sensor_t* sensor;
/**
* Common function used to get sensor data.
*/
void read_data ()
{
#ifdef FIFO_MODE
lis3dh_float_data_fifo_t fifo;
if (lis3dh_new_data (sensor))
{
uint8_t num = lis3dh_get_float_data_fifo (sensor, fifo);
printf("%.3f LIS3DH num=%d\n", (double)sdk_system_get_time()*1e-3, num);
for (int i=0; i < num; i++)
// max. full scale is +-16 g and best resolution is 1 mg, i.e. 5 digits
printf("%.3f LIS3DH (xyz)[g] ax=%+7.3f ay=%+7.3f az=%+7.3f\n",
(double)sdk_system_get_time()*1e-3,
fifo[i].ax, fifo[i].ay, fifo[i].az);
}
#else
lis3dh_float_data_t data;
if (lis3dh_new_data (sensor) &&
lis3dh_get_float_data (sensor, &data))
// max. full scale is +-16 g and best resolution is 1 mg, i.e. 5 digits
printf("%.3f LIS3DH (xyz)[g] ax=%+7.3f ay=%+7.3f az=%+7.3f\n",
(double)sdk_system_get_time()*1e-3,
data.ax, data.ay, data.az);
#endif // FIFO_MODE
}
#ifdef INT_USED
/**
* In this case, any of the possible interrupts on interrupt signal *INT1* is
* used to fetch the data.
*
* When interrupts are used, the user has to define interrupt handlers that
* either fetches the data directly or triggers a task which is waiting to
* fetch the data. In this example, the interrupt handler sends an event to
* a waiting task to trigger the data gathering.
*/
static QueueHandle_t gpio_evt_queue = NULL;
// User task that fetches the sensor values.
void user_task_interrupt (void *pvParameters)
{
uint8_t gpio_num;
while (1)
{
if (xQueueReceive(gpio_evt_queue, &gpio_num, portMAX_DELAY))
{
lis3dh_int_data_source_t data_src = {};
lis3dh_int_event_source_t event_src = {};
lis3dh_int_click_source_t click_src = {};
// get the source of the interrupt and reset *INTx* signals
#ifdef INT_DATA
lis3dh_get_int_data_source (sensor, &data_src);
#endif
#ifdef INT_EVENT
lis3dh_get_int_event_source (sensor, &event_src, lis3dh_int_event1_gen);
#endif
#ifdef INT_CLICK
lis3dh_get_int_click_source (sensor, &click_src);
#endif
// in case of DRDY interrupt or inertial event interrupt read one data sample
if (data_src.data_ready)
read_data ();
// in case of FIFO interrupts read the whole FIFO
else if (data_src.fifo_watermark || data_src.fifo_overrun)
read_data ();
// in case of event interrupt
else if (event_src.active)
{
printf("%.3f LIS3DH ", (double)sdk_system_get_time()*1e-3);
if (event_src.x_low) printf("x is lower than threshold\n");
if (event_src.y_low) printf("y is lower than threshold\n");
if (event_src.z_low) printf("z is lower than threshold\n");
if (event_src.x_high) printf("x is higher than threshold\n");
if (event_src.y_high) printf("y is higher than threshold\n");
if (event_src.z_high) printf("z is higher than threshold\n");
}
// in case of click detection interrupt
else if (click_src.active)
printf("%.3f LIS3DH %s\n", (double)sdk_system_get_time()*1e-3,
click_src.s_click ? "single click" : "double click");
}
}
}
// Interrupt handler which resumes user_task_interrupt on interrupt
void IRAM int_signal_handler (uint8_t gpio)
{
// send an event with GPIO to the interrupt user task
xQueueSendFromISR(gpio_evt_queue, &gpio, NULL);
}
#else // !INT_USED
/*
* In this example, user task fetches the sensor values every seconds.
*/
void user_task_periodic(void *pvParameters)
{
vTaskDelay (100/portTICK_PERIOD_MS);
while (1)
{
// read sensor data
read_data ();
// passive waiting until 1 second is over
vTaskDelay(100/portTICK_PERIOD_MS);
}
}
#endif // INT_USED
/* -- main program ------------------------------------------------- */
void user_init(void)
{
// Set UART Parameter.
uart_set_baud(0, 115200);
// Give the UART some time to settle
vTaskDelay(1);
/** -- MANDATORY PART -- */
#ifdef SPI_USED
// init the sensor connnected to SPI
spi_bus_init (SPI_BUS, SPI_SCK_GPIO, SPI_MISO_GPIO, SPI_MOSI_GPIO);
// init the sensor connected to SPI_BUS with SPI_CS_GPIO as chip select.
sensor = lis3dh_init_sensor (SPI_BUS, 0, SPI_CS_GPIO);
#else
// init all I2C bus interfaces at which LIS3DH sensors are connected
i2c_init (I2C_BUS, I2C_SCL_PIN, I2C_SDA_PIN, I2C_FREQ);
// init the sensor with slave address LIS3DH_I2C_ADDRESS_1 connected to I2C_BUS.
sensor = lis3dh_init_sensor (I2C_BUS, LIS3DH_I2C_ADDRESS_1, 0);
#endif
if (sensor)
{
#ifdef INT_USED
/** --- INTERRUPT CONFIGURATION PART ---- */
// Interrupt configuration has to be done before the sensor is set
// into measurement mode to avoid losing interrupts
// create an event queue to send interrupt events from interrupt
// handler to the interrupt task
gpio_evt_queue = xQueueCreate(10, sizeof(uint8_t));
// configure interupt pins for *INT1* and *INT2* signals and set the interrupt handler
gpio_enable(INT1_PIN, GPIO_INPUT);
gpio_set_interrupt(INT1_PIN, GPIO_INTTYPE_EDGE_POS, int_signal_handler);
#endif // INT_USED
/** -- SENSOR CONFIGURATION PART --- */
// set polarity of INT signals if necessary
// lis3dh_config_int_signals (sensor, lis3dh_high_active);
#ifdef INT_DATA
// enable data interrupts on INT1 (data ready or FIFO status interrupts)
// data ready and FIFO status interrupts must not be enabled at the same time
#ifdef FIFO_MODE
lis3dh_enable_int (sensor, lis3dh_int_fifo_overrun , lis3dh_int1_signal, true);
lis3dh_enable_int (sensor, lis3dh_int_fifo_watermark, lis3dh_int1_signal, true);
#else
lis3dh_enable_int (sensor, lis3dh_int_data_ready, lis3dh_int1_signal, true);
#endif // FIFO_MODE
#endif // INT_DATA
#ifdef INT_EVENT
// enable data interrupts on INT1
lis3dh_int_event_config_t event_config;
event_config.mode = lis3dh_wake_up;
// event_config.mode = lis3dh_free_fall;
// event_config.mode = lis3dh_6d_movement;
// event_config.mode = lis3dh_6d_position;
// event_config.mode = lis3dh_4d_movement;
// event_config.mode = lis3dh_4d_position;
event_config.threshold = 10;
event_config.x_low_enabled = false;
event_config.x_high_enabled = true;
event_config.y_low_enabled = false;
event_config.y_high_enabled = true;
event_config.z_low_enabled = false;
event_config.z_high_enabled = true;
event_config.duration = 0;
event_config.latch = true;
lis3dh_set_int_event_config (sensor, &event_config, lis3dh_int_event1_gen);
lis3dh_enable_int (sensor, lis3dh_int_event1, lis3dh_int1_signal, true);
#endif // INT_EVENT
#ifdef INT_CLICK
// enable click interrupt on INT1
lis3dh_int_click_config_t click_config;
click_config.threshold = 10;
click_config.x_single = false;
click_config.x_double = false;
click_config.y_single = false;
click_config.y_double = false;
click_config.z_single = true;
click_config.z_double = false;
click_config.latch = true;
click_config.time_limit = 1;
click_config.time_latency = 1;
click_config.time_window = 3;
lis3dh_set_int_click_config (sensor, &click_config);
lis3dh_enable_int (sensor, lis3dh_int_click, lis3dh_int1_signal, true);
#endif // INT_CLICK
#ifdef FIFO_MODE
// clear FIFO and activate FIFO mode if needed
lis3dh_set_fifo_mode (sensor, lis3dh_bypass, 0, lis3dh_int1_signal);
lis3dh_set_fifo_mode (sensor, lis3dh_stream, 10, lis3dh_int1_signal);
#endif
// configure HPF and reset the reference by dummy read
lis3dh_config_hpf (sensor, lis3dh_hpf_normal, 0, true, true, true, true);
lis3dh_get_hpf_ref (sensor);
// enable ADC inputs and temperature sensor for ADC input 3
lis3dh_enable_adc (sensor, true, true);
// LAST STEP: Finally set scale and mode to start measurements
lis3dh_set_scale(sensor, lis3dh_scale_2_g);
lis3dh_set_mode (sensor, lis3dh_odr_10, lis3dh_high_res, true, true, true);
/** -- TASK CREATION PART --- */
// must be done last to avoid concurrency situations with the sensor
// configuration part
#ifdef INT_USED
// create a task that is triggered only in case of interrupts to fetch the data
xTaskCreate(user_task_interrupt, "user_task_interrupt", TASK_STACK_DEPTH, NULL, 2, NULL);
#else // INT_USED
// create a user task that fetches data from sensor periodically
xTaskCreate(user_task_periodic, "user_task_periodic", TASK_STACK_DEPTH, NULL, 2, NULL);
#endif
}
else
printf("Could not initialize LIS3DH sensor\n");
}

1039
extras/lis3dh/README.md Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,10 @@
# Component makefile for extras/lis3dh
# expected anyone using SHT3x driver includes it as 'lis3dh/lis3dh.h'
INC_DIRS += $(lis3dh_ROOT)..
INC_DIRS += $(lis3dh_ROOT)
# args for passing into compile rule generation
lis3dh_SRC_DIR = $(lis3dh_ROOT)
$(eval $(call component_compile_rules,lis3dh))

1274
extras/lis3dh/lis3dh.c Normal file

File diff suppressed because it is too large Load diff

456
extras/lis3dh/lis3dh.h Normal file
View file

@ -0,0 +1,456 @@
/**
* Driver for LIS3DH 3-axes digital accelerometer connected to I2C or SPI.
*
* This driver is for the usage with the ESP8266 and FreeRTOS (esp-open-rtos)
* [https://github.com/SuperHouse/esp-open-rtos]. It is also working with ESP32
* and ESP-IDF [https://github.com/espressif/esp-idf.git] as well as Linux
* based systems using a wrapper library for ESP8266 functions.
*
* ---------------------------------------------------------------------------
*
* The BSD License (3-clause license)
*
* Copyright (c) 2017 Gunar Schorcht (https://github.com/gschorcht)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __LIS3DH_H__
#define __LIS3DH_H__
// Uncomment one of the following defines to enable debug output
// #define LIS3DH_DEBUG_LEVEL_1 // only error messages
// #define LIS3DH_DEBUG_LEVEL_2 // debug and error messages
// LIS3DH addresses (also used for LIS2DH, LIS2DH12 and LIS2DE12)
#define LIS3DH_I2C_ADDRESS_1 0x18 // SDO pin is low
#define LIS3DH_I2C_ADDRESS_2 0x19 // SDO pin is high
// LIS3DE addresse (also used for LIS2DE)
#define LIS3DE_I2C_ADDRESS_1 0x28 // SDO pin is low
#define LIS3DE_I2C_ADDRESS_2 0x29 // SDO pin is high
// LIS3DH chip id
#define LIS3DH_CHIP_ID 0x33 // LIS3DH_REG_WHO_AM_I<7:0>
// Definition of error codes
#define LIS3DH_OK 0
#define LIS3DH_NOK -1
#define LIS3DH_INT_ERROR_MASK 0x000f
#define LIS3DH_DRV_ERROR_MASK 0xfff0
// Error codes for I2C and SPI interfaces ORed with LIS3DH driver error codes
#define LIS3DH_I2C_READ_FAILED 1
#define LIS3DH_I2C_WRITE_FAILED 2
#define LIS3DH_I2C_BUSY 3
#define LIS3DH_SPI_WRITE_FAILED 4
#define LIS3DH_SPI_READ_FAILED 5
#define LIS3DH_SPI_BUFFER_OVERFLOW 6
// LIS3DH driver error codes ORed with error codes for I2C and SPI interfaces
#define LIS3DH_WRONG_CHIP_ID ( 1 << 8)
#define LIS3DH_WRONG_BANDWIDTH ( 2 << 8)
#define LIS3DH_GET_RAW_DATA_FAILED ( 3 << 8)
#define LIS3DH_GET_RAW_DATA_FIFO_FAILED ( 4 << 8)
#define LIS3DH_WRONG_INT_TYPE ( 5 << 8)
#define LIS3DH_CONFIG_INT_SIGNALS_FAILED ( 6 << 8)
#define LIS3DH_CONFIG_INT_FAILED ( 7 << 8)
#define LIS3DH_INT_SOURCE_FAILED ( 8 << 8)
#define LIS3DH_CONFIG_HPF_FAILED ( 9 << 8)
#define LIS3DH_ENABLE_HPF_FAILED (10 << 8)
#define LIS3DH_CONFIG_CLICK_FAILED (11 << 8)
#define LIS3DH_CLICK_SOURCE_FAILED (12 << 8)
#define LIS3DH_GET_ADC_DATA_FAILED (13 << 8)
#define LIS3DH_SENSOR_IN_BYPASS_MODE (14 << 8)
#define LIS3DH_SENSOR_IN_FIFO_MODE (15 << 8)
#define LIS3DH_ODR_TOO_HIGH (16 << 8)
#include "lis3dh_platform.h"
#include "lis3dh_types.h"
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief Initialize the sensor
*
* Reset the sensor and switch to power down mode. All registers are reset to
* default values. FIFO is cleared.
*
* @param bus I2C or SPI bus at which LIS3DH sensor is connected
* @param addr I2C addr of the LIS3DH sensor, 0 for using SPI
* @param cs SPI CS GPIO, ignored for I2C
* @return pointer to sensor data structure, or NULL on error
*/
lis3dh_sensor_t* lis3dh_init_sensor (uint8_t bus, uint8_t addr, uint8_t cs);
/**
* @brief Set sensor mode
*
* @param dev pointer to the sensor device data structure
* @param odr sensor output data rate (ODR)
* @param res sensor resolution
* @param x true enable x-axis, false disable x-axis
* @param y true enable y-axis, false disable y-axis
* @param z true enable z-axis, false disable z-axis
* @return true on success, false on error
*/
bool lis3dh_set_mode (lis3dh_sensor_t* dev,
lis3dh_odr_mode_t odr, lis3dh_resolution_t res,
bool x, bool y, bool z);
/**
* @brief Set scale (full scale range)
*
* @param dev pointer to the sensor device data structure
* @param scale full range scale
* @return true on success, false on error
*/
bool lis3dh_set_scale (lis3dh_sensor_t* dev, lis3dh_scale_t scale);
/**
* @brief Set FIFO mode
*
* FIFO watermark can be used to generate an interrupt when FIFO content
* exceeds the value. It is ignored in bypass mode.
*
*
* @param dev pointer to the sensor device data structure
* @param mode FIFO mode
* @param thresh FIFO watermark (ignored in bypass mode)
* @param trigger interrupt signal used as trigger (only in Stream-to-FIFO)
* @return true on success, false on error
*/
bool lis3dh_set_fifo_mode (lis3dh_sensor_t* dev, lis3dh_fifo_mode_t mode,
uint8_t thresh, lis3dh_int_signal_t trigger);
/**
* @brief Test whether new data samples are available
*
* @param dev pointer to the sensor device data structure
* @return true on new data, otherwise false
*/
bool lis3dh_new_data (lis3dh_sensor_t* dev);
/**
* @brief Get one sample of sensor data as floating point values (unit g)
*
* Function works only in bypass mode and fails in FIFO modes. In FIFO modes,
* function *lis3dh_get_float_data_fifo* has to be used instead to get data.
*
* @param dev pointer to the sensor device data structure
* @param data pointer to float data structure filled with g values
* @return true on success, false on error
*/
bool lis3dh_get_float_data (lis3dh_sensor_t* dev,
lis3dh_float_data_t* data);
/**
* @brief Get all samples of sensor data stored in the FIFO (unit g)
*
* In bypass mode, it returns only one sensor data sample.
*
* @param dev pointer to the sensor device data structure
* @param data array of 32 float data structures filled with g values
* @return number of data sets read from fifo on success or 0 on error
*/
uint8_t lis3dh_get_float_data_fifo (lis3dh_sensor_t* dev,
lis3dh_float_data_fifo_t data);
/**
* @brief Get one sample of raw sensor data as 16 bit two's complements
*
* Function works only in bypass mode and fails in FIFO modes. In FIFO modes,
* function *lis3dh_get_raw_data_fifo* has to be used instead to get data.
*
* @param dev pointer to the sensor device data structure
* @param raw pointer to raw data structure filled with values
* @return true on success, false on error
*/
bool lis3dh_get_raw_data (lis3dh_sensor_t* dev, lis3dh_raw_data_t* raw);
/**
* @brief Get all samples of raw sensor data stored in the FIFO
*
* In bypass mode, it returns only one raw data sample.
*
* @param dev pointer to the sensor device data structure
* @param raw array of 32 raw data structures
* @return number of data sets read from fifo on success or 0 on error
*/
uint8_t lis3dh_get_raw_data_fifo (lis3dh_sensor_t* dev,
lis3dh_raw_data_fifo_t raw);
/**
* @brief Enable / disable an interrupt on signal INT1 or INT2
*
* @param dev pointer to the sensor device data structure
* @param type interrupt to be enabled or disabled
* @param signal interrupt signal that is activated for the interrupt
* @param value true to enable or false to disable the interrupt
* @return true on success, false on error
*/
bool lis3dh_enable_int (lis3dh_sensor_t* dev,
lis3dh_int_type_t type,
lis3dh_int_signal_t signal, bool value);
/**
* @brief Get the source of data ready and FIFO interrupts on INT1
*
* @param dev pointer to the sensor device data structure
* @param source pointer to the interrupt source
* @return true on success, false on error
*/
bool lis3dh_get_int_data_source (lis3dh_sensor_t* dev,
lis3dh_int_data_source_t* source);
/**
* @brief Set the configuration of an inertial event interrupt generator
*
* Inertial interrupt generators produce interrupts when certain inertial event
* occures (event interrupts), that is, the acceleration of defined axes is
* higher or lower than a defined threshold and one of the following event is
* recognized: axis movement / wake up, free fall, 6D/4D orientation detection.
*
* @param dev pointer to the sensor device data structure
* @param config pointer to the interrupt generator configuration
* @param gen interrupt generator to which the function is applied
* @return true on success, false on error
*/
bool lis3dh_set_int_event_config (lis3dh_sensor_t* dev,
lis3dh_int_event_config_t* config,
lis3dh_int_event_gen_t gen);
/**
* @brief Get the configuration of an inertial event interrupt generator
*
* Inertial interrupt generators produce interrupts when certain inertial event
* occures (event interrupts), that is, the acceleration of defined axes is
* higher or lower than a defined threshold and one of the following event is
* recognized: axis movement / wake up, free fall, 6D/4D orientation detection.
*
* @param dev pointer to the sensor device data structure
* @param config pointer to the interrupt generator configuration
* @param gen interrupt generator to which the function is applied
* @return true on success, false on error
*/
bool lis3dh_get_int_event_config (lis3dh_sensor_t* dev,
lis3dh_int_event_config_t* config,
lis3dh_int_event_gen_t gen);
/**
* @brief Get the source of an inertial event interrupt INT1/INT2
*
* Returns a byte with flags that indicate the event which triggered
* the interrupt signal (see INTx_SRC register in datasheet for details)
*
* @param dev pointer to the sensor device data structure
* @param source pointer to the interrupt source data structure
* @param gen interrupt generator to which the function is applied
* @return true on success, false on error
*/
bool lis3dh_get_int_event_source (lis3dh_sensor_t* dev,
lis3dh_int_event_source_t* source,
lis3dh_int_event_gen_t gen);
/**
* @brief Set the configuration of the click detection interrupt generator
*
* Set the configuration for interrupts that are generated when single or
* double clicks are detected.
*
* @param dev pointer to the sensor device data structure
* @param config pointer to the interrupt generator configuration
* @return true on success, false on error
*/
bool lis3dh_set_int_click_config (lis3dh_sensor_t* dev,
lis3dh_int_click_config_t* config);
/**
* @brief Get the configuration of the click detection interrupt generator
*
* Set the configuration for interrupts that are generated when single or
* double clicks are detected.
*
* @param dev pointer to the sensor device data structure
* @param config pointer to the interrupt generator configuration
* @return true on success, false on error
*/
bool lis3dh_get_int_click_config (lis3dh_sensor_t* dev,
lis3dh_int_click_config_t* config);
/**
* @brief Get the source of the click detection interrupt on signal INT1/INT2
*
* Returns a byte with flags that indicate the activity which triggered
* the interrupt signal (see CLICK_SRC register in datasheet for details)
*
* @param dev pointer to the sensor device data structure
* @param source pointer to the interrupt source
* @return true on success, false on error
*/
bool lis3dh_get_int_click_source (lis3dh_sensor_t* dev,
lis3dh_int_click_source_t* source);
/**
* @brief Set signal configuration for INT1 and INT2 signals
*
* @param dev pointer to the sensor device data structure
* @param level define interrupt signal as low or high active
* @return true on success, false on error
*/
bool lis3dh_config_int_signals (lis3dh_sensor_t* dev,
lis3dh_int_signal_level_t level);
/**
* @brief Config HPF (high pass filter)
*
* @param dev pointer to the sensor device data structure
* @param mode filter mode
* @param cutoff filter cutoff frequency (depends on ODR) [0 ... 3]
* @param data if true, use filtered data as sensor output
* @param click if true, use filtered data for CLICK function
* @param int1 if true, use filtered data for interrupt INT1 generation
* @param int2 if true, use filtered data for interrupt INT2 generation
* @return true on success, false on error
*/
bool lis3dh_config_hpf (lis3dh_sensor_t* dev,
lis3dh_hpf_mode_t mode, uint8_t cutoff,
bool data, bool click, bool int1, bool int2);
/**
* @brief Set HPF (high pass filter) reference
*
* Used to set the reference of HPF in reference mode *lis3dh_hpf_reference*.
* Used to reset the HPF in autoreset mode *lis3dh_hpf_autoreset*.
* Reference is given as two's complement.
*
* @param dev pointer to the sensor device data structure
* @param ref reference *lis3dh_hpf_reference* mode, otherwise ignored
* @return true on success, false on error
*/
bool lis3dh_set_hpf_ref (lis3dh_sensor_t* dev, int8_t ref);
/**
* @brief Get HPF (high pass filter) reference
*
* Used to reset the HPF in normal mode *lis3dh_hpf_normal*.
*
* @param dev pointer to the sensor device data structure
* @return HPF reference as two's complement
*/
int8_t lis3dh_get_hpf_ref (lis3dh_sensor_t* dev);
/**
* @brief Enable / disable ADC or temperature sensor
*
* @param dev pointer to the sensor device data structure
* @param enable if true, ADC inputs are enabled
* @param temp if true, ADC input 3 is the output of temperature sensor
* @return true on success, false on error
*/
int8_t lis3dh_enable_adc (lis3dh_sensor_t* dev, bool enable, bool temp);
/**
* @brief Get ADC input or temperature
*
* @param dev pointer to the sensor device data structure
* @param adc1 ADC input 1
* @param adc2 ADC input 2
* @param adc3 ADC input 3 or temperature in degree if enabled
* @return true on success, false on error
*/
bool lis3dh_get_adc (lis3dh_sensor_t* dev,
uint16_t* adc1, uint16_t* adc2, uint16_t* adc3);
// ---- Low level interface functions -----------------------------
/**
* @brief Direct write to register
*
* PLEASE NOTE: This function should only be used to do something special that
* is not covered by the high level interface AND if you exactly know what you
* do and what effects it might have. Please be aware that it might affect the
* high level interface.
*
* @param dev pointer to the sensor device data structure
* @param reg address of the first register to be changed
* @param data pointer to the data to be written to the register
* @param len number of bytes to be written to the register
* @return true on success, false on error
*/
bool lis3dh_reg_write (lis3dh_sensor_t* dev,
uint8_t reg, uint8_t *data, uint16_t len);
/**
* @brief Direct read from register
*
* PLEASE NOTE: This function should only be used to do something special that
* is not covered by the high level interface AND if you exactly know what you
* do and what effects it might have. Please be aware that it might affect the
* high level interface.
*
* @param dev pointer to the sensor device data structure
* @param reg address of the first register to be read
* @param data pointer to the data to be read from the register
* @param len number of bytes to be read from the register
* @return true on success, false on error
*/
bool lis3dh_reg_read (lis3dh_sensor_t* dev,
uint8_t reg, uint8_t *data, uint16_t len);
#ifdef __cplusplus
}
#endif /* End of CPP guard */
#endif /* __LIS3DH_H__ */

View file

@ -0,0 +1,81 @@
/**
* Driver for LIS3DH 3-axes digital accelerometer connected to I2C or SPI.
*
* This driver is for the usage with the ESP8266 and FreeRTOS (esp-open-rtos)
* [https://github.com/SuperHouse/esp-open-rtos]. It is also working with ESP32
* and ESP-IDF [https://github.com/espressif/esp-idf.git] as well as Linux
* based systems using a wrapper library for ESP8266 functions.
*
* ---------------------------------------------------------------------------
*
* The BSD License (3-clause license)
*
* Copyright (c) 2017 Gunar Schorcht (https://github.com/gschorcht)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Platform file: platform specific definitions, includes and functions
*/
#include "lis3dh_platform.h"
// platform specific SPI functions
static const spi_settings_t bus_settings = {
.mode = SPI_MODE0,
.freq_divider = SPI_FREQ_DIV_1M,
.msb = true,
.minimal_pins = false,
.endianness = SPI_LITTLE_ENDIAN
};
bool spi_device_init (uint8_t bus, uint8_t cs)
{
gpio_enable(cs, GPIO_OUTPUT);
gpio_write (cs, true);
return true;
}
size_t spi_transfer_pf(uint8_t bus, uint8_t cs, const uint8_t *mosi, uint8_t *miso, uint16_t len)
{
spi_settings_t old_settings;
spi_get_settings(bus, &old_settings);
spi_set_settings(bus, &bus_settings);
gpio_write(cs, false);
size_t transfered = spi_transfer (bus, (const void*)mosi, (void*)miso, len, SPI_8BIT);
gpio_write(cs, true);
spi_set_settings(bus, &old_settings);
return transfered;
}

View file

@ -0,0 +1,80 @@
/**
* Driver for LIS3DH 3-axes digital accelerometer connected to I2C or SPI.
*
* This driver is for the usage with the ESP8266 and FreeRTOS (esp-open-rtos)
* [https://github.com/SuperHouse/esp-open-rtos]. It is also working with ESP32
* and ESP-IDF [https://github.com/espressif/esp-idf.git] as well as Linux
* based systems using a wrapper library for ESP8266 functions.
*
* ---------------------------------------------------------------------------
*
* The BSD License (3-clause license)
*
* Copyright (c) 2017 Gunar Schorcht (https://github.com/gschorcht)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Platform file: platform specific definitions, includes and functions
*/
#ifndef __LIS3DH_PLATFORM_H__
#define __LIS3DH_PLATFORM_H__
#if !defined(ESP_OPEN_RTOS)
#define ESP_OPEN_RTOS 1
#endif
#ifdef ESP_OPEN_RTOS // ESP8266
// platform specific includes
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "espressif/esp_common.h"
#include "espressif/sdk_private.h"
#include "esp/uart.h"
#include "esp/spi.h"
#include "i2c/i2c.h"
// platform specific SPI functions
#define spi_bus_init(bus,sck,miso,mosi) // not needed on ESP8266
extern bool spi_device_init (uint8_t bus, uint8_t cs);
extern size_t spi_transfer_pf (uint8_t bus, uint8_t cs,
const uint8_t *mosi, uint8_t *miso,
uint16_t len);
#endif // ESP_OPEN_RTOS
#endif // __LIS3DH_PLATFORM_H__

View file

@ -0,0 +1,355 @@
/**
* Driver for LIS3DH 3-axes digital accelerometer connected to I2C or SPI.
*
* This driver is for the usage with the ESP8266 and FreeRTOS (esp-open-rtos)
* [https://github.com/SuperHouse/esp-open-rtos]. It is also working with ESP32
* and ESP-IDF [https://github.com/espressif/esp-idf.git] as well as Linux
* based systems using a wrapper library for ESP8266 functions.
*
* ---------------------------------------------------------------------------
*
* The BSD License (3-clause license)
*
* Copyright (c) 2017 Gunar Schorcht (https://github.com/gschorcht)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO Activity SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __LIS3DH_TYPES_H__
#define __LIS3DH_TYPES_H__
#include "stdint.h"
#include "stdbool.h"
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief Output data rates (ODR), related to resolution modes
*/
typedef enum {
lis3dh_power_down = 0, // power down mode
lis3dh_odr_1, // high resolution / normal / low power 1 Hz
lis3dh_odr_10, // high resolution / normal / low power 10 Hz
lis3dh_odr_25, // high resolution / normal / low power 25 Hz
lis3dh_odr_50, // high resolution / normal / low power 50 Hz
lis3dh_odr_100, // high resolution / normal / low power 100 Hz
lis3dh_odr_200, // high resolution / normal / low power 200 Hz
lis3dh_odr_400, // high resolution / normal / low power 400 Hz
lis3dh_odr_1600, // low power mode 1.6 kHz
lis3dh_odr_5000, // normal 1.25 kHz / low power 5 kHz
} lis3dh_odr_mode_t;
/**
* @brief Resolution modes, related to output data rates (ODR)
*/
typedef enum {
lis3dh_low_power, // low power mode resolution ( 8 bit data)
lis3dh_normal, // normal mode resolution (10 bit data)
lis3dh_high_res // high resolution mode (12 bit data)
} lis3dh_resolution_t;
/**
* @brief Full scale measurement range
*/
typedef enum {
lis3dh_scale_2_g = 0, // default
lis3dh_scale_4_g,
lis3dh_scale_8_g,
lis3dh_scale_16_g
} lis3dh_scale_t;
/**
* @brief FIFO mode
*/
typedef enum {
lis3dh_bypass = 0, // default
lis3dh_fifo = 1,
lis3dh_stream = 2,
lis3dh_trigger= 3
} lis3dh_fifo_mode_t;
/**
* @brief Interrupt signals
*/
typedef enum {
lis3dh_int1_signal = 0,
lis3dh_int2_signal = 1
} lis3dh_int_signal_t;
/**
* @brief Inertial event interrupt generators
*/
typedef enum {
lis3dh_int_event1_gen = 0,
lis3dh_int_event2_gen = 1
} lis3dh_int_event_gen_t;
/**
* @brief Interrupt types for interrupt signals INT1/INT2
*/
typedef enum {
lis3dh_int_data_ready, // data ready for read interrupt (only INT1)
lis3dh_int_fifo_watermark, // FIFO exceeds the threshold (only INT1)
lis3dh_int_fifo_overrun, // FIFO is completely filled (only INT1)
lis3dh_int_event1, // inertial event interrupt 1
lis3dh_int_event2, // inertial event interrupt 2
lis3dh_int_click // click detection interrupt
} lis3dh_int_type_t;
/**
* @brief Data ready and FIFO status interrupt source for INT1
*/
typedef struct {
bool data_ready; // true when acceleration data are ready to read
bool fifo_watermark; // true when FIFO exceeds the FIFO threshold
bool fifo_overrun; // true when FIFO is completely filled
} lis3dh_int_data_source_t;
/**
* @brief Inertial interrupt generator configuration for INT1/INT2
*
* Inertial events are: wake-up, free-fall, 6D/4D detection.
*/
typedef struct {
enum { // interrupt mode
lis3dh_wake_up, // AOI = 0, 6D = 0
lis3dh_free_fall, // AOI = 1, 6D = 0
lis3dh_6d_movement, // AOI = 0, 6D = 1, D4D = 0
lis3dh_6d_position, // AOI = 1, 6D = 1, D4D = 0
lis3dh_4d_movement, // AOI = 0, 6D = 1, D4D = 1
lis3dh_4d_position, // AOI = 1, 6D = 1, D4D = 1
} mode;
uint8_t threshold; // threshold used for comparison for all axes
bool x_low_enabled; // x lower than threshold interrupt enabled
bool x_high_enabled; // x higher than threshold interrupt enabled
bool y_low_enabled; // y lower than threshold interrupt enabled
bool y_high_enabled; // y higher than threshold interrupt enabled
bool z_low_enabled; // z lower than threshold interrupt enabled
bool z_high_enabled; // z higher than threshold interrupt enabled
bool latch; // latch the interrupt when true until the
// interrupt source has been read
uint8_t duration; // duration in 1/ODR an interrupt condition has
// to be given before the interrupt is generated
} lis3dh_int_event_config_t;
/**
* @brief Inertial event source type for interrupt generator INT1/INT2
*/
typedef struct {
bool active:1; // true - one ore more events occured
bool x_low :1; // true - x lower than threshold event
bool x_high:1; // true - x higher than threshold event
bool y_low :1; // true - z lower than threshold event
bool y_high:1; // true - z higher than threshold event
bool z_low :1; // true - z lower than threshold event
bool z_high:1; // true - z higher than threshold event
} lis3dh_int_event_source_t;
/**
* @brief Click interrupt configuration for interrupt signals INT1/INT2
*/
typedef struct {
bool x_single; // x-axis single tap interrupt enabled
bool x_double; // x-axis double tap interrupt enabled
bool y_single; // y-axis single tap interrupt enabled
bool y_double; // y-axis double tap interrupt enabled
bool z_single; // z-axis single tap interrupt enabled
bool z_double; // z-axis double tap interrupt enabled
uint8_t threshold; // threshold used for comparison for all axes
bool latch; // latch the interrupt when true until the
// interrupt source has been read
uint8_t time_limit; // maximum time interval between the start and the
// end of a cick (accel increases and falls back)
uint8_t time_latency; // click detection is disabled for that time after
// a was click detected (in 1/ODR)
uint8_t time_window; // time interval in which the second click has to
// to be detected in double clicks (in 1/ODR)
} lis3dh_int_click_config_t;
/**
* @brief Click interrupt source for interrupt signals INT1/INT2
*/
typedef struct {
bool x_click:1; // click detected in x direction
bool y_click:1; // click detected in y direction
bool z_click:1; // click detected in z direction
bool sign :1; // click sign (0 - posisitive, 1 - negative)
bool s_click:1; // single click detected
bool d_click:1; // double click detected
bool active :1; // true - one ore more event occured
} lis3dh_int_click_source_t;
/**
* @brief INT1, INT2 signal activity level
*/
typedef enum {
lis3dh_high_active = 0,
lis3dh_low_active
} lis3dh_int_signal_level_t;
/**
* @brief Raw data set as two complements
*/
typedef struct {
int16_t ax; // acceleration on x axis
int16_t ay; // acceleration on y axis
int16_t az; // acceleration on z axis
} lis3dh_raw_data_t;
/**
* @brief Raw data FIFO type
*/
typedef lis3dh_raw_data_t lis3dh_raw_data_fifo_t[32];
/**
* @brief Floating point output value set in g
*/
typedef struct {
float ax; // acceleration on x axis
float ay; // acceleration on y axis
float az; // acceleration on z axis
} lis3dh_float_data_t;
/**
* @brief Floating point output value FIFO type
*/
typedef lis3dh_float_data_t lis3dh_float_data_fifo_t[32];
/**
* @brief HPF (high pass filter) modes
*/
typedef enum {
lis3dh_hpf_normal = 0, // normal mode (reset by reading reference)
lis3dh_hpf_reference, // reference signal for filtering
lis3dh_hpf_normal_x, // normal mode
lis3dh_hpf_autoreset // autoreset on interrupt Activity
} lis3dh_hpf_mode_t;
/**
* @brief LIS3DH sensor device data structure type
*/
typedef struct {
int error_code; // error code of last operation
uint8_t bus; // I2C = x, SPI = 1
uint8_t addr; // I2C = slave address, SPI = 0
uint8_t cs; // ESP8266, ESP32: GPIO used as SPI CS
// __linux__: device index
lis3dh_scale_t scale; // full range scale (default 2 g)
lis3dh_resolution_t res; // resolution used
lis3dh_fifo_mode_t fifo_mode; // FIFO operation mode (default bypass)
bool fifo_first; // first FIFO access
} lis3dh_sensor_t;
#ifdef __cplusplus
}
#endif /* End of CPP guard */
#endif /* __LIS3DH_TYPES_H__ */