Talking to Ultrasonic Distance Sensor HC-SR04 using nRF51822

image description

Communicating with Ultrasonic Distance Sensor HC-SR04 using nRF51-DK (nRF51822/nRF51422), and transmitting measured distance over BLE UART.

http://electronut.in/nrf51-hcsr04/

  • hello sir,

    I followed the same steps as explained by you to interface Hc SR 04. The only difference in my case is I am using nRF52832 and want to print the distance on serial monitor. But couldnot able to get it. Please help me. This is my code for refrence:-

    /**
     * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    /** @file
     * @defgroup uart_example_main main.c
     * @{
     * @ingroup uart_example
     * @brief UART Example Application main file.
     *
     * This file contains the source code for a sample application using UART.
     *
     */
    
    #include <stdbool.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <math.h> 
    #include "app_uart.h"
    #include "app_error.h"
    #include "nrf_delay.h"
    #include "nrf.h"
    #include "bsp.h"
    #if defined (UART_PRESENT)
    #include "nrf_uart.h"
    #endif
    #if defined (UARTE_PRESENT)
    #include "nrf_uarte.h"
    #endif
    
    
    //#define ENABLE_LOOPBACK_TEST  /**< if defined, then this example will be a loopback test, which means that TX should be connected to RX to get data loopback. */
    
    #define MAX_TEST_DATA_BYTES     (15U)                /**< max number of test bytes to be used for tx and rx. */
    #define UART_TX_BUF_SIZE 256                         /**< UART TX buffer size. */
    #define UART_RX_BUF_SIZE 256                         /**< UART RX buffer size. */
    
    //////////////////////////////////////////////////////////////////////////////////////////////
    
    void gpio_toggle(void);
    void trig_pulse(void);
    float compute_distance(void);
    
    #define pinTrig 5
    #define pinEcho 7
    #define InPin 1
    #define OutPin 0
    
    float countToUs ; 
    float distance ; 
    uint32_t tCount ;
    
    //////////////////////////////////////////////////////////////////////////////////////////////
    
    void uart_error_handle(app_uart_evt_t * p_event)
    {
        if (p_event->evt_type == APP_UART_COMMUNICATION_ERROR)
        {
            APP_ERROR_HANDLER(p_event->data.error_communication);
        }
        else if (p_event->evt_type == APP_UART_FIFO_ERROR)
        {
            APP_ERROR_HANDLER(p_event->data.error_code);
        }
    }
    
    
    #ifdef ENABLE_LOOPBACK_TEST
    /* Use flow control in loopback test. */
    #define UART_HWFC APP_UART_FLOW_CONTROL_ENABLED
    
    /** @brief Function for setting the @ref ERROR_PIN high, and then enter an infinite loop.
     */
    static void show_error(void)
    {
    
        bsp_board_leds_on();
        while (true)
        {
            // Do nothing.
        }
    }
    
    
    /** @brief Function for testing UART loop back.
     *  @details Transmitts one character at a time to check if the data received from the loopback is same as the transmitted data.
     *  @note  @ref TX_PIN_NUMBER must be connected to @ref RX_PIN_NUMBER)
     */
    static void uart_loopback_test()
    {
        uint8_t * tx_data = (uint8_t *)("\r\nLOOPBACK_TEST\r\n");
        uint8_t   rx_data;
    
        // Start sending one byte and see if you get the same
        for (uint32_t i = 0; i < MAX_TEST_DATA_BYTES; i++)
        {
            uint32_t err_code;
            while (app_uart_put(tx_data[i]) != NRF_SUCCESS);
    
            nrf_delay_ms(10);
            err_code = app_uart_get(&rx_data);
    
            if ((rx_data != tx_data[i]) || (err_code != NRF_SUCCESS))
            {
                show_error();
            }
        }
        return;
    }
    #else
    /* When UART is used for communication with the host do not use flow control.*/
    #define UART_HWFC APP_UART_FLOW_CONTROL_DISABLED
    #endif
    
    
    ////////////////////////////////////////////////////////////////////////////////////////////
    
    void gpio_toggle(void)
    {
      NRF_GPIO->OUT = (1 << pinTrig) ;
      nrf_delay_ms(2000);
      NRF_GPIO->OUT = (0 << pinTrig) ;
      nrf_delay_ms(2000);
    }
    
    void trig_pulse(void)
    {
     // send 12us trigger pulse
    //    _
    // __| |__
    nrf_gpio_pin_clear(pinTrig);
    nrf_delay_us(20);
    nrf_gpio_pin_set(pinTrig);
    nrf_delay_us(12);
    nrf_gpio_pin_clear(pinTrig);
    nrf_delay_us(20);
    }
    
    
    // set up and start Timer1
    void start_timer(void)
    {   
      NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;  
      NRF_TIMER1->TASKS_CLEAR = 1;
      // set prescalar n
      // f = 16 MHz / 2^(n)
      uint8_t prescaler = 0;
        NRF_TIMER1->PRESCALER = prescaler;
        NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
    
      // 16 MHz clock generates timer tick every 1/(16000000) s = 62.5 nano s
      // With compare enabled, the interrupt is fired every: 62.5 * comp1 nano s
      // = 0.0625*comp1 micro seconds
      // multiply this by 2^(prescalar)
    
      uint16_t comp1 = 500;
      // set compare
        NRF_TIMER1->CC[1] = comp1;
    
      // set conversion factor
      countToUs = 0.0625*comp1*(1 << prescaler);
    
      printf("timer tick = %f us\n", countToUs);
    
      // enable compare 1
        NRF_TIMER1->INTENSET =
        (TIMER_INTENSET_COMPARE1_Enabled << TIMER_INTENSET_COMPARE1_Pos);
    
      // use the shorts register to clear compare 1
      NRF_TIMER1->SHORTS = (TIMER_SHORTS_COMPARE1_CLEAR_Enabled <<
                            TIMER_SHORTS_COMPARE1_CLEAR_Pos);
    
      // enable IRQ
      NVIC_EnableIRQ(TIMER1_IRQn);
    
      // start timer
      NRF_TIMER1->TASKS_START = 1;
    }
    
    // Timer 1 IRQ handler
    // just increment count
    void TIMER1_IRQHandler(void)
    {
        if (NRF_TIMER1->EVENTS_COMPARE[1] &&
          NRF_TIMER1->INTENSET & TIMER_INTENSET_COMPARE1_Msk) {
    
        // clear compare register event
        NRF_TIMER1->EVENTS_COMPARE[1] = 0;
    
        tCount++;
      }
    }
    
    
    
    // Reverses a string 'str' of length 'len' 
    void reverse(char* str, int len) 
    { 
        int i = 0, j = len - 1, temp; 
        while (i < j) { 
            temp = str[i]; 
            str[i] = str[j]; 
            str[j] = temp; 
            i++; 
            j--; 
        } 
    } 
      
    // Converts a given integer x to string str[].  
    // d is the number of digits required in the output.  
    // If d is more than the number of digits in x,  
    // then 0s are added at the beginning. 
    int intToStr(int x, char str[], int d) 
    { 
        int i = 0; 
        while (x) { 
            str[i++] = (x % 10) + '0'; 
            x = x / 10; 
        } 
      
        // If number of digits required is more, then 
        // add 0s at the beginning 
        while (i < d) 
            str[i++] = '0'; 
      
        reverse(str, i); 
        str[i] = '\0'; 
        return i; 
    } 
      
    // Converts a floating-point/double number to a string. 
    void ftoa(float n, char* res, int afterpoint) 
    { 
        // Extract integer part 
        int ipart = (int)n; 
      
        // Extract floating part 
        float fpart = n - (float)ipart; 
      
        // convert integer part to string 
        int i = intToStr(ipart, res, 0); 
      
        // check for display option after point 
        if (afterpoint != 0) { 
            res[i] = '.'; // add dot 
      
            // Get the value of fraction part upto given no. 
            // of points after dot. The third parameter  
            // is needed to handle cases like 233.007 
            fpart = fpart * pow(10, afterpoint); 
      
            intToStr((int)fpart, res + i + 1, afterpoint); 
        } 
    } 
    
    /*
    static void gpio_init(void)
    {
       ret_code_t err_code ;
       
       err_code = nrf_drv_gpiote_init() ;
       APP_ERROR_CHECK(err_code) ;
    
       nrf_drv_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_SIMPLE(false) ; 
    
       err_code = nrf_drv_gpiote_out_init(DEBUG_PIN_OUT , &out_config) ;
       APP_ERROR_CHECK(err_code) ;
    
       nrf_drv_gpiote_out_set(DEBUG_PIN_OUT) ; 
    
       nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
       in_config.pull = NRF_GPIO_PIN_PULLUP ;
    
       err_code = nrf_drv_gpiote_in_init(DEBUG_PIN_IN , &in_config , in_pin_handler) ; 
        APP_ERROR_CHECK(err_code) ;
    
    
    
    }
    */
    ////////////////////////////////////////////////////////////////////////////////////////////
    
    /**
     * @brief Function for main application entry.
     */
    int main(void)
    {
    /*  //  bsp_board_init(BSP_INIT_LEDS);
       nrf_gpio_cfg_output(pinTrig);   // pin no. 5
       nrf_gpio_cfg_output(OutPin);    // pin no. 0
       nrf_gpio_cfg_input(InPin , BUTTON_PULL) ;  // pin no. 1
        
     //   NRF_GPIO->DIRSET = 0x00000020 ;
        nrf_gpio_pin_clear(pinTrig);
        nrf_gpio_pin_clear(OutPin);
       while(true)
       {
         gpio_toggle() ; 
        while(!nrf_gpio_pin_read(InPin))
         {
          nrf_gpio_pin_set(OutPin);
         }
       }
    
    */
    
        uint32_t err_code;
    
        bsp_board_init(BSP_INIT_LEDS);
    
        const app_uart_comm_params_t comm_params =
          {
              RX_PIN_NUMBER,
              TX_PIN_NUMBER,
              RTS_PIN_NUMBER,
              CTS_PIN_NUMBER,
              UART_HWFC,
              false,
    #if defined (UART_PRESENT)
              NRF_UART_BAUDRATE_115200
    #else
              NRF_UARTE_BAUDRATE_115200
    #endif
          };
    
        APP_UART_FIFO_INIT(&comm_params,
                             UART_RX_BUF_SIZE,
                             UART_TX_BUF_SIZE,
                             uart_error_handle,
                             APP_IRQ_PRIORITY_LOWEST,
                             err_code);
    
        APP_ERROR_CHECK(err_code);
    
    #ifndef ENABLE_LOOPBACK_TEST
        printf("\r\nUART example started.\r\n");
       
        distance = 0 ;
        nrf_gpio_cfg_output(pinTrig);
        nrf_gpio_cfg_input(pinEcho , BUTTON_PULL) ;
        nrf_gpio_pin_clear(pinTrig);
        printf("Interfacing of HC-SR-04 with nRF52:-") ; 
    
       // char res[20]; 
        char test[20];
      //  float n = 233.007; 
        
       
       
        while(true)
        {
          printf("inside loop");
          trig_pulse() ;
          printf("After trig pulse");
        //  printf("\"res=%s\"\n", res);
        //  nrf_delay_ms(1000);
        
           // listen for echo and time it
      //       ____________
      // _____|            |___
    
      // wait till Echo pin goes high
      while(!nrf_gpio_pin_read(pinEcho));
      // reset counter
      tCount = 0;
      // wait till Echo pin goes low
      while(nrf_gpio_pin_read(pinEcho));
    
      // calculate duration in us
      float duration = countToUs*tCount;
    
      // dist = duration * speed of sound * 1/2
      // dist in cm = duration in us * 10^-6 * 340.29 * 100 * 1/2
      float distance = duration*0.017;
      ftoa(distance, test, 4); 
      printf("\"test=%s\"\n", test);
      nrf_delay_ms(1000);
    
      }
    
    
    
    
        while (true)
        {
           
            uint8_t cr;
            while (app_uart_get(&cr) != NRF_SUCCESS);
            while (app_uart_put(cr) != NRF_SUCCESS);
    
            if (cr == 'q' || cr == 'Q')
            {
                printf(" \r\nExit!\r\n");
    
                while (true)
                {
                    // Do nothing.
                }
            }
        }
    #else
    
        // This part of the example is just for testing the loopback .
        while (true)
        {
            uart_loopback_test();
        }
    #endif
    }
    
    
    /** @} */
    

  • Nice Article. Thank you very much for sharing this awesome post with us. Keep Posting.