Skip to content

Commit

Permalink
Merge pull request #5025 from tonhuisman/feature/P047-add-adafruit-40…
Browse files Browse the repository at this point in the history
…26-sensor

[P047] Add support for Adafruit I2C Capacitive Moisture sensor
  • Loading branch information
TD-er committed May 1, 2024
2 parents 7abff37 + d53ecbe commit 01aa5ad
Show file tree
Hide file tree
Showing 7 changed files with 278 additions and 77 deletions.
27 changes: 23 additions & 4 deletions docs/source/Plugin/P047.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ Supported hardware

.. image:: P047_BeFlESensor.png

* Adafruit:

Where to buy: `Adafruit webshop or local distributor <https://www.adafruit.com/product/4026>`_

Arduino library: `Adafruit SeeSaw library on GitHub.com <https://github.com/adafruit/Adafruit_Seesaw>`_ (only uswed for inspiration)

.. image:: P047_Adafruit4026.png
:height: 115px

Though not directly applicable, as it is about selecting an Analog Soil-moisture sensor, `this Youtube video <https://www.youtube.com/watch?v=IGP38bz-K48>`_ has usable tips on finding a reliable sensor.

Configuration
Expand All @@ -58,19 +67,23 @@ The available settings here depend on the build used. At least the **Force Slow

* **I2C Address (Hex)**: The address the device is using. The default I2C address is prefilled, and can be configured to use a different address, see below. As this can be any valid I2C address in range: 0x01..0x7F, it has to be typed here, using a hexadecimal value.

For the Adafruit I2C Capacitive Moisture sensor, only addresses 0x36..0x39 can be configured, by connecting the A0/A1 address soldering pads. For this sensor only these addresses can be selected.

.. note:: If the device doesn't stay enabled after setting the Enabled checkbox, then possibly the address of the sensor is changed from the default. The I2C Scan on the Tools page can be used to detect what I2C device addresses are in use (disconnect other I2C devices to avoid confusion). Possibly, another device-model is listed for this sensor, but that is caused by the feature that it can have any address set that's in the I2C allowed range of 0x00 to 0x7F.

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

* **Sensor model**: Select the model of the used sensor. When changing the selection the page will be reloaded to adjust the content of the screen.
* **Sensor model**: Select the model of the used sensor. When changing the selection the page will be reloaded to adjust the available configuration options, tailored to the selected sensor.

.. image:: P047_SensorModelOptions.png

* *Catnip electronics/miceuz (default)*: The originally supported soil moisture sensor, that supports temperature, moisture and light measurement, has a sleep-mode, and can report a version number, to optionally validate if the sensor is supported.

* *BeFlE*: An I2C soil moisture sensor that supports temperature and moisture measurement. There is no sleep mode or version check available.

* *Adafruit (4026)*: An I2C soil moisture sensor that supports temperature and moisture measurement. There is no sleep mode available, and the version is only logged at startup.

When selecting the BeFlE sensor, only these **Device Settings** will be available:

.. image:: P047_SensorModelBeFlE.png
Expand All @@ -79,9 +92,9 @@ When selecting the BeFlE sensor, only these **Device Settings** will be availabl

* **Check sensor version**: To validate if the sensor is of the correct mode, the version can be validated. (Catnip sensor only).

* **Change sensor address**: To use multiple sensors connected to a single ESP unit, a sensor can be configured to use a different I2C address. To change that address, this checkbox has to be enabled, and a different I2C address should be entered in the **Change I2C Address to (Hex)** field in hexadecimal format, range: 0x01..0x7F.
* **Change sensor address**: To use multiple sensors connected to a single ESP unit, a sensor can be configured to use a different I2C address. To change that address, this checkbox has to be enabled, and a different I2C address should be entered in the **Change I2C Address to (Hex)** field in hexadecimal format, range: 0x01..0x7F. This option isn't available for the Adafruit sensor.

* **Change I2C Addr. to (Hex)**: The new address to be used by the sensor. The change will be applied the next time the task is enabled. The **I2C Address (Hex)** field, above, will be updated with the new value. After the change is applied, **the tasks Settings have to be saved once more to save the new address** as the address to use.
* **Change I2C Addr. to (Hex)**: The new address to be used by the sensor. The change will be applied the next time the task is enabled. The **I2C Address (Hex)** field, above, will be updated with the new value. After the change is applied, **the tasks Settings have to be saved once more to save the new address** as the address to use. This option isn't available for the Adafruit sensor.

