Water Level Detection Using Interrupt

Hello all, I am working on project that performs several functions one of which is to fill a small container with water. I currently use sensors to determine if it water is at the desired level.

I would like to build a “secondary stop” that uses the interrupt pin. Such that regards where you are in the program if this secondary stop is tripped I can stop the program.

My first attempt was to simply place a wire in the container and watch for CHANGE. I expected that once the water reach the wire the interrupt will be triggered. The approach did not the yield the expected results. Any suggestions would be great! I would like to avoid using another sensor for this.

The approach did not the yield the expected results.

But, you aren't going to show us the code, or tell us what the actual results were, or what the expected results were? Well, then, good luck.

Any suggestions would be great!

Hmmm. I somehow doubt that.

PaulS:

The approach did not the yield the expected results.

But, you aren't going to show us the code, or tell us what the actual results were, or what the expected results were? Well, then, good luck.

Any suggestions would be great!

Hmmm. I somehow doubt that.

The code?? Here it is, but it is nothing earth shattering

pinMode(19, OUTPUT);
digitalWrite(19,HIGH);
attachInterrupt(4, DrainFUNCTION, CHANGE);

You also asked for the expected results, I thought I stated what I need implemented, that is the EXPECTED results, to detect when the water is at the wire and then trigger the interrupt. If you mean to ask what the unexpected results were that I experienced then it was random at best. It seemed to CHANGE at a whim.

Thanks for your comments, hope this clarifies things. Any additional help would be GREAT!!

aerouta: I would like to build a “secondary stop” that uses the interrupt pin. Such that regards where you are in the program if this secondary stop is tripped I can stop the program.

This does not seem a particularly sensible approach to me. The problem does not call for interrupts, all you need to do is design your code to monitor the input at suitable intervals.

However, if your interrupt based solution doesn't call your interrupt handler when you expect then I think that the problem is likely to be caused by the external circuit, which you haven't told us anything about. You could easily test that by replacing the external circuit with a pull-up resistor and a switch.

A wire dangling in water isn't going to produce enough signal to trigger a digital input. You'll need some amplification. A float switch would be more sensible.

gm1mfn: A wire dangling in water isn't going to produce enough signal to trigger a digital input.

It would do (without amplification) if it was wired correctly - but we don't know how it is wired.

I'm have not used interrupts before but from the little research it seems like this problem is best solved using interrupts. It will be very impractical to "monitor the input at suitable intervals", and it seems to me that this is the whole point of using interrupts; to prevent you from writing code that continuously monitors an input?

I have used float switches before but I cannot at this time due to space limitations. Additionally this is a fail safe measure i.e. if the normally stopping mechanisms fails (float switch, sensors, etc.) this interrupt will trigger a function to prevent an overflow. I would like to have the water it self be the trigger and not use additional hardware interfaces. That is easy and I have already implemented those. I am just fishing to see if I can add additional safety to the system.

The external circuit is identical to that found in the digital read page, http://arduino.cc/en/Tutorial/DigitalReadSerial

The IDEA is to have two leads in the container, one will be pulled down to ground as shown in the circuit and the other will be a charged lead either 12v or 5v. Once the water "shorts" the two, the interrupt is triggered. Again this is just an idea, and I would like to know if this is a possibility or if it will fry the board, etc.

And here is the current test code which is modified from the arduino site.

int pin = 13;
volatile int state = HIGH;

void setup()
{
  Serial.begin(9600); 
  pinMode(pin, OUTPUT);
  attachInterrupt(1, blink, RISING);
}

void loop()
{
  digitalWrite(pin, state);
  delay(1000);
    Serial.println("checking");
}

void blink()
{
  Serial.println("Interrupt Triggered");
  state = !state;
}

The above approach triggers the interrupt but sometimes also crashes the board.

aerouta:
I’m have not used interrupts before but from the little research it seems like this problem is best solved using interrupts. It will be very impractical to “monitor the input at suitable intervals”,

