Skip to content

Commit

Permalink
Merge pull request #5016 from tonhuisman/feature/P064-add-separate-ge…
Browse files Browse the repository at this point in the history
…sture-events-option

[P064] Add Separate Gesture events option
  • Loading branch information
TD-er committed May 1, 2024
2 parents 0b38ed1 + 0be6cab commit 7abff37
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 51 deletions.
67 changes: 51 additions & 16 deletions docs/source/Plugin/P064.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,43 +26,75 @@ Description

The APDS9960 sensor provides Gesture, Proximity and Ambient Light data or R/G/B color values from the light sensor, depending on the Plugin Mode. After changing the Plugin Mode, the Values arguments may need to be adjusted according to their function (Gesture, Proximity, Light or R, G, B). If the initial Values names are used, they will be replaced when switching the Plugin Mode, and the settings are actually saved.

Device Configuration
--------------------

.. image:: P064_DeviceConfiguration.png

* **Name**: Required by ESPEasy, must be unique among the list of available devices/tasks.

* **Enabled**: The device can be disabled or enabled. When not enabled the device should not use any resources.

I2C options
^^^^^^^^^^^

The available settings here depend on the build used. At least the **Force Slow I2C speed** option is available, but selections for the I2C Multiplexer can also be shown. For details see the :ref:`Hardware_page`

There is only 1 I2C address available for this sensor, ``0x39`` (not shown).

The Gain, LED Drive and LED Boost parameters may need adjustment from the defaults as some of the low-cost clone sensors aren't as carefully calibrated as the original SparkFun or AdaFruit sensors. The suggested defaults are taken from the original SparkFun driver software settings. When first configuring this plugin it is advised to start with these default settings, and adjust when the sensor isn't responding as required.

Device Settings
^^^^^^^^^^^^^^^

* **Plugin Mode**: Select the desired operation mode.

.. image:: P064_PluginModeOptions.png

* *Gesture/Proximity/Ambient Light Sensor*: Will measure the Gesture, Proximity and Ambient light values. If **Separate Gesture events** is disabled, then events will be generated when a Gesture is detected. Also, when **Interval** is set, events are generated.
* *R/G/B Colors*: Will measure the R, G and B components of the current Ambient light condition. Will generate events if **Interval** is set.

For the R/G/B Colors mode, only Light Sensor Gain and Light Sensor LED Drive parameters are available. They correspond with the Ambient Light Sensor Gain and Proximity/ALS LED Drive parameters (and use the same settings storage), but with different labels.

NB: Defaults are *not* automatically set after adding the plugin!

Gesture parameters
------------------
^^^^^^^^^^^^^^^^^^

Gesture Gain: Selection of the gain factor, select from 1x, 2x, 4x (default) or 8x.
* **Gesture Gain**: Selection of the gain factor, select from 1x, 2x, 4x (default) or 8x.

Gesture LED Drive: Selection of the current to drive the Gesture IR LED, select from 100 mA (default), 50 mA, 25 mA or 12.5 mA.
* **Gesture LED Drive**: Selection of the current to drive the Gesture IR LED, select from 100 mA (default), 50 mA, 25 mA or 12.5 mA.

Gesture LED Boost: Selection of the LED Boost factor, select from 100%, 150%, 200% or 300% (default).
* **Gesture LED Boost**: Selection of the LED Boost factor, select from 100%, 150%, 200% or 300% (default).

Proximity & Ambient Light Sensor parameters
-------------------------------------------
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Proximity Gain: Selection of the gain factor, select from 1x, 2x, 4x (default) or 8x.
* **Proximity Gain**: Selection of the gain factor, select from 1x, 2x, 4x (default) or 8x.

Ambient Light Sensor Gain: Selection of the gain factor, select from 1x, 2x, 4x (default) or 8x.
* **Ambient Light Sensor Gain**: Selection of the gain factor, select from 1x, 2x, 4x (default) or 8x.

Proximity/ALS LED Drive: Selection of the current to drive the Proximity/Ambient Light Sensor IR LED, select from 100 mA (default), 50 mA, 25 mA or 12.5 mA.
* **Proximity/ALS LED Drive**: Selection of the current to drive the Proximity/Ambient Light Sensor IR LED, select from 100 mA (default), 50 mA, 25 mA or 12.5 mA.

R/G/B Colors parameters
-----------------------
^^^^^^^^^^^^^^^^^^^^^^^

* **Light Sensor Gain**: Selection of the gain factor, select from 1x, 2x, 4x (default) or 8x.

