Im struggling with a delay bug in my code/project

good day, So I am trying to make a motor operate when my ultrasonic sensor senses a certain distance. I manage to make everything work but when I wanted to implement a delay for reason that I want the motor to only operate for few seconds things started to go wrong. for example, the motor goes on and off whenever the distance condition is met.

here is my code.

#define trigPin 13

#define echoPin 12

#define motor 11

void setup()

{ Serial.begin (9600);

pinMode(trigPin, OUTPUT);

pinMode(echoPin, INPUT);

pinMode(motor, OUTPUT);

}

void loop()

{ long duration, distance;

digitalWrite(trigPin, LOW);

delayMicroseconds(2);

digitalWrite(trigPin, HIGH);

delayMicroseconds(10);

digitalWrite(trigPin, LOW);

duration = pulseIn(echoPin, HIGH);

distance = (duration/2) / 29.1;

if (distance <= 70)

{ 
  digitalWrite(motor,HIGH);
   delay(2000);
   digitalWrite(motor, LOW);
  
}

else {

digitalWrite(motor,LOW);

}

Serial.print(distance);

Serial.println(" cm");

delay(500);

}

Please edit your post and add code tags as described in How to get the best out of this forum

This makes the code easier to read and copy for examination

I suspect that your problem is here

  if (distance <= 70)
  {
    digitalWrite(motor, HIGH);
    delay(2000);
    digitalWrite(motor, LOW);
  }

You are detecting when the distance is less than the trigger distance rather than when it becomes less than the trigger distance

Think what happens when the 2 second delay ends and the distance is still less than the trigger distance. I assume that you don't want the motor to run again

Is that what is happening ?

ok wil do

yes I want it to stop after running for 2 seconds.

Take a look at the StateChangeDetection example in the IDE as a starting point to detecting when some the values becomes less than the trigger value

how can one change it from when it is less than trigg to when it becomes less than?

You've just been pointed to the StateChangeDetection example - if you understand how that achieves it triggering the exact same principle applies to your situation.

In short you maintain a variable to tell you want the last state was and compare to see if there's a change.

Still doesn't work but thanks anyways.

Hi, @steph_arduin
Welcome to the forum.

If the distance is still below the threshold when the motor has done its 2 second run, do you want the motor to keep running, then stop 2s after the distance has increased?

Tom... :smiley: :+1: :coffee: :australia:
PS, It sounds like you want the vehicle/robot to stop 2s after it has cleared the obstruction.

What is it that doesn't work ?

Hi, @TomGeorge

Yes, what I want to happen is the following.

  1. The ultrasonic sensor will detect an obstruction in front of it within the threshold set by me.
  2. then the motor will run for 2seconds.
  3. After the 2seconds have passed I want the motor to stop completely and wait for it to sense another obstruction.

thanks.

Is that so you can measure again?

Without the delays you can ping many times a second even as you move.
The code to ping should run by itself and update a status variable continuously.
The motor task could be just motor code or contain the on/off decision process.
Neither task can be allowed to block the other from running even just to stop.
At some point maybe add IR-remote or wifi?

Hi

If it hasn't cleared the obstacle do you want the motor to keep running?

Would it be better if it stopped 2s AFTER it cleared the obstacle.

In other words you start the motor when the obstacle is too close and stop the motor 2s after the obstacle is outside the threshold?

Tom... :smiley: :+1: :coffee: :australia:

@GoForSmoke @TomGeorge

Thanks your opinions had me thinking and I now know what I will be doing.
I am going to just put in a short delay after turning off the motor.

because what's happing is there are objects that are moving towards the ultrasonic sensor, and if it detects the object it will move away from it and wait for the next object to come towards it. and in my code, there is an else statement that will cut out the problem if the object doesn't even reach the threshold, so that's all cleared up.

thanks to all.

Why play checkers when you could RTS?

Why a delay of any kind ? If there is an object in range then don't you want to keep moving ?

at a certain distance between sensor and object i want to do a action and in this instants make a motor run

An Arduino not delayed is incredibly fast.
How fast will the vehicle move in mm/sec?
The closer that you get to the obstacle, the faster the echo return.

