I can not find the error in my code.

I have been working on this on and off for over 3 hours now and it is only my stubbornness and the fact I don’t want to make the same error again that has stopped me from just rewriting it all over again. my project is going to be a basic S,L,A,M but right now it is a mapping robot.

When I run my code it returns a distance of 0. I had never worked with this type of range sensor before, so I loaded a sample sketch to test that I had it hooked up right and that ran no problem. However my code still will not work. I even coped and pasted the part of the sample sketch that runs the sensor and it still did not work. I am at my wits end with it and need a new set of eyes to look over it or I’m just going to rewrite it all.

edit: my sensor is a HC-sr04 sonic range finder.

my sketch:

// SLAM
// Levi  
// code on: 6/14/16

#include <Servo.h> // import servo library 
#include <Ethernet.h>

// pin setup
#define servoPin 6
#define trigPin 9
#define echoPin 10
#define error 4

// the media access control (ethernet hardware) address for the shield:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };  
//the IP address for the shield:
byte ip[] = { 192, 168, 1, 20 };
byte server[] = {192,168,1,3};
EthernetClient client;

// servo setup
Servo servo1;

//setup vars
int theta = 0;
int stepSize = 3; // degreas between meserments

void setup() {
  // set pin mode's
  pinMode(servoPin, OUTPUT);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  
  //debug
  Serial.begin(9600);

  Ethernet.begin(mac, ip);
  delay(1000);
  client.connect(server, 4444);
  delay(5000);
  client.println("SLAM");
  delay(5000);

  // setup the servo
  servo1.attach(servoPin);
  servo1.write(90);
}

void loop() {
  servo1.write(theta);
  delay(500);
  int range = dist();
  client.println(String(range) + "," + String(theta));
  theta += stepSize;
  if (theta > 180) theta = 0;
}

long dist() {
  long dist1, dist2;
  while (true) {
    dist1 = getRange();
    delay(200);
    dist2 = getRange();
    if (abs(dist1 - dist2) < error) {
      return (dist1 + dist2) / 2;  
    }
  }
}

long getRange() {
  long duration;
  digitalWrite(trigPin, LOW);
  delay(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  int distance = duration*0.034/2;
    // I put a Serial.println(duration); here and it still only returned 0 both to the server and the serial monitor
  return distance;
}

sample sketch:

/*
* Ultrasonic Sensor HC-SR04 and Arduino Tutorial
*
* Crated by Dejan Nedelkovski,
* www.HowToMechatronics.com
*
*/

// defines pins numbers
const int trigPin = 9;
const int echoPin = 10;

// defines variables
long duration;
int distance;

void setup() {
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
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);
}

where is distance initialized?