* **Light Sensor LED Drive**: Selection of the current to drive the Light Sensor IR LED, select from 100 mA (default), 50 mA, 25 mA or 12.5 mA.

Event generation
^^^^^^^^^^^^^^^^

Light Sensor Gain: Selection of the gain factor, select from 1x, 2x, 4x (default) or 8x.
* **Separate Gesture events**: When enabled will generate a ``<TaskName>#Swipe=<gesture>`` event (see below), independent from **Interval**. This allows gestures to be handled independently from measuring the proximity and ambient light, or R/G/B colors. The ``Gesture`` value will be updated for every gesture detected, but the Values events will only trigger on Interval, if this checkbox is enabled.

Light Sensor LED Drive: Selection of the current to drive the Light Sensor IR LED, select from 100 mA (default), 50 mA, 25 mA or 12.5 mA.
Values
^^^^^^

Supported hardware
------------------
Depending on the **Plugin Mode** setting either the Values are ``Gesture``, ``Proximity`` and ``Light`` or ``R``, ``G`` and ``B``. When not manually changed, they will be switched by the plugin when selecting the other Plugin Mode setting.

.. Supported hardware
.. ^^^^^^^^^^^^^^^^^^
|P064_usedby|

Expand All @@ -71,17 +103,20 @@ Supported hardware
.. .. include:: P064_commands.repl
.. Events
.. ~~~~~~
Events
~~~~~~

.. .. include:: P064_events.repl
.. include:: P064_events.repl

Change log
----------

.. versionchanged:: 2.0
...

|added| 2024-03-30: Separate Gesture events option.


|added|
Major overhaul for 2.0 release.

Expand Down
Binary file added docs/source/Plugin/P064_DeviceConfiguration.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/Plugin/P064_PluginModeOptions.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions docs/source/Plugin/P064_events.repl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.. csv-table::
:header: "Event", "Example"
:widths: 30, 20

"
``<TaskName>#Swipe,<gesture>``

``<gesture>`` values:

* ``0``: None
* ``1``: Left
* ``2``: Right
* ``3``: Up
* ``4``: Down
* ``5``: Near (towards the sensor)
* ``6``: Far (away from the sensor)
","
Will trigger when the configuration option **Separate Gesture events** is enabled.

These values are the same for the ``Gesture`` value when that is used.
"
6 changes: 3 additions & 3 deletions docs/source/Reference/Events.rst
Original file line number Diff line number Diff line change
Expand Up @@ -398,10 +398,10 @@ P053 :ref:`P053_page`
.. .. include:: ../Plugin/P063_events.repl
.. P064 :ref:`P064_page`
.. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
P064 :ref:`P064_page`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. .. include:: ../Plugin/P064_events.repl
.. include:: ../Plugin/P064_events.repl


.. P065 :ref:`P065_page`
Expand Down
102 changes: 70 additions & 32 deletions src/_P064_APDS9960.ino
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

// Note: The chip has a wide view-of-angle. If housing is in this angle the chip blocks!

// 2024-03-30 tonhuisman: Add 'Separate Gesture event' option (<taskname>#Swipe=<gesture>) so it doesn't interfere with light/color
// measurement
// 2022-08-12 tonhuisman: Remove [DEVELOPMENT] tag
// 2022-08-05 tonhuisman: Remove [TESTING] tag, Improvement: INIT, 10/sec and READ events now return false if errors occur during processing
// 2022-06-17 tonhuisman: Remove I2C address selector, as there is nothing to choose...
Expand All @@ -29,7 +31,7 @@
// Added settings for Gain (Gesture, Proximity, Ambient Light Sensor), Led Power (Gesture and Proximity/ALS) and Led Boost (Gesture)
// to allow better tuning for use of the sensor. Also adapted the SparkFun_APDS9960 driver for enabling this.
// R/G/B Colors mode has it's settings shared with the Gesture/Proximity/ALS as they are the exact same parameters, but with different
// labels only.
// labels only.


# define PLUGIN_064
Expand All @@ -45,7 +47,9 @@

# define PLUGIN_MODE_GPL_064 0 // GPL = Gesture/Proximity/(Ambient) Light Sensor mode
# define PLUGIN_MODE_RGB_064 1 // RGB = R/G/B Colors mode
# define P064_I2C_ADDRESS 0x39

# define P064_GESTURE_EVENT PCONFIG(0)
# define P064_MODE PCONFIG(1)
# define P064_GGAIN PCONFIG(2)
# define P064_GLDRIVE PCONFIG(3)
Expand Down Expand Up @@ -107,15 +111,15 @@ boolean Plugin_064(uint8_t function, struct EventStruct *event, String& string)

