-->
Page 1 of 2

Hooking up the HC-SR04 ultrasonic distance sensor

PostPosted: Thu Sep 15, 2016 12:22 pm
by livetv
Has anybody hooked one of these up and successfully used it with ESPbasic? Because it involves precise timing at much shorter intervals than the IO() function operates, normal polling will not work.

I have a couple ideas on how this could be done but I thought I'd ask first.

Re: Hooking up the HC-SR04 ultrasonic distance sensor

PostPosted: Thu Sep 15, 2016 7:52 pm
by Padlnpack
I have two hooked up to a Wemos Mini but I am using regular Arduino code. It will not work if the
inputs are not 5V so I am using a 4 position level shifter.

I also was still getting some unstable results so I took the average of 3 readings and compared it to a 4th.
If the result is with in 5 cm I called it a good reading. Even doing this the device can take readings in on both sensors and output the results without an obvious delay.

Re: Hooking up the HC-SR04 ultrasonic distance sensor

PostPosted: Mon Sep 19, 2016 11:12 am
by livetv
I'll try to avoid the level shifter. I can power with 5v, I think it will trigger from 3.3v, and I can voltage divide the echo pin. Think it'll work?

The problem with this sensor is that it returns a pulse of a width that has to be precisely measured to derive the distance. ESPbasic doesn't execute commands fast enough to poll a GPIO pin with the kind of resolution needed, so something different has to be used. I have two strategies I'm trying out but I wanted to know if anyone else has pulled off a trick like this. I don't think interrupts will do it.

Re: Hooking up the HC-SR04 ultrasonic distance sensor

PostPosted: Wed Sep 21, 2016 1:54 am
by livetv
Success!!

After a failed attempt at using a serial port to provide the precision timing necessary for reading the width of the echo pulse, I gave up on that idea. The theory was sound but the characteristics of the port and the truly blecherous code it required made this approach simply unmanageable.

So here's how I did it: I took a capacitor (47uf) and grounded the proper end. From the echo pin of the sensor, I ran through 3 diodes to cut the voltage to 3.2v then through a 330ohm resistor. The size of the capacitor and resistor were chosen so that I would have a relevant charge time from the echo pin while still keeping the current under control. The positive side of the capacitor is connected to the ADC pin of the ESP8266. It also connects through a resistor (180ohm) to a GPIO pin (#4 in my case because it was neither pulled up nor down by my development board). Another GPIO pin (#12 here because my board has an LED on that one) connects to the trigger pin on the sensor and with 5v and ground to the sensor, the circuit is complete.

The program (which I'll post later) starts by outputting a 0 on GPIO4 to drain the capacitor, and a 0 on GPIO12 to hold the trigger line low. These are left that way most of the time. To read a distance, I release GPIO4 by reading a value from it, placing it in input mode. This will allow the sensor to have free reign of the capacitor without interference. The I pulse the trigger pin by outputting a 1 then a 0 from GPIO12. I delay 30 milliseconds which gives the sensor time to do its work and return a high pulse of a width representing the distance. When the echo pin goes high, current can flow through the diodes at a 3.2v max. Since current is limited, the capacitor charges for as long as the pulse is present. The wider the pulse, the more the capacitor charges. Once the pulse goes low and the 30ms delay has expired, I read the ADC to get a voltage level in the capacitor. Then I discharge the capacitor by grounding GPIO4. This is not instantaneous and I have to let some time pass before I can assume the capacitor is discharged (as it goes through a current limiting resistor). Experimentally, about 100ms seems to work but as a general rule I don't think I'll poll much faster than about 5 times a second.

How well does it work? Pretty good. I wrote some code to do simple statistical analysis of the performance because the sensor does return some erroneous readings, usually due to longer distances. Still, it's pretty accurate from about 2 inches to about 2 feet, with few errors happening. As I go under 2 inches, there is distortion in the readings due to the physical separation of the sender and receiver, causing a longer triangular path. As I approach 4 feet, I get about 20% errors in my readings and the ADC saturates at 4 feet. My calculations say I should be able to go further than that distance but I think my 5v is a little bit over that (allowing the capacitor to charge to more than the ADC can measure). That will also cause it to charge too quickly, shortening the distance I can sense.

Substituting a 560ohm resistor for the 33ohm one extends my range to about 6 feet before I saturate the ADC. However, error rates increase to well above 50%. This is a limitation of the sensor. I'd call it good up to 4 feet if you want to do simplistic error checking and if you want to go to 6 feet you should add some simple statistical analysis to detect and discard errors. I'll post later about how to do this.

I will tweak this a little to try and get better performance but if I was to redesign it, I'd go with a slightly larger capacitor and larger resistors. Know that some good calculations do matter to get you in the right ballpark with both charge times and current limiting. This is why I started with 50uf for the capacitor, deriving that from current limiting resistors and necessary charge times.

The last thing I have to do is to make precise distance and ADC reading correlations and build a table so that I can translate from ADC readings to fairly precise distances. So far though, it looks like this can get to within a 1/3 inch of resolution over much of the range. Didn't expect that.