Skip to content

inductivekickback/hc-sr04

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 

Repository files navigation

This is a Zephyr RTOS driver for the HC-SR04 Ultrasonic Ranging Module. It conforms to the Sensor subsystem API and was built from the v1.4.0 tag of the nRF Connect SDK (NCS).

About the sensor

The HC-SR04 ranging module is an inexpensive sensor for measuring distance in a variety of applications. It is relatively easy to use:

  1. Set the TRIG pin high for at least 10us
  2. Wait for the ECHO pin to go high and then measure how long it remains high
  3. Convert the measured time to meters using the speed of sound

Although the HC-SR04 is a 5V device, its TRIG pin works fine when driven at 3V and it's trivial to use a couple of resistors as a voltage divider on the ECHO pin. The following configuration works fine with an nRF52840 DK:

The TRIG (top, 11us) and ECHO (bottom, 9.3ms) pulses look like this when the sensor is pointed at a ceiling that is ~1.5M away:

If the sensor can't get a valid measurement -- because the target is too close or too far away -- then the ECHO pulse is 128.6ms long followed by a second 6us pulse about 145us later. This error pulse can't be truncated so when it occurs it effectively reduces the sensor's 40Hz working rate.

Perhaps the biggest consideration when using these devices is that performing measurements using multiple HC-SR04 devices simultaneously can cause erroneous results because the individual sensors can't differentiate their own echo pulses from the pulses produced by the other devices.

About the driver

The driver assumes --and uses a mutex to enforce-- that only one HC-SR04 will be actively measuring at any given time. There are two variants of the driver:

  • HC_SR04 uses a pin-change interrupt to measure by calling k_cycle_get_32 in rising-edge and falling-edge interrupts.
    • PRO: Should work reasonably well on most platforms
    • PRO: Uses the standard GPIO driver
    • CON: Any latency when servicing the pin-change interrupt will affect the measurement
  • HC_SR04_NRFX uses GPIOTE, TIMER, PPI, and EGU peripherals to measure using a hardware timer and then triggers an interrupt after completion.
    • PRO: Only one CPU interrupt per measurement
    • PRO: Measurement is not affected if interrupt is delayed
    • CON: Uses nRF52-specific hardware peripherals
    • CON: Uses GPIOTE driver --but not the GPIOTE interrupt-- so it's not entirely compatible with standard GPIO driver

Using the HC_SR04 variant

This is an example DT entry in the project's local overlay (e.g. "nrf52840dk_nrf52840.overlay") when using HC_SR04:

us0: hc-sr04 {
    compatible = "elecfreaks,hc-sr04";
    label = "HC-SR04_0";
    trig-gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>;
    echo-gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>;
    status = "okay";
};

Then add the following to prj.conf:

CONFIG_SENSOR=y
CONFIG_GPIO=y
CONFIG_HC_SR04=y

Using the HC_SR04_NRFX variant

The HC_SR04_NRFX version is similar but uses NRFX-style pin numbers instead:

us0_nrfx: hc-sr04_nrfx {
    compatible = "elecfreaks,hc-sr04_nrfx";
    label = "HC-SR04_NRFX_0";
    trig-pin = <26>;
    echo-pin = <27>;
    status = "okay";
};

Device tree definitions for SoCs like the nRF52840 don't always contain EGU instances. They can be added to the project's overlay by using the memory addresses from the Product Specification:

/ {
    soc {

        egu0: egu@40014000 {
                compatible = "nordic,nrf-egu";
                reg = <0x40014000 0x1000>;
                interrupts = <20 2>;
                status = "okay";
        };

        egu1: egu@40015000 {
                compatible = "nordic,nrf-egu";
                reg = <0x40015000 0x1000>;
                interrupts = <21 2>;
                status = "okay";
        };

        egu2: egu@40016000 {
                compatible = "nordic,nrf-egu";
                reg = <0x40016000 0x1000>;
                interrupts = <22 2>;
                status = "okay";
        };

        egu3: egu@40017000 {
                compatible = "nordic,nrf-egu";
                reg = <0x40017000 0x1000>;
                interrupts = <23 2>;
                status = "okay";
        };

        egu4: egu@40018000 {
                compatible = "nordic,nrf-egu";
                reg = <0x40018000 0x1000>;
                interrupts = <24 2>;
                status = "okay";
        };

        egu5: egu@40019000 {
                compatible = "nordic,nrf-egu";
                reg = <0x40019000 0x1000>;
                interrupts = <25 2>;
                status = "okay";
        };
    };
};

Then add the following to prj.conf:

CONFIG_SENSOR=y
CONFIG_GPIO=n
CONFIG_HC_SR04_NRFX=y

The HC_SR04_NRFX Kconfig allows the user to select which TIMER and EGU instances to use.

NOTE: the project will compile normally if CONFIG_GPIO is enabled but unexpected side effects will happen if the native GPIO driver is used to configure pin change interrupts -- the NRFX GPIOTE driver should be used instead.

Releases

No releases published

Packages

No packages published