minor changes and typos

This commit is contained in:
Gunar Schorcht 2017-12-30 15:11:13 +01:00
parent 814e4405dc
commit 85ad051e83
6 changed files with 289 additions and 243 deletions

View file

@ -33,17 +33,16 @@
// use following constants to define the example mode // use following constants to define the example mode
// #define SPI_USED // if defined SPI is used, otherwise I2C // #define SPI_USED // if defined SPI is used, otherwise I2C
// #define INT1_USED // axes movement / wake up interrupts // #define INT_EVENT // event interrupts used (axes movement and wake up)
// #define INT2_USED // data ready and FIFO status interrupts // #define INT_DATA // data interrupts used (data ready and FIFO status)
// #define FIFO_MODE // multiple sample read mode // #define FIFO_MODE // multiple sample read mode
#if defined(INT1_USED) || defined(INT2_USED) #if defined(INT_EVENT) || defined(INT_DATA)
#define INT_USED #define INT_USED
#endif #endif
/* -- includes -------------------------------------------------- */ /* -- includes -------------------------------------------------- */
#include <string.h>
#include "l3gd20h.h" #include "l3gd20h.h"
/* -- platform dependent definitions ---------------------------- */ /* -- platform dependent definitions ---------------------------- */
@ -149,21 +148,21 @@ void user_task_interrupt (void *pvParameters)
{ {
if (gpio_num == INT1_PIN) if (gpio_num == INT1_PIN)
{ {
l3gd20h_int1_source_t source; l3gd20h_int_event_source_t source;
// get the source of the interrupt and reset INT1 signal // get the source of INT1 reset INT1 signal
l3gd20h_get_int1_source (sensor, &source); l3gd20h_get_int_event_source (sensor, &source);
// if data ready interrupt, get the results and do something with them // in case of data ready interrupt, get the results and do something with them
if (source.active) if (source.active)
read_data (); read_data ();
} }
else if (gpio_num == INT2_PIN) else if (gpio_num == INT2_PIN)
{ {
l3gd20h_int2_source_t source; l3gd20h_int_data_source_t source;
// get the source of the interrupt // get the source of INT2
l3gd20h_get_int2_source (sensor, &source); l3gd20h_get_int_data_source (sensor, &source);
// if data ready interrupt, get the results and do something with them // if data ready interrupt, get the results and do something with them
read_data(); read_data();
@ -265,40 +264,42 @@ void user_init(void)
// set polarity of INT signals if necessary // set polarity of INT signals if necessary
// l3gd20h_config_int_signals (dev, l3gd20h_high_active, l3gd20h_push_pull); // l3gd20h_config_int_signals (dev, l3gd20h_high_active, l3gd20h_push_pull);
#ifdef INT1_USED #ifdef INT_EVENT
// enable event interrupts // enable event interrupts (axis movement and wake up)
l3gd20h_int1_config_t int1_config; l3gd20h_int_event_config_t int_cfg;
l3gd20h_get_int1_config (sensor, &int1_config); l3gd20h_get_int_event_config (sensor, &int_cfg);
int1_config.x_high_enabled = true; int_cfg.x_high_enabled = true;
int1_config.y_high_enabled = true; int_cfg.y_high_enabled = true;
int1_config.z_high_enabled = true; int_cfg.z_high_enabled = true;
int1_config.x_low_enabled = false; int_cfg.x_low_enabled = false;
int1_config.y_low_enabled = false; int_cfg.y_low_enabled = false;
int1_config.z_low_enabled = false; int_cfg.z_low_enabled = false;
int1_config.x_threshold = 1000; int_cfg.x_threshold = 1000;
int1_config.y_threshold = 1000; int_cfg.y_threshold = 1000;
int1_config.z_threshold = 1000; int_cfg.z_threshold = 1000;
int1_config.filter = l3gd20h_hpf_only; int_cfg.filter = l3gd20h_hpf_only;
int1_config.and_or = false; int_cfg.and_or = false;
int1_config.duration = 0; int_cfg.duration = 0;
int1_config.latch = true; int_cfg.latch = true;
l3gd20h_set_int1_config (sensor, &int1_config); l3gd20h_set_int_event_config (sensor, &int_cfg);
#endif // INT1_USED l3gd20h_enable_int (sensor, l3gd20h_int_event, true);
#ifdef INT2_USED #endif // INT_EVENT
#ifdef INT_DATA
// enable data ready (DRDY) and FIFO interrupt signal *INT2* // enable data ready (DRDY) and FIFO interrupt signal *INT2*
// NOTE: DRDY and FIFO interrupts must not be enabled at the same time // NOTE: DRDY and FIFO interrupts must not be enabled at the same time
#ifdef FIFO_MODE #ifdef FIFO_MODE
l3gd20h_enable_int2 (sensor, l3gd20h_fifo_overrun, true); l3gd20h_enable_int (sensor, l3gd20h_int_fifo_overrun, true);
l3gd20h_enable_int2 (sensor, l3gd20h_fifo_threshold, true); l3gd20h_enable_int (sensor, l3gd20h_int_fifo_threshold, true);
#else #else
l3gd20h_enable_int2 (sensor, l3gd20h_data_ready, true); l3gd20h_enable_int (sensor, l3gd20h_int_data_ready, true);
#endif #endif
#endif // INT2_USED #endif // INT_DATA
#ifdef FIFO_MODE #ifdef FIFO_MODE
// clear FIFO and activate FIFO mode if needed // clear FIFO and activate FIFO mode if needed

View file

@ -16,7 +16,7 @@ L3GD20H is a low-power **3-axis angular rate sensor** connected to **I2C** or **
- 7 measuring rates from 12.5 Hz to 800 Hz with 4 bandwidths - 7 measuring rates from 12.5 Hz to 800 Hz with 4 bandwidths
- 16 bit angular rate value data output - 16 bit angular rate value data output
- 8 bit temperature data output - 8 bit temperature data output
- 2 dedicated interrupt signals (axis movement wake up and data ready) - 2 dedicated interrupt signals for data and event interrupts
- integrated high-pass filters with 3 modes and 10 different cut off frequencies - integrated high-pass filters with 3 modes and 10 different cut off frequencies
- embedded temperature sensor - embedded temperature sensor
- embedded 32 levels of 16 bit data output FIFO - embedded 32 levels of 16 bit data output FIFO
@ -141,7 +141,7 @@ The functions ```l3gd20h_get_float_data``` and ```l3gd20h_get_raw_data``` always
### Filters ### Filters
L3GD20H provides embedded low-pass as well as high-pass filtering capabilities to improve measurement results. L3GD20H provides embedded low-pass as well as high-pass filtering capabilities to improve measurement results.
It is possible to independently apply the filters on the output data and/or on the data used for selective axes movement / wake up interrupt generation (see below) separately. Please refer the [datasheet](http://www.st.com/resource/en/datasheet/l3gd20.pdf) or [application note](http://www.st.com/resource/en/application_note/dm00119036.pdf) for more details. It is possible to independently apply the filters on the output data and/or on the data used for event interrupt generation (selective axis movement and wake up, see below) separately. Please refer the [datasheet](http://www.st.com/resource/en/datasheet/l3gd20.pdf) or [application note](http://www.st.com/resource/en/application_note/dm00119036.pdf) for more details.
The filters applied to the output data are selected with function ```l3gd20h_select_output_filter```. Following selections are possible: The filters applied to the output data are selected with function ```l3gd20h_select_output_filter```. Following selections are possible:
@ -152,7 +152,7 @@ l3gd20h_hpf_only | x | -
l3gd20h_lpf2_only | - | x l3gd20h_lpf2_only | - | x
l3gd20h_hpf_and_lpf2 | x | x l3gd20h_hpf_and_lpf2 | x | x
These filters can also be applied to data used for selective axes movement / wake up interrupt generation. The filter mode is defined by member ```filter``` in the settings for interrupt configuration, see function ```l3gd20h_set_int1_config```. These filters can also be applied to data used for event interrupt generation (selective axis movement and wake up). The filter mode is defined by member ```filter``` in the settings of interrupt generator configuration, see function ```l3gd20h_set_int_event_config```.
While the cutoff frequency of the low pass filter (LPF2) is fixed and depends only on the output data rate (ODR), the mode and the cutoff frequency of the high pass filter can be configured using function ```l3gd20h_config_hpf```. Following HPF modes are available: While the cutoff frequency of the low pass filter (LPF2) is fixed and depends only on the output data rate (ODR), the mode and the cutoff frequency of the high pass filter can be configured using function ```l3gd20h_config_hpf```. Following HPF modes are available:
@ -177,7 +177,7 @@ l3gd20h_get_hpf_ref (sensor);
... ...
``` ```
**Please note:** Since same filters are used for the output data as well as the data used for selective axes movement / wake up interrupt generation, the configuration of the filters always affects both data. **Please note:** Since same filters are used for the output data as well as the data used for event interrupt generation (selective axes movement / wake up), the configuration of the filters always affects both data.
### FIFO ### FIFO
@ -243,37 +243,37 @@ void user_task_periodic (void *pvParameters)
The L3GD20H allows to activate interrupts on two dedicated interrupt signals The L3GD20H allows to activate interrupts on two dedicated interrupt signals
- for data ready and FIFO interrupts (**```DRDY/INT2```**), and - for data interrupts (data ready and FIFO status) on signal **```DRDY/INT2```**, and
- for axes movement / wake up interrupts (**```INT1```**). - for event interrupts (axis movement and wake up) on signal **```INT1```**.
#### Data ready and FIFO interrupts (```DRDY/INT2```) #### Data interrupts (data ready and FIFO status) on signal **```DRDY/INT2```**
Interrupts on signal ```DRDY/INT2``` can be generated by following sources: Interrupts on signal ```DRDY/INT2``` can be generated by following sources:
Interrupt source | Driver symbol Interrupt source | Driver symbol
:-----------------|:------------- :-----------------|:-------------
Output data become ready to read | l3gd20h_data_ready Output data become ready to read | l3gd20h_int_data_ready
FIFO content exceeds the watermark level | l3gd20h_fifo_threshold FIFO content exceeds the watermark level | l3gd20h_int_fifo_threshold
FIFO is completely filled | l3gd20h_fifo_overrun FIFO is completely filled | l3gd20h_int_fifo_overrun
FIFO becomes empty | l3gd20h_fifo_empty FIFO becomes empty | l3gd20h_int_fifo_empty
Each of these interrupt sources can be enabled or disabled separately with function ```l3gd20h_enable_int2```. By default all interrupt sources are disabled. Each of these interrupt sources can be enabled or disabled separately with function ```l3gd20h_enable_int```. By default all interrupt sources are disabled.
``` ```
l3gd20h_enable_int2 (sensor, l3gd20h_data_ready, true); l3gd20h_enable_int (sensor, l3gd20h_int_data_ready, true);
``` ```
Whenever the interrupt signal ```DRDY/INT2``` is generated, function ```l3gd20h_get_int2_source``` can be used to determine the source of the interrupt signal. This function returns a data structure of type ```l3gd20h_int2_source_t``` that contains a boolean member for each source that can be tested for true. Whenever the interrupt signal ```DRDY/INT2``` is generated, function ```l3gd20h_get_int_data_source``` can be used to determine the source of the interrupt signal. This function returns a data structure of type ```l3gd20h_int_data_source_t``` that contains a boolean member for each source that can be tested for true.
``` ```
void int2_handler () void int2_handler ()
{ {
l3gd20h_int2_source_t source; l3gd20h_int_data_source_t source;
// get interrupt source of INT2 // get the interrupt source of INT2
l3gd20h_get_int2_source (sensor, &source); l3gd20h_get_int_data_source (sensor, &source);
// if data ready interrupt, get the results and do something with them // in case of data ready interrupt, get the results and do something with them
if (source.data_ready) if (source.data_ready)
{ {
l3gd20h_get_float_data (sensor, &data) l3gd20h_get_float_data (sensor, &data)
@ -284,7 +284,7 @@ void int2_handler ()
} }
``` ```
#### Axes movement / wake up interrupts (**```INT1```**) #### Event interrupts (Axes movement and wake up) on signal **```INT1```**
This interrupt signal allows to recognize independent rotations of the x, y and z axes. For this purpose, a separate threshold can be defined for each axis. If activated, the angular rate of each axis is compared with its threshold to check whether it is below or above the threshold. The results of all activated comparisons are combined OR or AND to generate the interrupt signal. This interrupt signal allows to recognize independent rotations of the x, y and z axes. For this purpose, a separate threshold can be defined for each axis. If activated, the angular rate of each axis is compared with its threshold to check whether it is below or above the threshold. The results of all activated comparisons are combined OR or AND to generate the interrupt signal.
@ -294,39 +294,40 @@ The configuration of the thresholds, the activated comparisons and selected AND/
- **Axis movement wake up (WU)** means that the angular rate of any axis is above its threshold (OR). - **Axis movement wake up (WU)** means that the angular rate of any axis is above its threshold (OR).
To configure the axes movements and wake up interrupts, the function ```l3gd20h_set_int1_config``` has to be used with a parameter of structured data type ```l3gd20h_int1_config_t``` which contains the configuration. For example, selective axis movement recognition (SA) for the z-axis could be configured as following: To configure event interrupts, the function ```l3gd20h_set_int_event_config``` has to be used with a parameter of structured data type ```l3gd20h_int_event_config_t``` which contains the configuration. For example, selective axis movement recognition (SA) for the z-axis could be configured as following:
``` ```
l3gd20h_int1_config_t int1_config; l3gd20h_int_event_config_t int_cfg;
// thresholds // thresholds
int1_config.x_threshold = 100; int_cfg.x_threshold = 100;
int1_config.y_threshold = 100; int_cfg.y_threshold = 100;
int1_config.z_threshold = 1000; int_cfg.z_threshold = 1000;
// x axis below threshold // x axis below threshold
int1_config.x_low_enabled = false; int_cfg.x_low_enabled = false;
int1_config.x_high_enabled = true; int_cfg.x_high_enabled = true;
// y axis below threshold // y axis below threshold
int1_config.y_low_enabled = true; int_cfg.y_low_enabled = true;
int1_config.y_high_enabled = false; int_cfg.y_high_enabled = false;
// z axis below threshold // z axis below threshold
int1_config.z_low_enabled = false; int_cfg.z_low_enabled = false;
int1_config.z_high_enabled = true; int_cfg.z_high_enabled = true;
// AND combination of all conditions // AND combination of all conditions
int1_config.and_or = true; int_cfg.and_or = true;
// further parameters // further parameters
int1_config.filter = l3gd20h_hpf_only; int_cfg.filter = l3gd20h_hpf_only;
int1_config.latch = true; int_cfg.latch = true;
int1_config.duration = 0; int_cfg.duration = 0;
int1_config.wait = false; int_cfg.wait = false;
// set configuration // set the configuration and enable the interrupt
l3gd20h_set_int1_config (sensor, &int1_config); l3gd20h_set_int_cfg (sensor, &int_cfg);
l3gd20h_enable_int (sensor, l3gd20h_int_event, true);
``` ```
Furthermore, with this data structure it is also configured Furthermore, with this data structure it is also configured
@ -341,10 +342,10 @@ As with data ready and FIFO interrupts, function ```l3gd20h_get_int1_source``` c
``` ```
void int1_handler () void int1_handler ()
{ {
l3gd20h_int1_source_t source; l3gd20h_int_event_source_t source;
// get interrupt source of INT1 // get the source of INT1 reset INT1 signal
l3gd20h_get_int1_source (sensor, &source); l3gd20h_get_int_event_source (sensor, &source);
// if all conditions where true interrupt // if all conditions where true interrupt
if (source.active) if (source.active)
@ -360,30 +361,31 @@ void int1_handler ()
**Please note** Activating all threshold comparisons and the OR combination is the most flexible way, functions like selective axis movement can then be realized combining the different interrupt sources. Following example realizes also the selective axis movement recognition (SA) for the z-axis. **Please note** Activating all threshold comparisons and the OR combination is the most flexible way, functions like selective axis movement can then be realized combining the different interrupt sources. Following example realizes also the selective axis movement recognition (SA) for the z-axis.
``` ```
l3gd20h_int1_config_t int1_config; l3gd20h_int_event_config_t int_cfg;
// thresholds // thresholds
int1_config.x_threshold = 100; int_cfg.x_threshold = 100;
int1_config.y_threshold = 100; int_cfg.y_threshold = 100;
int1_config.z_threshold = 100; int_cfg.z_threshold = 100;
// x axis // x axis
int1_config.x_low_enabled = true; int_cfg.x_low_enabled = true;
int1_config.x_high_enabled = true; int_cfg.x_high_enabled = true;
// y axis // y axis
int1_config.y_low_enabled = true; int_cfg.y_low_enabled = true;
int1_config.y_high_enabled = true; int_cfg.y_high_enabled = true;
// z axis // z axis
int1_config.z_low_enabled = true; int_cfg.z_low_enabled = true;
int1_config.z_high_enabled = true; int_cfg.z_high_enabled = true;
// OR combination of all conditions // OR combination of all conditions
int1_config.and_or = false; int_cfg.and_or = false;
... ...
// set configuration // set the configuration and enable the interrupt
l3gd20h_set_int1_config (sensor, &int1_config); l3gd20h_set_int_cfg (sensor, &int_cfg);
l3gd20h_enable_int (sensor, l3gd20h_int_event, true);
``` ```
``` ```
@ -391,9 +393,10 @@ void int1_handler ()
{ {
l3gd20h_int1_source_t source; l3gd20h_int1_source_t source;
// get interrupt source of INT1 // get the interrupt source of INT1
l3gd20h_get_int1_source (sensor, &source); l3gd20h_get_int1_source (sensor, &source);
// if all conditions where true interrupt
if (source.y_low && source.y_low && source.z_high) if (source.y_low && source.y_low && source.z_high)
{ {
// selective axis movement of z-axis // selective axis movement of z-axis
@ -590,7 +593,7 @@ The user task simply tests periodically with a higher rate than the output data
A different approach is to use one of the **interrupts** INT1 or INT2. A different approach is to use one of the **interrupts** INT1 or INT2.
- **```DRDY/INT2```** is triggered when new data become available or the FIFO queue status changes. - **```DRDY/INT2```** is triggered when new data become available or the FIFO queue status changes.
- **```INT1```** is triggered when configured axes movements are recognized. - **```INT1```** is triggered when configured axis movements are recognized.
In both cases, the user has to implement an interrupt handler that either fetches the data directly or triggers a task, that is waiting to fetch the data. In both cases, the user has to implement an interrupt handler that either fetches the data directly or triggers a task, that is waiting to fetch the data.
@ -669,14 +672,46 @@ l3gd20h_set_mode (sensor, l3gd20h_normal_odr_12_5, 3, true, true, true);
## Full Example ## Full Example
``` ```
/* -- use following constants to define the example mode ----------- */ /**
* 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
* for axes movement wake up *INT1* and data ready interrupt *INT2* is used
* or the new data are fetched periodically.
*
* Harware configuration:
*
* I2C
*
* +-----------------+ +----------+
* | ESP8266 / ESP32 | | L3GD20H |
* | | | |
* | GPIO 14 (SCL) ----> SCL |
* | GPIO 13 (SDA) <---> SDA |
* | GPIO 5 <---- INT1 |
* | GPIO 4 <---- DRDY/INT2|
* +-----------------+ +----------+
*
* SPI
*
* +---------------+ +----------+ +---------------+ +----------+
* | ESP8266 | | L3GD20H | | ESP32 | | L3GD20H |
* | | | | | | | |
* | 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 |
* | GPIO 4 <---- DRDY/INT2| | GPIO 4 <---- DRDY/INT2|
* +---------------+ +---------+ +---------------+ +----------+
*/
// use following constants to define the example mode
// #define SPI_USED // if defined SPI is used, otherwise I2C // #define SPI_USED // if defined SPI is used, otherwise I2C
// #define INT1_USED // axes movement / wake up interrupts // #define INT_EVENT // event interrupts used (axes movement and wake up)
// #define INT2_USED // data ready and FIFO status interrupts // #define INT_DATA // data interrupts used (data ready and FIFO status)
// #define FIFO_MODE // multiple sample read mode // #define FIFO_MODE // multiple sample read mode
#if defined(INT1_USED) || defined(INT2_USED) #if defined(INT_EVENT) || defined(INT_DATA)
#define INT_USED #define INT_USED
#endif #endif
@ -688,10 +723,10 @@ l3gd20h_set_mode (sensor, l3gd20h_normal_odr_12_5, 3, true, true, true);
#ifdef ESP_PLATFORM // ESP32 (ESP-IDF) #ifdef ESP_PLATFORM // ESP32 (ESP-IDF)
// user task stack depth for ESP32 // user task stack depth
#define TASK_STACK_DEPTH 2048 #define TASK_STACK_DEPTH 2048
// SPI interface definitions for ESP32 // define SPI interface for L3GD20H sensors
#define SPI_BUS HSPI_HOST #define SPI_BUS HSPI_HOST
#define SPI_SCK_GPIO 16 #define SPI_SCK_GPIO 16
#define SPI_MOSI_GPIO 17 #define SPI_MOSI_GPIO 17
@ -700,10 +735,10 @@ l3gd20h_set_mode (sensor, l3gd20h_normal_odr_12_5, 3, true, true, true);
#else // ESP8266 (esp-open-rtos) #else // ESP8266 (esp-open-rtos)
// user task stack depth for ESP8266 // user task stack depth
#define TASK_STACK_DEPTH 256 #define TASK_STACK_DEPTH 256
// SPI interface definitions for ESP8266 // define SPI interface for L3GD20H sensors
#define SPI_BUS 1 #define SPI_BUS 1
#define SPI_SCK_GPIO 14 #define SPI_SCK_GPIO 14
#define SPI_MOSI_GPIO 13 #define SPI_MOSI_GPIO 13
@ -712,13 +747,13 @@ l3gd20h_set_mode (sensor, l3gd20h_normal_odr_12_5, 3, true, true, true);
#endif // ESP_PLATFORM #endif // ESP_PLATFORM
// I2C interface defintions for ESP32 and ESP8266 // define I2C interfaces for L3GD20H sensors
#define I2C_BUS 0 #define I2C_BUS 0
#define I2C_SCL_PIN 14 #define I2C_SCL_PIN 14
#define I2C_SDA_PIN 13 #define I2C_SDA_PIN 13
#define I2C_FREQ I2C_FREQ_100K #define I2C_FREQ I2C_FREQ_100K
// interrupt GPIOs defintions for ESP8266 and ESP32 // define GPIOs for interrupt
#define INT1_PIN 5 #define INT1_PIN 5
#define INT2_PIN 4 #define INT2_PIN 4
@ -787,21 +822,21 @@ void user_task_interrupt (void *pvParameters)
{ {
if (gpio_num == INT1_PIN) if (gpio_num == INT1_PIN)
{ {
l3gd20h_int1_source_t source; l3gd20h_int_event_source_t source;
// get the source of the interrupt and reset INT1 signal // get the source of INT1 reset INT1 signal
l3gd20h_get_int1_source (sensor, &source); l3gd20h_get_int_event_source (sensor, &source);
// if data ready interrupt, get the results and do something with them // in case of data ready interrupt, get the results and do something with them
if (source.active) if (source.active)
read_data (); read_data ();
} }
else if (gpio_num == INT2_PIN) else if (gpio_num == INT2_PIN)
{ {
l3gd20h_int2_source_t source; l3gd20h_int_data_source_t source;
// get the source of the interrupt // get the source of INT2
l3gd20h_get_int2_source (sensor, &source); l3gd20h_get_int_data_source (sensor, &source);
// if data ready interrupt, get the results and do something with them // if data ready interrupt, get the results and do something with them
read_data(); read_data();
@ -903,40 +938,42 @@ void user_init(void)
// set polarity of INT signals if necessary // set polarity of INT signals if necessary
// l3gd20h_config_int_signals (dev, l3gd20h_high_active, l3gd20h_push_pull); // l3gd20h_config_int_signals (dev, l3gd20h_high_active, l3gd20h_push_pull);
#ifdef INT1_USED #ifdef INT_EVENT
// enable event interrupts // enable event interrupts (axis movement and wake up)
l3gd20h_int1_config_t int1_config; l3gd20h_int_event_config_t int_cfg;
l3gd20h_get_int1_config (sensor, &int1_config); l3gd20h_get_int_event_config (sensor, &int_cfg);
int1_config.x_high_enabled = true; int_cfg.x_high_enabled = true;
int1_config.y_high_enabled = true; int_cfg.y_high_enabled = true;
int1_config.z_high_enabled = true; int_cfg.z_high_enabled = true;
int1_config.x_low_enabled = false; int_cfg.x_low_enabled = false;
int1_config.y_low_enabled = false; int_cfg.y_low_enabled = false;
int1_config.z_low_enabled = false; int_cfg.z_low_enabled = false;
int1_config.x_threshold = 1000; int_cfg.x_threshold = 1000;
int1_config.y_threshold = 1000; int_cfg.y_threshold = 1000;
int1_config.z_threshold = 1000; int_cfg.z_threshold = 1000;
int1_config.filter = l3gd20h_hpf_only; int_cfg.filter = l3gd20h_hpf_only;
int1_config.and_or = false; int_cfg.and_or = false;
int1_config.duration = 0; int_cfg.duration = 0;
int1_config.latch = true; int_cfg.latch = true;
l3gd20h_set_int1_config (sensor, &int1_config); l3gd20h_set_int_event_config (sensor, &int_cfg);
#endif // INT1_USED l3gd20h_enable_int (sensor, l3gd20h_int_event, true);
#ifdef INT2_USED #endif // INT_EVENT
#ifdef INT_DATA
// enable data ready (DRDY) and FIFO interrupt signal *INT2* // enable data ready (DRDY) and FIFO interrupt signal *INT2*
// NOTE: DRDY and FIFO interrupts must not be enabled at the same time // NOTE: DRDY and FIFO interrupts must not be enabled at the same time
#ifdef FIFO_MODE #ifdef FIFO_MODE
l3gd20h_enable_int2 (sensor, l3gd20h_fifo_overrun, true); l3gd20h_enable_int (sensor, l3gd20h_int_fifo_overrun, true);
l3gd20h_enable_int2 (sensor, l3gd20h_fifo_threshold, true); l3gd20h_enable_int (sensor, l3gd20h_int_fifo_threshold, true);
#else #else
l3gd20h_enable_int2 (sensor, l3gd20h_data_ready, true); l3gd20h_enable_int (sensor, l3gd20h_int_data_ready, true);
#endif #endif
#endif // INT2_USED #endif // INT_DATA
#ifdef FIFO_MODE #ifdef FIFO_MODE
// clear FIFO and activate FIFO mode if needed // clear FIFO and activate FIFO mode if needed

View file

@ -1,6 +1,6 @@
# Component makefile for extras/l3gd20h # Component makefile for extras/l3gd20h
# expected anyone using SHT3x driver includes it as 'l3gd20h/l3gd20h.h' # expected anyone using L3GD20H driver includes it as 'l3gd20h/l3gd20h.h'
INC_DIRS += $(l3gd20h_ROOT).. INC_DIRS += $(l3gd20h_ROOT)..
INC_DIRS += $(l3gd20h_ROOT) INC_DIRS += $(l3gd20h_ROOT)

View file

@ -498,8 +498,40 @@ uint8_t l3gd20h_get_raw_data_fifo (l3gd20h_sensor_t* dev, l3gd20h_raw_data_fifo_
} }
bool l3gd20h_set_int1_config (l3gd20h_sensor_t* dev, bool l3gd20h_enable_int (l3gd20h_sensor_t* dev,
l3gd20h_int1_config_t* config) l3gd20h_int_types_t type, bool value)
{
if (!dev) return false;
dev->error_code = L3GD20H_OK;
uint8_t mask;
switch (type)
{
case l3gd20h_int_data_ready: mask = L3GD20H_INT2_DRDY; break;
case l3gd20h_int_fifo_threshold: mask = L3GD20H_INT2_FTH; break;
case l3gd20h_int_fifo_overrun: mask = L3GD20H_INT2_ORUN; break;
case l3gd20h_int_fifo_empty: mask = L3GD20H_INT2_EMPTY; break;
case l3gd20h_int_event: mask = L3GD20H_INT1_IG; break;
default: dev->error_code = L3GD20H_WRONG_INT_TYPE;
error_dev ("Wrong interrupt type", __FUNCTION__, dev);
return false;
}
if (!l3gd20h_update_reg (dev, L3GD20H_REG_CTRL3, mask, value))
{
error_dev ("Could not %s interrupt INT2", __FUNCTION__, dev, value ? "enable" : "disable");
dev->error_code |= L3GD20H_CONFIG_INT2_FAILED;
return false;
}
return true;
}
bool l3gd20h_set_int_event_config (l3gd20h_sensor_t* dev,
l3gd20h_int_event_config_t* config)
{ {
if (!dev || !config) return false; if (!dev || !config) return false;
@ -538,10 +570,7 @@ bool l3gd20h_set_int1_config (l3gd20h_sensor_t* dev,
!l3gd20h_write_reg (dev, L3GD20H_REG_IG_DURATION, &ig_dur, 1) || !l3gd20h_write_reg (dev, L3GD20H_REG_IG_DURATION, &ig_dur, 1) ||
// write INT1 configuration to IG_CFG // write INT1 configuration to IG_CFG
!l3gd20h_write_reg (dev, L3GD20H_REG_IG_CFG, &ig_cfg, 1) || !l3gd20h_write_reg (dev, L3GD20H_REG_IG_CFG, &ig_cfg, 1))
// enable or disable the INT1 signal in register CTRL3
!l3gd20h_update_reg (dev, L3GD20H_REG_CTRL3, L3GD20H_INT1_IG, (ig_cfg & 0x3f) ? 1 : 0))
{ {
error_dev ("Could not configure interrupt INT1", __FUNCTION__, dev); error_dev ("Could not configure interrupt INT1", __FUNCTION__, dev);
dev->error_code |= L3GD20H_CONFIG_INT1_FAILED; dev->error_code |= L3GD20H_CONFIG_INT1_FAILED;
@ -565,8 +594,8 @@ bool l3gd20h_set_int1_config (l3gd20h_sensor_t* dev,
} }
bool l3gd20h_get_int1_config (l3gd20h_sensor_t* dev, bool l3gd20h_get_int_event_config (l3gd20h_sensor_t* dev,
l3gd20h_int1_config_t* config) l3gd20h_int_event_config_t* config)
{ {
if (!dev || !config) return false; if (!dev || !config) return false;
@ -617,14 +646,14 @@ bool l3gd20h_get_int1_config (l3gd20h_sensor_t* dev,
} }
bool l3gd20h_get_int1_source (l3gd20h_sensor_t* dev, l3gd20h_int1_source_t* source) bool l3gd20h_get_int_event_source (l3gd20h_sensor_t* dev, l3gd20h_int_event_source_t* source)
{ {
if (!dev || !source) return false; if (!dev || !source) return false;
dev->error_code = L3GD20H_OK; dev->error_code = L3GD20H_OK;
l3gd20h_int1_source_t ig_cfg; l3gd20h_int_event_source_t ig_cfg;
l3gd20h_int1_source_t ig_src; l3gd20h_int_event_source_t ig_src;
if (!l3gd20h_read_reg (dev, L3GD20H_REG_IG_CFG, (uint8_t*)&ig_cfg, 1) || if (!l3gd20h_read_reg (dev, L3GD20H_REG_IG_CFG, (uint8_t*)&ig_cfg, 1) ||
!l3gd20h_read_reg (dev, L3GD20H_REG_IG_SRC, (uint8_t*)&ig_src, 1)) !l3gd20h_read_reg (dev, L3GD20H_REG_IG_SRC, (uint8_t*)&ig_src, 1))
@ -646,38 +675,7 @@ bool l3gd20h_get_int1_source (l3gd20h_sensor_t* dev, l3gd20h_int1_source_t* sour
} }
bool l3gd20h_enable_int2 (l3gd20h_sensor_t* dev, bool l3gd20h_get_int_data_source (l3gd20h_sensor_t* dev, l3gd20h_int_data_source_t* source)
l3gd20h_int2_types_t type, bool value)
{
if (!dev) return false;
dev->error_code = L3GD20H_OK;
uint8_t mask;
switch (type)
{
case l3gd20h_data_ready: mask = L3GD20H_INT2_DRDY; break;
case l3gd20h_fifo_threshold: mask = L3GD20H_INT2_FTH; break;
case l3gd20h_fifo_overrun: mask = L3GD20H_INT2_ORUN; break;
case l3gd20h_fifo_empty: mask = L3GD20H_INT2_EMPTY; break;
default: dev->error_code = L3GD20H_WRONG_INT_TYPE;
error_dev ("Wrong interrupt type", __FUNCTION__, dev);
return false;
}
if (!l3gd20h_update_reg (dev, L3GD20H_REG_CTRL3, mask, value))
{
error_dev ("Could not %s interrupt INT2", __FUNCTION__, dev, value ? "enable" : "disable");
dev->error_code |= L3GD20H_CONFIG_INT2_FAILED;
return false;
}
return true;
}
bool l3gd20h_get_int2_source (l3gd20h_sensor_t* dev, l3gd20h_int2_source_t* source)
{ {
if (!dev || !source) return false; if (!dev || !source) return false;

View file

@ -241,70 +241,68 @@ uint8_t l3gd20h_get_raw_data_fifo (l3gd20h_sensor_t* dev,
/** /**
* @brief Enable or disable interrupt signal INT1 (axis movement wake up) * @brief Enable / disable data or event interrupts on signal INT1/INT2
*
* Set the configuration for interrupts that are generated when a certain
* angular rate is higher or lower than defined thresholds. It enables the
* the interrupt if any interrupt source in the configuration is enabled and
* disables the interrupt in the case that all interrupt sources are disabled.
* *
* @param dev pointer to the sensor device data structure * @param dev pointer to the sensor device data structure
* @param config INT1 configuration * @param type type of the interrupt to be enabled/disabled
* @param value true to enable or false to disable the interrupt
* @return true on success, false on error * @return true on success, false on error
*/ */
bool l3gd20h_set_int1_config (l3gd20h_sensor_t* dev, bool l3gd20h_enable_int (l3gd20h_sensor_t* dev,
l3gd20h_int1_config_t* config); l3gd20h_int_types_t type, bool value);
/** /**
* @brief Get configuration for interrupt signal INT1 * @brief Set the configuration of the event interrupt generator
* *
* Get the configuration for interrupts that are generated when a certain * The event interrupt generator produces interrupts (axis movement and wake up)
* angular rate is higher or lower than defined thresholds. * on signal INT1 whenever the angular rate of one or more axes becomes higher
* or lower than defined thresholds.
* *
* @param dev pointer to the sensor device data structure * @param dev pointer to the sensor device data structure
* @param config INT1 configuration * @param config pointer to the interrupt generator configuration
* @return true on success, false on error * @return true on success, false on error
*/ */
bool l3gd20h_get_int1_config (l3gd20h_sensor_t* dev, bool l3gd20h_set_int_event_config (l3gd20h_sensor_t* dev,
l3gd20h_int1_config_t* config); l3gd20h_int_event_config_t* config);
/** /**
* @brief Get the source of the interrupt signal INT1 when happened * @brief Get the configuration of the event interrupt generator
*
* The event interrupt generator produces interrupts (axis movement and wake up)
* on signal INT1 whenever the angular rate of one or more axes becomes higher
* or lower than defined thresholds.
*
* @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 l3gd20h_get_int_event_config (l3gd20h_sensor_t* dev,
l3gd20h_int_event_config_t* config);
/**
* @brief Get the source of an event interrupt (axis movement and wake up)
* *
* @param dev pointer to the sensor device data structure * @param dev pointer to the sensor device data structure
* @param type pointer to the interrupt source * @param type pointer to the interrupt source
* @return true on success, false on error * @return true on success, false on error
*/ */
bool l3gd20h_get_int1_source (l3gd20h_sensor_t* dev, bool l3gd20h_get_int_event_source (l3gd20h_sensor_t* dev,
l3gd20h_int1_source_t* source); l3gd20h_int_event_source_t* source);
/** /**
* @brief Enable/disable interrupt signal INT2 (data ready / fifo) * @brief Get the source of a data interrupt (data ready or FIFO status)
*
* Enables or diables interrupts that are generated either when data are
* ready to read or FIFO events happen.
*
* @param dev pointer to the sensor device data structure
* @param type type of interrupt to be enabled/disabled
* @param value true to enable/false to disable the interrupt
* @return true on success, false on error
*/
bool l3gd20h_enable_int2 (l3gd20h_sensor_t* dev,
l3gd20h_int2_types_t type, bool value);
/**
* @brief Get the source of the interrupt signal INT2 when happened
* *
* @param dev pointer to the sensor device data structure * @param dev pointer to the sensor device data structure
* @param source pointer to the interrupt source * @param source pointer to the interrupt source
* @return true on success, false on error * @return true on success, false on error
*/ */
bool l3gd20h_get_int2_source (l3gd20h_sensor_t* dev, bool l3gd20h_get_int_data_source (l3gd20h_sensor_t* dev,
l3gd20h_int2_source_t* source); l3gd20h_int_data_source_t* source);
/** /**

View file

@ -56,7 +56,8 @@ extern "C"
/** /**
* @brief Output data rates (ODR) * @brief Output data rates (ODR)
*/ */
typedef enum { typedef enum
{
l3gd20h_power_down = 0, // power down mode l3gd20h_power_down = 0, // power down mode
l3gd20h_normal_odr_12_5, // normal mode with low output data rate 12.5 Hz l3gd20h_normal_odr_12_5, // normal mode with low output data rate 12.5 Hz
l3gd20h_normal_odr_25, // normal mode with low output data rate 25 Hz l3gd20h_normal_odr_25, // normal mode with low output data rate 25 Hz
@ -65,23 +66,27 @@ typedef enum {
l3gd20h_normal_odr_200, // normal mode with high output data rate 200 Hz l3gd20h_normal_odr_200, // normal mode with high output data rate 200 Hz
l3gd20h_normal_odr_400, // normal mode with high output data rate 400 Hz l3gd20h_normal_odr_400, // normal mode with high output data rate 400 Hz
l3gd20h_normal_odr_800, // normal mode with high output data rate 800 Hz l3gd20h_normal_odr_800, // normal mode with high output data rate 800 Hz
} l3gd20h_mode_t; } l3gd20h_mode_t;
/** /**
* @brief Sensitivity level * @brief Sensitivity level
*/ */
typedef enum { typedef enum
{
l3gd20h_scale_245dps = 0, // default l3gd20h_scale_245dps = 0, // default
l3gd20h_scale_500dps, l3gd20h_scale_500dps,
l3gd20h_scale_2000dps l3gd20h_scale_2000dps
} l3gd20h_scale_t; } l3gd20h_scale_t;
/** /**
* @brief FIFO mode * @brief FIFO mode
*/ */
typedef enum { typedef enum
{
l3gd20h_bypass = 0, // default l3gd20h_bypass = 0, // default
l3gd20h_fifo = 1, l3gd20h_fifo = 1,
l3gd20h_stream = 2, l3gd20h_stream = 2,
@ -89,27 +94,46 @@ typedef enum {
l3gd20h_bypass_to_stream = 5, l3gd20h_bypass_to_stream = 5,
l3gd20h_dynamic_stream = 6, l3gd20h_dynamic_stream = 6,
l3gd20h_bypass_to_fifo = 7 l3gd20h_bypass_to_fifo = 7
} l3gd20h_fifo_mode_t; } l3gd20h_fifo_mode_t;
/** /**
* @brief High pass filter (HPF) and low pass filter 2 (LPF2) modes * @brief High pass filter (HPF) and low pass filter 2 (LPF2) modes
*/ */
typedef enum { typedef enum
{
l3gd20h_no_filter = 0, // HPF not used, LPF2 not used l3gd20h_no_filter = 0, // HPF not used, LPF2 not used
l3gd20h_hpf_only, // HPF used, LPF2 not used l3gd20h_hpf_only, // HPF used, LPF2 not used
l3gd20h_lpf2_only, // HPF not used, LPF2 used l3gd20h_lpf2_only, // HPF not used, LPF2 used
l3gd20h_hpf_and_lpf2 // HPF used, LPF2 used l3gd20h_hpf_and_lpf2 // HPF used, LPF2 used
} l3gd20h_filter_t; } l3gd20h_filter_t;
/** /**
* @brief INT1 signal configuration (axis movement wake up interrupts) * @brief Interrupt types
*
* memset to 0 to disable all INT1 interrupt conditions (default)
*/ */
typedef struct { typedef enum {
l3gd20h_int_data_ready, // data are ready to read (INT2)
l3gd20h_int_fifo_threshold, // FIFO filling exceds FTH level (INT2)
l3gd20h_int_fifo_overrun, // FIFO is completely filled (INT2)
l3gd20h_int_fifo_empty, // FIFO becomes empty (INT2)
l3gd20h_int_event // angular rate of one or more axes becomes
// lower or higher than threshold (INT1)
} l3gd20h_int_types_t;
/**
* @brief Event interrupt generator configuration (axis movement and wake up)
*
* memset to 0 to disable all interrupt conditions (default)
*/
typedef struct
{
bool x_low_enabled; // x lower than threshold interrupt enabled bool x_low_enabled; // x lower than threshold interrupt enabled
bool x_high_enabled; // x higher than threshold interrupt enabled bool x_high_enabled; // x higher than threshold interrupt enabled
uint16_t x_threshold; // x threshold value uint16_t x_threshold; // x threshold value
@ -140,52 +164,40 @@ typedef struct {
bool counter_mode; // DCRM is not documented and not used therefore bool counter_mode; // DCRM is not documented and not used therefore
} l3gd20h_int1_config_t; } l3gd20h_int_event_config_t;
/** /**
* @brief INT1 source type (axis movement wake up interrupts) * @brief Event interrupt source (axis movement and wake up)
*/ */
typedef struct { typedef struct {
bool x_low :1; // true - x low event occured bool x_low :1; // true - x is lower event occured
bool x_high:1; // true - x high event occured bool x_high:1; // true - x is higher event occured
bool y_low :1; // true - z low event occured bool y_low :1; // true - z is lower event occured
bool y_high:1; // true - z high event occured bool y_high:1; // true - z is higher event occured
bool z_low :1; // true - z low event occured bool z_low :1; // true - z is lower event occured
bool z_high:1; // true - z high event occured bool z_high:1; // true - z is higher event occured
bool active:1; // true - one ore more have been generated bool active:1; // true - one ore more have been generated
} l3gd20h_int1_source_t; } l3gd20h_int_event_source_t;
/** /**
* @brief INT2 signal interrupt types (data ready and FIFO interrupts) * @brief Data interrupt source type (data ready and FIFO status)
*/
typedef enum {
l3gd20h_data_ready, // interrupt when data are ready to read
l3gd20h_fifo_threshold, // interrupt when FIFO filling >= FTH level
l3gd20h_fifo_overrun, // interrupt when FIFO is completely filled
l3gd20h_fifo_empty // interrupt when FIFO becomes empty
} l3gd20h_int2_types_t;
/**
* @brief INT2 source type (data ready and FIFO interrupts)
*/ */
typedef struct { typedef struct {
bool data_ready; // true when data are ready to read bool data_ready; // true when data are ready to read
bool fifo_threshold; // true when FIFO filling >= FTH level bool fifo_threshold; // true when FIFO filling >= FTH level
bool fifo_overrun; // true when FIFO is completely filled bool fifo_overrun; // true when FIFO is completely filled
bool fifo_empty; // true when FIFO is empty bool fifo_empty; // true when FIFO is empty
} l3gd20h_int2_source_t; } l3gd20h_int_data_source_t;
/** /**