HC-SR04 with low delay, causes to all go slow

Hi all, I'm trying to build a Pad for a DancePad, that game where you press buttons on the floor at the rythm of a song.

Well, the pads on the floor, due to the force we use can break, so I wanted to try something new, using a distance sensor, the main concept is, if the distance is lower than a specified error I send the pressed button instruction, if goes up the distance over certain error, the button is released.

The base of the code is done, and is working fine at some extent, the lack of presicion of HC-SR04 is something to handle, 2mm for this game is too much, but I have found two ways to handle this.

  1. Take n samples, calc the average, I need to wait get the n samples
  2. Take n samples, remove the oldest element, add a new one, calc the average, While higher the n_samples, I need to update enough samples to notice something changed

In particular, this works pretty well, the error was reduced a lot, from 15 of error (with one value) to 5 with method 1 and 7 with method 2, but still more samples to get, means more time I need.

Oks, here is the point, how fast we press a pad? in a hard song, can be 3 times per second, a lot and still not the hardest song, the average is 333ms, and the time the pad goes up is still fast, while faster the pad goes up, we can play hardest songs.

The HC-SR04 has enough sample rate to get a lot of samples per second, but no idea why, Arduino is doing weird things, I'm using Arduino Leonardo.

const int Trigger = 2;
const int Echo = 3;

void setup() {
  Serial.begin(115200);
  pinMode(Trigger, OUTPUT);
  pinMode(Echo, INPUT);
  digitalWrite(Trigger, LOW);
}

void loop()
{

  long t;

  digitalWrite(Trigger, HIGH);
  delayMicroseconds(10);
  digitalWrite(Trigger, LOW);
  
  t = pulseIn(Echo, HIGH);

  Serial.println(t);
  delay(11);
}

The above is a sample code to describe what happens, first, to get samples with arduino, the time we need per sample is the delay function, which is 11, if I want to take 4 samples, will be at least 44ms.

As described above, the game works with a pretty fast speed, but should not be enough speed for digital things, so what is the matter?

The last delay(11) is the bottleneck, the program works great when you use 11 as delay, but use 10 instead and all the program slow down! you might think, is because I'm sending too much through the Serial, but I tested this on the project too, only showing when a button is pressed or released.

When press I check the times on the monitor, with 11 is pretty fast, with 1 or 2 samples I can get 33-250ms of delay, but going down delay to 10 or lower the delay of the messages are over 750ms, when I print if something is pressed or released only prints if changes, so there is almost not data send through Serial. Because the point is only know when the Pad is pressed and released.

So, the delay part is one issue.

The second issue is... zeros.

When the delay is lower than 11, what happens is the HC-SR04 starts getting two interleaced measures, one with 0, and the measure.

13:10:20.143 -> Distance 231 :0
13:10:20.143 -> Distance 232 :231

Very weird, I tested use delay 10 and keep it getting samples, and then for some reason started working fine, but is almost luck, no idea why happens this.

If I try to get two samples and then use delay(11), still the zeros problem.

With this two issues, I'm unable to get better presicion with HC-SR04, but no idea why happens.

Someone know why?

