Simple code, help needed

Hi,

Before starting, please know that I am a complete begginer in programming (and not english native speaker)

I’m trying to build a simple small project using :

Arduino Uno
Mini bread board
Led
Servo
Ultrasonic sensor (4 pins)

I found several videos on youtube and managed to salvage some code parts, yet i’m strugling with 2 parts in my code

Here’s the goal of the project :
IF something is a detected by sensor (less than 20cm)
for at least 10 seconds
and ONCE it goes away for at least 10 seconds
THEN light up led and move servo for 3 seconds
then servo goes back to original positions

My problems :

  1. What does buffer means ? I can not understand what it is used for ? Is there another way easier to write what it does ?
  2. On my code, servo is triggered even in objet is still in front of sensor

Here is the code :

#include <Servo.h> // servo library
Servo servo1; //name servo
int buffer; //two more integer variables we will use as buffers
const int led = 2; 
const int trigPin = 3;
const int echoPin = 4;
long duration;
int distance;
void setup() {
pinMode(trigPin, OUTPUT); 
pinMode(echoPin, INPUT); 
servo1.attach(5); //set the servo to pin 5
  pinMode(led, OUTPUT); //set the led pin as an output
Serial.begin(9600); // Starts the serial communication
}
void loop() {
// 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;
// Prints the distance on the Serial Monitor
Serial.print("Distance: ");
Serial.println(distance);


  if (distance< 20) flusher(); //if the reading is less than 20 start the flush function
  else //if the reading is not less than 20
  {
    buffer--; //decrease the buffer
    if (buffer < 0) buffer = 0; //make sure the buffer cant be less than 0
    servo1.write(360); //put the servo in the far right position
    digitalWrite(led, LOW); //turn off the LED
  }
  delay(1000); //wait a 1 second before checking again
}

void flusher()
{
  buffer++; //increase the buffer counter
  if (buffer > 15) //if the buffer counter is over 15 (which would be 1500 or 1.5 seconds)
  {
    servo1.write(41); //put the servo in the far left position
    digitalWrite(led, HIGH); //turn the led on
    delay(1000); //wait one second
    servo1.write(360); //put the servo in the far right position
    delay(3000); //wait 3 second
    buffer = 0; //reset the buffer
  }
}

How could I improve this code and make it work for what I need ?

Thanks in advance for the help :slight_smile:

Buffer counts the number of time the distance is either less than 20 (if greater subtract one). As this is done once per loop and the loop loops about every second, if buffer reaches 15 it kinda means you have been about 15 seconds close to an object very recently and the flusher function moves the servo

Thank you for your answer,

So by increasing the buffer i will solve one problem.

How can I prevent the code to move to "void flusher ()" before object is gone for at least 10 seconds ? what kind of variable should I use ?

Thanks for the help

You need to start from scratch and with a proper state machine...

Thank you for your answer,

Starting scratch is really hard as i barely have no knowledge about programming,

Adapting an existing code using some help would be for me the best option (and easiest one)

well you want to do this

IF something is a detected by sensor (less than 20cm)
for at least 10 seconds
and ONCE it goes away for at least 10 seconds
THEN light up led and move servo for 3 seconds
then servo goes back to original positions

and the code you have does not do this at all... Adapting and rewriting in this case are very very close concepts...

Thank you for your answer,

I have started from scratch and worked almost all night to come to this code :

Is it better ? Does it seem plausible for you ?

#include <Servo.h> // servo library
Servo servo1; //name servo

const int led = 2; 
const int trigPin = 3;
const int echoPin = 4;
long duration;
int distance;
int PreparingToFlush=0;

void setup() {
pinMode(trigPin, OUTPUT); 
pinMode(echoPin, INPUT); 
servo1.attach(5); //set the servo to pin 5
Serial.begin(9600); // Starts the serial communication
}
void loop() {
// 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;
// Prints the distance on the Serial Monitor
Serial.print("Distance: ");
Serial.println(distance);

if (distance <20){ //if distance less than 20
  delay(2000);//wait
  if (distance <20){ // check again
  PreparingToFlush=1;
  }
}

if (PreparingToFlush==1){ //in someone is detected
  if (distance <30){ //if person left
  delay(1000);
  if (distance <30){ // checking that person actually left
  
  servo1.write(360); //Flush
    delay(1000); //wait one second
    servo1.write(3); //reset servo original position
    delay(3000); //wait 3 second

  PreparingToFlush=0; //reset the trigger
}
}
}

  delay(10);
}

No, you still don’t have the idea. You can’t use delays like that. It won’t work. You need to learn about millis() and use non-blocking timing or keep doing it the original way.

To give an example: what you’re now doing is when distance < 20 you’re waiting for 2 seconds (not 10) and checking to see if the variable distance that you set 2 seconds ago is still <20…which it must be because the delay(2000) means nothing was happening so it cannot possibly have changed. What you needed was to read the sensor again not just check a variable already set.

What the original code was doing was reading the sensor once a second and counting (in buffer) how many times in a row it had been <20. It’s a clunky way of doing it but it could have worked if you used two counters one to count seconds that distance <20 and another to count seconds that distance >20 and a few flags to tell the state it’s in. But you’ve taken all that out.

BTW what is supposed to happen if you detect an object for say 35 seconds then it goes away for 5 or 6 seconds and comes back? Anything? What if you detect an object and it just stays there? Anything?

Steve

So your advice would be to use buffer ?

Everyone is telling me that it's not going to work, but no one is actually giving me clues to code it... :confused:

Hi,
Have you been writing your code in stages?
First write code to JUST get the Sonic Sensor working?

google newping library

It will make your Sonic sensor code so much easier to use.
The library , once you install it, will have examples in the IDE examples section.

