Help with a button press duration sketch...

Hello World!

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.

I appreciate any and all help in advance!

Joe

Could anyone give me some pointers?

char *ptr = "Programming questions involve code YOU post. Project Guidance is for when you haven't a clue";

something like this untested bit:

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);
  }
}

Thanks for the replies both.

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

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.

jlavery31:
Thanks for the replies both.

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 :blush:

//  pirtrippoint5sec
//
//  wait for 5 secs of constant detection
//  ** works  07APR2014 **

unsigned long refTime;
unsigned long trippoint;

const long threshold = 5000;

byte DET;
const byte pirPin = 8;
const byte ledPin = 13;

void setup ()
{
  //pirPin is INPUT by default, BUT use ExtPullup
  pinMode (ledPin,OUTPUT);
  digitalWrite (ledPin,LOW);
}

void loop ()
{
  DET = digitalRead(pirPin);
  if (DET == 1)  // inactive
  {
    refTime = millis();
    trippoint = refTime;
  }
  else   // Active Low
  {
    pir_active();
  }
}

void pir_active ()
{
  trippoint = millis();
  if ((trippoint-refTime) > threshold)
  {
    digitalWrite(ledPin,HIGH);
  }
}