Skip to content
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c50f175
First try of a plugin for reading current through ADS1015 + SCT013 ov…
Feb 6, 2022
889b135
Successfull creation of plugin to get current from an alternative pow…
Feb 6, 2022
61835ce
Merge branch 'letscontrolit:mega' into mega
handfreezer Feb 6, 2022
e4e5f38
Merge branch 'letscontrolit:mega' into mega
handfreezer Mar 5, 2022
74232c3
Validation préparation du pull request en plugin 130 dans une branche
Mar 6, 2022
c7b6530
Merge branch 'mega' of https://github.com/handfreezer/ESPEasy into mega
Mar 6, 2022
5f89618
removing local P126 as failed POC
Mar 6, 2022
3119a25
Migrating plugin from local POC P127 to official P130
Mar 6, 2022
1135c89
Applying right way to get a personnal build without polluting git rep…
Mar 6, 2022
26af21f
Few rename and cleaning code/default values
Mar 6, 2022
6ffd1c1
Changing default conversion rate to get a more stable value
Mar 6, 2022
89be65e
rolling back to origin
Mar 6, 2022
69e9877
Adding possibility to select Sample Per Second between 1600/2400/3300
Mar 6, 2022
e77eace
Update README.md
handfreezer Mar 13, 2022
d192d93
Adding documentation for P130 plugin Current Sensor through ADS1015
Apr 3, 2022
eddff51
Merge pull request #1 from handfreezer/mega
handfreezer Apr 3, 2022
5647d1f
Merge branch 'mega' into P130_01
handfreezer Apr 18, 2022
1a76556
Remove local testing profil
handfreezer Apr 18, 2022
afcf524
Merge branch 'mega' into P130_01
TD-er Nov 21, 2022
6e2ecdb
Merge branch 'letscontrolit:mega' into P130_01
handfreezer Nov 25, 2022
f25c9da
Merge branch 'mega' into P130_01
TD-er Dec 23, 2022
95e83cd
Merge branch 'mega' into P130_01
TD-er Sep 1, 2023
02a67dc
Merge branch 'mega' into P130_01
TD-er Oct 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# ⚠️ This is a fork of [letscontrolit/ESPEasy](https://github.com/letscontrolit/ESPEasy) and you should prefer to start from original project! This fork is for personnal maintenance and making PR to original project. ⚠️
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should go into the official ESPEasy repository... please remove this from this PR (you can of course keep it in your fork)



