HC-SR04 and FreeBSD
eksffa at freebsdbrasil.com.br
Mon Aug 25 19:58:04 UTC 2014
On 24/08/2014, at 19:29, Evandro Nunes <evandronunes12 at gmail.com> wrote:
> On Sat, Aug 23, 2014 at 5:51 PM, Patrick Tracanelli <eksffa at freebsdbrasil.com.br> wrote:
> On 08/22/14 16:55, Luiz Otavio O Souza wrote:
> > On 22 August 2014 00:43, Evandro Nunes wrote:
> >> On Thu, Aug 21, 2014 at 4:13 PM, Rui Paulo wrote:
> >>> You can use an led instead of a multimeter. The point I'm trying to make
> >>> is to make sure the gpio number really corresponds to that port number.
> >> still no success, but just an update...
> >> ok I added two led:
> >> pin 02: 0 gpio_2<IN> ===> echo (orange LED)
> >> pin 03: 0 gpio_3<OUT> ===> trigger (blue LED)
> >> pin 49: 0 gpio_49<IN> ===> previous echo
> >> and I have the two simple loops below.
> >> when I run loop1, BLUE LED blinks every second;
> >> when I run loop2 while loop1 stills run, ORANGE LED won't blink, and loop2
> >> value still shows 0 value
> >> if I "gpioctl -c 2 OUT ; gpioctl -t 2", ORANGE LED will light, confirming
> >> LED is OK; thoses leds will light with 2-5v input... however I have no idea
> >> if the sonar output will range 2-5 or if it will be below 2 (i tried adding
> >> my hand very close and far away from the sensor but led was never lit)
> As far as I know, for this specific ultrasonic sensor, you are missing
> to set the echo GPIO pin to high. This sonar sensor will bring it back
> to 0 when the triggered sound get back to the sensor (round-trip).
> So the correct sequence should be, in a loop:
> 1 - Set echo pin to HIGH
> 2 - Trigger the sensor for 10us (it means your 100ms is more than you
> need, but no, it won’t cause a problem)
> 3 - Wait until echo in is LOW
> When the sound come back to sensor, the device will LOW the GPIO pin again.
> So what you have to do is to measure how long it took from step 1 to 3.
> This is your duration. And it means a sound-speed duration from 0 (your
> transmitter) until the object and back. We are talking about a 58.22
> sound speed.
> Therefore, what you want is to determine the duration of a pulse with
> microsecond accuracy, to measure the duration of HIGH or LOW pulse on a pin.
> How to do this? I don’t know how you can get this with in the command
> line. First of, date(1) won’t display the time with enough precision. I
> believe date “+%s” is the best precision you have and it’s epoch (1 full
> second, not a fraction).
> You can use some code, however, to get a usec precision “now”. Example
> code below I have used in the past will do the trick.
> But how will you “wait” from 1 to 0 on your GPIO echo pin, on a shell
> script, without using almost all CPU you’ve got in your BeagleBone (and
> this is not much CPU), I have no idea.
> I would test some loop similar to this:
> gpioctl -c 2 IN
> gpioctl -c 3 OUT
> gpioctl 3 0
> gpioctl 2 0
> while true ; do
> gpioctl 3 1 ; sleep .10; gpioctl 3 0 # trigger
> gpioctl 2 1 # set echo HIGH
> inicio=$(/root/date-precisao) # what time is it?
> while [ $(gpioctl 2 | tail -1) -gt 0 ] ; do
> echo "...” #does nothing, because the pin is still HIGH
> fim=$(/root/date-precisao) # pin is now LOW, what time is it?
> dura=$(( $fim - $inicio )) # echo duration (HIGH to LOW usec duration)
> dura2=$(( $dura * 10 )) # sh doesn’t like X.Y precision, make it integer
> dist=$(( $dura2 / 582 )) # 58.22 should be the number but 58.2 is OK
> echo "Distance: $dist” # this is your not much precise distance
> sleep 1
> The above code is untested, I just wrote it on this e-mail. Your CPU
> will be insanely high because this is not something that should be done
> on shell script, and therefore, your distance precision won’t be
> reliable. However, you will have a relative reference.
> Meaning, add an object 10cm from the sensor and you will have a number.
> Add an object 100cm from the and you will have another number, hopefully
> a 10 times higher number — maybe 9, maybe 12, expect imprecision caused
> by high CPU usage and a big latency on shell commands getting executed
> to do a math that should be done somehow else.
> Good luck with your experiments.
> FreeBSD/arm with a BeagleBone is a HELL of a FUN ]:-)
> * Dummy code to print date with usec precision
> * Patrick Tracanelli <eksffa at freebsdbrasil.com.br>
> * clang date-precisao.c -o date-precisao (should cleanly compile)
> #include <time.h>
> #include <stdio.h>
> #include <sys/time.h>
> int main(void)
> struct timeval agora;
> struct tm *t;
> char time;
> int ret;
> ret = gettimeofday(&agora, 0);
> t = localtime(&agora.tv_sec);
> ret = strftime(time, sizeof(time), "%H%M%S", t);
> // xunxo 999 pq as vezes em armv6 fica zerado...
> printf("999%s%06ld\n", time, agora.tv_usec);
> return 0;
> hey patrick
> yea somehow it made some sense now
> first test was your afirmation that sensor will set pin value to zero, it really does as soon as I set to 1, sensor will set it to 0 again
> i really expected to get a value on echo pin other than 0 or 1 :(
> i run your shell script and while cpu was high, it was not exausting the board, about 20% cpu comsuption running this loop
> when i add an object say 5cm from the sensor I get values that mean nothing, around 2201, 2300
> when i add the object at 10cm i get values around 48000-49000
> when i add the object at 1 meter i get values around 200000-230000
> so yes the values mean nothing but they make some relative sense, with a lot of imprecision for sure, sometimes deviation is upper some times lower
> so it means we need a library in freebsd for electronics, so we can have functions like arduino's pulseIn which seem to do just that, wait for a pin status and return how long it took until that value was received, the kind of libs we see out there in nodejs, python...
> now that you made clear how the sensor works, i will try to write something to do that more precisely instead of using a shell script
> thank you all
Yes, that’s it.
What you wanna do is to measure how long HIGH takes.
I just made a better test so you can actually "see" the sensor working. Run this more simple loop:
gpioctl -c 2 IN
gpioctl -c 3 OUT
gpioctl 3 0
while true ; do
gpioctl 3 1 ; sleep .10; gpioctl 3 0
while [ $(gpioctl 2 | tail -1) -gt 0 ] ; do
echo "..." #nada
On a second shell, run this horrible cpu consuming loop:
sh -c "while true ; do /root/date-precisao && gpioctl 2 ; done"
And check for the date when PIN 2 becomes high and later when it becomes low again.
Speed of sound is 340 meters per second. Since this sensor measures round-trip, you shall divide by two, so here is a simple measurement by hand:
An object added 1 meter from sensor:
(eksffa at localhost):~% echo "((999013225427212-999013225364525)/340)/2" | bc
An object added 2 meters from sensor:
(eksffa at localhost):~% echo "((999013003943898-999013003811223)/340)/2" | bc
So, now you have a better precision, but insanely high CPU usage due to the second loop.
Yes, you are right, I personally agree some library with basic electronic functions would be very valuable to FreeBSD.
Good to read you will try to write something, I believe Rui Paulo's library is a good start to hack, reading GPIO device, detecting when a PIN is HIGH and measuring the time until it becomes LOW is probably a good starter challenge ;-)
One sensor I am trying to make work is DHT11 temperature and humidity, according to datasheet on section 7, this "single-wire bi-directional" sensor seems to return a 32bit value which shall be calculated in 4 octets.
This is a kind of sensor that deserves a library for sure (and FreeBSD deserves to have such a library) but hopefully not the kind of Arduino library which is device specific. A more generic library that reads a selectable 8/16/32bit value and returns it in different formats (decimal, hex, ...) would do the job for this sensor as well as other single-wire pin sensors.
FreeBSD Brasil LTDA.
Tel.: (31) 3516-0800
316601 at sip.freebsdbrasil.com.br
"Long live Hanin Elias, Kim Deal!"
More information about the freebsd-arm