case PLUGIN_I2C_HAS_ADDRESS:
{
success = (event->Par1 == 0x39);
success = (event->Par1 == P064_I2C_ADDRESS);

break;
}

# if FEATURE_I2C_GET_ADDRESS
case PLUGIN_I2C_GET_ADDRESS:
{
event->Par1 = 0x39;
event->Par1 = P064_I2C_ADDRESS;
success = true;
break;
}
Expand Down Expand Up @@ -164,20 +168,20 @@ boolean Plugin_064(uint8_t function, struct EventStruct *event, String& string)

{
// Gain options, multiple gain optionsets in SparkFun_APDS9960.h have the same valueset, so only defined once here
const __FlashStringHelper *optionsGain[4] = {
const __FlashStringHelper *optionsGain[] = {
F("1x"),
F("2x"),
F("4x (default)"),
F("8x") };
const int optionsGainValues[4] = { PGAIN_1X, PGAIN_2X, PGAIN_4X, PGAIN_8X }; // Also used for optionsALSGain
const int optionsGainValues[] = { PGAIN_1X, PGAIN_2X, PGAIN_4X, PGAIN_8X }; // Also used for optionsALSGain

// Led_Drive options, all Led_Drive optionsets in SparkFun_APDS9960.h have the same valueset, so only defined once here
const __FlashStringHelper *optionsLedDrive[4] = {
const __FlashStringHelper *optionsLedDrive[] = {
F("100 mA (default)"),
F("50 mA"),
F("25 mA"),
F("12.5 mA") };
const int optionsLedDriveValues[4] = { LED_DRIVE_100MA, LED_DRIVE_50MA, LED_DRIVE_25MA, LED_DRIVE_12_5MA };
const int optionsLedDriveValues[] = { LED_DRIVE_100MA, LED_DRIVE_50MA, LED_DRIVE_25MA, LED_DRIVE_12_5MA };


String lightSensorGainLabel;
Expand All @@ -186,23 +190,38 @@ boolean Plugin_064(uint8_t function, struct EventStruct *event, String& string)
if (P064_IS_GPL_SENSOR) { // Gesture/Proximity/ALS mode
addFormSubHeader(F("Gesture parameters"));

addFormSelector(F("Gesture Gain"), F("ggain"), 4, optionsGain, optionsGainValues, P064_GGAIN);

addFormSelector(F("Gesture LED Drive"), F("gldrive"), 4, optionsLedDrive, optionsLedDriveValues, P064_GLDRIVE);
addFormSelector(F("Gesture Gain"),
F("ggain"),
NR_ELEMENTS(optionsGainValues),
optionsGain,
optionsGainValues,
P064_GGAIN);

addFormSelector(F("Gesture LED Drive"),
F("gldrive"),
NR_ELEMENTS(optionsLedDriveValues),
optionsLedDrive,
optionsLedDriveValues,
P064_GLDRIVE);
{
// Gesture Led-boost values
const __FlashStringHelper *optionsLedBoost[4] = {
const __FlashStringHelper *optionsLedBoost[] = {
F("100 %"),
F("150 %"),
F("200 %"),
F("300 % (default)") };
const int optionsLedBoostValues[4] = { LED_BOOST_100, LED_BOOST_150, LED_BOOST_200, LED_BOOST_300 };
addFormSelector(F("Gesture LED Boost"), F("lboost"), 4, optionsLedBoost, optionsLedBoostValues, P064_LED_BOOST);
const int optionsLedBoostValues[] = { LED_BOOST_100, LED_BOOST_150, LED_BOOST_200, LED_BOOST_300 };
addFormSelector(F("Gesture LED Boost"),
F("lboost"),
NR_ELEMENTS(optionsLedBoostValues),
optionsLedBoost,
optionsLedBoostValues,
P064_LED_BOOST);
}

addFormSubHeader(F("Proximity & Ambient Light Sensor parameters"));

addFormSelector(F("Proximity Gain"), F("pgain"), 4, optionsGain, optionsGainValues, P064_PGAIN);
addFormSelector(F("Proximity Gain"), F("pgain"), NR_ELEMENTS(optionsGainValues), optionsGain, optionsGainValues, P064_PGAIN);

lightSensorGainLabel = F("Ambient Light Sensor Gain");
lightSensorDriveLabel = F("Proximity & ALS LED Drive");
Expand All @@ -214,15 +233,26 @@ boolean Plugin_064(uint8_t function, struct EventStruct *event, String& string)
}
{
// Ambient Light Sensor Gain options, values are equal to PGAIN values, so again avoid duplication
const __FlashStringHelper *optionsALSGain[4] = {
const __FlashStringHelper *optionsALSGain[] = {
F("1x"),
F("4x (default)"),
F("16x"),
F("64x") };
addFormSelector(lightSensorGainLabel, F("again"), 4, optionsALSGain, optionsGainValues, P064_AGAIN);
addFormSelector(lightSensorGainLabel, F("again"), NR_ELEMENTS(optionsGainValues), optionsALSGain, optionsGainValues, P064_AGAIN);
}
addFormSelector(lightSensorDriveLabel, F("ldrive"), 4, optionsLedDrive, optionsLedDriveValues, P064_LDRIVE);
addFormSelector(lightSensorDriveLabel,
F("ldrive"),
NR_ELEMENTS(optionsLedDriveValues),
optionsLedDrive,
optionsLedDriveValues,
P064_LDRIVE);
}

addFormSubHeader(F("Event generation"));

addFormCheckBox(F("Separate Gesture events"), F("gevent"), P064_GESTURE_EVENT == 1);
addFormNote(F("Generates event: &lt;Taskname&gt;#Swipe=&lt;gesture&gt;"));

success = true;
break;
}
Expand All @@ -240,6 +270,8 @@ boolean Plugin_064(uint8_t function, struct EventStruct *event, String& string)
P064_AGAIN = getFormItemInt(F("again"));
P064_LDRIVE = getFormItemInt(F("ldrive"));

P064_GESTURE_EVENT = isFormItemChecked(F("gevent")) ? 1 : 0;

success = true;
break;
}
Expand All @@ -259,27 +291,26 @@ boolean Plugin_064(uint8_t function, struct EventStruct *event, String& string)
P064_data->sensor.enablePower();

if (!P064_data->sensor.enableLightSensor(false)) {
log += F("Error during light sensor init!");
log += F(" Error during light sensor init!");
success = false;
}

if (P064_IS_GPL_SENSOR) { // Gesture/Proximity/ALS mode
if (!P064_data->sensor.enableProximitySensor(false)) {
log += F("Error during proximity sensor init!");
success = false;
}
// Always enable the proximity/gesture sensor.
if (!P064_data->sensor.enableProximitySensor(false)) {
log += F(" Error during proximity sensor init!");
success = false;
}

if (!P064_data->sensor.enableGestureSensor(false, P064_LED_BOOST)) {
log += F("Error during gesture sensor init!");
success = false;
}
if (!P064_data->sensor.enableGestureSensor(false, P064_LED_BOOST)) {
log += F(" Error during gesture sensor init!");
success = false;
}
} else {
log += F("Error during APDS-9960 init!");
success = false;
}

addLogMove(LOG_LEVEL_INFO, log);
addLogMove(success ? LOG_LEVEL_INFO : LOG_LEVEL_ERROR, log);
}
break;
}
Expand All @@ -288,7 +319,7 @@ boolean Plugin_064(uint8_t function, struct EventStruct *event, String& string)
{
P064_data_struct *P064_data = static_cast<P064_data_struct *>(getPluginTaskData(event->TaskIndex));

if ((nullptr == P064_data) || (P064_MODE != PLUGIN_MODE_GPL_064) || !P064_data->sensor.isGestureAvailable()) {
if ((nullptr == P064_data) || !P064_data->sensor.isGestureAvailable()) {
break;
}

Expand All @@ -314,10 +345,17 @@ boolean Plugin_064(uint8_t function, struct EventStruct *event, String& string)
}
# endif // ifndef BUILD_NO_DEBUG

UserVar.setFloat(event->TaskIndex, 0, static_cast<float>(gesture));
event->sensorType = Sensor_VType::SENSOR_TYPE_SWITCH;
if (P064_MODE == PLUGIN_MODE_GPL_064) {
UserVar.setFloat(event->TaskIndex, 0, static_cast<float>(gesture));
}

if (P064_GESTURE_EVENT == 1) {
const String eventvalues = strformat(F("%d"), gesture);
eventQueue.add(event->TaskIndex, F("Swipe"), eventvalues);
} else if (P064_MODE == PLUGIN_MODE_GPL_064) {
sendData(event); // Process immediately
}

sendData(event); // Process immediately
success = true;
}

Expand Down

0 comments on commit 7abff37

Please sign in to comment.