You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
509 lines
14 KiB
509 lines
14 KiB
/** |
|
* @file sensor.h |
|
* |
|
* @brief Public APIs for the sensor driver. |
|
*/ |
|
|
|
/* |
|
* Copyright (c) 2016 Intel Corporation |
|
* |
|
* SPDX-License-Identifier: Apache-2.0 |
|
*/ |
|
#ifndef ZEPHYR_INCLUDE_SENSOR_H_ |
|
#define ZEPHYR_INCLUDE_SENSOR_H_ |
|
|
|
/** |
|
* @brief Sensor Interface |
|
* @defgroup sensor_interface Sensor Interface |
|
* @ingroup io_interfaces |
|
* @{ |
|
*/ |
|
|
|
#include <zephyr/types.h> |
|
#include <device.h> |
|
#include <errno.h> |
|
|
|
#ifdef __cplusplus |
|
extern "C" { |
|
#endif |
|
|
|
/** |
|
* @brief Representation of a sensor readout value. |
|
* |
|
* The value is represented as having an integer and a fractional part, |
|
* and can be obtained using the formula val1 + val2 * 10^(-6). Negative |
|
* values also adhere to the above formula, but may need special attention. |
|
* Here are some examples of the value representation: |
|
* |
|
* 0.5: val1 = 0, val2 = 500000 |
|
* -0.5: val1 = 0, val2 = -500000 |
|
* -1.0: val1 = -1, val2 = 0 |
|
* -1.5: val1 = -1, val2 = -500000 |
|
*/ |
|
struct sensor_value { |
|
/** Integer part of the value. */ |
|
s32_t val1; |
|
/** Fractional part of the value (in one-millionth parts). */ |
|
s32_t val2; |
|
}; |
|
|
|
/** |
|
* @brief Sensor channels. |
|
*/ |
|
enum sensor_channel { |
|
/** Acceleration on the X axis, in m/s^2. */ |
|
SENSOR_CHAN_ACCEL_X, |
|
/** Acceleration on the Y axis, in m/s^2. */ |
|
SENSOR_CHAN_ACCEL_Y, |
|
/** Acceleration on the Z axis, in m/s^2. */ |
|
SENSOR_CHAN_ACCEL_Z, |
|
/** Acceleration on the X, Y and Z axes. */ |
|
SENSOR_CHAN_ACCEL_XYZ, |
|
/** Angular velocity around the X axis, in radians/s. */ |
|
SENSOR_CHAN_GYRO_X, |
|
/** Angular velocity around the Y axis, in radians/s. */ |
|
SENSOR_CHAN_GYRO_Y, |
|
/** Angular velocity around the Z axis, in radians/s. */ |
|
SENSOR_CHAN_GYRO_Z, |
|
/** Angular velocity around the X, Y and Z axes. */ |
|
SENSOR_CHAN_GYRO_XYZ, |
|
/** Magnetic field on the X axis, in Gauss. */ |
|
SENSOR_CHAN_MAGN_X, |
|
/** Magnetic field on the Y axis, in Gauss. */ |
|
SENSOR_CHAN_MAGN_Y, |
|
/** Magnetic field on the Z axis, in Gauss. */ |
|
SENSOR_CHAN_MAGN_Z, |
|
/** Magnetic field on the X, Y and Z axes. */ |
|
SENSOR_CHAN_MAGN_XYZ, |
|
/** Device die temperature in degrees Celsius. */ |
|
SENSOR_CHAN_DIE_TEMP, |
|
/** Ambient temperature in degrees Celsius. */ |
|
SENSOR_CHAN_AMBIENT_TEMP, |
|
/** Pressure in kilopascal. */ |
|
SENSOR_CHAN_PRESS, |
|
/** |
|
* Proximity. Adimensional. A value of 1 indicates that an |
|
* object is close. |
|
*/ |
|
SENSOR_CHAN_PROX, |
|
/** Humidity, in percent. */ |
|
SENSOR_CHAN_HUMIDITY, |
|
/** Illuminance in visible spectrum, in lux. */ |
|
SENSOR_CHAN_LIGHT, |
|
/** Illuminance in infra-red spectrum, in lux. */ |
|
SENSOR_CHAN_IR, |
|
/** Illuminance in red spectrum, in lux. */ |
|
SENSOR_CHAN_RED, |
|
/** Illuminance in green spectrum, in lux. */ |
|
SENSOR_CHAN_GREEN, |
|
/** Illuminance in blue spectrum, in lux. */ |
|
SENSOR_CHAN_BLUE, |
|
/** Altitude, in meters */ |
|
SENSOR_CHAN_ALTITUDE, |
|
|
|
/** 1.0 micro-meters Particulate Matter, in ug/m^3 */ |
|
SENSOR_CHAN_PM_1_0, |
|
/** 2.5 micro-meters Particulate Matter, in ug/m^3 */ |
|
SENSOR_CHAN_PM_2_5, |
|
/** 10 micro-meters Particulate Matter, in ug/m^3 */ |
|
SENSOR_CHAN_PM_10, |
|
/** Distance. From sensor to target, in meters */ |
|
SENSOR_CHAN_DISTANCE, |
|
|
|
/** CO2 level, in parts per million (ppm) **/ |
|
SENSOR_CHAN_CO2, |
|
/** VOC level, in parts per billion (ppb) **/ |
|
SENSOR_CHAN_VOC, |
|
|
|
/** Voltage, in volts **/ |
|
SENSOR_CHAN_VOLTAGE, |
|
/** Current, in amps **/ |
|
SENSOR_CHAN_CURRENT, |
|
|
|
/** Angular rotation, in degrees */ |
|
SENSOR_CHAN_ROTATION, |
|
|
|
/** All channels. */ |
|
SENSOR_CHAN_ALL, |
|
}; |
|
|
|
/** |
|
* @brief Sensor trigger types. |
|
*/ |
|
enum sensor_trigger_type { |
|
/** |
|
* Timer-based trigger, useful when the sensor does not have an |
|
* interrupt line. |
|
*/ |
|
SENSOR_TRIG_TIMER, |
|
/** Trigger fires whenever new data is ready. */ |
|
SENSOR_TRIG_DATA_READY, |
|
/** |
|
* Trigger fires when the selected channel varies significantly. |
|
* This includes any-motion detection when the channel is |
|
* acceleration or gyro. If detection is based on slope between |
|
* successive channel readings, the slope threshold is configured |
|
* via the @ref SENSOR_ATTR_SLOPE_TH and @ref SENSOR_ATTR_SLOPE_DUR |
|
* attributes. |
|
*/ |
|
SENSOR_TRIG_DELTA, |
|
/** Trigger fires when a near/far event is detected. */ |
|
SENSOR_TRIG_NEAR_FAR, |
|
/** |
|
* Trigger fires when channel reading transitions configured |
|
* thresholds. The thresholds are configured via the @ref |
|
* SENSOR_ATTR_LOWER_THRESH and @ref SENSOR_ATTR_UPPER_THRESH |
|
* attributes. |
|
*/ |
|
SENSOR_TRIG_THRESHOLD, |
|
|
|
/** Trigger fires when a single tap is detected. */ |
|
SENSOR_TRIG_TAP, |
|
|
|
/** Trigger fires when a double tap is detected. */ |
|
SENSOR_TRIG_DOUBLE_TAP, |
|
}; |
|
|
|
/** |
|
* @brief Sensor trigger spec. |
|
*/ |
|
struct sensor_trigger { |
|
/** Trigger type. */ |
|
enum sensor_trigger_type type; |
|
/** Channel the trigger is set on. */ |
|
enum sensor_channel chan; |
|
}; |
|
|
|
/** |
|
* @brief Sensor attribute types. |
|
*/ |
|
enum sensor_attribute { |
|
/** |
|
* Sensor sampling frequency, i.e. how many times a second the |
|
* sensor takes a measurement. |
|
*/ |
|
SENSOR_ATTR_SAMPLING_FREQUENCY, |
|
/** Lower threshold for trigger. */ |
|
SENSOR_ATTR_LOWER_THRESH, |
|
/** Upper threshold for trigger. */ |
|
SENSOR_ATTR_UPPER_THRESH, |
|
/** Threshold for any-motion (slope) trigger. */ |
|
SENSOR_ATTR_SLOPE_TH, |
|
/** |
|
* Duration for which the slope values needs to be |
|
* outside the threshold for the trigger to fire. |
|
*/ |
|
SENSOR_ATTR_SLOPE_DUR, |
|
/** Oversampling factor */ |
|
SENSOR_ATTR_OVERSAMPLING, |
|
/** Sensor range, in SI units. */ |
|
SENSOR_ATTR_FULL_SCALE, |
|
/** |
|
* The sensor value returned will be altered by the amount indicated by |
|
* offset: final_value = sensor_value + offset. |
|
*/ |
|
SENSOR_ATTR_OFFSET, |
|
/** |
|
* Calibration target. This will be used by the internal chip's |
|
* algorithms to calibrate itself on a certain axis, or all of them. |
|
*/ |
|
SENSOR_ATTR_CALIB_TARGET, |
|
}; |
|
|
|
/** |
|
* @typedef sensor_trigger_handler_t |
|
* @brief Callback API upon firing of a trigger |
|
* |
|
* @param "struct device *dev" Pointer to the sensor device |
|
* @param "struct sensor_trigger *trigger" The trigger |
|
*/ |
|
typedef void (*sensor_trigger_handler_t)(struct device *dev, |
|
struct sensor_trigger *trigger); |
|
|
|
/** |
|
* @typedef sensor_attr_set_t |
|
* @brief Callback API upon setting a sensor's attributes |
|
* |
|
* See sensor_attr_set() for argument description |
|
*/ |
|
typedef int (*sensor_attr_set_t)(struct device *dev, |
|
enum sensor_channel chan, |
|
enum sensor_attribute attr, |
|
const struct sensor_value *val); |
|
/** |
|
* @typedef sensor_trigger_set_t |
|
* @brief Callback API for setting a sensor's trigger and handler |
|
* |
|
* See sensor_trigger_set() for argument description |
|
*/ |
|
typedef int (*sensor_trigger_set_t)(struct device *dev, |
|
const struct sensor_trigger *trig, |
|
sensor_trigger_handler_t handler); |
|
/** |
|
* @typedef sensor_sample_fetch_t |
|
* @brief Callback API for fetching data from a sensor |
|
* |
|
* See sensor_sample_fetch() for argument description |
|
*/ |
|
typedef int (*sensor_sample_fetch_t)(struct device *dev, |
|
enum sensor_channel chan); |
|
/** |
|
* @typedef sensor_channel_get_t |
|
* @brief Callback API for getting a reading from a sensor |
|
* |
|
* See sensor_channel_get() for argument description |
|
*/ |
|
typedef int (*sensor_channel_get_t)(struct device *dev, |
|
enum sensor_channel chan, |
|
struct sensor_value *val); |
|
|
|
struct sensor_driver_api { |
|
sensor_attr_set_t attr_set; |
|
sensor_trigger_set_t trigger_set; |
|
sensor_sample_fetch_t sample_fetch; |
|
sensor_channel_get_t channel_get; |
|
}; |
|
|
|
/** |
|
* @brief Set an attribute for a sensor |
|
* |
|
* @param dev Pointer to the sensor device |
|
* @param chan The channel the attribute belongs to, if any. Some |
|
* attributes may only be set for all channels of a device, depending on |
|
* device capabilities. |
|
* @param attr The attribute to set |
|
* @param val The value to set the attribute to |
|
* |
|
* @return 0 if successful, negative errno code if failure. |
|
*/ |
|
__syscall int sensor_attr_set(struct device *dev, |
|
enum sensor_channel chan, |
|
enum sensor_attribute attr, |
|
const struct sensor_value *val); |
|
|
|
static inline int z_impl_sensor_attr_set(struct device *dev, |
|
enum sensor_channel chan, |
|
enum sensor_attribute attr, |
|
const struct sensor_value *val) |
|
{ |
|
const struct sensor_driver_api *api = dev->driver_api; |
|
|
|
if (api->attr_set == NULL) { |
|
return -ENOTSUP; |
|
} |
|
|
|
return api->attr_set(dev, chan, attr, val); |
|
} |
|
|
|
/** |
|
* @brief Activate a sensor's trigger and set the trigger handler |
|
* |
|
* The handler will be called from a thread, so I2C or SPI operations are |
|
* safe. However, the thread's stack is limited and defined by the |
|
* driver. It is currently up to the caller to ensure that the handler |
|
* does not overflow the stack. |
|
* |
|
* This API is not permitted for user threads. |
|
* |
|
* @param dev Pointer to the sensor device |
|
* @param trig The trigger to activate |
|
* @param handler The function that should be called when the trigger |
|
* fires |
|
* |
|
* @return 0 if successful, negative errno code if failure. |
|
*/ |
|
static inline int sensor_trigger_set(struct device *dev, |
|
struct sensor_trigger *trig, |
|
sensor_trigger_handler_t handler) |
|
{ |
|
const struct sensor_driver_api *api = dev->driver_api; |
|
|
|
if (api->trigger_set == NULL) { |
|
return -ENOTSUP; |
|
} |
|
|
|
return api->trigger_set(dev, trig, handler); |
|
} |
|
|
|
/** |
|
* @brief Fetch a sample from the sensor and store it in an internal |
|
* driver buffer |
|
* |
|
* Read all of a sensor's active channels and, if necessary, perform any |
|
* additional operations necessary to make the values useful. The user |
|
* may then get individual channel values by calling @ref |
|
* sensor_channel_get. |
|
* |
|
* Since the function communicates with the sensor device, it is unsafe |
|
* to call it in an ISR if the device is connected via I2C or SPI. |
|
* |
|
* @param dev Pointer to the sensor device |
|
* |
|
* @return 0 if successful, negative errno code if failure. |
|
*/ |
|
__syscall int sensor_sample_fetch(struct device *dev); |
|
|
|
static inline int z_impl_sensor_sample_fetch(struct device *dev) |
|
{ |
|
const struct sensor_driver_api *api = dev->driver_api; |
|
|
|
return api->sample_fetch(dev, SENSOR_CHAN_ALL); |
|
} |
|
|
|
/** |
|
* @brief Fetch a sample from the sensor and store it in an internal |
|
* driver buffer |
|
* |
|
* Read and compute compensation for one type of sensor data (magnetometer, |
|
* accelerometer, etc). The user may then get individual channel values by |
|
* calling @ref sensor_channel_get. |
|
* |
|
* This is mostly implemented by multi function devices enabling reading at |
|
* different sampling rates. |
|
* |
|
* Since the function communicates with the sensor device, it is unsafe |
|
* to call it in an ISR if the device is connected via I2C or SPI. |
|
* |
|
* @param dev Pointer to the sensor device |
|
* @param type The channel that needs updated |
|
* |
|
* @return 0 if successful, negative errno code if failure. |
|
*/ |
|
__syscall int sensor_sample_fetch_chan(struct device *dev, |
|
enum sensor_channel type); |
|
|
|
static inline int z_impl_sensor_sample_fetch_chan(struct device *dev, |
|
enum sensor_channel type) |
|
{ |
|
const struct sensor_driver_api *api = dev->driver_api; |
|
|
|
return api->sample_fetch(dev, type); |
|
} |
|
|
|
/** |
|
* @brief Get a reading from a sensor device |
|
* |
|
* Return a useful value for a particular channel, from the driver's |
|
* internal data. Before calling this function, a sample must be |
|
* obtained by calling @ref sensor_sample_fetch or |
|
* @ref sensor_sample_fetch_chan. It is guaranteed that two subsequent |
|
* calls of this function for the same channels will yield the same |
|
* value, if @ref sensor_sample_fetch or @ref sensor_sample_fetch_chan |
|
* has not been called in the meantime. |
|
* |
|
* For vectorial data samples you can request all axes in just one call |
|
* by passing the specific channel with _XYZ suffix. The sample will be |
|
* returned at val[0], val[1] and val[2] (X, Y and Z in that order). |
|
* |
|
* @param dev Pointer to the sensor device |
|
* @param chan The channel to read |
|
* @param val Where to store the value |
|
* |
|
* @return 0 if successful, negative errno code if failure. |
|
*/ |
|
__syscall int sensor_channel_get(struct device *dev, |
|
enum sensor_channel chan, |
|
struct sensor_value *val); |
|
|
|
static inline int z_impl_sensor_channel_get(struct device *dev, |
|
enum sensor_channel chan, |
|
struct sensor_value *val) |
|
{ |
|
const struct sensor_driver_api *api = dev->driver_api; |
|
|
|
return api->channel_get(dev, chan, val); |
|
} |
|
|
|
/** |
|
* @brief The value of gravitational constant in micro m/s^2. |
|
*/ |
|
#define SENSOR_G 9806650LL |
|
|
|
/** |
|
* @brief The value of constant PI in micros. |
|
*/ |
|
#define SENSOR_PI 3141592LL |
|
|
|
/** |
|
* @brief Helper function to convert acceleration from m/s^2 to Gs |
|
* |
|
* @param ms2 A pointer to a sensor_value struct holding the acceleration, |
|
* in m/s^2. |
|
* |
|
* @return The converted value, in Gs. |
|
*/ |
|
static inline s32_t sensor_ms2_to_g(const struct sensor_value *ms2) |
|
{ |
|
s64_t micro_ms2 = ms2->val1 * 1000000LL + ms2->val2; |
|
|
|
if (micro_ms2 > 0) { |
|
return (micro_ms2 + SENSOR_G / 2) / SENSOR_G; |
|
} else { |
|
return (micro_ms2 - SENSOR_G / 2) / SENSOR_G; |
|
} |
|
} |
|
|
|
/** |
|
* @brief Helper function to convert acceleration from Gs to m/s^2 |
|
* |
|
* @param g The G value to be converted. |
|
* @param ms2 A pointer to a sensor_value struct, where the result is stored. |
|
*/ |
|
static inline void sensor_g_to_ms2(s32_t g, struct sensor_value *ms2) |
|
{ |
|
ms2->val1 = ((s64_t)g * SENSOR_G) / 1000000LL; |
|
ms2->val2 = ((s64_t)g * SENSOR_G) % 1000000LL; |
|
} |
|
|
|
/** |
|
* @brief Helper function for converting radians to degrees. |
|
* |
|
* @param rad A pointer to a sensor_value struct, holding the value in radians. |
|
* |
|
* @return The converted value, in degrees. |
|
*/ |
|
static inline s32_t sensor_rad_to_degrees(const struct sensor_value *rad) |
|
{ |
|
s64_t micro_rad_s = rad->val1 * 1000000LL + rad->val2; |
|
|
|
if (micro_rad_s > 0) { |
|
return (micro_rad_s * 180LL + SENSOR_PI / 2) / SENSOR_PI; |
|
} else { |
|
return (micro_rad_s * 180LL - SENSOR_PI / 2) / SENSOR_PI; |
|
} |
|
} |
|
|
|
/** |
|
* @brief Helper function for converting degrees to radians. |
|
* |
|
* @param d The value (in degrees) to be converted. |
|
* @param rad A pointer to a sensor_value struct, where the result is stored. |
|
*/ |
|
static inline void sensor_degrees_to_rad(s32_t d, struct sensor_value *rad) |
|
{ |
|
rad->val1 = ((s64_t)d * SENSOR_PI / 180LL) / 1000000LL; |
|
rad->val2 = ((s64_t)d * SENSOR_PI / 180LL) % 1000000LL; |
|
} |
|
|
|
/** |
|
* @brief Helper function for converting struct sensor_value to double. |
|
* |
|
* @param val A pointer to a sensor_value struct. |
|
* @return The converted value. |
|
*/ |
|
static inline double sensor_value_to_double(struct sensor_value *val) |
|
{ |
|
return (double)val->val1 + (double)val->val2 / 1000000; |
|
} |
|
|
|
#include <syscalls/sensor.h> |
|
|
|
#ifdef __cplusplus |
|
} |
|
#endif |
|
|
|
/** |
|
* @} |
|
*/ |
|
|
|
#endif /* ZEPHYR_INCLUDE_SENSOR_H_ */
|
|
|