programm stopping

Hi,
I'm completely new to Arduino. I'm trying to use a sensor, a hc-sr04 (ultrasonic ranging module).
I run this program :

#define trigPin 13
#define echoPin 12

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

}

void loop() {
long duration, distance;
digitalWrite(trigPin, LOW); // Added this line
delayMicroseconds(2); // Added this line
digitalWrite(trigPin, HIGH);
// delayMicroseconds(1000); - Removed this line
delayMicroseconds(10); // Added this line
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = (duration/2) / 29.1;

if (distance >= 200 || distance <= 0){
Serial.println("Out of range");
}
else {
Serial.print(distance);
Serial.println(" cm");
}
delay(500);
}

It works fine, I can see the distance in the monitor, but after a short period of time, say 30 seconds, it just stops working and displays "out of range" continuously. What am I doing wrong?

(deleted)

spycatcher2k:
long duration, distance;

Take this out of loop and make then global, just after your #define

Why?

lucienR:
it just stops working and displays "out of range" continuously. What am I doing wrong?

First thing I would do (for debugging) is put Serial.print(distance); before the IF clause.

...R

I played with the HC-SR04 on Monday night for the first time. It depends on the 'material' that you use what is detected. I use a square metal can to reflect straight back and that works; the same metal can under an angle of 45 degrees gives a repeating sequence of incorrect readings and out-of-range. A piece of artificial fur gives a repeating correct reading followed by out-of-range.

So it depends on your material what the result will be; I think that it's somewhere stated that it has difficulty detecting people wearing clothes.

I used below code (a variation on your one). Note that I used different pins and had an RGB Led connected. I've added a counter for your convenience.

// HC-SR04 pins
#define ECHOPIN 7
#define TRIGGERPIN 8

// LEDS
#define LEDRED 9
#define LEDGREEN 10
#define LEDBLUE 11

// ranges in centimeters
#define MAXRANGE 350
#define MINRANGE 0
#define CRITICAL 5

// delay between HC-SR04 readings in milliseconds
// according to datasheet, this should be at least 60ms
//  to prevent interference between trigger and echo
#define DELAY_HCSR04 500

void setup()
{
  Serial.begin (9600);

  pinMode(TRIGGERPIN, OUTPUT);
  pinMode(ECHOPIN, INPUT);
  pinMode(LEDRED, OUTPUT);
  pinMode(LEDGREEN, OUTPUT);
  pinMode(LEDBLUE, OUTPUT);

  digitalWrite(LEDRED, LOW);
  digitalWrite(LEDGREEN, LOW);
  digitalWrite(LEDBLUE, HIGH);

  digitalWrite(TRIGGERPIN, LOW);
  delayMicroseconds(2);
}

void loop()
{
  static unsigned long startDistancemeasurement = millis();
  static unsigned long count = 0;

  if (millis() - startDistancemeasurement > DELAY_HCSR04)
  {
    // timing
    startDistancemeasurement = millis();

    // counter to count iterations
    count++;

    // get distance
    long distance = checkDistance();
    Serial.print(count);
    Serial.print(F(" "));

    if (distance >= MAXRANGE || distance <= MINRANGE)
    {
      Serial.print(F("Out of range: "));
      Serial.print(distance);
      Serial.println(F(" cm"));

      // out of range indicated by BLUE on and RED and GREEN off
      digitalWrite(LEDRED, LOW);
      digitalWrite(LEDGREEN, LOW);
      digitalWrite(LEDBLUE, HIGH);
    }
    else
    {
      Serial.print(distance);
      Serial.println(F(" cm"));

      // in range, switch BLUE off
      digitalWrite(LEDBLUE, LOW);
      if (distance < CRITICAL)
      {
        // too close, RED on and GREEN off
        digitalWrite(LEDRED, HIGH);
        digitalWrite(LEDGREEN, LOW);
      }
      else
      {
        // safe, GREEN on and RED off
        digitalWrite(LEDRED, LOW);
        digitalWrite(LEDGREEN, HIGH);
      }
    }
  }
}

unsigned long checkDistance()
{
  // send a 10us trigger pulse
  digitalWrite(TRIGGERPIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIGGERPIN, LOW);

  // read duration of echo in milliseconds
  unsigned long duration = pulseIn(ECHOPIN, HIGH);

//  Serial.print(F("Duration: "));
//  Serial.print(duration);
//  Serial.println(F(" ms"));

  // calculate and return distance in cm
  return (duration / 2) / 29.1;
}

This isn't doing what you think it is doing.

distance = (duration/2) / 29.1;

The variable "distance" is an integer and you're trying to divide "duration/2" which is also an integer, by a float constant.

aarg:
This isn't doing what you think it is doing.

distance = (duration/2) / 29.1;

The variable "distance" is an integer and you're trying to divide "duration/2" which is also an integer, by a float constant.

I know :wink:

aarg:
This isn't doing what you think it is doing.

distance = (duration/2) / 29.1;

The variable "distance" is an integer and you're trying to divide "duration/2" which is also an integer, by a float constant.

And . . ?

There is loss of precision if "duration" is an odd number. :slight_smile: (tapdancing... He he). I get it that it works now and, it doesn't matter in this case because that loss is swamped by the division. But a more general approach that avoids the risk in cases where that is not true, would be:

distance = (duration / 2.0) / 29.1;

Consider how bad something like:

distance = (duration / 99) / 29.1;

would be, if those were the constants.

I am entitled to one mistake a day.

aarg:
There is loss of precision if "duration" is an odd number. :slight_smile:

Have you ever considered a career in politics? :smiley:

Sorry guys but I still don't see what I should do...

spycatcher2k:
long duration, distance;

Take this out of loop and make then global, just after your #define

I'm new to programming, how does this translate into code?

Robin2:
First thing I would do (for debugging) is put Serial.print(distance); before the IF clause.

...R

... same question here...
Sorry, it might be obvious for you, but I don't get it.
Thanks

Uncompiled, untested

const byte trigPin = 13;
const byte echoPin = 12;

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

void loop() 
{
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  unsigned long duration = pulseIn(echoPin, HIGH);
  unsigned long distance= (duration/2) / 29.1;

  //Debug prints.
  Serial.print(F("Duration = "));
  Serial.print(duration);
  Serial.print(F("   distance = "));
  Serial.print(distance);
 
  if (distance >= 200 || distance <= 0){
    Serial.println("Out of range");
  }
  else {
    Serial.print(distance);
    Serial.println(" cm");
  }
  delay(500);
}

Thank you.
It works but I still have the same problem, after some time (between 5 seconds and 1 minute) it stops working, I get the "out of range" message...

How are you powering this?

I'm not sure I get your question (total newbie here, sorry, I'm a PD user, completely new to Arduino). 5v to Vcc, is it what you asked?

Sterretje I just tried your code, and surprisingly it bugs in a slightly different way. It works as long as I keep an object in front of it. As soon as I remove it it displays "out of range", and it won't work again, unless I compile it again.

You need to call pulseIn() with a timeout value.

Hmm, on my system it happily recovers from out-of-range. Can't help further.

PS duration is in microseconds, not milliseconds; little mistake in my comments and displaying in checkDistance().

aarg:
You need to call pulseIn() with a timeout value.

How do you translate that into code ? Sorry, I can't code at all.

https://www.arduino.cc/en/Reference/PulseIn

Your code as well as mine already use pulseIn. Did you even understand the original (or my) code? Start with understanding it before using it.

pulseIn reference