My plugin is based on the existing Analog ADC Plugin (P002), and also uses interrupt code and calculations from a Henry's Bench arduino sketch. My present code is functioning ok, reading the waveform of the mains AC through a current-transformer sensor module (I'm using a TA12-100). The interrupt routine identifies the peaks in the alternating current, then the main code of the plugin converts this peak data to a RMS (root mean square) value for current, and finally sends the result via MQTT to openHAB2. It also correctly displays the values in the Log. I've begun to set up some parameters which can be entered/changed at runtime in the device configuration page, then saved, such as the ratio of the current transformer, mains voltage, etc. Potentially this could allow the plugin to be used with other sensor devices. So far so good!
The problem I have is this. Whereas all other plugins display the value of their measurements in the Devices screen, at present this isn't happenIng with my plugin

Here is my code, with thanks and acknowledgements to the authors of Plugin 002 and Henry's Bench ....
Code: Select all
//#######################################################################################################
//#################################### Plugin 202: AC current C.T. sensor ###############
//#######################################################################################################
#define PLUGIN_202
#define PLUGIN_ID_202 202
#define PLUGIN_NAME_202 "Analog AC current sensor"
#define PLUGIN_VALUENAME1_202 "nVPP"
#define PLUGIN_VALUENAME2_202 "ACcurrentRMS"
#define PLUGIN_VALUENAME3_202 "ACwatts"
// float Plugin_202_nVPP[TASKS_MAX]; // Signal voltage measured across C.T. resistor, converted to float.
float Plugin_202_nVPP;
//float Plugin_202_nCurrThruResistorPP[TASKS_MAX]; // peak to peak current through resistor.
//float Plugin_202_nCurrThruResistorPP;
//float Plugin_202_nCurrThruResistorRMS[TASKS_MAX]; // RMS current through Resistor
//float Plugin_202_nCurrentThruWire[TASKS_MAX]; // Actual RMS current in Wire
float Plugin_202_nCurrentThruWire;
//float Plugin_202_watts[TASKS_MAX]; // watts (VA) assuming constant mains voltage and resistive load.
float Plugin_202_watts;
/*
// Parameters (variables so they can eventually be changed via web interface)
int plugin_202_CT_ratio[TASKS_MAX]; // turns ratio of Current Transformer
int plugin_202_Resistor_ohms[TASKS_MAX]; // burden resistor value 200
int plugin_202_mains_volts[TASKS_MAX]; // assumed to be constant voltage 241
float plugin_202_current_zero_error[TASKS_MAX]; // 93.0 zero correction in mA (from independent measurement)
*/
boolean Plugin_202(byte function, struct EventStruct *event, String& string)
{
boolean success = false;
switch (function)
{
case PLUGIN_DEVICE_ADD:
{
Device[++deviceCount].Number = PLUGIN_ID_202;
Device[deviceCount].Type = DEVICE_TYPE_ANALOG;
Device[deviceCount].VType = SENSOR_TYPE_TEMP_HUM_BARO;
Device[deviceCount].Ports = 0;
Device[deviceCount].PullUpOption = false;
Device[deviceCount].InverseLogicOption = false;
Device[deviceCount].FormulaOption = true;
Device[deviceCount].ValueCount = 3;
Device[deviceCount].SendDataOption = true;
Device[deviceCount].TimerOption = true;
Device[deviceCount].GlobalSyncOption = true;
break;
}
case PLUGIN_GET_DEVICENAME:
{
string = F(PLUGIN_NAME_202);
break;
}
case PLUGIN_GET_DEVICEVALUENAMES:
{
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_202));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_202));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_202));
break;
}
case PLUGIN_WEBFORM_LOAD:
{
char tmpString[256]; // was 128 - too small?
sprintf_P(tmpString, PSTR("<TR><TD>CT ratio:<TD><input type='text' name='plugin_202_CT_ratio' value='%u'>"), Settings.TaskDevicePluginConfig[event->TaskIndex][0]);
string += tmpString;
sprintf_P(tmpString, PSTR("<TR><TD>Resistor ohms :<TD><input type='text' name='plugin_202_Resistor_ohms' value='%u'>"), Settings.TaskDevicePluginConfig[event->TaskIndex][1]);
string += tmpString;
sprintf_P(tmpString, PSTR("<TR><TD>Mains volts :<TD><input type='text' name='plugin_202_mains_volts' value='%u'>"), Settings.TaskDevicePluginConfig[event->TaskIndex][2]);
string += tmpString;
sprintf_P(tmpString, PSTR("<TR><TD>Current Zero Error (mA) :<TD><input type='text' name='plugin_202_current_zero_error' value='%u'>"), Settings.TaskDevicePluginConfig[event->TaskIndex][3]);
string += tmpString;
success = true;
break;
}
case PLUGIN_WEBFORM_SAVE:
{
String plugin1 = WebServer.arg("plugin_202_CT_ratio");
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
String plugin2 = WebServer.arg("plugin_202_Resistor_ohms");
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = plugin2.toInt();
String plugin3 = WebServer.arg("plugin_202_mains_volts");
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = plugin3.toInt();
String plugin4 = WebServer.arg("plugin_202_current_zero_error");
Settings.TaskDevicePluginConfig[event->TaskIndex][3] = plugin4.toInt();
success = true;
break;
}
case PLUGIN_WEBFORM_SHOW_VALUES:
{
/*
string += ExtraTaskSettings.TaskDeviceValueNames[0];
string += F(":");
string += plugin_202_CT_ratio[event->TaskIndex];
// string += F("<BR>");
string += ExtraTaskSettings.TaskDeviceValueNames[1];
string += F(":");
string += plugin_202_Resistor_ohms[event->TaskIndex];
// string += F("<BR>");
string += ExtraTaskSettings.TaskDeviceValueNames[2];
string += F(":");
string += plugin_202_mains_volts[event->TaskIndex];
// string += F("<BR>");
string += ExtraTaskSettings.TaskDeviceValueNames[3];
string += F(":");
string += plugin_202_current_zero_error[event->TaskIndex];
string += F("<BR>");
*/
success = true;
break;
}
case PLUGIN_READ:
{
Plugin_202_nVPP = (float)Plugin_202_getVPP(); // Calls method below to sample AC waveform and pick up digital signal of peak to peak voltage
// Convert the digital data to a voltage
Plugin_202_nVPP *= 3.3; // NodeMCU works at 3.3v
Plugin_202_nVPP *= 1.1032; // empirical range correction
Plugin_202_nVPP /= 1024.0; // 1024 analog values in range.
Plugin_202_nCurrentThruWire = (Plugin_202_nVPP / 200.0) * 1000.0; // 200 = R, 1000 = conversion to mA
Plugin_202_nCurrentThruWire *= 0.707; // factor for sinewave to convert to RMS
Plugin_202_nCurrentThruWire *= 1000.0; // 1000 is CT ratio, current in mA
Plugin_202_nCurrentThruWire -= 93.0; // 93.0 is zero error
if (Plugin_202_nCurrentThruWire < 0.0 ) {
Plugin_202_nCurrentThruWire = 0.0;
}
// Plugin_202_watts = 241.0 * Plugin_202_nCurrentThruWire / 1000.0; // 241 = Plugin_202_mains_volts
// calculate watts (V*A), assumes constant mains voltage and 100% PF (pure resistive load)
Plugin_202_watts = Plugin_202_nCurrentThruWire * Settings.TaskDevicePluginConfig[event->TaskIndex][2]; // multiply by mains volts
Plugin_202_watts /= 1000.0; // convert mW to Watts
UserVar[event->BaseVarIndex] = (float) Plugin_202_nVPP; // peak to peak signal volts
UserVar[event->BaseVarIndex+1] = Plugin_202_nCurrentThruWire; // RMS AC current in mA
UserVar[event->BaseVarIndex+2] = Plugin_202_watts; // Watts
String log = F(" BaseVar : ");
log += UserVar[event->BaseVarIndex];
log += F(" BaseVar+1 : ");
log += UserVar[event->BaseVarIndex+1];
log += F(" BaseVar+2 : ");
log += UserVar[event->BaseVarIndex+2];
addLog(LOG_LEVEL_INFO,log);
success = true;
break;
}
}
return success;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//////////////// Function to read peak to peak signal volts from CT sensor unit //////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
float Plugin_202_getVPP() { // was float
// int result; // was float
int readValue; // instantaneous volt value read from the sensor
int maxValue = 0; // store max voltvalue here
uint32_t start_time = millis();
while((millis()-start_time) < 100) //sample for 100 milliSec, each cycle of mains is 1/50th sec = 20 millisec
{
readValue = analogRead(A0); // read digital signal representing instantaneous volt value from sensor (0-254)
// see if we have a new maxValue
if (readValue > maxValue)
{
// record the maximum sensor value
maxValue = readValue;
}
}
/*
// Convert the digital data to a voltage
result = (maxValue * 3.3 * 1.1032)/1024.0; // NodeMCU works at 3.3v
// 1.1032 = empirical range correction
// factor to match meter.
// 1024 analog values in range.
*/
// result = maxValue; // temporary for debug!
return maxValue;
}
.. and here is a screenshot of my Devices page (with no values from this plugin) ...
... and my device configuration screen for the plugin... All help and advice welcome! Thanks in advance!.
AndrewJ