-
Notifications
You must be signed in to change notification settings - Fork 2.2k
[P130] Add simple circuit to get a current sensor , result is Irms #4009
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: mega
Are you sure you want to change the base?
Changes from 18 commits
c50f175
889b135
61835ce
e4e5f38
74232c3
c7b6530
5f89618
3119a25
1135c89
26af21f
6ffd1c1
89be65e
69e9877
e77eace
d192d93
eddff51
5647d1f
1a76556
afcf524
6e2ecdb
f25c9da
95e83cd
02a67dc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| 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. | ||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
| 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)` | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 // | ||
|
||
| // #define USES_P130 // Current Sensor Irms - ADS1015 | ||
|
|
||
| // Special plugins needing IR library | ||
| // #define USES_P016 // IR | ||
|
|
||
| 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" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To have plugin names with the same structure, this should probably be |
||
| #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)); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To more reliably convert that to a |
||
| 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); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See above, |
||
|
|
||
| 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; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
| 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 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 | ||
|
|
@@ -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 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This plugin should IMHO better fit in the |
||
| #endif | ||
|
|
||
|
|
||
|
|
@@ -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) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|
|
||
There was a problem hiding this comment.
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)