The trick to time with millis() or micros() is that time-checks have to run frequently.
The code to do a task runs a little step of it at a time, it runs over and over until it's done.
The usual way to break a task up is with a switch-case statement and a variable to tell which case to run.

Here is an example of getting delays out of a simple "random blink" sketch.
It can be modified to suit you now and take a lot of adding on later.
Making code flexible was one of my goals in the 80's since no customer knew what they wanted before they had you write it just to move the goalpost past a rewrite.

// New name addUndelay
// add-a-sketch_un-delay 2018 by GoForSmoke @ Arduino.cc Forum
// Free for use, Apr 30/18 by GFS. Compiled on Arduino IDE 1.6.9.
// This sketch shows a general method to get rid of delays in code.
// You could upgrade code with delays to work with add-a-sketch.

#include <avr/io.h>
#include "Arduino.h"

const byte ledPin = 13;
unsigned long delayStart, delayWait;

void setup()
{
  Serial.begin( 115200 );
  Serial.println( F( "\n\n\n  Un-Delay Example, free by GoForSmoke\n" ));
  Serial.println( F( "This sketch shows how to get rid of delays in code.\n" ));

  pinMode( ledPin, OUTPUT );
};


/* The section of the original sketch with delays:
 * 
 * digitalWrite( ledPin, HIGH );   --  0
 * delay( 500 );
 * digitalWrite( ledPin, LOW );    --  1
 * delay( 250 );
 * digitalWrite( ledPin, HIGH );   --  2
 * delay( 250 );
 * digitalWrite( ledPin, LOW );    --  3
 * delay( 250 );
 * digitalWrite( ledPin, HIGH );   --  4
 * delay( 1000 );
 * digitalWrite( ledPin, LOW );    --  5
 * delay( 1000 );
 */

byte blinkStep; // state tracking for BlinkPattern() below

void BlinkPattern()
{
  // This one-shot timer replaces every delay() removed in one spot.  
  // start of one-shot timer
  if ( delayWait > 0 ) // one-shot timer only runs when set
  {
    if ( millis() - delayStart < delayWait )
    {
      return; // instead of blocking, the undelayed function returns
    }
    else
    {
      delayWait = 0; // time's up! turn off the timer and run the blinkStep case
    }
  }
  // end of one-shot timer

  // here each case has a timed wait but cases could change Step on pin or serial events.
  switch( blinkStep )  // runs the case numbered in blinkStep
  {
    case 0 :
    digitalWrite( ledPin, HIGH );
    Serial.println( F( "Case 0 doing something unspecified here at " ));
    Serial.println( delayStart = millis()); // able to set a var to a value I pass to function
    delayWait = 500; // for the next half second, this function will return on entry.
    blinkStep = 1;   // when the switch-case runs again it will be case 1 that runs
    break; // exit switch-case

    case 1 :
    digitalWrite( ledPin, LOW );
    Serial.println( F( "Case 1 doing something unspecified here at " ));
    Serial.println( delayStart = millis());
    delayWait = 250;
    blinkStep = 2;
    break;

    case 2 :
    digitalWrite( ledPin, HIGH );
    Serial.println( F( "Case 2 doing something unspecified here at " ));
    Serial.println( delayStart = millis());
    delayWait = 250;
    blinkStep = 3;
    break;

    case 3 :
    digitalWrite( ledPin, LOW );
    Serial.println( F( "Case 3 doing something unspecified here at " ));
    Serial.println( delayStart = millis());
    delayWait = 250;
    blinkStep = 4;
    break;

    case 4 :
    digitalWrite( ledPin, HIGH );
    Serial.println( F( "Case 4 doing something unspecified here at " ));
    Serial.println( delayStart = millis());
    delayWait = 1000;
    blinkStep = 5;
    break;

    case 5 :
    digitalWrite( ledPin, LOW );
    Serial.print( F( "Case 5 doing something unspecified here at " ));
    Serial.println( delayStart = millis());
    delayWait = 1000;
    blinkStep = 0;
    break;
  }
}


void loop()  // runs over and over, see how often
{            
  BlinkPattern();
}