Forget the rest of your code until you get this part working.

Then go on to getting another part of your project working with ITS OWN code..

I know it sounds long and laborious procedure, but you will end up with code that you understand and when combined will have the minimum of bugs.

Also you learn to program as you go.

Tom... :slight_smile:

slipstick:
To give an example: what you’re now doing is when distance < 20 you’re waiting for 2 seconds (not 10) and checking to see if the variable distance that you set 2 seconds ago is still <20…which it must be because the delay(2000) means nothing was happening so it cannot possibly have changed. What you needed was to read the sensor again not just check a variable already set.

BTW what is supposed to happen if you detect an object for say 35 seconds then it goes away for 5 or 6 seconds and comes back? Anything? What if you detect an object and it just stays there? Anything?

Steve

Indeed, my sensor will wait for 2 seconds, and will then check again (if it’s still 20cm) Which is exactly the goal.

“Is someone here ?”
WAIT
“Is someone still here ???”
START FLUSHING SEQUENCE
“Has the person left ?”
WAIT
"Has the person really left ???’
THEN FLUSH the toilet

 if (distance <20){ //if distance less than 20
  delay(2000);//wait
  if (distance <20){ // check again
  PreparingToFlush=1;
  }
}

if (PreparingToFlush==1){ //in someone is detected
  if (distance <30){ //if person left
  delay(1000);
  if (distance <30){ // checking that person actually left
  
  servo1.write(360); //Flush

How is that wrong ?

google newping library

It will make your Sonic sensor code so much easier to use.

I did download the library

#include <NewPing.h>
#include <Servo.h> // servo library
Servo servo1; //name servo
#define TRIGGER_PIN  3
#define ECHO_PIN  4
#define MAX_DISTANCE 200
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
int PreparingToFlush=0;

void setup() {

servo1.attach(5); //set the servo to pin 5
Serial.begin(115200); // Starts the serial communication
}

void loop() {

if(sonar.ping_cm() < 20) 
  {

Does it seem a good start ?

Hi,
Looks good, but forget the servo for the moment, and get the reading from NewPing onto your serial monitor.

You need to get the distance value from the library, look at the Example code for NewPing to see how they get the distance.

Tom... :slight_smile:

nicolasweber8:
Indeed, my sensor will wait for 2 seconds, and will then check again (if it’s still 20cm) Which is exactly the goal.

“Is someone here ?”
WAIT
“Is someone still here ???”

How is that wrong ?

Except what your code says is:

  1. Check the distance and remember it
  2. Is the number I just remembered < 20? So someone is here.
  3. WAIT 2 seconds
  4. Is the number I remembered at 1. still < 20?
    **** You haven’t checked the sensor again so of course it’s still the same number and you have no idea if anyone is still there ****

Can you see yet why it doesn’t work? And that’s not really a code problem it’s a logic problem.

Steve

TomGeorge:
You need to get the distance value from the library, look at the Example code for NewPing to see how they get the distance.

 if(sonar.ping_cm()

like this ?

**** You haven't checked the sensor again so of course it's still the same number and you have no idea if anyone is still there ****

So how do you make the sensor check again ?

Hi,

Why didn’t you just use an Example from the NewPing Examples
Try this;

// ---------------------------------------------------------------------------
// Example NewPing library sketch that does a ping about 20 times per second.
// ---------------------------------------------------------------------------
#include <NewPing.h>
#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
void setup() {
  Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.
}
void loop() {
  delay(50);                      // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
  Serial.print("Ping: ");
  Serial.print(uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");
}

Tom… :slight_smile:

Thank you for the quick answer,

Oups ineed i forgot a lot of code,

How does that look ?

#include <NewPing.h>
#include <Servo.h> // servo library
Servo servo1; //name servo
#define TRIGGER_PIN  3
#define ECHO_PIN  4
#define MAX_DISTANCE 200
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
int PreparingToFlush=0;

void setup() {

servo1.attach(5); //set the servo to pin 5
Serial.begin(115200); // Starts the serial communication
}

void loop() {
  delay(50);                      // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
  Serial.print("Ping: ");
  Serial.print(uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");
  if ("cm" < 20){
    delay(1000);                      // Wait to check if person still here.
  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
  Serial.print("Ping: ");
  Serial.print(uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");
  if ("cm" < 20){
  PreparingToFlush=1;
  }
  }
  if (PreparingToFlush==1){ //in someone is detected
  delay(50);                      // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
  Serial.print("Ping: ");
  Serial.print(uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");
  if ("cm" > 20){
    delay(1000);                      // Wait to check if person still here.
  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
  Serial.print("Ping: ");
  Serial.print(uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");
  if ("cm" > 20){ 
  }  
  } 
  }
}

Is this how to make the sensor check again ?

Hi,
**STOP!!!!!! **

Did you try the code I posted, just the code no other additions.
Did it work?

You cannot go adding more and more code for other parts of your code until you get the first bit working.

Do you get a reading in the IDE monitor with JUST the code I posted?

Tom.... :slight_smile:

No idea, i havent received my arduino yet... :frowning:

Trying to work on the code prior to receiving it.

What is wrong ?

Hi,
The more you work on your code without verifying that it works as you go, means you could be compounding problems with your code.

When a car is designed, they do not design, build and sell the car in one go.
They develop and test each component as they go.

It sounds like you are impatient and need your code to run, but I'm sorry until you get your UNO, making big untested batches of code will only lead to a code that may run on the UNO, but not do what you want.

Programming in stages and testing each stage makes for stable code and you the writer learning as you go and getting experience at troubleshooting your code.

Tom.... :slight_smile:

Ok, i should receive it by the end of the week.

While waiting, is there some good reference that you would advise to learn a little bit much aout coding ? (webpage, ebook, etc...?)