|Latest Nightly | Build Status | Downloads | Docs | Patreon | Ko-Fi | PayPal |
|-------|-------|-------|-------|-------|-------|-------|
| [![GitHub version](https://img.shields.io/github/release/letscontrolit/ESPEasy/all.svg)](https://github.com/letscontrolit/ESPEasy/releases/latest) | ![Build status](https://github.com/letscontrolit/ESPEasy/actions/workflows/build.yml/badge.svg) | [![Downloads](https://img.shields.io/github/downloads/letscontrolit/ESPEasy/total.svg)](https://github.com/letscontrolit/ESPEasy/releases) | [![Documentation Status](https://readthedocs.org/projects/espeasy/badge/?version=latest)](https://espeasy.readthedocs.io/en/latest/?badge=latest) | [![donate](https://img.shields.io/badge/donate-Patreon-blue.svg)](https://www.patreon.com/GrovkillenTDer) | [![donate](https://img.shields.io/badge/donate-KoFi-blue.svg)](https://ko-fi.com/grovkillentder) | [![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://www.paypal.me/espeasy) |
Expand Down
128 changes: 128 additions & 0 deletions docs/source/Plugin/P130.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
.. include:: ../Plugin/_plugin_substitutions_p13x.repl
.. _P130_page:

|P130_typename|
==================================================

|P130_shortinfo|

Plugin details
--------------

Type: |P130_type|

Name: |P130_name|

Status: |P130_status|

GitHub: |P130_github|_

Maintainer: |P130_maintainer|

Used libraries: |P130_usedlibraries|



Introduction
------------

.. image:: P130_vue_globale.jpg

This plugin can be used to measure Current usage through `Irms <https://en.wikipedia.org/wiki/Root_mean_square method>` using an ADS1015 through I2C.
It is the most simple schematic I succeed to create.
To get it to work, you have to buy an ADS1015 board, an ESP32 (not that ESP8266 might be too slow), and current sensors (I encouraged you to buy the black version, more robust, and smaller).
The only requirement is to buy a current sensor doing the conversion over 1Vac. You have to choose the right calibration in other cases you may definitely break your ADS1015. Say you bought a 30A/1V current sensor, if you try to measure a current of 60A, output voltage will be 2V and your ADS1015 will be burned out!
Note that each ADS1015 can manage TWO sensors! as I'm using the ADS1015 in a differential mode (this avoid managing an offset voltage and a complicated way to get a full range measure)
As ADS1015 can have four I2C addresses, you can manage up to EIGHT current sensors within one ESPEasy unit.

Specifications:
* Output: Irms Current
* Input: 1Vac through current sensor

Wiring
------

.. code-block:: none
ESP ADS1015
GPIO (SCL) <--> SCL
GPIO (SDA) <--> SDA
ADDR (choose on our side, see note below)
Power
3.3V <--> VCC
GND <--> GND
Current Sensor 1 (Canal 1)
P1 <--> ADC0
P2 <--> ADC1
Current Sensor 2 (Canal 2)
P1 <--> ADC2
P2 <--> ADC3
The ADDR pin have to be used to set the wanted address of your choice (have a look on datasheet to configure one)

Setup
-----

.. image:: P130_device_configuration_page.png

Task settings
~~~~~~~~~~~~~

* **Device**: Name of plugin
* **Name**: Name of the task (example name **Irms**)
* **Enable**: Should the task be enabled or not

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

* **I2C Address**: Default 0x48 is used.
* **Force Slow I2C speed**: not needed for ADS1015, and should not be used as it can reduce sampling rate

Calibration - General
^^^^^^^^^^^^^^^^^^^^^

* **SPS** : Sample Per Second : based on my tests, 2400 SPS give the same real SPS as 3600 because of internal code of ESPEasy. Setting to 2400 will slo down the internal converter of the ADS1015 and so, sampling will have a more stable result.
* **Current Frequency** : Needed to calculate the period of sampling for a sinus
* **Nb Sinus to read** : more sinus implies more accuracy, BUT also more blocking time in plugin, SO: I suggest 2 sinus for 50Hz (even for 60Hz too)
* **ADC Conversion Mode Continuous** : this option was coded for test purposes but do not give better result, I suggest to leave it UNchecked (the default)
* **Small Debug to INFO log** : this allow you to get statistic of each conversion on serial console without switching global log level to debug (becuase it is slowing down conversion rate, and so bad results)
* **Voltage estimated** : this is to get from plugin a power conversion. as it is not a real value, the power value is an estimated one based on this voltage.

Calibration
^^^^^^^^^^^

This is where you specify the calibration of the current sensor you connected, say you have connected a current sensor given for 50A/1V, you will indicate 50.

* **Canal 1 - Max current** : Current value for 1V
* **Canal 2 - Max current** : Current value for 1V
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Canal is most likely French, in English this should be Channel, ditto in _P130_IRMS_ADS1015.ino (and you probably need to update the screenshots too)


Where to buy
------------

.. csv-table::
:header: "Store", "Link"
:widths: 5, 40

"AliExpress ESP32",""
"AliExpress ADS1015 board",""
"AliExpress SCT013",""
"AliExpress OPCT10AL",""

* **Note : to simply help this famous project ESPEasy, just bought through referral link above!**

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

.. versionadded:: 1.0
...

|added|
Initial release version.





Loading
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/P130_vue_globale.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/source/Plugin/_Plugin.rst
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ There are different released versions of ESP Easy:
":ref:`P125_page`","|P125_status|","P125"
":ref:`P126_page`","|P126_status|","P126"
":ref:`P127_page`","|P127_status|","P125"
":ref:`P130_page`","|P130_status|","P130"


Internal GPIO handling
Expand Down
2 changes: 1 addition & 1 deletion docs/source/Plugin/_plugin_categories.repl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
.. |Plugin_Display| replace:: :ref:`P012_page`, :ref:`P023_page`, :ref:`P036_page`, :ref:`P057_page`, :ref:`P073_page`, :ref:`P075_page`, :ref:`P095_page`, :ref:`P104_page`, :ref:`P116_page`
.. |Plugin_Distance| replace:: :ref:`P110_page`, :ref:`P113_page`
.. |Plugin_Dust| replace:: :ref:`P018_page`, :ref:`P053_page`, :ref:`P056_page`
.. |Plugin_Energy_AC| replace:: :ref:`P076_page`, :ref:`P077_page`, :ref:`P078_page`, :ref:`P102_page`, :ref:`P108_page`
.. |Plugin_Energy_AC| replace:: :ref:`P076_page`, :ref:`P077_page`, :ref:`P078_page`, :ref:`P102_page`, :ref:`P108_page`, :ref:`P130_page`
.. |Plugin_Energy_DC| replace:: :ref:`P027_page`, :ref:`P085_page`, :ref:`P115_page`
.. |Plugin_Energy_Heat| replace:: :ref:`P088_page`, :ref:`P093_page`
.. |Plugin_Environment| replace:: :ref:`P004_page`, :ref:`P005_page`, :ref:`P006_page`, :ref:`P014_page`, :ref:`P024_page`, :ref:`P028_page`, :ref:`P030_page`, :ref:`P031_page`, :ref:`P032_page`, :ref:`P034_page`, :ref:`P039_page`, :ref:`P047_page`, :ref:`P051_page`, :ref:`P068_page`, :ref:`P069_page`, :ref:`P072_page`, :ref:`P103_page`, :ref:`P104_page`, :ref:`P105_page`, :ref:`P106_page`
Expand Down
1 change: 1 addition & 0 deletions docs/source/Plugin/_plugin_substitutions.repl
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@
.. include:: ../Plugin/_plugin_substitutions_p10x.repl
.. include:: ../Plugin/_plugin_substitutions_p11x.repl
.. include:: ../Plugin/_plugin_substitutions_p12x.repl
.. include:: ../Plugin/_plugin_substitutions_p13x.repl
13 changes: 13 additions & 0 deletions docs/source/Plugin/_plugin_substitutions_p13x.repl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.. |P130_name| replace:: :cyan:`Current Irms via ADS1015 I2C`
.. |P130_type| replace:: :cyan:`Current`
.. |P130_typename| replace:: :cyan:`Current - ADS1015 (I2C)`
.. |P130_porttype| replace:: `.`
.. |P130_status| replace:: :yellow:`TESTING E`
.. |P130_github| replace:: P130_IRMS_ADS1015.ino
.. _P130_github: https://github.com/handfreezer/ESPEasy/blob/P130_01/src/_P130_IRMS_ADS1015.ino
.. |P130_usedby| replace:: `.`
.. |P130_shortinfo| replace:: `Current Irms sensor`
.. |P130_maintainer| replace:: `handfreezer`
.. |P130_compileinfo| replace:: `.`
.. |P130_usedlibraries| replace:: `(none)`

2 changes: 1 addition & 1 deletion platformio_esp32_envs.ini
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ board = esp32dev
extends = esp32_common
lib_deps = ${esp32_common.lib_deps}, ServoESP32
build_flags = ${esp32_common.build_flags}
-DFEATURE_ARDUINO_OTA
-D FEATURE_ARDUINO_OTA
-D PLUGIN_DISPLAY_COLLECTION
board = esp32dev

Expand Down
4 changes: 3 additions & 1 deletion src/Custom-sample.h
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,9 @@ static const char DATA_ESPEASY_DEFAULT_MIN_CSS[] PROGMEM = {
// #define USES_P125 // ADXL345 SPI Acceleration / Gravity
// #define USES_P126 // 74HC595 Shift register
// #define USES_P127 // CDM7160

// #define USES_P128 //
// #define USES_P129 //
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P128 and P129 will define their own here, no need to fill the gap, and it will probably cause minor merge issues

// #define USES_P130 // Current Sensor Irms - ADS1015

// Special plugins needing IR library
// #define USES_P016 // IR
Expand Down
166 changes: 166 additions & 0 deletions src/_P130_IRMS_ADS1015.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#include "_Plugin_Helper.h"
#ifdef USES_P130

// #######################################################################################################
// ############################# Plugin 130: Irms ADS1015 I2C (base : 0x48) #############################
// #######################################################################################################


#include "src/PluginStructs/P130_data_struct.h"

#define PLUGIN_130
#define PLUGIN_ID_130 130
#define PLUGIN_NAME_130 "Current Sensor Irms - ADS1015"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To have plugin names with the same structure, this should probably be Current - ADS1015 IRMS [TESTING] (or use Irms), and include the status of the plugin (either Development or Testing).

#define PLUGIN_VALUENAME1_130 "current1"
#define PLUGIN_VALUENAME2_130 "power1"
#define PLUGIN_VALUENAME3_130 "current2"
#define PLUGIN_VALUENAME4_130 "power2"


boolean Plugin_130(uint8_t function, struct EventStruct *event, String& string)
{
boolean success = false;

// static uint8_t portValue = 0;
switch (function)
{
case PLUGIN_DEVICE_ADD:
{
Device[++deviceCount].Number = PLUGIN_ID_130;
Device[deviceCount].Type = DEVICE_TYPE_I2C;
Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE;
Device[deviceCount].Ports = 0;
Device[deviceCount].PullUpOption = false;
Device[deviceCount].InverseLogicOption = false;
Device[deviceCount].FormulaOption = true;
Device[deviceCount].ValueCount = 4;
Device[deviceCount].SendDataOption = true;
Device[deviceCount].TimerOption = true;
Device[deviceCount].GlobalSyncOption = true;
break;
}

case PLUGIN_GET_DEVICENAME:
{
string = F(PLUGIN_NAME_130);
break;
}

case PLUGIN_GET_DEVICEVALUENAMES:
{
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_130));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_130));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_130));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[3], PSTR(PLUGIN_VALUENAME4_130));
break;
}

