From 57cf6e1063f76222ec6340727f788c51874716e6 Mon Sep 17 00:00:00 2001 From: Mit4el Date: Sat, 8 Apr 2023 23:07:14 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=BE=D0=B2=D1=8B=D0=B9=20Acs712,=20?= =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B8=D0=BB=20=D0=BE=D0=BF=D0=B8?= =?UTF-8?q?=D1=81=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D0=B0=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE=20Pzem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/sensors/Acs712/Acs712.cpp | 101 ++++++++++++++++------ src/modules/sensors/Acs712/modinfo.json | 36 +++++--- src/modules/sensors/Pzem004t/modinfo.json | 2 +- 3 files changed, 102 insertions(+), 37 deletions(-) diff --git a/src/modules/sensors/Acs712/Acs712.cpp b/src/modules/sensors/Acs712/Acs712.cpp index 79d9bc76..ed4984e2 100644 --- a/src/modules/sensors/Acs712/Acs712.cpp +++ b/src/modules/sensors/Acs712/Acs712.cpp @@ -3,6 +3,14 @@ extern IoTGpio IoTgpio; +#ifdef ESP32 + #define SC_ADC 4095. //Scale ADC +#else + #define SC_ADC 1023. //Scale ADC +#endif + +#define DEF_NAN 50 //количество отсчетов АПЦ которые мы принимаем за отсутствие датчика (в идеале 0, но все равно Acs712 выдает минимум 0,5В) + class Acs712 : public IoTItem { private: @@ -10,56 +18,97 @@ private: const unsigned long _sampleTime = 100000UL; // sample over 100ms, it is an exact number of cycles for both 50Hz and 60Hz mains const unsigned long _numSamples = 250UL; // choose the number of samples to divide sampleTime exactly, but low enough for the ADC to keep up const unsigned long _sampleInterval = _sampleTime / _numSamples; // the sampling interval, must be longer than then ADC conversion time - int _adc_zero1; //Переменная автоматической калибровки + int _adc_zero1; // Переменная автоматической калибровки + int _fl_rms; // 1 - подсчет средне-квадратического тока (переменный), 0 - подсчет средне-арифмитического тока (постоянный) + int _sens = 100; //Чувствительность датчика тока: 5A = 185mВ/A, 20A = 100mВ/A, 30A = 66mВ/A + int _vref; //"Vref (мВ) - Опороное наряжение питания Acs712, по умолчанию = 5000мВ", + float k ; //Чувствительность(разрешение) Acs712 по току, сколько тока в одном отсчете АЦП, k=VACP/sens (30А->74mА, 20A->49mA, 5A->26mA для esp8266) + bool f_nan = false; //Флаг отсутствия входа на АЦП + float vacp; //Напряжение в мВ для смещения одного разряда АЦП esp8266 = 4.887, esp32 = 1.221; vacp = vcc*1000/1023 public: - Acs712(String parameters) : IoTItem(parameters) { String tmp; jsonRead(parameters, "pin", tmp); _pin = tmp.toInt(); - _adc_zero1 = determineVQ(_pin); + jsonRead(parameters, "adczero", tmp); + _adc_zero1 = tmp.toInt(); // determineVQ(_pin); + jsonRead(parameters, "rms", tmp); + _fl_rms = tmp.toInt(); + jsonRead(parameters, "sens", tmp); + _sens = tmp.toInt(); + jsonRead(parameters, "vref", tmp); + _vref = tmp.toInt(); + vacp = _vref/SC_ADC; + k = vacp / (float)_sens; //коэффециент для домножения измерений АЦП } - + void doByInterval() { - - unsigned long currentAcc = 0; - unsigned int count = 0; - unsigned long prevMicros = micros() - _sampleInterval; - while (count < _numSamples) + f_nan = false; + unsigned long currentAcc = 0; + unsigned int count = 0; + unsigned long prevMicros = micros() - _sampleInterval; + while (count < _numSamples) + { + if (micros() - prevMicros >= _sampleInterval) { - if (micros() - prevMicros >= _sampleInterval) - { - int adc_raw = IoTgpio.analogRead(_pin) - _adc_zero1; + int adc_raw = IoTgpio.analogRead(_pin); + if (adc_raw > DEF_NAN) f_nan = true; //Если за цикл измерений не было АЦП больше 50, то считаем что нет датчика + adc_raw -= _adc_zero1; + if (_fl_rms == 0) + currentAcc += (unsigned long)abs(adc_raw); + else currentAcc += (unsigned long)(adc_raw * adc_raw); - ++count; - prevMicros += _sampleInterval; - } + ++count; + prevMicros += _sampleInterval; } - #ifdef ESP32 - value.valD = int(sqrt((float)currentAcc / (float)_numSamples) * (75.7576 / 4095.0)); - #else - value.valD = int(sqrt((float)currentAcc / (float)_numSamples) * (75.7576 / 1023.0)); - #endif + } + + if (_fl_rms == 0) + { +#ifdef ESP32 + value.valD = ((float)currentAcc / (float)_numSamples) * k; +#else + value.valD = ((float)currentAcc / (float)_numSamples) * k; +#endif + } + else + { +#ifdef ESP32 + value.valD = (sqrt((float)currentAcc / (float)_numSamples) * k); +#else + value.valD = (sqrt((float)currentAcc / (float)_numSamples) * k); +#endif + } + if (f_nan) regEvent(value.valD, "Acs712"); + else + regEvent(NAN, "Acs712"); } - + + void onModuleOrder(String &key, String &value) + { + if (key == "setZero") + { + _adc_zero1 = determineVQ(_pin); + SerialPrint("i", F("Acs712"), "User run calibration ADC zero: " + String(_adc_zero1)); + // TODO wtitejson to config.json????? + } + } + int determineVQ(int PIN) { long VQ = 0; - // read 5000 samples to stabilise value - for (int i = 0; i < 5000; i++) + for (int i = 0; i < 100; i++) { VQ += IoTgpio.analogRead(PIN); - //delay(1); // depends on sampling (on filter capacitor), can be 1/80000 (80kHz) max. } - VQ /= 5000; + VQ /= 100; return int(VQ); } - ~Acs712(){}; }; diff --git a/src/modules/sensors/Acs712/modinfo.json b/src/modules/sensors/Acs712/modinfo.json index b9b15347..a3540924 100644 --- a/src/modules/sensors/Acs712/modinfo.json +++ b/src/modules/sensors/Acs712/modinfo.json @@ -3,7 +3,7 @@ "configItem": [ { "name": "Acs712 Ток", - "type": "Reading", + "type": "Reading", "subtype": "Acs712", "id": "amp", "widget": "anydataAmp", @@ -11,26 +11,42 @@ "descr": "Ток", "round": 3, "pin": 39, - "int": 5 + "int": 5, + "rms": 1, + "vref": 5000, + "sens": 100, + "adczero" : 512, + "btn-setZero": "nil" } ], "about": { - "authorName": "Yuriy Kuneev", - "authorContact": "https://t.me/Kuneev07", - "authorGit": "", + "authorName": "Bubnov Mikhail", + "authorContact": "https://t.me/Mitchel", + "authorGit": "https://github.com/Mit4el", "exampleURL": "https://iotmanager.org/wiki", "specialThanks": "", "moduleName": "Acs712", - "moduleVersion": "1.0", - "moduleDesc": "Позволяет получить текущее значение тока на аналоговом пине с помощью модуля Acs712.", + "moduleVersion": "2.0", + "moduleDesc": "Позволяет получить текущее значение тока на аналоговом пине с помощью модуля Acs712. Не забываем про делитель для входа на АЦП/", "propInfo": { - "pin": "Аналоговый GPIO номер, к которому подключен датчик.", - "int": "Количество секунд между опросами датчика." + "pin": "Аналоговый GPIO номер, к которому подключен датчик. Для esp8266 0", + "int": "Количество секунд между опросами датчика.", + "rms": "1 - подсчет средне-квадратического тока (переменный), 0 - подсчет средне-арифмитического тока (постоянный)", + "vref": "Vref (мВ) - Опороное наряжение питания Acs712, по умолчанию = 5000мВ", + "sens": "Чувствительность датчика тока: 5A = 185mВ/A , 20A = 100mВ/A , 30A = 66mВ/A ", + "adczero" : "Переменная калибровки нулевого значения отсчетов АЦП при нулевой нагрузке. Для ESP8266 - 512, Для ESP32 -2048, это 2.5В = 0А (1,65 с делителем) для Acs712 20A и 30A при стабильном токе 5В", + "btn-setZero": "Кнопка калибровки нулевого значения отсчетов АЦП при нулевой нагрузке. Нагрузка в момент калибровки должна быть отключена! После перезагрузки будет установлено в значение по умолчанию adczero. Для сохранение смотрим лог, и изменияем adczero" } }, "defActive": true, "usedLibs": { "esp32_4mb": [], - "esp8266_4mb": [] + "esp8266_4mb": [], + "esp8266_1mb": [], + "esp8266_1mb_ota": [], + "esp8285_1mb": [], + "esp8285_1mb_ota": [], + "esp8266_2mb": [], + "esp8266_2mb_ota": [] } } \ No newline at end of file diff --git a/src/modules/sensors/Pzem004t/modinfo.json b/src/modules/sensors/Pzem004t/modinfo.json index 56a1fd58..697015f9 100644 --- a/src/modules/sensors/Pzem004t/modinfo.json +++ b/src/modules/sensors/Pzem004t/modinfo.json @@ -119,7 +119,7 @@ "moduleDesc": "Считает потраченную электроэнергию, измеряет напряжение, частоту, силу тока и прочие параметры", "propInfo": { "addr": "Адрес modbus", - "int": "Количество секунд между опросами датчика. Желателно устанавливать разные интервалы для параметров что бы опросы происходили в разное время.", + "int": "Количество секунд между опросами датчика. Желателно устанавливать одинаковые интервалы для параметров (для одного адреса Pzem) что опрос происходил один раз, остальные из 500мс буфера.", "changeaddr": "Поставьте этот параметр равным 1 и перезагрузите esp - будет установлен адрес указанный в setaddr. Смотрите в логе результат: [i] Pzem address set: 0x01", "setaddr": "Новый адрес который нужно назначить", "reset": "Поставьте этот параметр равным 1 и pzem будет сброшен к нулю. Смотрите в логе результат: [i] Pzem reset done"