.. note:: The newly set address is permanently stored in the sensor, and can be changed again at a later time if desired.

Expand All @@ -97,7 +110,9 @@ Values

The measured values are available in ``Temperature``, ``Moisture`` and ``Light``. A formula can be set to recalculate. The number of decimals is by default set to 2, and can be set to 0 for ``Moisture``, as no decimals are provided from the measurement.

NB: The BeFlE sensor doesn't support a Light value, so that won't be available if that **Sensor model** is selected.
NB: The BeFlE and Adafruit sensors don't support a Light value, so that won't be available if that **Sensor model** is selected.

NB2: The Adafruit sensor has a different range for the moisture values: 200..2000 compared to the Catnip and BeflE sensors: 1..800, so any moisture calibration has to be based on actual observation, and not on absolute numbers.


.. Commands available
Expand All @@ -116,6 +131,10 @@ Change log
.. versionchanged:: 2.0
...

|added| 2024-04: Add support for Adafruit I2C moisture sensor.

|added| 2023-03: Add support for BeFlE I2C moisture sensor.

|added|
Major overhaul for 2.0 release.

Expand Down
Binary file added docs/source/Plugin/P047_Adafruit4026.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/source/Plugin/P047_SensorModelOptions.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
105 changes: 77 additions & 28 deletions src/_P047_i2c-soil-moisture-sensor.ino
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
//

