//#######################################################################################################
//#################################### Plugin 128: HC-SR04 (w/Median) ###################################
//#######################################################################################################
#define PLUGIN_128
#define PLUGIN_ID_128 128
#define PLUGIN_NAME_128 "Ultr. Sensor - HC-SR04 (w/Median)"
#define PLUGIN_VALUENAME1_128 "Distance"
void Plugin_128_interrupt() ICACHE_RAM_ATTR;
boolean Plugin_128_init = false;
volatile unsigned long Plugin_128_timer = 0;
volatile unsigned long Plugin_128_state = 0;
byte Plugin_128_TRIG_Pin = 0;
byte Plugin_128_IRQ_Pin = 0;
int readcount_128 = 0;
float* medianValues_128;
boolean Plugin_128(byte function, struct EventStruct *event, String& string)
{
static byte switchstate[TASKS_MAX];
boolean success = false;
switch (function)
{
case PLUGIN_DEVICE_ADD:
{
Device[++deviceCount].Number = PLUGIN_ID_128;
Device[deviceCount].Type = DEVICE_TYPE_DUAL;
Device[deviceCount].VType = SENSOR_TYPE_SINGLE;
Device[deviceCount].Ports = 0;
Device[deviceCount].PullUpOption = false;
Device[deviceCount].InverseLogicOption = false;
Device[deviceCount].FormulaOption = false;
Device[deviceCount].ValueCount = 1;
Device[deviceCount].SendDataOption = true;
Device[deviceCount].TimerOption = true;
Device[deviceCount].GlobalSyncOption = true;
break;
}
case PLUGIN_GET_DEVICENAME:
{
string = F(PLUGIN_NAME_128);
break;
}
case PLUGIN_GET_DEVICEVALUENAMES:
{
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_128));
break;
}
case PLUGIN_WEBFORM_LOAD:
{
byte choice = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
String options[2];
options[0] = F("Value");
options[1] = F("State");
int optionValues[2];
optionValues[0] = 1;
optionValues[1] = 2;
string += F("
Mode: | ");
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == 2)
{
char tmpString[128];
sprintf_P(tmpString, PSTR(" |
Threshold: | "), Settings.TaskDevicePluginConfig[event->TaskIndex][1]);
string += tmpString;
}
char tmpString[128];
sprintf_P(tmpString, PSTR(" |
Nbr. Values: | "), Settings.TaskDevicePluginConfig[event->TaskIndex][2]);
string += tmpString;
success = true;
break;
}
case PLUGIN_WEBFORM_SAVE:
{
String plugin1 = WebServer.arg("plugin_128_mode");
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == 2)
{
String plugin2 = WebServer.arg("plugin_128_threshold");
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = plugin2.toInt();
}
String plugin3 = WebServer.arg("plugin_128_medianvals");
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = plugin3.toInt();
success = true;
break;
}
case PLUGIN_INIT:
{
Plugin_128_init = true;
pinMode(Settings.TaskDevicePin1[event->TaskIndex], OUTPUT);
pinMode(Settings.TaskDevicePin2[event->TaskIndex], INPUT_PULLUP);
Plugin_128_IRQ_Pin = Settings.TaskDevicePin2[event->TaskIndex];
attachInterrupt(Settings.TaskDevicePin2[event->TaskIndex], Plugin_128_interrupt, CHANGE);
if (medianValues_128)
delete [] medianValues_128;
medianValues_128 = 0;
if (Settings.TaskDevicePluginConfig[event->TaskIndex][2] > 0)
{
if (Settings.TaskDevicePluginConfig[event->TaskIndex][2] < 5)
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = 5;
}
if (Settings.TaskDevicePluginConfig[event->TaskIndex][2] > 0)
{
medianValues_128 = new float[Settings.TaskDevicePluginConfig[event->TaskIndex][2]];
for (byte valNr = 0; valNr < Settings.TaskDevicePluginConfig[event->TaskIndex][2]; valNr++)
*(medianValues_128 + valNr) = 0;
}
success = true;
break;
}
case PLUGIN_WRITE:
{
String log = "";
String command = parseString(string, 1);
if (command == F("status"))
{
if (parseString(string, 2) == F("valuehcsr04"))
{
success = true;
float value = 0;
if (Settings.TaskDevicePluginConfig[event->TaskIndex][2] > 0)
value = *(medianValues_128 + ((int) (Settings.TaskDevicePluginConfig[event->TaskIndex][2] / 2))); //select median reading
else
value = Plugin_128_read();
log = String(F("SW : HCSR04 ")) + String(F(" Send current value: "));
log += value;
addLog(LOG_LEVEL_INFO, log);
String status = F("SR04 : Distance: ");
status += value;
SendStatus(event->Source, status);
}
}
break;
}
case PLUGIN_READ: // If we select value mode, read and send the value based on global timer
{
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == 1)
{
Plugin_128_TRIG_Pin = Settings.TaskDevicePin1[event->TaskIndex];
float value = Plugin_128_read();
String log = F("SR04 : Distance: ");
if (value != -1)
{
if (Settings.TaskDevicePluginConfig[event->TaskIndex][2] > 0)
{
if (readcount_128 >= Settings.TaskDevicePluginConfig[event->TaskIndex][2])
readcount_128 = 0;
*(medianValues_128 + readcount_128) = value;
readcount_128++;
insertionSort(medianValues_128, Settings.TaskDevicePluginConfig[event->TaskIndex][2]); //sort readings
value = *(medianValues_128 + ((int) (Settings.TaskDevicePluginConfig[event->TaskIndex][2] / 2))); //select median reading
}
UserVar[event->BaseVarIndex] = value;
log += UserVar[event->BaseVarIndex];
log += String(F(" [")) + String(value) + String(F("]"));
success = true;
}
else
log += F("No reading!");
addLog(LOG_LEVEL_INFO,log);
}
break;
}
case PLUGIN_TEN_PER_SECOND: // If we select state mode, do more frequent checks and send only state changes
{
Plugin_128_TRIG_Pin = Settings.TaskDevicePin1[event->TaskIndex];
byte state = 0;
float value = Plugin_128_read();
if (value != -1)
{
if (Settings.TaskDevicePluginConfig[event->TaskIndex][2] > 0)
{
if (readcount_128 >= Settings.TaskDevicePluginConfig[event->TaskIndex][2])
readcount_128 = 0;
*(medianValues_128 + readcount_128) = value;
readcount_128++;
insertionSort(medianValues_128, Settings.TaskDevicePluginConfig[event->TaskIndex][2]); //sort readings
value = *(medianValues_128 + ((int) (Settings.TaskDevicePluginConfig[event->TaskIndex][2] / 2))); //select median reading
}
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == 2)
{
if (value < Settings.TaskDevicePluginConfig[event->TaskIndex][1])
state = 1;
if (state != switchstate[event->TaskIndex])
{
String log = F("SR04 : State ");
log += state;
addLog(LOG_LEVEL_INFO,log);
switchstate[event->TaskIndex] = state;
UserVar[event->BaseVarIndex] = state;
event->sensorType = SENSOR_TYPE_SWITCH;
sendData(event);
}
}
else if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == 1)
{
if (Settings.TaskDevicePluginConfig[event->TaskIndex][2] > 0)
{
if (readcount_128 >= Settings.TaskDevicePluginConfig[event->TaskIndex][2])
readcount_128 = 0;
*(medianValues_128 + readcount_128) = value;
readcount_128++;
insertionSort(medianValues_128, Settings.TaskDevicePluginConfig[event->TaskIndex][2]); //sort readings
value = *(medianValues_128 + ((int) (Settings.TaskDevicePluginConfig[event->TaskIndex][2] / 2))); //select median reading
}
UserVar[event->BaseVarIndex] = value;
}
}
success = true;
break;
}
}
return success;
}
/*********************************************************************/
float Plugin_128_read()
/*********************************************************************/
{
float value = -1;
Plugin_128_timer = 0;
Plugin_128_state = 0;
noInterrupts();
digitalWrite(Plugin_128_TRIG_Pin, LOW);
delayMicroseconds(2);
digitalWrite(Plugin_128_TRIG_Pin, HIGH);
delayMicroseconds(10);
digitalWrite(Plugin_128_TRIG_Pin, LOW);
interrupts();
delay(25); // wait for measurement to finish (max 400 cm * 58 uSec = 23uSec)
if (Plugin_128_state == 2)
{
value = (float)Plugin_128_timer / 58;
}
return value;
}
/*********************************************************************/
void Plugin_128_interrupt()
/*********************************************************************/
{
byte pinState = digitalRead(Plugin_128_IRQ_Pin);
if (pinState == 1) // Start of pulse
{
Plugin_128_state = 1;
Plugin_128_timer = micros();
}
else // End of pulse, calculate timelapse between start & end
{
Plugin_128_state = 2;
Plugin_128_timer = micros() - Plugin_128_timer;
}
}
|