Strange issue with a very simple code

Hi all,

I'm quite new to programming and using various sensors with Arduino.
As part of a bigger project, I need precise distance measurement, now I'm experimenting with a HC-SR04 ultrasonic sensor. At this point I only need a reliable distance measurement, all the other things will be put together later.

The good thing is that gives nice linear results for the range I've tested for (10-80 cm). However, when it comes to converting the raw measurement results (echo times) to distance, the code I've written gives some totally unexpected numbers, not even close to the real value.

What's even stranger is that using the value of the variable "echoTime" in some lines of code seems to alter the value stored in "echoTime", while it isn't given a new value at all.

So here is my very basic test code for the sensor:

int triggerPin=7;
int echoPin=6;
int distance;
int echoTime;

void setup() {
  // put your setup code here, to run once:

pinMode(triggerPin, OUTPUT); // Trigger lab kimenet
pinMode(echoPin, INPUT); // Echo lab bemenet

Serial.begin(9600);

}


void loop() {
  // put your main code here, to run repeatedly:


 digitalWrite(triggerPin,HIGH);
 delayMicroseconds(10);
 digitalWrite(triggerPin,LOW);
 echoTime=pulseIn(echoPin,HIGH);

 distance=echoTime*(344/20000)-(0,1801*(echoTime*(344/20000))-0,2015);


Serial.println(echoTime);
delay(500);

}

All it does is reading out the value from the sensor and sending it to the serial port. The formula for the distance is based on some corrections, which I figured out by putting the echotime values in an Excel table, but it doesn't matter at the moment. The distance value is used for nothing in this program intentionally, because my problem is, that if I exclude that line of code with a "// " the echotime will print different numbers.
How is that possible when I don't change its value at all? If I try with another formula, let's say "distance = echoTime+5; " than it gives different results for echotime again. (Greater than it should be.) If I just simply insert the value of echotime into the variable "distance" (distance = echoTime;) than I get smaller numbers for the echotime.

This is something very strange. How could the value of a variable change if no line of code alters is?
I just use it to calculate another variable, but it changes itself...

Any idea would be very much appreciated!

(Arduino Due & HC-SR04 ultrasonic sensor)

 distance=echoTime*(344/20000)-(0,1801*(echoTime*(344/20000))-0,2015);

Where did you get that formula?

344/20000 = 0, so much of what that is doing is useless. The commas in there are wrong, no matter what you are trying to do.

 distance=echoTime*(344/20000)-(0,1801*(echoTime*(344/20000))-0,2015);

C uses a full stop as the decimal point, not a comma

Thank you, the commas were an amateur mistake indeed.

But the basic issue is not the calculation of distance, but the change of the echotime variable as it shouldn't be changed until when the next measurement cycle updates it.

Just disregard the distance calculation formula. I'm wondering why the value of the echotime (which would be the base of calculation) changes if I use its value (but not change it).

Why does the "distance= ..." line influence the raw time result that I get from the sensor?

How do you know that the value of echoTime is changed by the calculation ?

The loop() function will repeat very fast and read a new, possibly different, value of echoTime and print it.

No, actually it doesn't repeat very fast, I inserted a 500ms delay to read & print a measurement twice a second.

The change I mean is that if I use the echoTime variable for a calculation (or just copy its value into another variable) and then print the echoTime's value, then it gives a different reading compared to the case when the calculation is excluded from the program.

So it's two different programs, but everything else is unchanged, except for the presence of the calculation. It should give the same results for the same distance.

In other words:
If you look at my code in the first post and put a "//" before the line beginning with "distance" (making it a comment so that the compiler will ignore it), it will print a completely different number for the echoTime.

It's very strange to me. I don't understand how a variable could change depending on what I use its value for. The echoTime is not updated in this line, but the "distance" variable is. So if I measure the same distance it should be the same, with some minor deviations due to the inaccuracy of the sensor.

I don't understand how a variable could change depending on what I use its value for.

You've offered no proof that a change happens. If you were to print the value of echoTime, with identifier, before the distance calculation statement, and print the value of echoTime, with identifier, after the distance calculation you might convince us that using the variable in a calculation affects the contents of the variable. Until then, though, I'm sticking with the idea that it is your misinterpretation of the output that is the problem.

Have you fixed the commas?

You still misunderstand me. I've made two screenshots of the program running, it explains the difference. (Of course I had to reload the program to the Arduino after the modification.)