long getRange() {
  long duration;
  digitalWrite(trigPin, LOW);
  delay(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = duration*0.034/2;  //<<<<<<<<<<<<<<< ??
    // I put a Serial.println(duration); here and it still only returned 0 both to the server and the serial monitor
  return distance;  // Seems important
}

BulldogLowell:
where is distance initialized?

I had removed distance during debugging but added it back in for the post. it is initialized at the time of first use. and I just retested it with the exact code of my post (plus distance initialized) and it still did not work.

int distance = duration*0.034/2;

leviathan01:

int distance = duration*0.034/2;

You are doing a float calculation and force the result into an integer variable. This will not work as expected :frowning:

leviathan01:
I had removed distance during debugging but added it back in for the post. it is initialized at the time of first use. and I just retested it with the exact code of my post (plus distance initialized) and it still did not work.

int distance = duration*0.034/2;

The variable distance will be 0 no matter what the value of duration. 0.034 rounds to zero, so: distance = duration * 0/2

ChrisTenone:
The variable distance will be 0 no matter what the value of duration. 0.034 rounds to zero, so: distance = duration * 0/2

No. Only the result gets trunctated.

void setup() {
  Serial.begin(115200);
  for (long duration= 30; duration <2000; duration+=30) {
    long distance = duration*0.034/2;
    Serial.print(F("duration "));
    Serial.print(duration);
    Serial.print(F(" distance "));
    Serial.println(distance);
  }
}
void loop() {}
duration 30 distance 0
duration 60 distance 1
duration 90 distance 1
duration 120 distance 2
duration 150 distance 2
duration 180 distance 3
duration 210 distance 3
duration 240 distance 4
duration 270 distance 4
duration 300 distance 5
duration 330 distance 5
duration 360 distance 6
duration 390 distance 6
duration 420 distance 7
duration 450 distance 7
duration 480 distance 8
duration 510 distance 8
duration 540 distance 9
duration 570 distance 9
duration 600 distance 10
duration 630 distance 10
duration 660 distance 11
duration 690 distance 11
duration 720 distance 12
duration 750 distance 12
duration 780 distance 13
duration 810 distance 13
duration 840 distance 14
duration 870 distance 14
duration 900 distance 15
duration 930 distance 15
duration 960 distance 16
duration 990 distance 16
duration 1020 distance 17
duration 1050 distance 17
duration 1080 distance 18
duration 1110 distance 18
duration 1140 distance 19
duration 1170 distance 19
duration 1200 distance 20
duration 1230 distance 20
duration 1260 distance 21
duration 1290 distance 21
duration 1320 distance 22
duration 1350 distance 22
duration 1380 distance 23
duration 1410 distance 23
duration 1440 distance 24
duration 1470 distance 24
duration 1500 distance 25
duration 1530 distance 26
duration 1560 distance 26
duration 1590 distance 27
duration 1620 distance 27
duration 1650 distance 28
duration 1680 distance 28
duration 1710 distance 29
duration 1740 distance 29
duration 1770 distance 30
duration 1800 distance 30
duration 1830 distance 31
duration 1860 distance 31
duration 1890 distance 32
duration 1920 distance 32
duration 1950 distance 33
duration 1980 distance 33

Well, whatever, you are multiplying a long by a float literal and then dividing by an integer and assigning the result to an integer.

You should not write such stupid expressions unless you know exactly how that will be calculated. Particularly if you are unsure what the value of "duration" is going to be.

Whandall:
No. Only the result gets trunctated.

True. I was imprecise. The literal constant 0.034 is still a float equal to 3.4*10^-3. Multiplied by distance and divided by 2 it is still a floating point number. When stuffed into the (short) integer variable, it gets truncated (not rounded) to zero. When you used a long, the integer part of the number was preserved, because the 32 bits of a long integer are enough to hold the result of the multiplication (but the result is still an integer, because long is an integer.)

ps, the long winded explanation is for the OP’s understanding.

I made it a long, because there was no definition and it was returned as a long.

It works just the same with an short integer.

The formula computes the distance in cm from the microseconds that the echo takes to return to the receiver.
The HC-SR04s work up to a range of around 400 cm which fits perfectly in a short int.

Whandall:
I made it a long, because there was no definition and it was returned as a long.

It works just the same with an short integer.

The formula computes the distance in cm from the microseconds that the echo takes to return to the receiver.
The HC-SR04s work up to a range of around 400 cm which fits perfectly in a short int.

Ok... thanks.

I don't have one of those. I should have had a better sense of what was needed. My initial idea was to use floats, but at 30 microseconds per reading, it can measure about 1000 ft/sec!

Using an integer only computationdistance = duration / 29 / 2;
gives a result very close to the slow floatingpoint computation.

void setup() {
  Serial.begin(115200);
  for (long duration = 0; duration < 25000; duration += 1000) {
    int distance = duration * 0.034 / 2;
    int distance1 = duration / 29 / 2;
    Serial.print(F("duration "));
    Serial.print(duration);
    Serial.print(F(" distance float "));
    Serial.print(distance);
    Serial.print(F(" distance int "));
    Serial.println(distance1);
  }
}
void loop() {}
duration 0 distance float 0 distance int 0
duration 1000 distance float 17 distance int 17
duration 2000 distance float 34 distance int 34
duration 3000 distance float 51 distance int 51
duration 4000 distance float 68 distance int 68
duration 5000 distance float 85 distance int 86
duration 6000 distance float 102 distance int 103
duration 7000 distance float 119 distance int 120
duration 8000 distance float 136 distance int 137
duration 9000 distance float 153 distance int 155
duration 10000 distance float 170 distance int 172
duration 11000 distance float 187 distance int 189
duration 12000 distance float 204 distance int 206
duration 13000 distance float 221 distance int 224
duration 14000 distance float 238 distance int 241
duration 15000 distance float 255 distance int 258
duration 16000 distance float 272 distance int 275
duration 17000 distance float 289 distance int 293
duration 18000 distance float 306 distance int 310
duration 19000 distance float 323 distance int 327
duration 20000 distance float 340 distance int 344
duration 21000 distance float 357 distance int 362
duration 22000 distance float 374 distance int 379
duration 23000 distance float 391 distance int 396
duration 24000 distance float 408 distance int 413

:slight_smile:

I like that!

It would be a good idea to call pulseIn with a timeout parameter (30000 would be reasonable),
the standard 1000000 microseconds seems to be way to high.

I think you don't want the program to block for one full second if the sensor fails to get an echo.

A very good library that handles HC-SR04 (and other such sensors) is the NewPing Arduino Library for Arduino.

long getRange() {
   // other stuff
   int distance =  /* some calculation  */
   return distance;
}

This really isn't much good, either. If the function says it will return a long, then calculate a long. It will probably work, but may require unnecessary register manipulation.

As already stated, the highest value is well below 32767, an int would be a better choice for the function type.

Extending ints to longs is very efficient (just insert two 0x00 or 0xFF) and the return value is guaranteed to reside in registers.

even with my new code based on what was said it still does not work.

// SLAM
// Levi  
// code on: 6/14/16

#include <Servo.h> // import servo library 
#include <Ethernet.h>

// pin setup
#define servoPin 6
#define trigPin 9
#define echoPin 10
#define error 4

// the media access control (ethernet hardware) address for the shield:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };  
//the IP address for the shield:
byte ip[] = { 192, 168, 1, 20 };
byte server[] = {192,168,1,3};
EthernetClient client;

// servo setup
Servo servo1;

//setup vars
int theta = 0;
int stepSize = 3; // degreas between meserments

void setup() {
  // set pin mode's
  pinMode(servoPin, OUTPUT);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  
  //debug
  Serial.begin(9600);

  Ethernet.begin(mac, ip);
  delay(1000);
  client.connect(server, 4444);
  delay(5000);
  client.println("SLAM");
  delay(5000);

  // setup the servo
  servo1.attach(servoPin);
  servo1.write(90);
}

void loop() {
  servo1.write(theta);
  delay(500);
  int range = dist();
  client.println(String(range) + "," + String(theta));
  theta += stepSize;
  if (theta > 180) theta = 0;
}

int dist() {
  int dist1, dist2;
  while (true) {
    dist1 = getRange();
    delay(200);
    dist2 = getRange();
    if (abs(dist1 - dist2) < error) {
      return (dist1 + dist2) / 2;  
    }
  }
}

int getRange() {
  // initializing vars
  int duration;
  int distance;

  // reset trigPin to a known state
  digitalWrite(trigPin, LOW);
  delay(2);

  // use the sensor
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  
  Serial.println("duration:" + String(duration)); // prints 0
  
  distance = duration / 29 / 2; // math done using int only i think
  
  Serial.println("distance:" + String(distance)); // prints 0
  return distance; // returns 0
}

Then you have a problem with your wiring or hardware and the demo code should fail like your code.

This code (which is essentially your code)

const byte trigPin = 9;
const byte echoPin = 10;

int getRange() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  int duration = pulseIn(echoPin, HIGH);
  Serial.print(F("duration: "));
  Serial.println(duration);
  int distance = duration / 29 / 2; // math done using int only i think
  Serial.print(F("distance: "));
  Serial.println(distance);
  return distance; // returns 0
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(trigPin, OUTPUT);
  Serial.begin(115200);
}

void loop() {
  static unsigned long lastSecond;
  unsigned long topLoop = millis();

  if (topLoop - lastSecond > 1000) {
    getRange();
    lastSecond = topLoop;
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  }
}

produces

duration: 16542
distance: 285
duration: 16516
distance: 284
duration: 16567
distance: 285
duration: 16567
distance: 285
duration: 16541
distance: 285
duration: 16566
distance: 285
duration: 16517
distance: 284
duration: 16566
distance: 285
duration: 9074
distance: 156
duration: 9025
distance: 155
duration: 9022
distance: 155

That's what I thought to but with out even touching the hardware I can upload the sample sketch and it will work then I can upload my sketch and it will run but will give a distance of 0. I will probably just use the information on this thread to rewrite it but I like to understand my mistakes, so I can avoid them in the future. Thanks for the help, and any ideas of the problem are still greatly appreciated.

I have one module that has problems recovering from a zero reading.
I can bring it into this state by covering the transmitter with a finger.
It keeps returning zeros, if I 'click' receiver or transmitter with my fingernail it starts working again.
Power cycling the module works also.

Do you have a second module you could try?

Yes, and I have tried both, same problem.