How to send ON signal ONCE when within range of sensor

Hi all,

I am working on a project to have a open/close a solenoid at certain ranges (using HC-SR04 ultrasonic sensor).

#include <NewPing.h>2

#define Relay1 7 

#define Relay2 8

NewPing SonarRight(12, 11, 400);

void setup() {
  pinMode(Relay1, OUTPUT);
  pinMode(Relay2, OUTPUT);
}

void loop() {

  unsigned int uS1 = SonarRight.ping();
  delay(50); 

  if (uS1 / US_ROUNDTRIP_CM > 15) 
    digitalWrite(Relay1, HIGH);
    delay(100);
    digitalWrite(Relay1, LOW);
    delay(1000);
      

  if (uS1 / US_ROUNDTRIP_CM < 5)
    digitalWrite(Relay2, HIGH);
    delay(100);
    digitalWrite(Relay2, LOW);
    delay(1000);
  
}

I got the sensor to ping correct and the distances are reading accurately. I have it to where once sensor reads that the object is more than 15cm away, the solenoid opens but it keeps clicking open until the object goes back to the dead zone (5-15cm). Same thing when less than 5cm. Essentially what i am trying to accomplish is to have the solenoid fill up a tank when the water level get low. So when the water drops 10cm (x>15) the solenoid opens and then once the water is replenished (x<5), the solenoid closes.

How do i go about doing this without sending a constant OPEN/CLOSE to the solenoid

Please note that i have not actually used it for its intended purpose im supply moving an object back and forth to simulate water distance.

Thanks

if (uS1 / US_ROUNDTRIP_CM > 15) digitalWrite(Relay1, HIGH); delay(100); digitalWrite(Relay1, LOW); delay(1000);

Why do you keep turning the solenoid on and off ?

UKHeliBob: Why do you keep turning the solenoid on and off ?

It is a latch solenoid, it does not need consume constant power. Just needs a burst of current to tell the latch to open

Sorry, but another question. Why do you need two relays to control one solenoid ? Does the solenoid have two sets of inputs, one to open it and another to close it ? Does it matter, apart from power consumption, if the solenoid remains powered ?

A link to the solenoid that you are using would be helpful

Hello bkwillkper2,

you need a (boolean) marker variable (or likely, a pair of them) to remember if you already executed the relay action while in the proper sensor range, and then you’d reset the marker variable when leaving the range.

So I’ve introduced two of these for you. Try this (untested):

#include <NewPing.h>2
#define Relay1 7
#define Relay2 8

NewPing SonarRight(12, 11, 400);

// Boolean markers for (possibly reoccurring) one-time execution:
bool once_15cm=false, once_5cm=false;

void setup() {
  pinMode(Relay1, OUTPUT);
  pinMode(Relay2, OUTPUT);
}

void loop() {

  unsigned int uS1 = SonarRight.ping();
  delay(50);

  if (uS1 / US_ROUNDTRIP_CM > 15) {
    if ( !(once_15cm) ) {
      // once_15cm is false, i.e. not yet executed this part, then do it now:
      digitalWrite(Relay1, HIGH);
      delay(100);
      digitalWrite(Relay1, LOW);
      delay(1000);
      // mark one-time execution as done:
      once_15cm=true;
     }
   }
   else {
     // left the range, so reset "once" marker for next re-entry:
     once_15cm=false;
   }

   if (uS1 / US_ROUNDTRIP_CM < 5) {
     if (!(once_5cm)) {
       // same as above, only for other range:
       digitalWrite(Relay2, HIGH);
       delay(100);
       digitalWrite(Relay2, LOW);
       delay(1000);
       // mark one-time execution as done:
       once_5cm=true;
     }
   }     
   else {
     // left the range, so reset "once" marker for next re-entry:
     once_5cm=false;
   }
}

(However, I think something like that bit of logic should not be out of this world :wink: )

By the way, I wonder about the “2” behind the first “#include” directive - I think that’s a typo…

BR

stargar

bkwillpker2: It is a latch solenoid, it does not need consume constant power. Just needs a burst of current to tell the latch to open

That only explains the first time that (uS1 / US_ROUNDTRIP_CM > 15) is true. He's asking why you do it again.

UKHeliBob: Sorry, but another question. Why do you need two relays to control one solenoid ? Does the solenoid have two sets of inputs, one to open it and another to close it ? Does it matter, apart from power consumption, if the solenoid remains powered ?

A link to the solenoid that you are using would be helpful

Correct there are 2 wire for open and close. It is a battery powered solenoid so limited power consumption is necessary.

stargar: you need a (boolean) marker variable (or likely, a pair of them) to remember if you already executed the relay action while in the proper sensor range, and then you'd reset the marker variable when leaving the range.

Oh wow i never i even thought about that, that makes things seem so simple. That should do the trick, thank you.

bkwillpker2: Please note that i have not actually used it for its intended purpose im supply moving an object back and forth to simulate water distance.

Thanks

Use a flag:

uint8_t flag = 0;

// water level rises
void hilevel (void)
    if (flag == 0) {
        flag = 1; // flag we send an ON
        solenoid = 1; // whatever turns it on
    }
}

// water level falls
void lowlevel (void) {
    if (flag == 1) {
        flag = 0;
        solenoid = 0; // whatever
    }
}

See? Let's say the water falls and you repeatedly call "lowlevel". The first time through, the flag will allow the solenoid to change, next time through the flag stops it.

Make sense?

Please post links to valve and relay datasheets and a wiring diagram.

I think your code rattles a bit; e.g.

if (uS1 / US_ROUNDTRIP_CM < 5)
    digitalWrite(Relay2, HIGH);
    delay(100);
    digitalWrite(Relay2, LOW);
    delay(1000);

Your missing a pair of { and }. As it stands now, the last three lines are always executed.

For the question in the title, what your looking for is called state change detection; your interested in when the distance changed to ‘too close’ or to ‘too far’, not the fact that it is ‘too close’ or 'too far.