Although this is my first forum post, I have been working with Arduino and electronics for about three years now, so I am not what you would call a 'newbie'. I do however struggle with some of the more complex logic/mathematical aspects of programming, hence this post.
In the past twelve months, I have built a number of devices to increase efficiency and solve minor problems at the public aquarium where I work. The most recent of these is a flow-through control system on a group of small tanks, all connected together by a common sump. Water flows into these tanks all day, overflowing into this common sump where the water is then pumped out into an adjacent filter system. The pumps drain the sump tank until a 'low level' float switch indicates that the water level is sufficiently low; the tank then stops draining and starts to fill back up by gravity from the tanks above; when the sump tank is full, a 'high level' float switch is engaged, and the pumps then switch back on and drain the sump tank to the 'low level' float switch again. Now whilst all of this works perfectly, I would like to add some redundancy in the event that there is a mechanical failure with the pump or associated relays, and water continues to fill the sump tank causing a flood.
To do this, my plan was to create a timestamp when the 'high level' float switch was first engaged. I then planned to incorporate an 'if statement' that would activate an alarm sequence (loud buzzer and an LED) if the float switch remained engaged for, say, ten seconds (i.e. if the tank was draining too much, or about to overflow). I also have some solenoid valves connected to the inlets to each of the tanks, which can be closed to prevent undue flooding.
The problem I encountered is that in the event that the tank is overflowing, the float switch would remain in the same position, thus I am unable to compare an 'up time' and 'down time' to see if it exceeded ten seconds. Instead, I need to find a way of measuring how long the float switch has been engaged, performing a task if it exceeds ten seconds.
Could anyone give me some pointers? I would post the existing code but it is very long! If I can figure out how to code this part, I can then go back and add it into the existing code, and upload to the system for a full test.
const int floatSensor = 3;
const int led = 13;//onboard led
unsigned long startTime;
int lastSensorStatus;
boolean tripped;
void setup()
{
Serial.begin(9600);
pinMode(led,OUTPUT);
pinMode(floatSensor,INPUT);
}
void loop()
{
int sensorStatus = digitalRead(floatSensor);
if (sensorStatus == HIGH) //you certainly have to check to see if your sensor's output is HIGH or LOW
{
if (lastSensorStatus == LOW)// only indicates tripped on the transition from LOW to HIGH
{
tripped = true;
startTime = millis();
Serial.println("Tripped!");
}
}
else
{
tripped = false;
digitalWrite(led, LOW);
Serial.println("not tripped...");
}
lastSensorStatus = sensorStatus;
if (tripped)
{
alarmSound();
}
}
void alarmSound()
{
if (millis() - startTime > 10000UL)
{
digitalWrite(led, HIGH);
}
}
Bulldog, the line [ if (millis() - startTime > 10000UL) ] will surely always become true because at some point, as the sketch has been running for a certain amount of time, mills() - startTime will exceed 10000UL. Or have I missed something?
I have been at this for a good few hours now, and did come up with an idea. If I test to see whether the float switch is HIGH, and increment a variable by 1 if it is, then I can have a number representing the amount of loop() cycles that the float switch has been HIGH for. If I then include a 100UL delay, it would take 100 cycles to be equivalent to ten seconds, thus when the variable reached 100 the sketch could initiate the alarm response. The next step would be to reset the variable to zero if the float switch goes LOW inside the ten second limit.
Can someone with more experience confirm whether I am on the right track?
That test only happens in the tripped state - while the high level is exceeded.
I would recommend learning a bit about finite state machines, because this is
a classic example.
Identify the states:
overfull, underfull, filling, draining
Then identify what to do in each state for each input and any timeouts
that need to be checked in each state.
For instance the high level switch should only trip in the state filling,
causing the state to change to overfull and the drain pump to be activated.
when the high level switch reverts, move to state draining. If you are
10s or more in the overfull state, sound the alarm...
Learn to draw state-transition diagrams, they are powerful tools.
Bulldog, the line [ if (millis() - startTime > 10000UL) ] will surely always become true because at some point, as the sketch has been running for a certain amount of time, mills() - startTime will exceed 10000UL. Or have I missed something?
I have been at this for a good few hours now, and did come up with an idea. If I test to see whether the float switch is HIGH, and increment a variable by 1 if it is, then I can have a number representing the amount of loop() cycles that the float switch has been HIGH for. If I then include a 100UL delay, it would take 100 cycles to be equivalent to ten seconds, thus when the variable reached 100 the sketch could initiate the alarm response. The next step would be to reset the variable to zero if the float switch goes LOW inside the ten second limit.
Can someone with more experience confirm whether I am on the right track?
Joe
why not try it? See how it works with a pushbutton switch attached to pin3
if it doesn't work, I'll give you one free re-write