Servo related to time and distance

I’m using arduino for two weeks now and I need to use it in a project for school.

For my project I use an ultrasonic sensor (HC-SR04) to control a servo. I used an if/else statement to define two different positions for the servo related to a certain distance. My problem is that in the else statement the servo has to rotate to the given position after 10 seconds. I can’t use the delay function because than my ultrasonic also only pulsates after 10 seconds while it needs to pulsate every second.

Code:

#define echoPin 7 // Echo Pin
#define trigPin 8 // Trigger Pin

#include <VarSpeedServo.h>
VarSpeedServo myservo;

int position1 = 0;
int position2 = 45;

int maximumRange = 10; // Maximum range needed
int minimumRange = 5; // Minimum range needed
long duration, distance; // Duration used to calculate distance

int countTime = 0;

void setup() {
Serial.begin (9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);

myservo.attach(10); // attaches the servo on pin 10 to the servo object
//myservo.slowmove(position1, 5); // set servo to position 1
}

void loop() {

digitalWrite(trigPin, LOW);
delayMicroseconds(2);

digitalWrite(trigPin, HIGH);
delayMicroseconds(10);

digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);

distance = duration/58.2; //Calculate the distance (in cm) based on the speed of sound.

// Sensor checks distance every second
delay(1000);

// person has right posture

if (distance < maximumRange && distance > minimumRange){
Serial.print(distance);
Serial.print(" cm");
Serial.print("\t");
Serial.print("\t");
Serial.print("\t");
Serial.println(countTime);

myservo.slowmove(position1, 5); // set servo to position 1

countTime ++;

}

// Person has wrong posture

else {
Serial.print(distance); // Send the distance to the computer using Serial protocol
Serial.print(" cm");
Serial.print("\t");
Serial.print("\t");
Serial.print("\t");
Serial.println(countTime);

myservo.slowmove(position2, 5); // set servo to position 2

countTime = 0;
}
}

Look at how to manage time using millis() as illustrated in the demo several things at a time.

...R

Thanks, I'm going to try!

And of course the BlinkWithoutDelay example is a good starting point too.

You did work through all the simple examples provided didn't you? :)

Yes, I worked through the beginner examples of Arduino.

I still can't figure out how to implement the timer because the servo is distance and time dependant.

Maybe somebody can take a look at my code and help me further with some tips.

I tried this now:

/*
HC-SR04 Ping distance sensor:
VCC to arduino 5v
GND to arduino GND
Echo to Arduino pin 7
Trig to Arduino pin 8

This sketch originates from Virtualmix: http://goo.gl/kJ8Gl
Has been modified by Winkle ink here: http://winkleink.blogspot.com.au/2012/05/arduino-hc-sr04-ultrasonic-distance.html
And modified further by ScottC here: http://arduinobasics.blogspot.com.au/2012/11/arduinobasics-hc-sr04-ultrasonic-sensor.html
on 10 Nov 2012.

*/

#define echoPin 7 // Echo Pin
#define trigPin 8 // Trigger Pin

#include <VarSpeedServo.h>
VarSpeedServo myservo;

int position1 = 0;
int position2 = 45;

int maximumRange = 10; // Maximum range needed
int minimumRange = 5; // Minimum range needed

long duration, distance; // Duration used to calculate distance

int interval = 10000;
unsigned long previousMillis=0;

void setup() {
Serial.begin (9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);

myservo.attach(10); // attaches the servo on pin 10 to the servo object
//myservo.slowmove(position1, 5); // set servo to mid-point
}

void loop() {

/* The following trigPin/echoPin cycle is used to determine the
distance of the nearest object by bouncing soundwaves off of it. */
digitalWrite(trigPin, LOW);
delayMicroseconds(2);

digitalWrite(trigPin, HIGH);
delayMicroseconds(10);

digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);

distance = duration/58.2; //Calculate the distance (in cm) based on the speed of sound.

// Sensor checks distance every second
delay(500);

// person has right posture

if (distance < minimumRange || distance > maximumRange){

// if object dichtenbij komt dan minimumrange of verder weg dan maximumrange start met tellen
unsigned long currentMillis = millis();
Serial.print(distance);
Serial.print(" cm");
Serial.print("\t");
Serial.print("\t");
Serial.print("\t");
Serial.println(currentMillis);

// if object dichtenbij komt dan minimumrange start met tellen
if ((unsigned long)(currentMillis - previousMillis) >= interval) {
myservo.slowmove(position2, 5); // set servo to mid-point
}
}

if (distance > minimumRange && distance < maximumRange){
Serial.print(distance);
Serial.print(" cm");
Serial.print("\t");
Serial.print("\t");
Serial.print("\t");

myservo.slowmove(position1, 5); // set servo to mid-point
}
}

