Using a distance sensor to keep a relay on for extended amout of time after I walk out of range

I want to modify this code so that the relay turns on as soon as I'm withing 2ft of the HC-SR04 but not turn the relay off till 15minutes after I'm outside that 2 foot range.

// defines pins numbers
const int trigPin = 11;
const int echoPin = 10;
const int relayPin = 6;

// defines variables
long duration;
int distance;
long distancemm;

void setup() {
  // put your setup code here, to run once:
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
pinMode(relayPin, OUTPUT);// Control Pin 
//Serial.begin(9600); // Starts the serial communication
}

void loop() {
  // put your main code here, to run repeatedly:
// Clears the trigPin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
// Calculating the distance
distance= duration*0.034/2;
distancemm = distance*10+30;

//Control 
if (distancemm <= 610)
{
 for (int i=0; i <= 50; i++){
      digitalWrite(relayPin, HIGH);
      delay(10);
   }
   
}
else if (distancemm >= 611)
{
  digitalWrite(relayPin, LOW); 
}
else
{
  //Safe! Continue usual tasks...
}

// Prints the distance on the Serial Monitor
//Serial.print("Distance: ");
//Serial.println(distance);
//Serial.print("Distance: ");
//Serial.print(distancemm);
//Serial.println("mm");
delay(250);
}

That's quite useless; once a pin is written HIGH, it will stay HIGH.

To answer your question, consider the use of a small finite state machine (FSM). You will have three states, I call the START, LIGHTON and TIMER.

You start in the START state where you wait till the distance is less than 610.
If that happens you switch to the LIGHTON state where you switch the relay on and wait till the distance is greater than 611.
If that happens you set the start time for a millis() based timer and switch to the TIMER state where you wait till the timer expires (current time - start time > 15 minutes).
If the timer expires, you go back to the start state.

In that last state you can also switch back to the LIGHTON state if the distance becomes less than 610 again. This is optional depending on your needs.

You can implement the FSM using e.g. switch/case statements.

Go ahead and show us your modifications.

Or, do you want somebody to modify this code for you?

If someone is willing to modify it for me that would be wonderful but I don't want to assume it is appropriate to ask for someone to do that. This is code I found online for basic distance sensor function which does work. I just need it to do a bit more. I'm new to Arduino and struggling. I'm in a group project building an arcade machine. I want to be able to walk up to the machine and the distance sensor to trigger the relay when I get close so that the screen and some leds turn on and then don't turn of till the user has walked away for at least 15mins. I'm trying to read about FSM as suggested by @sterretje but initially it seems a little out of my depth but I may need to just keep looking for FSM walk through geared towards newbies though it seems that's more of a novice skill set from how it's being presented in the guides I've found so far.

This covers the basics

enum STATES
{
  START,
  LIGHTON,
  TIMER,
};

const int8_t relayPin = 6;
const uint32_t duration = 900000UL;

void setup()
{
  Serial.begin(115200);
  pinMode(relayPin, OUTPUT);
}

void loop()
{
  fsm();
}

/*
  Read the distance
  Returns:
    distance in mm
*/
long readDistance()
{
  long distancemm;
  // to do
  // distancemm = ... 

  // return the distance
  return distancemm;
}

/*
  finite statemachine for light control
*/
void fsm()
{
  // state that we're in
  static STATES state = START;

  // start time for timer
  static uint32_t startTime;

  // read the distance
  long distancemm = readDistance();

  // state machine
  switch (state)
  {
    case START:
      if (distancemm <= 610)
      {
        // switch the light on
        digitalWrite(relayPin, HIGH);
        // go to next state
        state = LIGHTON;
      }
      break;
    case LIGHTON:
      if (distancemm >= 611)
      {
        // 'start' the timer
        startTime = millis();
        // go to next state
        state = TIMER;
      }
      break;
    case TIMER:
      // if timer expired
      if (millis() - startTime >= duration)
      {
        // switch light off
        digitalWrite(relayPin, LOW);
        // go to START
        state = START;
      }
      // if triggered again, go back to LIGHTON
      if (distancemm <= 610)
      {
        state = LIGHTON;
      }
      break;
  }
}

The enum is like an integer but only knows certain values. As shown, START equals 0 and the others are incremented by 1.

There are two functions.

fsm() is the implementation of the FSM. It reads the distance using the function readDistance() and next takes decisions in the switch/state.

You will have to implement the readDistance() by copying parts of your existing program (the triggering, the pulsin() and the calculation).

I hope that this gets you on track; ask what you don't understand.

Not tested; but does compile

Couple of practical points:

Will you remain within two feet of the HC-SR04 after reaching the target?

No one else nearby or within the trigger range?

Or any other moving objects that could cause ambiguity?

Unless this is a set project, did you consider the option of simply toggling a button on arriving at the target?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.