/** Changelog:
* 2024-04-05 tonhuisman: Complete implementation for Afafruit I2C Capacitive Moisture sensor.
* Log sensor name and version (or 0 when not available) at plugin startup.
* 2024-03-23 tonhuisman: Start implementation of Adafruit I2C Capacitive Moisture Sensor (product ID 4026)
* From a forum request: https://www.letscontrolit.com/forum/viewtopic.php?t=10107
* 2023-04-07 tonhuisman: Correct typo BelFlE to BeFlE
* 2023-04-01 tonhuisman: Implement staged reading instead of a fixed delay during PLUGIN_READ
* Add range-check on save for I2C address inputs (0x01..0x7F)
Expand Down Expand Up @@ -91,11 +95,20 @@ boolean Plugin_047(uint8_t function, struct EventStruct *event, String& string)

case PLUGIN_WEBFORM_SHOW_I2C_PARAMS:
{
addFormTextBox(F("I2C Address (Hex)"), F("i2c_addr"),
formatToHex_decimal(P047_I2C_ADDR), 4);
addUnit(F("0x01..0x7F"));
# if P047_FEATURE_ADAFRUIT

if (P047_MODEL_ADAFRUIT == static_cast<P047_SensorModels>(P047_MODEL)) {
const uint8_t i2cAddressValues[] = { P047_ADAFRUIT_DEFAULT_ADDR, 0x37, 0x38, 0x39 };

addFormSelectorI2C(F("i2c_addr"), 4, i2cAddressValues, P047_I2C_ADDR);
} else
# endif // if P047_FEATURE_ADAFRUIT
{
addFormTextBox(F("I2C Address (Hex)"), F("i2c_addr"),
formatToHex_decimal(P047_I2C_ADDR), 4);
addUnit(F("0x01..0x7F"));
}

// FIXME TD-er: Why not using addFormSelectorI2C here?
break;
}

Expand All @@ -118,12 +131,18 @@ boolean Plugin_047(uint8_t function, struct EventStruct *event, String& string)
{
{
const __FlashStringHelper *SensorModels[] = {
F("Catnip electronics/miceuz (default)"),
F("BeFlE"),
toString(P047_MODEL_CATNIP),
toString(P047_MODEL_BEFLE),
# if P047_FEATURE_ADAFRUIT
toString(P047_MODEL_ADAFRUIT),
# endif // if P047_FEATURE_ADAFRUIT
};
const int SensorModelIds[] = {
static_cast<int>(P047_MODEL_CATNIP),
static_cast<int>(P047_MODEL_BEFLE),
# if P047_FEATURE_ADAFRUIT
static_cast<int>(P047_MODEL_ADAFRUIT),
# endif // if P047_FEATURE_ADAFRUIT
};
constexpr size_t P047_MODEL_OPTIONS = NR_ELEMENTS(SensorModelIds);
addFormSelector(F("Sensor model"), F("model"), P047_MODEL_OPTIONS, SensorModels, SensorModelIds, P047_MODEL, true);
Expand All @@ -138,12 +157,18 @@ boolean Plugin_047(uint8_t function, struct EventStruct *event, String& string)
addFormCheckBox(F("Check sensor version"), F("version"), P047_CHECK_VERSION);
}

addFormSeparator(2);
# if P047_FEATURE_ADAFRUIT

addFormCheckBox(F("Change Sensor address"), F("changeAddr"), false);
addFormTextBox(F("Change I2C Addr. to (Hex)"), F("newAddr"),
formatToHex_decimal(P047_I2C_ADDR), 4);
addUnit(F("0x01..0x7F"));
if (P047_MODEL_ADAFRUIT != static_cast<P047_SensorModels>(P047_MODEL))
# endif // if P047_FEATURE_ADAFRUIT
{
addFormSeparator(2);

addFormCheckBox(F("Change Sensor address"), F("changeAddr"), false);
addFormTextBox(F("Change I2C Addr. to (Hex)"), F("newAddr"),
formatToHex_decimal(P047_I2C_ADDR), 4);
addUnit(F("0x01..0x7F"));
}

success = true;
break;
Expand All @@ -152,14 +177,25 @@ boolean Plugin_047(uint8_t function, struct EventStruct *event, String& string)
case PLUGIN_WEBFORM_SAVE:
{
success = true;
String webarg = webArg(F("i2c_addr"));
int addr = static_cast<int>(strtol(webarg.c_str(), 0, 16));

if ((addr > 0x00) && (addr < 0x80)) {
P047_I2C_ADDR = addr;
} else {
addHtmlError(F("I2C Address (Hex) error, range: 0x01..0x7F"));
success = false;
String webarg;
int addr;

# if P047_FEATURE_ADAFRUIT

if (P047_MODEL_ADAFRUIT == static_cast<P047_SensorModels>(P047_MODEL)) {
P047_I2C_ADDR = getFormItemInt(F("i2c_addr"));
} else
# endif // if P047_FEATURE_ADAFRUIT
{
webarg = webArg(F("i2c_addr"));
addr = static_cast<int>(strtol(webarg.c_str(), 0, 16));

if ((addr > 0x00) && (addr < 0x80)) {
P047_I2C_ADDR = addr;
} else {
addHtmlError(F("I2C Address (Hex) error, range: 0x01..0x7F"));
success = false;
}
}

uint8_t model = getFormItemInt(F("model"));
Expand All @@ -170,25 +206,38 @@ boolean Plugin_047(uint8_t function, struct EventStruct *event, String& string)
if (P047_MODEL_CATNIP == static_cast<P047_SensorModels>(model)) {
P047_I2C_ADDR = P047_CATNIP_DEFAULT_ADDR;
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_047)); // Gets wiped when switching nr. of values
} else {
} else if (P047_MODEL_BEFLE == static_cast<P047_SensorModels>(model)) {
P047_I2C_ADDR = P047_BEFLE_DEFAULT_ADDR;
# if P047_FEATURE_ADAFRUIT
} else {
P047_I2C_ADDR = P047_ADAFRUIT_DEFAULT_ADDR;
# endif // if P047_FEATURE_ADAFRUIT
}
}

P047_SENSOR_SLEEP = isFormItemChecked(F("sleep"));

P047_CHECK_VERSION = isFormItemChecked(F("version"));

webarg = webArg(F("newAddr"));
addr = static_cast<int>(strtol(webarg.c_str(), 0, 16));
# if P047_FEATURE_ADAFRUIT

if ((addr > 0x00) && (addr < 0x80)) {
P047_NEW_ADDR = addr;
} else {
addHtmlError(F("Change I2C Addr. to (Hex) error, range: 0x01..0x7F"));
success = false;
if (P047_MODEL_ADAFRUIT != static_cast<P047_SensorModels>(P047_MODEL))
# endif // if P047_FEATURE_ADAFRUIT
{
webarg = webArg(F("newAddr"));

if (!webarg.isEmpty()) {
addr = static_cast<int>(strtol(webarg.c_str(), 0, 16));

if ((addr > 0x00) && (addr < 0x80)) {
P047_NEW_ADDR = addr;
P047_CHANGE_ADDR = isFormItemChecked(F("changeAddr"));
} else {
addHtmlError(F("Change I2C Addr. to (Hex) error, range: 0x01..0x7F"));
success = false;
}
}
}
P047_CHANGE_ADDR = isFormItemChecked(F("changeAddr"));

break;
}
Expand Down

0 comments on commit 01aa5ad

Please sign in to comment.