case PLUGIN_I2C_HAS_ADDRESS:
case PLUGIN_WEBFORM_SHOW_I2C_PARAMS:
{
#define ADS1015_I2C_ADDR_COUNT 4
const uint8_t i2cAddressValues[] = { 0x48, 0x49, 0x4A, 0x4B };
if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) {
addFormSelectorI2C(F("i2c_addr"), ADS1015_I2C_ADDR_COUNT, i2cAddressValues, PCONFIG(0));
} else {
success = intArrayContains(ADS1015_I2C_ADDR_COUNT, i2cAddressValues, event->Par1);
}
break;
}

case PLUGIN_WEBFORM_LOAD:
{
#define ADS1015_SPS_AVAILABLE_COUNT 3
const String spsAvailableStr[] = {String(1600), String(2400), String(3300)};
const int spsAvailableVal[] = {P130_ADS1015_RATE_1600SPS,
P130_ADS1015_RATE_2400SPS,
P130_ADS1015_RATE_3300SPS};
addFormSubHeader(F("Calibration - General"));
addFormSelector(F("SPS"),F("p130_sps"), ADS1015_SPS_AVAILABLE_COUNT, spsAvailableStr,spsAvailableVal, PCONFIG_LONG(3));
addFormNumericBox(F("Current Frequency"), F("p130_frequency"), PCONFIG_LONG(0), 50, 60);
addFormNumericBox(F("Nb Sinus to read"), F("p130_nb_sinus"), PCONFIG_LONG(1), 1, 25);
addFormNote("Take care! Reading sinus is a blocking process. With a SCT013 (60A/50A/30A - 1V), reading 2 sinus on 50Hz giving stable values.");
addFormCheckBox(F("ADC Conversion Mode Continous"), F("p130_adc_continous"), PCONFIG_LONG(2));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To more reliably convert that to a bool, better use PCONFIG_LONG(2) == 1 here.

addFormCheckBox(F("Small Debug to INFO Log"), F("p130_debug"), PCONFIG(3));
addFormFloatNumberBox(F("Voltage Estimated"), F("p130_voltageEstimated"), PCONFIG_FLOAT(0), 0.0, 380.0, 2);
addFormSubHeader(F("Calibration"));
addFormNumericBox(F("Canal 1 - Max Current"), F("p130_calCurrent1"), PCONFIG(1), 1, 250);
addFormNumericBox(F("Canal 2 - Max Current"), F("p130_calCurrent2"), PCONFIG(2), 1, 250);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above, Canal -> Channel


success = true;
break;
}

