Servo activated by Ultrasonic Sensor

I have a servo and an Ultrasonic Sensor (HC-SR04) connected to my Arduino Uno. The goal is to create an automatic toilet flusher. The times and distances I am using in the code will be adjusted later, but they are like that for testing purposes currently.

Once someone has been in range for so long (in the code it is 3 inches for 5 seconds), it is to wait for them to leave range, then trigger a servo to move all the way over, then all the way back (this being the flush). Then reset for the next time someone uses it.

Now, currently what it does is, every 10 seconds or so, the servo will 'flush'. However, when the sensor reads an object in range, the servo will not 'flush'. I'm not sure what's going wrong here. I am very new to all of this so if anyone could help me that would be great!

#include <Servo.h>
Servo servo1;
const int trigPin = 2, echoPin = 3;
int startFlush = 0;

void setup() {
  servo1.attach(9); //set the servo to pin 9
  Serial.begin(9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop()
{
  long duration, inches; // establish variables for duration of the ping, and the distance result in inches 

  // The sensor is triggered by a HIGH pulse of 2 or more microseconds.
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  inches = pulseIn(echoPin, HIGH)/ 74 / 2; //read from the pin, divide by 74 to account for the speed of sound, then by 2 to account for the return trip)
  
  if (inches<3) { //if less than 3 inches, wait 5 seconds then check again
    delay(5000);
    if (inches<3) {
      startFlush = 1;
    } //if the reading is less than 3 start the flush function
  }

  if (startFlush==1) {
    delay(1000);
    if (inches>3) {
      servo1.write(0);//put servo in far left position
      delay(1000);
      servo1.write(180); //put servo in far right position
      delay(3000);
      startFlush = 0;//reset
    }   
  }
}
if (inches<3) { //if less than 3 inches, wait 5 seconds then check again
   delay(5000);
   if (inches<3) {

If the distance was less than 3, waiting 5 seconds and not reading again, how will the distance possibly have changed?

if (inches<3) {
     startFlush = 1;
   } //if the reading is less than 5 start the flush function
 }

When the useless comments do not agree with the code, the comments are not only useless they are wrong.

What do your Serial.print()s tell you is happening with respect to the distance measurement?

I don't quite understand the first comment.. Are you saying I need an else statement to say do nothing if the distance is greater than 3?

And i realize the comments were off. I have fixed those (I changed the distance not even worrying about the comment earlier).

Also, the serial monitor shows nothing

if (inches<3) { //if less than 3 inches, wait 5 seconds then check again
delay(5000);
if (inches<3) {
startFlush = 1;
} //if the reading is less than 3 start the flush function
}

What's doing your program is looping because the second "if" still "<3" so it goes to startFlush=1.

Try to make it just like an AND GATE:
if(inches<=3 && startFlush==0){
delay(1000);
startFlush=1;
}

Here.....

  1. if (startFlush==1) {
  2. delay(1000);
  3. if (inches>3) {
  4. servo1.write(0);//put servo in far left position
  5. delay(1000);
  6. servo1.write(180); //put servo in far right position
  7. delay(3000);
  8. startFlush = 0;//reset
  9. }
  10. }

ok, try to make it an AND GATE again.

if(startFlush==1 && inches>=3)
{
delay(500);
servo1.write(0);//put servo in far left position
delay(1000);
servo1.write(180); //put servo in far right position
delay(3000);
startFlush = 0;//reset
}

Also, the serial monitor shows nothing

I'd concentrate on fixing that first - no point in working in the dark

AWOL:
I'd concentrate on fixing that first - no point in working in the dark

Isn't it not supposed to show anything unless i tell it to print something?

mike1360:
Isn't it not supposed to show anything unless i tell it to print something?

Don't you think it would be a good idea to get your sketch to tell you what it is doing?

AWOL:
Don't you think it would be a good idea to get your sketch to tell you what it is doing?

I agree with that. I will work on adding some print statements in

israelfco:
if (inches<3) { //if less than 3 inches, wait 5 seconds then check again
delay(5000);
if (inches<3) {
startFlush = 1;
} //if the reading is less than 3 start the flush function
}

What's doing your program is looping because the second "if" still "<3" so it goes to startFlush=1.

Try to make it just like an AND GATE:
if(inches<=3 && startFlush==0){
delay(1000);
startFlush=1;
}

Here.....

  1. if (startFlush==1) {
  2. delay(1000);
  3. if (inches>3) {
  4. servo1.write(0);//put servo in far left position
  5. delay(1000);
  6. servo1.write(180); //put servo in far right position
  7. delay(3000);
  8. startFlush = 0;//reset
  9. }
  10. }

ok, try to make it an AND GATE again.

if(startFlush==1 && inches>=3)
{
delay(500);
servo1.write(0);//put servo in far left position
delay(1000);
servo1.write(180); //put servo in far right position
delay(3000);
startFlush = 0;//reset
}

I tried fixing it the way you describe and still ran into the same error. On the first couple if statements, I would like to keep the second check that way it doesnt cause a flush if someones just walking by

I tried fixing it the way you describe and still ran into the same error.

It would be useful to see your attempt

AWOL:
It would be useful to see your attempt

Ok here is the new code with the print lines in them

#include <Servo.h>
Servo servo1; 
const int trigPin = 2, echoPin = 3;
int startFlush = 0;

void setup() {
  servo1.attach(9);
  Serial.begin(9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  Serial.println("Startup Initiated");
}

void loop()
{
  long duration, inches; // establish variables for duration of the ping, and the distance result in inches 

  // The sensor is triggered by a HIGH pulse of 2 or more microseconds.
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  inches = pulseIn(echoPin, HIGH)/ 74 / 2; //read from the pin, divide by 74 to account for the speed of sound, then by 2 to account for the return trip)
  
  if (inches<3) { //if less than 3 inches, wait 5 seconds then check again
    Serial.println("Object in range");
    delay(5000);
    if (inches<3) {
      Serial.println("Flush ready");
      startFlush = 1;
    } //if the reading is less than 3 start the flush function
  }

  if (startFlush==1) {
    delay(1000);
    if (inches>3) {
      Serial.println("Flush activated");
      servo1.write(0);//put servo in far left position
      delay(1000);
      servo1.write(180); //put servo in far right position
      delay(3000);
      startFlush = 0;//reset
      Serial.println("Reset");
    }   
  }
}

What i found from testing it is, at first i thought it was just running through the whole code over and over. But i found that the sensor is being a lot more sensitive than planned. The distance in which it registers an object in range is more like 6 inches instead of 3.

The distance in which it recognizes an object in range is much greater than the distance it requires to 'flush'. I can 6 inches away and it will recognize an object. But, when doing the next check to see if the object has left, it activates a flush while still being at the same distance.

Also, if i pass my hand in front real fast, it reads the object yet continues to "Flush Ready" and activates it

if (inches<3) { //if less than 3 inches, wait 5 seconds then check again
    Serial.println("Object in range");
    delay(5000);
    if (inches<3) {

What could have caused the value of "inches" to have changed in the 80 million-plus clock cycles the processor has been twiddling its silicon thumbs?