(I'm using HC-SR04 because is cheap)

Thx!

Try changing this to t = pulseIn(Echo, HIGH, 20000);

If pulseIn() does not see the end of the pulse for whatever reason, it times out after 1 second (having blocked code execution for a second) and returns zero. The line above will timeout after 20000 microseconds if no pulse end is seen.

:open_mouth: that is great.

Set the timeout reading the sensor fixes the timing, now all works fast, even we can use 10ms as delay!

This open new issues with the HC-SR04.

First, all my test was done with a surface at 5cm/7cm, so in first place, we should never get a timeout but happens!

I updated the code to get the number of samples and timout cased by a certain delay.

Delay: 10 -> 85.09 samples/s -> 0 Timout/s
Delay: 9 -> 29.62 samples/s -> 29.59 Timout/s
Delay: 8 -> 31.49 samples/s -> 31.45 Timout/s
Delay: 7 -> 33.59 samples/s -> 33.57 Timout/s
Delay: 6 -> 36.02 samples/s -> 35.99 Timout/s
Delay: 5 -> 38.82 samples/s -> 38.78 Timout/s
....
Delay 0 -> 64.38 samples/s -> 63.32 Timout/s

So... for some reason the HC-SR04 has a lot of timeout that should not happens.... this causes to lost a lot of presicion on the project.

Any idea why so much timeouts?

Read the documentation to discover the number of actual pulses transmitted. Your time-out has to be longer than the echo from the LAST pulse.

The test was done with the 20000us timeout, the echo is done with 10us.

Sadly I can't see the point here, using 10 Delay, 20000 of timeout and 10us Echo it works.

But only changing the Delay, not the tiemout and Echo causes to get timeouts....

Edited:

I did some tests with two params, if you keep 20000 of timeout, and you increases the Echo time and reduce the Delay time, in the end to get a value, you need the Echo to be close the 11ms and a Delay of 0ms, the Echo now is similar to the first Delay I used (11ms)... how weird.

It is often recommended to have a delay of 30 ms or more between pings, to prevent reverberating echos from falsely triggering the sensor.

ufff, 30ms is too much for this project.

At the same time, is possible to the echos cause to get timeouts? I test this without move the object from 7cm of the sensor.

Hi, @latot
Welcome to the forum.

Have you had a look at the NewPing library to do all your ultrasonic work?

Tom... :grinning: :+1: :coffee: :australia:

Not fully understanding the question, due to the grammar, but...

...lack of echos causes timeouts.

Hi, sorry my grammar, actually, the main problem now, is that, even with a object, the sensor has a lot of timeouts when using delay lower to 10.

That is the weird part, without touch how much time do the ECHO, without touch the timeout from pulseIn, only changing the last line of the code, the Delay, it causes timeout on the device.

In many examples, a short LOW is used before the HIGH trigger. That seems superfluous to me, but perhaps it really is needed or helpful. The NewPing lib says it is necessary.

Also, on some types of ultrasonic sensors similar to the HC-SR04, the trigger pulse needs to be a bit longer than 10 us. Maybe you have an odd ball HC-SR04 that needs a bit more.

So, I'd try:

  digitalWrite(trigPin, LOW);
  delayMicroseconds(5); // some examples have this = 2 us; NewPing lib uses 4 us
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(x);  // x =  some number between 10 us and, say 15 us; NewPing uses 10 us
  digitalWrite(trigPin, LOW);

Yeah, I tested with that, the first tests was using delay of 11 to not get timeouts.

Then with the fixes and recomendations I started testing the Echo values, but is weird, in order to not get the timeouts I need to increase the Echo almost the same I reduce the Delay.

In a way, we can says there is the Low_Trigger (the time in low) the Echo_Time (time we send the sound) and the Delay time of the program.

To not get timeouts: Delay + Echo_Time + Low_Trigger ~ 11ms (the min is closer to 10ms).

That relation is so weird... why Delay is affecting the sensor....!!

Almost seems the sensor needs time to rest or do something in that 11ms to be able to get the next measure.

That can be simplified to Delay >= 10 or 11 ms, because there is no practical difference between 10.000 ms and 10.015 ms (where the 0.015 ms is the sum of the microsecond delays between switching the trigger pin between LOW and HIGH).

I can't answer your question about why you get timeouts if the delay between pings is less than about 10 ms, but by using delays less than the usual 30 ms or so (for example, NewPing uses 29 ms), you are in uncharted water, which it is best to avoid.

If you really need 10 ms or less between measurements, I'd say you should consider a different sensor.

Good luck with your project.

very bad idea to use US-measurement for recognizing a pressing of pad. I think this is the worst solution ever. Hall sensor, weight sensor, shake sensor, even two metallic pads - everything is better as ultrasonic distance sensor HC-SR04.

1 Like

Well, there is several reasons why US and why I havent choosen something like a weight sensor.

I don't have too much experience with Arduino.

For the Pad, I'm trying to split the system, do not use something that touches the Pad itself, a US does not need to touch it, in that way is an option (awful one). Part of the idea is skip designs that broke easily or if they broke is expensive to fix. At the same time is ideal to found a cheap way to do it, but must be functional, that is priority. This is why I skipped weight sensor, shake sensor and similars.

A Hall sensor could be a interesting option, put a magnet on the pad and when pressed to be close, I think is a little risky IIRC Hall sensors does not have too much distance to measure.

US yeah, has a lot of troubles but I was able to get some decent measures using average and handling errors, with the solutions proposed here there is even the option to use two US to double the sample rate.

Thinking in ToF or other sensors, get presision and high refresh rate would be the challange (for short distance).

If there is some recomendations I'm open to them :slight_smile:

Why not use a limit switch?

image

Each pad could have a mechanical stop to prevent excessive pushing on the arm. Also, long arm switches are available.

Or, what about FSRs?

I seriously doubt you could break a Tekscan FSR or even the less expensive ones. The Tekscan FSRs can measure up to 1,000 lbs (and probably survive even higher forces).

They are interesting options.

I have some ideas for it, sadly I'm out of USA and I can't found a similar option for high lbs, like max 22lbs which is pretty low.

I usually try to skip some "too presise" designs, this is because I want to build it with materials we can get easily, a design that requires a platform of too specific mm are hard to buildm still there is tricks for that.

About the sensors, the min weight you can easily push on a pad is 100lbs... if you jump and hit hard you achieve easily a lot more, a platform is not easy to break, even the metal ones, but after some time they start breaking, I want to be able to have an easy fix for this.

Something to limit the escessive pushing also sounds great :slight_smile:

Excluding TakScan ones... need to look on some more ideas.

Your 22 lb FSR may be capable of withstanding much greater force. Check the datasheet or talk to the vendor. The tiny Tekscan A201 "standard" force range is up to 25 lb, but as noted it is capable of handling much more.

Hi! good day, I have checked options, sadly no one has an option like the one you shows.

Avoid break the pad and sensor is improtant, if I'm able to find a sensor like that I'll check how to include it in the design.

Rn I'm thinking again how to use something similar, or a more analog approach, seems the digital ones and US can not have enough refresh rate for this.

If your FSRs are cheap enough, it may be worthwhile to buy a few and do some abusive testing.