case PLUGIN_WEBFORM_SAVE:
{
PCONFIG(0) = getFormItemInt(F("i2c_addr"));
PCONFIG(1) = getFormItemInt(F("p130_calCurrent1"));
PCONFIG(2) = getFormItemInt(F("p130_calCurrent2"));
PCONFIG(3) = (true == isFormItemChecked(F("p130_debug")))?1:0;

PCONFIG_LONG(0) = getFormItemInt(F("p130_frequency"));
PCONFIG_LONG(1) = getFormItemInt(F("p130_nb_sinus"));
PCONFIG_LONG(2) = (true == isFormItemChecked(F("p130_adc_continous")))?1:0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C/C++ treats a non-zero value as true, so no need to compare to true

PCONFIG_LONG(3) = getFormItemInt(F("p130_sps"));

PCONFIG_FLOAT(0) = getFormItemFloat(F("p130_voltageEstimated"));

success = true;
break;
}

case PLUGIN_INIT:
{
const uint8_t address = PCONFIG(0);
const uint8_t calCurrent1 = PCONFIG(1);
const uint8_t calCurrent2 = PCONFIG(2);
const uint8_t debug = PCONFIG(3);
const uint8_t currentFreq = PCONFIG_LONG(0);
const uint8_t nbSinus = PCONFIG_LONG(1);
const uint8_t adc_continous = PCONFIG_LONG(2);
const uint8_t sps = PCONFIG_LONG(3);
const float_t voltageEstimated = PCONFIG_FLOAT(0);

initPluginTaskData(event->TaskIndex, new (std::nothrow) P130_data_struct(address, calCurrent1, calCurrent2, voltageEstimated, currentFreq, nbSinus, adc_continous, sps));
P130_data_struct *P130_data =
static_cast<P130_data_struct *>(getPluginTaskData(event->TaskIndex));

if (nullptr != P130_data) {
P130_data->setDebug(debug);
success = true;
}
break;
}

