Files
IoTManager/src/modules/sensors/Acs712/Acs712.cpp

126 lines
4.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "Global.h"
#include "classes/IoTItem.h"
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:
unsigned int _pin;
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 _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();
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()
{
f_nan = false;
unsigned long currentAcc = 0;
unsigned int count = 0;
unsigned long prevMicros = micros() - _sampleInterval;
while (count < _numSamples)
{
if (micros() - prevMicros >= _sampleInterval)
{
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;
}
}
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;
for (int i = 0; i < 100; i++)
{
VQ += IoTgpio.analogRead(PIN);
}
VQ /= 100;
return int(VQ);
}
~Acs712(){};
};
void *getAPI_Acs712(String subtype, String param)
{
if (subtype == F("Acs712"))
{
return new Acs712(param);
}
else
{
return nullptr;
}
}