But when “(distance < minimumRange || distance > maximumRange)” the servo reacts immediately and doesn’t wait for 10 seconds.

teezke:
Maybe somebody can take a look at my code and help me further with some tips.

Please edit your post to put that long code in code tags so

it looks like this and is much easier to work with

Use the button that looks like a scroll with <> on top of it

Help us to help you.

…R

My code is now like this:

/*
 HC-SR04 Ping distance sensor:
 VCC to arduino 5v 
 GND to arduino GND
 Echo to Arduino pin 7 
 Trig to Arduino pin 8
 
 This sketch originates from Virtualmix: http://goo.gl/kJ8Gl
 Has been modified by Winkle ink here: http://winkleink.blogspot.com.au/2012/05/arduino-hc-sr04-ultrasonic-distance.html
 And modified further by ScottC here: http://arduinobasics.blogspot.com.au/2012/11/arduinobasics-hc-sr04-ultrasonic-sensor.html
 on 10 Nov 2012.
 
 Modified by Martijn Bohnen, Pre-Master ID 'Smart Health'
 */

#define echoPin 7 // Echo Pin
#define trigPin 8 // Trigger Pin
#define LED1Pin 11
#define LED2pin 12

#include <VarSpeedServo.h>
VarSpeedServo myservo;

// Positie servo
int position1 = 90;
int position2 = 45;

// Ultrasone sensor, afstand waarde
int outOfRange = 40;
int maximumRange = 10; // Maximum range needed
int minimumRange = 5; // Minimum range needed
int duration;
int distance; // Duration used to calculate distance

// Tijdsduur
//int countTime = 0;
int introTimecount = 0;
int tenSec = 20; // ten seconden bij delay(500)

void setup() {
  Serial.begin (9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(LED1Pin, OUTPUT);
  pinMode(LED2Pin, OUTPUT);

  myservo.attach(10);  // attaches the servo on pin 10 to the servo object
  myservo.slowmove(position1, 5);  // set servo to mid-point  
}

void loop() {

  /* The following trigPin/echoPin cycle is used to determine the
   distance of the nearest object by bouncing soundwaves off of it. */
  digitalWrite(trigPin, LOW); 
  delayMicroseconds(2); 
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10); 
  digitalWrite(trigPin, LOW);
 
  duration = pulseIn(echoPin, HIGH);
  distance = duration/58.2; //Calculate the distance (in cm) based on the speed of sound.


  if (distance <= outOfRange) {
/*    Serial.print(distance);
    Serial.print(" cm");   
    Serial.print("\t");  
    Serial.print(introTimecount);
    Serial.print("\t");
    Serial.println("Iemand gespot");*/ 
    digitalWrite(LED2Pin,HIGH);
  
    
    if (distance <= minimumRange){ 
      Serial.print(distance);
      Serial.print(" cm");   
      Serial.print("\t");  
      Serial.print(introTimecount);
      Serial.print("\t");
      Serial.println("Close");
      Serial.println();
      
      introTimecount = 0;
      introTimecount ++;
      
      // if object dichtenbij komt dan minimumrange start met tellen
      if (introTimecount > tenSec) {   
        introTimecount = 200;
        myservo.slowmove(position1, 5);  // set servo to mid-point
      }
    }
      
    if (distance >= maximumRange){
      Serial.print(distance);
      Serial.print(" cm");   
      Serial.print("\t");  
      Serial.print(introTimecount);
      Serial.print("\t");
      Serial.println("Far");
      Serial.println();   
      
      introTimecount = 0;
      introTimecount ++;
      
      // if object dichtenbij komt dan minimumrange start met tellen
      if (introTimecount > tenSec) {   
        introTimecount = 200;
        myservo.slowmove(position1, 5);  // set servo to mid-point
      }
    }
      
    if (distance > minimumRange && distance < maximumRange){
      Serial.print(distance);
      Serial.print(" cm");   
      Serial.print("\t");  
      Serial.print(introTimecount);
      Serial.print("\t");
      Serial.println("Right");  
      Serial.println();
      
      introTimecount = 0;
      introTimecount ++;
     
      // if object dichtenbij komt dan minimumrange start met tellen
      if (introTimecount > tenSec) {   
        introTimecount = 200;
        myservo.slowmove(position1, 5);  // set servo to mid-point
      } 
    }     
  }
  else {
    Serial.print(distance);
    Serial.println(" cm");   
    introTimecount = 0;
    digitalWrite(LED2Pin,LOW);
  }


// Sensor checks distance every second
  delay(500);
  
}

The only problem which is still left is that I need to reset the timer everytime the ultrasonic sensor registrate the object in a different range. So when the object moves from the area minimumRange to maximumRange for example the timer should reset.