I must disagree – it is very practical to monitor input at intervals, since intervals of less than a millisecond (1/1,000th of a second) are typical of Arduino applications. Even a few dozen milliseconds seems like an acceptable delay before acting on a water overflow issue.

and it seems to me that this is the whole point of using interrupts; to prevent you from writing code that continuously monitors an input?

I’m afraid I must disagree again – your code should continuously monitor for inputs. The purpose of an interrupt is to respond to high-priority events within microseconds (1/1,000,000th of a second). An interrupt might be used to fire the ignition spark on a gasoline engine, for example. Interrupts can also be useful if you put your Arduino to sleep to save on battery power.

Additionally this is a fail safe measure i.e. if the normally stopping mechanisms fails (float switch, sensors, etc.) this interrupt will trigger a function to prevent an overflow.

I am just fishing to see if I can add additional safety to the system.

I would recommend using the watchdog as a safety mechanism. If your code is so buggy that it hangs, the watchdog will be far more beneficial than an interrupt since the watchdog will “fix” your whole program and not just one little part of it.

aerouta: I'm have not used interrupts before but from the little research it seems like this problem is best solved using interrupts. It will be very impractical to "monitor the input at suitable intervals", and it seems to me that this is the whole point of using interrupts; to prevent you from writing code that continuously monitors an input?

Common misunderstanding.

Newbies to programming think "interrupts" are for interrupting the flow of the program - like a sort of "goto" which is of course, discouraged.

That isn't what interrupts are for at all. Interrupts are to do something that you need to do fast and without disturbing the primary execution of the program. And "fast" in this context means computer fast - microseconds or less.

In your case, writing code that continuously monitors an input by "polling" - checking it every time you go through you main loop - is precisely what you want your code to do. That way you can choose when in your code you need to take the appropriate action. The "suitable interval" is the point in your loop code when you need to make the decision on that particular event.

Also note that any switching function external to the Arduino should be a switch to ground, not to any 5V or 12V. This is fundamental design sense; the container is likely to be grounded somewhere anyway, feeding 5 or 12V into it will cause electrolysis (hydrogen production!), you risk short circuiting your 5 or 12V supply and the Arduino is designed with internal pull-ups to facilitate switches going to ground.

A point on which unfortunately many of the tutorials regarding switches, encoders and contact bounce (something you need to study up on as well) are sadly misleading.

What kind of water are we talking about? Unless it’s distilled or DI water, it shouldn’t be a problem. I use the circuit below to monitor my sump for a high water level and it’s very sensitive. I just poll the sensor, no interrupts. The electrodes are stainless steel; I don’t worry about electrolysis because they’re supposed to be dry most of the time, and the current should be miniscule. I only turn the sense voltage on for a few milliseconds.

water sensor.png

