HC-SR04 and FreeBSD

Patrick Tracanelli eksffa at freebsdbrasil.com.br
Sat Aug 23 21:00:31 UTC 2014

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[9];
  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;

> Probably the echo output doesn't provide enough current to drive the
> LED (LEDs are driven by current and not by voltage).
> Be aware that you also need to limit the voltage on the sensor output
> to be within the 3.3V limit:
> https://www.modmypi.com/blog/hc-sr04-ultrasonic-range-sensor-on-the-raspberry-pi
> (you can can follow the explanation and the schematics)
>> so I'd better use a multimeter for sure...
> You'd be better with a logic analyser, this kind of short pulses can't
> be seen on a multimeter.
>> loop1:
>> while true ; do
>>  gpioctl -t 3; sleep .200; gpioctl -t 3
>>  #gpioctl 3
>>  sleep 1
>> done
>> loop2:
>> while true ; do
>>  gpioctl 2
>>  sleep .500
>> done
> The sensor output pulse will be active for a period of 116us ~ 23200us
> (2cm ~ 400cm, given the formula from data sheet: cm = us / 58).
> I'm not sure you can reliably measure such short periods from userland
> (but as the RPi link says it works... let's try it).
> You can try to remove the LED from the echo pin (to reduce its load)
> and reduce the sleep time on loop2 to see if you can read the sensor
> output.
> I'll see if i can get my hands on HC-SR04 so i can try it out.
> Luiz
> _______________________________________________
> freebsd-arm at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-arm
> To unsubscribe, send any mail to "freebsd-arm-unsubscribe at freebsd.org"

More information about the freebsd-arm mailing list