I implemented introTimecount = 0; and introTimecount ++; but than it keeps resetting and adding 1 so the timer stays at 1 all the time.

Thanks for your help.

teezke:
I implemented introTimecount = 0; and introTimecount ++; but than it keeps resetting and adding 1 so the timer stays at 1 all the time.

Which is what you would expect.

I think it would help to write down the sequence of steps that you want to happen with each one on a different line.

I don’t really understand exactly what you want to do.

…R

When an object comes within the 40 cm range the program starts to work.

When the object is between minimum and maximum range the servo needs to go to position 1 immediately. When the object stays in this range nothing else will happen.

If the object after a certain time comes closer than minimumrange or gets further away than the maximumrange a timer needs to start counting to 10. When the 10 seconds are past the servo needs to go to position 2 and stay there. When the object gets back to between minimumrange and maximumrange the servo again needs to go to position 1 immediately.

So the timer is only needed below the minimumrange and above the maximumrange. Between these points the servo needs to respond immediately.

I hope this makes it a little more clear to understand.

Thanks!

That is much clearer. It seems to me the following pseudo code would meet your need

if range < outerLimit
   objectInRange = true
else
   objectInRange = false

if objectInRange == true
  if range >= min && range <= max
      move servo to position 1
  else
     startMillis = millis()
     timerRunning = true

if timerRunning == true
  if millis() - startMills >= 10000
    move servo to position 2
    timer running = false

…R

Thanks for you help!

This should be the solution when I quickly look through it. I'm going to try and combine it with my code and see if it works.

MB

The code is implemented now

/*
 HC-SR04 Ping distance sensor:
 VCC to arduino 5v 
 GND to arduino GND
 Echo to Arduino pin 7 
 Trig to Arduino pin 8
 
 by Martijn Bohnen, Pre-Master ID 'Smart Health'
 */

#define echoPin 7 // Echo Pin
#define trigPin 8 // Trigger Pin

#include <VarSpeedServo.h>  // Control servo speed
VarSpeedServo myservo;

// Position servo
int position1 = 90;
int position2 = 45;

// Ultrasone sensor, distance
int outOfRange = 50;
int maximumRange = 10; // Maximum range needed
int minimumRange = 5; // Minimum range needed
int duration;
int distance; // Duration used to calculate distance

// Timer definitions
int objectInRange;
int startMillis;
int timerRunning;

void setup() {
  Serial.begin (9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);

  myservo.attach(10);  // attaches the servo on pin 10 to the servo object
  myservo.slowmove(position1, 5);  // set servo to mid-point  
}

void loop() {

  /* The following trigPin/echoPin cycle is used to determine the
   distance of the nearest object by bouncing soundwaves off of it. */
  digitalWrite(trigPin, LOW); 
  delayMicroseconds(2); 
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10); 
  digitalWrite(trigPin, LOW);

  duration = pulseIn(echoPin, HIGH);
  distance = duration/58.2; //Calculate the distance (in cm) based on the speed of sound.

  Serial.print(distance);
  Serial.print(" cm");
  Serial.println("\t");   

  if (distance < outOfRange) {
    objectInRange = true;
  }

  else {
    objectInRange = false;
  }

  if (objectInRange == true) {
    if (distance > minimumRange && distance < maximumRange){ 

      myservo.slowmove(position1, 5);  // set servo to position 2
    }

    else {
      startMillis = millis();
      timerRunning = true;
      Serial.print(startMillis);
      Serial.println("\t");
      Serial.println(millis());
    }
    
    if (timerRunning == true){
    if (millis()- startMillis >= 10000) {

      myservo.slowmove(position2, 5);  // set servo position 2
     }
     timerRunning = false;
  }
 
 }
  // Sensor checks distance every second
  delay(1000);
}

It is also working, but there is one little problem. Millis is never resetted which means that after 10 seconds Millis stays higher than 10000, so it only works once. Is there a way to reset the millis after the servo reached position2?

with kind regards,

Martijn Bohnen

teezke: It is also working, but there is one little problem. Millis is never resetted which means that after 10 seconds Millis stays higher than 10000, so it only works once. Is there a way to reset the millis after the servo reached position2?

You don't (ever) reset millis(). What you may need to do is update the value of startMillis - but from your description i don't know where this should happen - apart from where it happens already.

By the way it is very important that all variables connected with millis() are defined as unsigned long. An int is not big enough.

...R

I just made my own timer instead of using the millis(); function. Now it works perfect like it should be!

Without the code structure you sended me I wouldn't have made it. Next week I'm giving a presentation about my project so I'm glad it's finished now and I can finish the complete prototype!

Thanks a lot for your help.

MB

teezke: I just made my own timer instead of using the millis(); function.

Reinventing the wheel !

But I'm glad to hear it is working.

...R