summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/library/zephyr.zsensor.rst113
-rw-r--r--docs/zephyr/quickref.rst37
-rw-r--r--ports/zephyr/README.md1
-rw-r--r--ports/zephyr/modzsensor.c88
4 files changed, 235 insertions, 4 deletions
diff --git a/docs/library/zephyr.zsensor.rst b/docs/library/zephyr.zsensor.rst
index 4eadc926d..2a666bb82 100644
--- a/docs/library/zephyr.zsensor.rst
+++ b/docs/library/zephyr.zsensor.rst
@@ -20,7 +20,8 @@ See Zephyr documentation for sensor usage here: `Sensors
Sensors are defined in the Zephyr devicetree for each board. The quantities that a given sensor can
measure are called a sensor channels. Sensors can have multiple channels to represent different axes
of one property or different properties a sensor can measure. See `Channels`_ below for defined sensor
-channels.
+channels. Each channel may have multiple attributes that can be changed and/or queried.
+See `Channel Attributes`_ below for defined sensor channel attributes.
Constructor
~~~~~~~~~~~
@@ -59,6 +60,36 @@ Methods
Returns only the integer value of the measurement sample.
(Ex. value of ``(1, 500000)`` returns as ``1``)
+.. method:: Sensor.attr_set(sensor_channel, channel_attribute, val1, [val2])
+
+ Set the given channel's attribute to the given value.
+ ``val1`` may be a float, in which case ``val2`` is not given, or
+ ``val1`` can be used for the value's
+ integer part and ``val2`` for the value's fractional part in millionths.
+
+ Returns ``None`` if successful, or raises ``OSError``.
+
+.. method:: Sensor.attr_get_float(sensor_channel, channel_attribute)
+
+ Returns the value of the sensor channel's attribute as a float.
+
+ Many sensors do not support this or any other of the ``attr_get`` methods.
+
+.. method:: Sensor.attr_get_micros(sensor_channel, channel_attribute)
+
+ Returns the value of the sensor channel's attribute in millionths.
+ (Ex. value of ``(1, 500000)`` returns as ``1500000``)
+
+.. method:: Sensor.attr_get_millis(sensor_channel, channel_attribute)
+
+ Returns the value of the sensor channel's attribute in thousandths.
+ (Ex. value of ``(1, 500000)`` returns as ``1500``)
+
+.. method:: Sensor.attr_get_int(sensor_channel, channel_attribute)
+
+ Returns only the integer value of the channel's attribute.
+ (Ex. value of ``(1, 500000)`` returns as ``1``)
+
Channels
~~~~~~~~
@@ -74,6 +105,11 @@ Channels
Acceleration on the Z axis, in m/s^2.
+.. data:: ACCEL_XYZ
+
+ Pseudo-channel representing all three accelerometer axes.
+ Used for :meth:`Sensor.attr_set` and the ``Sensor.attr_get_xxx()`` methods.
+
.. data:: GYRO_X
Angular velocity around the X axis, in radians/s.
@@ -86,6 +122,11 @@ Channels
Angular velocity around the Z axis, in radians/s.
+.. data:: GYRO_XYZ
+
+ Pseudo-channel representing all three gyroscope axes.
+ Used for :meth:`Sensor.attr_set` and the ``Sensor.attr_get_xxx()`` methods.
+
.. data:: MAGN_X
Magnetic field on the X axis, in Gauss.
@@ -121,3 +162,73 @@ Channels
.. data:: ALTITUDE
Altitude, in meters.
+
+Channel Attributes
+~~~~~~~~~~~~~~~~~~~
+
+.. data:: ATTR_SAMPLING_FREQUENCY
+
+ Sensor sampling frequency, i.e. how many times a second the sensor takes a measurement.
+
+.. data:: ATTR_LOWER_THRESH
+
+ Lower threshold for trigger.
+
+.. data:: ATTR_UPPER_THRESH
+
+ Upper threshold for trigger.
+
+.. data:: ATTR_SLOPE_TH
+
+ Threshold for any-motion (slope) trigger.
+
+.. data:: ATTR_SLOPE_DUR
+
+ Duration for which the slope values needs to be outside the threshold for the trigger to fire.
+
+.. data:: ATTR_HYSTERESIS
+
+.. data:: ATTR_OVERSAMPLING
+
+ Oversampling factor.
+
+.. data:: ATTR_FULL_SCALE
+
+ Sensor range, in SI units.
+
+.. data:: ATTR_OFFSET
+
+ The sensor value returned will be altered by the amount indicated by offset: final_value = sensor_value + offset.
+
+.. data:: ATTR_CALIB_TARGET
+
+ Calibration target. This will be used by the internal chip's algorithms to calibrate itself on a certain axis, or all of them.
+
+.. data:: ATTR_CONFIGURATION
+
+ Configure the operating modes of a sensor.
+
+.. data:: ATTR_CALIBRATION
+
+ Set a calibration value needed by a sensor.
+
+.. data:: ATTR_FEATURE_MASK
+
+ Enable/disable sensor features.
+
+.. data:: ATTR_ALERT
+
+ Alert threshold or alert enable/disable.
+
+.. data:: ATTR_FF_DUR
+
+ Free-fall duration represented in milliseconds.
+ If the sampling frequency is changed during runtime, this attribute should be set to adjust freefall duration to the new sampling frequency.
+
+.. data:: ATTR_BATCH_DURATION
+
+ Hardware batch duration in ticks.
+
+.. data:: ATTR_GAIN
+
+.. data:: ATTR_RESOLUTION
diff --git a/docs/zephyr/quickref.rst b/docs/zephyr/quickref.rst
index 64054bf99..6025092a0 100644
--- a/docs/zephyr/quickref.rst
+++ b/docs/zephyr/quickref.rst
@@ -99,10 +99,10 @@ Hardware SPI is accessed via the :ref:`machine.SPI <machine.SPI>` class::
from machine import SPI
- spi = SPI("spi0") # construct a spi bus with default configuration
+ spi = SPI("spi0") # construct a SPI bus with default configuration
spi.init(baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB) # set configuration
- # equivalently, construct spi bus and set configuration at the same time
+ # equivalently, construct the SPI bus and set configuration at the same time
spi = SPI("spi0", baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB)
print(spi) # print device name and bus configuration
@@ -166,7 +166,7 @@ Use the :ref:`zephyr.FlashArea <zephyr.FlashArea>` class to support filesystem::
f.write('Hello world') # write to the file
print(open('/flash/hello.txt').read()) # print contents of the file
-The FlashAreas' IDs that are available are listed in the FlashArea module, as ID_*.
+The ``FlashAreas``' IDs that are available are listed in the FlashArea module, as ``ID_*``.
Sensor
------
@@ -185,3 +185,34 @@ Use the :ref:`zsensor.Sensor <zsensor.Sensor>` class to access sensor data::
accel.get_millis(zsensor.ACCEL_Y) # print measurement value for accelerometer Y-axis sensor channel in millionths
accel.get_micro(zsensor.ACCEL_Z) # print measurement value for accelerometer Z-axis sensor channel in thousandths
accel.get_int(zsensor.ACCEL_X) # print measurement integer value only for accelerometer X-axis sensor channel
+
+The channel IDs that are used as arguments to the :meth:`zsensor.Sensor.get_int`,
+:meth:`zsensor.Sensor.get_float()`, :meth:`zsensor.Sensor.get_millis()`, and
+:meth:`zsensor.Sensor.get_micros()` methods are constants in the :mod:`zsensor` module.
+
+You can use the :meth:`zsensor.Sensor.attr_set` method to set sensor attributes
+like full-scale range and update rate::
+
+ # Example for XIAO BLE NRF52840 SENSE
+ from zsensor import *
+ accel = Sensor('lsm6ds3tr_c') # name from Devicetree
+ # Set full-scale to 2g (19.613300 m/sec^2)
+ # units are micro-m/s^2 (given as a float)
+ accel.attr_set(ACCEL_XYZ, ATTR_FULL_SCALE, 19.613300)
+ # Set sampling frequency to 104 Hz (as a pair of integers)
+ accel.attr_set(ACCEL_XYZ, ATTR_SAMPLING_FREQUENCY, 104, 0)
+ accel.measure()
+ accel.get_float(ACCEL_X) # -0.508 (m/s^2)
+ accel.get_float(ACCEL_Y) # -3.62 (m/s^2)
+ accel.get_float(ACCEL_Z) # 9.504889 (m/s^2)
+
+There are also the :meth:`zsensor.Sensor.attr_get_float`, :meth:`zsensor.Sensor.attr_get_int`,
+:meth:`zsensor.Sensor.attr_get_millis`, and :meth:`zsensor.Sensor.attr_get_micros` methods,
+but many sensors do not support these::
+
+ full_scale = accel.attr_get_float(ATTR_FULL_SCALE)
+
+The attribute IDs that are used as arguments to the :meth:`zsensor.Sensor.attr_set`,
+:meth:`zsensor.Sensor.attr_get_float`, :meth:`zsensor.Sensor.attr_get_int`,
+:meth:`zsensor.Sensor.attr_get_millis`, and :meth:`zsensor.Sensor.attr_get_micros`
+methods are constants in the :mod:`zsensor` module named ``ATTR_*``.
diff --git a/ports/zephyr/README.md b/ports/zephyr/README.md
index 0f6b16d39..480ff5705 100644
--- a/ports/zephyr/README.md
+++ b/ports/zephyr/README.md
@@ -22,6 +22,7 @@ Features supported at this time:
* `machine.PWM` class for PWM control.
* `machine.ADC` class for ADC control.
* `socket` module for networking (IPv4/IPv6).
+* `zsensor` module for reading sensors.
* "Frozen modules" support to allow to bundle Python modules together
with firmware. Including complete applications, including with
run-on-boot capability.
diff --git a/ports/zephyr/modzsensor.c b/ports/zephyr/modzsensor.c
index 51b7b2dbf..c3a8b6d55 100644
--- a/ports/zephyr/modzsensor.c
+++ b/ports/zephyr/modzsensor.c
@@ -93,12 +93,77 @@ static mp_obj_t sensor_get_int(mp_obj_t self_in, mp_obj_t channel_in) {
}
MP_DEFINE_CONST_FUN_OBJ_2(sensor_get_int_obj, sensor_get_int);
+static void sensor_attr_get_internal(mp_obj_t self_in, mp_obj_t channel_in, mp_obj_t attr_in, struct sensor_value *res) {
+ mp_obj_sensor_t *self = MP_OBJ_TO_PTR(self_in);
+
+ int st = sensor_attr_get(self->dev, mp_obj_get_int(channel_in), mp_obj_get_int(attr_in), res);
+ if (st != 0) {
+ mp_raise_OSError(-st);
+ }
+}
+
+static mp_obj_t sensor_attr_get_float(mp_obj_t self_in, mp_obj_t channel_in, mp_obj_t attr_in) {
+ struct sensor_value val;
+ sensor_attr_get_internal(self_in, channel_in, attr_in, &val);
+ return mp_obj_new_float(val.val1 + (mp_float_t)val.val2 / 1000000);
+}
+MP_DEFINE_CONST_FUN_OBJ_3(sensor_attr_get_float_obj, sensor_attr_get_float);
+
+static mp_obj_t sensor_attr_get_micros(mp_obj_t self_in, mp_obj_t channel_in, mp_obj_t attr_in) {
+ struct sensor_value val;
+ sensor_attr_get_internal(self_in, channel_in, attr_in, &val);
+ return MP_OBJ_NEW_SMALL_INT(val.val1 * 1000000 + val.val2);
+}
+MP_DEFINE_CONST_FUN_OBJ_3(sensor_attr_get_micros_obj, sensor_attr_get_micros);
+
+static mp_obj_t sensor_attr_get_millis(mp_obj_t self_in, mp_obj_t channel_in, mp_obj_t attr_in) {
+ struct sensor_value val;
+ sensor_attr_get_internal(self_in, channel_in, attr_in, &val);
+ return MP_OBJ_NEW_SMALL_INT(val.val1 * 1000 + val.val2 / 1000);
+}
+MP_DEFINE_CONST_FUN_OBJ_3(sensor_attr_get_millis_obj, sensor_attr_get_millis);
+
+static mp_obj_t sensor_attr_get_int(mp_obj_t self_in, mp_obj_t channel_in, mp_obj_t attr_in) {
+ struct sensor_value val;
+ sensor_attr_get_internal(self_in, channel_in, attr_in, &val);
+ return MP_OBJ_NEW_SMALL_INT(val.val1);
+}
+MP_DEFINE_CONST_FUN_OBJ_3(sensor_attr_get_int_obj, sensor_attr_get_int);
+
+static mp_obj_t mp_sensor_attr_set(size_t n_args, const mp_obj_t *args) {
+ mp_obj_sensor_t *self = MP_OBJ_TO_PTR(args[0]);
+ mp_obj_t channel_in = args[1];
+ mp_obj_t attr_in = args[2];
+ struct sensor_value val;
+ if (n_args == 4) {
+ // One float argument
+ float v = mp_obj_get_float(args[3]);
+ val.val1 = (int32_t)v;
+ val.val2 = (int32_t)((v - val.val1) * 1000000);
+ } else {
+ // Two integer arguments
+ val.val1 = mp_obj_get_int(args[3]);
+ val.val2 = mp_obj_get_int(args[4]);
+ }
+ int st = sensor_attr_set(self->dev, mp_obj_get_int(channel_in), mp_obj_get_int(attr_in), &val);
+ if (st != 0) {
+ mp_raise_OSError(-st);
+ }
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(sensor_attr_set_obj, 4, 5, mp_sensor_attr_set);
+
static const mp_rom_map_elem_t sensor_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_measure), MP_ROM_PTR(&sensor_measure_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_float), MP_ROM_PTR(&sensor_get_float_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_micros), MP_ROM_PTR(&sensor_get_micros_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_millis), MP_ROM_PTR(&sensor_get_millis_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_int), MP_ROM_PTR(&sensor_get_int_obj) },
+ { MP_ROM_QSTR(MP_QSTR_attr_get_float), MP_ROM_PTR(&sensor_attr_get_float_obj) },
+ { MP_ROM_QSTR(MP_QSTR_attr_get_micros), MP_ROM_PTR(&sensor_attr_get_micros_obj) },
+ { MP_ROM_QSTR(MP_QSTR_attr_get_millis), MP_ROM_PTR(&sensor_attr_get_millis_obj) },
+ { MP_ROM_QSTR(MP_QSTR_attr_get_int), MP_ROM_PTR(&sensor_attr_get_int_obj) },
+ { MP_ROM_QSTR(MP_QSTR_attr_set), MP_ROM_PTR(&sensor_attr_set_obj) },
};
static MP_DEFINE_CONST_DICT(sensor_locals_dict, sensor_locals_dict_table);
@@ -119,12 +184,15 @@ static const mp_rom_map_elem_t mp_module_zsensor_globals_table[] = {
C(ACCEL_X),
C(ACCEL_Y),
C(ACCEL_Z),
+ C(ACCEL_XYZ),
C(GYRO_X),
C(GYRO_Y),
C(GYRO_Z),
+ C(GYRO_XYZ),
C(MAGN_X),
C(MAGN_Y),
C(MAGN_Z),
+ C(MAGN_XYZ),
C(DIE_TEMP),
C(AMBIENT_TEMP),
C(PRESS),
@@ -145,6 +213,26 @@ static const mp_rom_map_elem_t mp_module_zsensor_globals_table[] = {
C(GAS_RES),
C(VOLTAGE),
#undef C
+#define C(name) { MP_ROM_QSTR(MP_QSTR_ATTR_##name), MP_ROM_INT(SENSOR_ATTR_##name) }
+ C(SAMPLING_FREQUENCY),
+ C(LOWER_THRESH),
+ C(UPPER_THRESH),
+ C(SLOPE_TH),
+ C(SLOPE_DUR),
+ C(HYSTERESIS),
+ C(OVERSAMPLING),
+ C(FULL_SCALE),
+ C(OFFSET),
+ C(CALIB_TARGET),
+ C(CONFIGURATION),
+ C(CALIBRATION),
+ C(FEATURE_MASK),
+ C(ALERT),
+ C(FF_DUR),
+ C(BATCH_DURATION),
+ C(GAIN),
+ C(RESOLUTION),
+#undef C
};
static MP_DEFINE_CONST_DICT(mp_module_zsensor_globals, mp_module_zsensor_globals_table);