Hello, I have an application where I am reading an input voltage. The voltage needs to be between 2 and 3 volts to be good. If it goes outside of that bound and stays continuously outside of that bound for more than 15 minutes, I want to set off an alarm. If it goes outside of that bound but then returns to between 2 and 3 volts for less than 15 minutes, I do not want an alarm. I currently have the following code that will alarm if the voltage is greater than 3 volts or less than 2 volts, however I don't know how to make it alarm when it has stayed continuously outside of bound for 15 plus minutes. I don't want it to be instantaneous like it is now because it is nescience alarming. Any suggestions much appreciated! Thank you!
const int pinInput1 = A0;
//
const int pinRelay = 5;
#define RELAY_ON HIGH
#define RELAY_OFF LOW
void setup()
{
//
pinMode(pinInput1, INPUT);
//
pinMode(pinRelay, OUTPUT);
digitalWrite(pinRelay, RELAY_OFF);
}
void loop()
{
static unsigned long
timeRelay = 0;
unsigned long
timeNow;
float
v1;
int
a1;
//update every 1000mS
timeNow = millis();
if( timeNow - timeRelay >= 1000)
{
timeRelay = timeNow;
//read the analog channel
a1 = analogRead( pinInput1 );
//convert to floating point voltages for easy compares
v1 = (float)a1*5.0/1023.0;
//check the threshold
//If analog input pin A0 is less than 2 volts and greater
//than 3 volts, it will send a signal from output pin
//5 to operate a relay shield
if( (v1 < 2.0 || v1 > 3.0))
{
//turn on the relay
digitalWrite( pinRelay, RELAY_ON );
}//if
else
{
//turn off the relay
digitalWrite( pinRelay, RELAY_OFF );
}//else
}//if
}//Loop
When the alarm condition becomes true save the value of millis() as the start time and set a boolean to true to flag that timing is taking place.
Separately in loop() if the boolean is true and millis() minus than start time is equal to or greater than the required period then execute the appropriate code.
If at any time the alarm conditions are not true then set the boolean to false to prevent the alarm being triggered
Every time through the loop, of course you're going to check the analog condition. If that condition is good (which should be almost every time) reset the timer so it can't be triggered for 15 minutes.
In other words, you could make a variable called LastGoodTime.
There's no harm in that. It's more processing but you're not doing lots of other stuff where you need the CPU cycles.
But you aren't increasing resolution. With a standard Arduino and the 5V reference, each count of the ADC is about 5mV, and that's it. If you are going to calculate or display the voltage you should use float. (If you convert the integer ADC reading to an integer voltage, you are obviously loosing resolution.)
I'm not trying to tell you what to do, but if it was me... 2V should give a raw ADC reading of 409 and 3V is 614. I'd use those values directly (with comments referencing the voltages). And for clarity I'd probably make them named-variables (or constants) like HighLimit & LowLimit.
const int pinInput1 = A0;
const int pinRelay = 5;
#define RELAY_ON HIGH
#define RELAY_OFF LOW
void setup()
{
// pinMode(pinInput1, INPUT); // DON'T Use pinMode() on pins used for analogRead()
pinMode(pinRelay, OUTPUT);
digitalWrite(pinRelay, RELAY_OFF);
}
void loop()
{
static unsigned long timeRelay = 0;
static unsigned long lastInRangeTime = 0;
unsigned long timeNow;
float v1;
int a1;
//update every 1000mS
timeNow = millis();
if (timeNow - timeRelay >= 1000)
{
timeRelay = timeNow;
//read the analog channel
a1 = analogRead( pinInput1 );
//convert to floating point voltages for easy compares
v1 = (float)a1 * 5.0 / 1023.0;
//check the threshold
//If analog input pin A0 is less than 2 volts and greater
//than 3 volts, it will send a signal from output pin
//5 to operate a relay shield
if ( (v1 < 2.0 || v1 > 3.0))
{
//turn on the relay
digitalWrite(pinRelay, RELAY_ON);
lastInRangeTime = timeNow;
}
else
{
//turn off the relay
digitalWrite( pinRelay, RELAY_OFF );
}//else
if (timeNow - lastInRangeTime >= 15ul * 60ul * 1000ul) // 15 minutes
{
// Alarm
}
}//if
}// loop()