case PLUGIN_READ:
{
P130_data_struct *P130_data =
static_cast<P130_data_struct *>(getPluginTaskData(event->TaskIndex));

if (nullptr != P130_data) {
float_t value = 0.;
P130_data->readCurrent(1, value);
UserVar[event->BaseVarIndex+0] = value;
UserVar[event->BaseVarIndex+1] = P130_data->estimatePower(value);
P130_data->readCurrent(2, value);
UserVar[event->BaseVarIndex+2] = value;
UserVar[event->BaseVarIndex+3] = P130_data->estimatePower(value);

{
String log;
log = F("Irms - ADS1015 : Canal1{ current="); log += UserVar[event->BaseVarIndex+0];
log += F("; power="); log += UserVar[event->BaseVarIndex+1];
log += F(";} Canal2{ current="); log += UserVar[event->BaseVarIndex+2];
log += F("; power="); log += UserVar[event->BaseVarIndex+3];
log += F(";}");
addLog(LOG_LEVEL_INFO, log);
}
success = true;
}
break;
}
}
return success;
}

#endif // USES_P130
4 changes: 2 additions & 2 deletions src/src/CustomBuild/define_plugin_sets.h
Original file line number Diff line number Diff line change
Expand Up @@ -1053,7 +1053,6 @@ To create/register a plugin, you have to :
#define USES_P079 // Wemos Motoshield
#endif


#ifdef CONTROLLER_SET_STABLE
#define USES_C001 // Domoticz HTTP
#define USES_C002 // Domoticz MQTT
Expand Down Expand Up @@ -1192,6 +1191,7 @@ To create/register a plugin, you have to :
#define USES_P121 // HMC5883L
#define USES_P125 // ADXL345 SPI
#define USES_P126 // 74HC595 Shift register
#define USES_P130 // Current Sensor Irms - ADS1015
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This plugin should IMHO better fit in the PLUGIN_ENERGY_COLLECTION selection, not in the PLUGIN_SET_TESTING_E set. (And when moving there, should be updated in the documentation too).

#endif


Expand Down Expand Up @@ -1343,7 +1343,7 @@ To create/register a plugin, you have to :
//#define USES_P124 // Ventus_W266_RFM69
#define USES_P125 // ArduCAM
#define USES_P127 // Teleinfo
#define USES_P130 // VEML6075
#define USES_P130 // [Irms - ADS1015](https://github.com/letscontrolit/ESPEasy/issues/3839)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is defining the Experimental set of plugins, AKA ESPEasyPluginPlayGround. No need to change anything here, as that uses a separate plugin-ID range. This set can probably be removed or at least trimmed, but that should become be a separate PR, and handled by someone else 😉.

#define USES_P131 // SHT3X
#define USES_P133 // VL53L0X
#define USES_P141 // LedStrip
Expand Down
Loading