[quote author=Jack Christensen link=topic=192211.msg1421250#msg1421250 date=1381266854] I don't worry about electrolysis because they're supposed to be dry most of the time, and the current should be miniscule. I only turn the sense voltage on for a few milliseconds.[/quote]For continually immersed probes, I suppose you could swap the polarity of the probes after each sample. That should help keep electrolysis at bay.

One thing to consider, though. If some 120VAC ever leaks into your liquid (which happens far too frequently in aquariums with powerheads, heaters, and other devices that tend to suffer water intrusion due to manufacturing defects or age), and if you don't have a ground probe installed to give it a low-impedance path back out of the water, your Arduino could fry.

This makes sense, thanks for the suggestion on the switching and the circuit.

Regarding the interrupt... I am still having a hard time understanding why not using an interrupt would be beneficial. I am filling a 6ml container, yeah tiny. I have a trip two trip sensors setup to detect levels and those work well while the sensors are ON and being monitored. I am executing SEVERAL other functions which include several FOR loops, WHILE loops, etc.

I am not sure if we are understand the concept of a fail safe design, this is assuming something goes wrong, for example a pump fails ON, or a sensor is not tripped, and any one that has used a float switch for an extended period of time will know it is not a matter of IF it fails but WHEN. I would like the interrupt to be triggered and triggered instantly without waiting to exit a loop. The alternative would be to place a monitor in every loop in the code.

aerouta: I'm have not used interrupts before but from the little research it seems like this problem is best solved using interrupts.

Nothing about your requirements suggests that interrupts would be necessary or sensible to solve it.

aerouta: It will be very impractical to "monitor the input at suitable intervals", and it seems to me that this is the whole point of using interrupts; to prevent you from writing code that continuously monitors an input?

If it's impractical then your sketch design is wrong. The main reason for using interrupts is that they enable you to respond to an external event with minimal latency - useful if you're dealing with extremely high frequency or short duration events. But they introduce considerable extra complexity into your sketch and should only be used when absolutely necessary and only reluctantly then. They absolutely don't need to be used to monitor something as glacially slow as a water level input.

aerouta: I am executing SEVERAL other functions which include several FOR loops, WHILE loops, etc.

These loops should be non-blocking. I.e., your whole program, including all loops, should complete and start over within one millisecond. If things are taking longer than that, then the "right" thing to do is change your program to a non-blocking structure. See the BlinkWithoutDelay example for non-blocking code.

Now, if you're already spent hours and hours writing thousands of lines of code such that a total re-write with a non-blocking structure is distasteful, then yeah, I can see why using an interrupt starts to look pretty attractive. But if haven't already invested weeks of work in your program, I recommend you go ahead and change it to be non-blocking. You'll thank us later. ;)

it is not a matter of IF it fails but WHEN. I would like the interrupt to be triggered and triggered instantly without waiting to exit a loop.

Define "instantly". Is 1/1,000th of a second fast enough for you? If so, there is no need to use interrupts if your program is non-blocking in nature.

The alternative would be to place a monitor in every loop in the code.

No, you just need to restructure your program to be non-blocking. :)

That is a good point, I understand the concept of non blocking code and unfortunately there are several portions that are. A lot of comments keep referring to the speed of the event, from reading the info on the ardunio site and a few others, it seems that both the speed and priority of the event are considered when deciding to use an interrupt. If you have several say, 100 sequential events and one additional event that requires priority, does it make sense to code all 100 "non blocking" just for the one high priority event to be timely captured or would it make more sense to just use an interrupt.

That’s a good question. The answer is, of course, “it depends”. We’re descending now into the realm of subjective philosophy… without seeing the specific code in question, it’s hard to render an opinion, so I just have to say “avoid interrupts unless there’s a good reason to use one”.

Whether or not a particular reason is a good one, is open to debate. :slight_smile:

aerouta: That is a good point, I understand the concept of non blocking code and unfortunately there are several portions that are. A lot of comments keep referring to the speed of the event, from reading the info on the Arduino site and a few others, it seems that both the speed and priority of the event are considered when deciding to use an interrupt. If you have several say, 100 sequential events and one additional event that requires priority, does it make sense to code all 100 "non blocking" just for the one high priority event to be timely captured or would it make more sense to just use an interrupt.

Several matters are involved.

Firstly as others have pointed out, "blocking" code is virtually certainly going to bite you sooner or later, so your priority needs to be to resolve that because the blocking code is going to affect events that you perhaps didn't think were needing such priority, but actually do. Alternatively, it is highly likely that having troublesome blocking code is going to make later additions to the code much more difficult - which is really what you are experiencing now.

If something is of significant priority, you make it a subroutine, and call it regularly interspersed within your 100 other functions. Particularly for what you describe, you are hardly likely to be concerned about execution time.

Secondly, there is a limit to what you can do in an interrupt. You cannot do anything that in itself, involves interrupts or takes some time, such as communication (via the serial interface, or I2C, or SPI) - because these involve or may affect the timer interrupts. I am betting that what you imagine doing in this interrupt does - or you would like it to - involve something like this. What you generally can do is to set something immediately, likely an output and/ or a "flag" variable which will later be processed by the main loop.

Finally, you need to be careful about what can happen when an interrupt occurs within the execution of another function - where such function involves the same hardware or software elements which the interrupt will use.

thanks for the input and information on interrupts. I believe I will attempt to implement Jack Christensen circuit without using interrupts. Thanks for the comments!