What you can see is that in one case I ran the prog without any calculations and got echoTime readings around ~1796.

In the other case I used the value of echoTime for a simple calculation (which makes no sense regarding the distance, but it's just for investigating the problem so far). I added 5 to it and stored this in the "distance" variable. Noticeably, the calculation doesn't affect echoTime, but despite of this, the echoTime varies around ~1130.

I haven't even touched the test object between the two measurements, so it should give the same results. The change doesn't occur while the calculation is made, but it's between the two scenarios.

You still misunderstand me.

No. You claimed that using the value of echoTime in a calculation affected the value in echoTime. Clearly, your code and results show that this is NOT the case.

Now, it is also obvious that having the calculation in loop() is somehow changing the time it seems to take to get a pulse back, but that is something totally different.

The code on https://www.arduino.cc/en/Tutorial/Ping shows a somewhat different approach to measuring distance using a ping sensor. I've used that code, and I know that it works.

I also said that it's two separate programs that produce different results for the measurement when they should give exactly the same. This ping tutorial you've linked is the same approach, the only difference is that is uses a sensor with 3 pins instead of 4.

I've tested the program again, and it turned out that even the presence of the

Serial.print("Before ");
Serial.println(echoTime);

lines influence the echoTime. Again, different numbers with and without these lines...
So it remains a mystery, but thank you anyway! If anyone has any ideas please leave a comment!

Sorry, but I am not getting what you are saying. Please post a program and Serial output that definitely shows the value of echoTime changing without it being read again.

Here is the code:

int triggerPin=7;
int echoPin=6;
int distance;
int echoTime;

void setup() {
  // put your setup code here, to run once:

pinMode(triggerPin, OUTPUT);
pinMode(echoPin, INPUT);
Serial.begin(9600);

}


void loop() {
  // put your main code here, to run repeatedly:


 digitalWrite(triggerPin,HIGH);
 delayMicroseconds(10);
 digitalWrite(triggerPin,LOW);
 echoTime=pulseIn(echoPin,HIGH);


Serial.print("Before ");
Serial.println(echoTime);

// distance = echoTime+5;

Serial.print("After ");
Serial.println(echoTime);


delay(500);

}

But as I said before, the value doesn't change between two measurements. I attached two screenshots to post #7, please check them. My problem is the difference you can see between the two cases. Why does it give totally different echo times if some other code is executed in the loop cycle? (Obviously after reloading the program to the Arduino.)

It also influences the recorded echo time if I exclude one of the serial prints from the program, even though they do nothing with the echotime except for sending its value to the computer.

The reading from the sensor shouldn't depend on any other statements that are executed by the Arduino. But apparently it does.

Why not give the NewPing library a try. See if it solves your issue, since it does not use pulseIn().

This issue is related to the Due.

When I run your code on a Uno, I do not see the difference in values with the two versions.

This thread discusses the precision of pulseIn(). Other methods like using an interrupt to measure the echo time should provide very accurate results.

Peter13:
Thank you, the commas were an amateur mistake indeed.

The other rookie mistake is (344/20000). Because these two numbers are integral, C will do an integer division and get the value zero. Use (344.0/20000.0).

dlloyd:
This thread discusses the precision of pulseIn().

That's interesting. That thread says

in that it is a hard loop and returns a number * the assumed clock cycles it takes for per loop

  • I wonder how the assumption is made?
    To the OP, the optimiser may be rearranging your code in ways that you can't see. It might be interesting to add the line #pragma GCC optimize ("O0") to the top of your code and see if you get the same results. That line will tell the compiler to use your code as it is laid out and not try to do clever things to make it smaller or faster. (It won't solve your problem but might throw some more light on the causes)

PaulS:
Why not give the NewPing library a try. See if it solves your issue, since it does not use pulseIn().

Thank you, I've tried it and it seems to have solved the issue! :slight_smile: The time value doesn't change depending on the rest of the code. However the results are still not really accurate, but I will try to make some improvements with the processing of the measured results. I would be satisfied with a ~1cm accuracy, but the error varies with the distance, the best results are in the 30-40 cm domain.

I guess that as pulseIn is based on interrupts it may interfere with other instructions. So be careful when using it!

This issue is related to the Due.

When I run your code on a Uno, I do not see the difference in values with the two versions.

That's interesting. Maybe the bug in pulseIn doesn't show up using other boards then the Due.