I want to stop a loop until a measurement changes

Hi,
I'm pretty new to this so please be kind!
I'm helping a mate out who has asked me to help him with a video wall. He wants the scene to change as someone walks from 4m away from the wall upto the wall, with a signal going via four relay pins to the video controller every 0.5m.
I am using the standard HC-SR04 sensor to measure the distance. I am using four outputs from the Arduino to a 4 channel relay board. The four outputs will give eight different dry closed circuit contacts to the video wall controller.
So far everything works quite well. I want to improve the code because the relays are clicking away all the time (dependent on what delay I've put in).
The video wall controller only requires a 20ms pulse to change the scene and the scene wont change until one of the inputs change. So if the person isn't moving the scene wont change so there is no need to keep sending a signal from the Arduino to the wall controller.
In other words, I want to stop the relays doing their thing until the person moves into a different zone.
As I said I've jumped into this without much experience of coding and I have tried all sorts of things with out success.
Any advice would be much appreciated.
Cheers

// This uses Serial Monitor to display Range Finder distance readings 
// and outputs on four digital lines in HEX code.
 
// Include NewPing Library
#include "NewPing.h"
 
// Hook up HC-SR04 with Trig to Arduino Pin 2, Echo to Arduino pin 3
//Hook up relay board IN1, IN2, IN3, IN4 to Arduino pins 4,5,6,7
// Maximum Distance is 400 cm
 
#define trigger_pin  2
#define echo_pin    3
#define max_distance 400

 
NewPing sonar(trigger_pin, echo_pin, max_distance);
 
float duration; 
float distance;
int iterations = 10;
int d = 1000;   // Means I can change all the delays by changing this value
 
void setup() {
  Serial.begin (9600);   //Begin serial data
  pinMode(4, OUTPUT);    //
  pinMode(5, OUTPUT);    //  Define pins as outputs
  pinMode(6, OUTPUT);    //
  pinMode(7, OUTPUT);   //
  
   digitalWrite(7, HIGH);  // Write pins HIGH
   digitalWrite(6, HIGH);
   digitalWrite(5, HIGH);
   digitalWrite(4, HIGH);
   
}
 
void loop() {
   delay(50);
 
  duration = sonar.ping_median(iterations);   //Calculates duration with 10 iterations
  
  // Determine distance from duration
  // Use 343 metres per second as speed of sound
  
  distance = (duration / 2) * 0.0343;
  
  // Send results to Serial Monitor
  Serial.print("Duration = ");
  Serial.println(duration);
  Serial.print("  Distance = ");
 
  if ((distance < 400) && (distance >= 350)) {
    Serial.println("Between 4 and 3.5");
  
   digitalWrite(7, HIGH);   //
   digitalWrite(6, HIGH);
   digitalWrite(5, HIGH);
   digitalWrite(4, LOW);   // Activates relay on IN1
   delay(d);
   digitalWrite(7, HIGH);  //Reset all relays to open
   digitalWrite(6, HIGH);
   digitalWrite(5, HIGH);
   digitalWrite(4, HIGH); 
  }
  
  else if ((distance < 350) && (distance >= 300)) {
    Serial.println("Between 3.5 and 3");
  
   digitalWrite(7, HIGH);
   digitalWrite(6, HIGH);
   digitalWrite(5, LOW);   //Activates relay IN2
   digitalWrite(4, HIGH);
   delay(d);
   digitalWrite(7, HIGH);
   digitalWrite(6, HIGH);
   digitalWrite(5, HIGH);
   digitalWrite(4, HIGH);
  }
  
  else if ((distance < 300) && (distance >= 250)) {
    Serial.println("Between 3 and 2.5");
   digitalWrite(7, HIGH);
   digitalWrite(6, HIGH);
   digitalWrite(5, LOW);
   digitalWrite(4, LOW);
   delay(d);
   digitalWrite(7, HIGH);
   digitalWrite(6, HIGH);
   digitalWrite(5, HIGH);
   digitalWrite(4, HIGH);
  }
  
  else if ((distance < 250) && (distance >= 200)) {
    Serial.println("Between 2.5 and 2");
   digitalWrite(7, HIGH);
   digitalWrite(6, LOW);
   digitalWrite(5, HIGH);
   digitalWrite(4, HIGH);
   delay(d);
   digitalWrite(7, HIGH);
   digitalWrite(6, HIGH);
   digitalWrite(5, HIGH);
   digitalWrite(4, HIGH);
  }
  
  else if ((distance < 200) && (distance >= 150)) {
    Serial.println("Between 2 and 1.5");
    digitalWrite(7, HIGH);
    digitalWrite(6, LOW);
   digitalWrite(5, HIGH);
   digitalWrite(4, LOW);
   delay(d);
   digitalWrite(7, HIGH);
   digitalWrite(6, HIGH);
   digitalWrite(5, HIGH);
   digitalWrite(4, HIGH);
  }
  
  else if ((distance < 150) && (distance >= 100)) {
    Serial.println("Between 1.5 and 1");
    digitalWrite(7, HIGH);
    digitalWrite(6, LOW);
   digitalWrite(5, LOW);
   digitalWrite(4, HIGH);
   delay(d);
   digitalWrite(7, HIGH);
   digitalWrite(6, HIGH);
   digitalWrite(5, HIGH);
   digitalWrite(4, HIGH);
  }
  else if ((distance < 100) && (distance >= 50)) {
    Serial.println("Between 1 and 0.5");
   digitalWrite(7, HIGH);
   digitalWrite(6, LOW);
   digitalWrite(5, LOW);
   digitalWrite(4, LOW);
   delay(d);
   digitalWrite(7, HIGH);
   digitalWrite(6, HIGH);
   digitalWrite(5, HIGH);
   digitalWrite(4, HIGH);
  }
  else if ((distance <50) && (distance >=1))  {
    Serial.println("Between 0.5 and 0.01"); 
   digitalWrite(7, LOW);
   digitalWrite(6, HIGH);
   digitalWrite(5, HIGH);
   digitalWrite(4, HIGH);
   delay(d);
  digitalWrite(7, HIGH);
   digitalWrite(6, HIGH);
   digitalWrite(5, HIGH);
   digitalWrite(4, HIGH);
  }
  else 
      {
    Serial.println("Out of range");
  }
}

After you send a pulse, record the distance. When you read the distance the next time, compare the new distance to the previously recorded distance. Only send a new pulse if the distance has changed enough.

Hi,
Your code is neatly written, but the idea is not good.
The output of your code depends on both a distance and time. Using "delay" instructions is always a bad idea, but in your project leads you to a dead end.
You have to get the delays by using time variables: the arduino has an internal timer (clock) that may be consulted by means of the instruction millis(); although it looks you are complicating things at the beginning, loading time when you need (i.e.: start = millis()) and then testing the delay by comparing (i.e.: timeTranscurred = millis() - start; if timeTranscurred ...) lets you keep "looping" instead of stopping (delay) any arduino job.
Regards.

Thanks groundFungus for your quick reply....That is one of the ideas I've been working on but so far without any luck.

And thanks vffgaston for your reply. You've made me realise what I need to do is learn a lot more before diving in and saying I could help my mate!!
I'll have to ignore my wife and spend a few more hours on this.

Stevetypoohn:
I'll have to ignore my wife and spend a few more hours on this.

Think twice before doing so ... :sweat_smile:

(Any case, I will deny everything ...)

Best regards.

SORTED
I didn't have to keep the wife waiting too long vffgaston!
I'm not sure that I have followed either of your wise advice but thanks for your help, you have certainly given me plenty to look into.
What I've done is put a while loop in for each distance zone and tested the distance again, if the distance remains the same it just loops round until the distance changes and exits the while loop.

  if ((distance < 400) && (distance >= 350)) {
    Serial.println("Between 4 and 3.5");
  
   digitalWrite(7, HIGH);   //
   digitalWrite(6, HIGH);
   digitalWrite(5, HIGH);
   digitalWrite(4, LOW);   // Activates relay on IN1
   delay(d);
   digitalWrite(7, HIGH);  //Reset all relays to open
   digitalWrite(6, HIGH);
   digitalWrite(5, HIGH);
   digitalWrite(4, HIGH);
   while((distance < 400) && (distance >= 350))  // While the distance is between these values
   {                                             
    duration = sonar.ping_median(iterations);  //Check for a new value, if value changes
    distance = (duration / 2) * 0.0343;         //the loop is exited and a new pulse sent
    }
    
  }

if ((distance < 400) && (distance >= 350)) {
Serial.println("Between 4 and 3.5");

Most people think in terms of "between 3.5 and 4.0", not in terms of "between 4.0 and 3.5".

I thought people working with video/AV in general use SMPTE instead of relays.

EDIT : but then again, how should I know..

Delta_G:
What is the difference? Or could you just not find anything else to pick on in this code?

Are you that poor in math skills that you can't handle counting down? Cant handle counting down to the point that you feel the need to reopen a 4 day old thread?

Don't worry Paul. The rest of us can handle basic math. It really isn't a problem for those of us with moderate intelligence.

I think he was picking at the print statement not the test

Serial.println("Between 4 and 3.5");

for me this sounds weird indeed - not the way mere mortal would say that... So writing it the other way is improving the user interface :slight_smile:

So writing it the other way is improving the user interface

That's one part of it.

If you ask a bank teller who has just been robbed how tall the robber was, and he/she says "well, he was between 6' 5" and 4' 2"", you're going to have to question the accuracy of any other observations that person makes.

Logically, we think in terms of between the lower limit and the upper limit. When the code is not written that way, I question the ability of the programmer to think logically.

And, no Delta_Grump, I don't need anymore crap from you. Move on WITHOUT posting.

PaulS:
If you ask a bank teller who has just been robbed how tall the robber was, and he/she says "well, he was between 6' 5" and 4' 2"", you're going to have to question the accuracy of any other observations that person makes.

I would question the accuracy of any observation of someone talking in foot and inch and not using the metric system, but that's another story :slight_smile:

Delta_G:
Ok. So what if a rocket blew up on the launchpad and you asked someone, "at what point did it blow" and they said it was during the countdown between 5 and 4. That makes perfect sense.

In that case, the count "down" is counting up in time. You could think of the numbers as negative (-5, -4), so the lower limit is still first.

Delta_G:
All I'm saying is that you don't know what that guy's UI is trying to represent

We actually do....

it's a debug information, printing the distance in m (from a standard HC-SR04 sensor to the object ahead) to reach the goal described by OP of

I'm helping a mate out who has asked me to help him with a video wall. He wants the scene to change as someone walks from 4m away from the wall upto the wall, with a signal going via four relay pins to the video controller every 0.5m.I am using the to measure the distance.

So you could say there is a notion of count down there, but really the code is not tracking moving towards the screen and just displaying a notion of absolute distance interval from the video wall.

If that were me I would say "There is an object located between 3.5 and 4m of the wall" and not "There is an object located between 4m and 3.5m of the wall" as personal preference.

read again Paul's comment in #7, he was not stating anything else nor saying it's totally dumb or yelling at OP...

seems you are the one picky there...

Good thing though - everyone free to say what they think, and everyone free to ignore :slight_smile: