HC-SR04 using RMT - very fast

ESP_Sprite
Posts: 9757
Joined: Thu Nov 26, 2015 4:08 am

Re: HC-SR04 using RMT - very fast

Postby ESP_Sprite » Thu Jun 20, 2019 5:05 am

It possibly needs

Code: Select all

 rmt_config_t rmt_rx;
changed into

Code: Select all

 rmt_config_t rmt_rx={0};
.

uberthoth
Posts: 6
Joined: Tue Jun 11, 2019 4:06 am

Re: HC-SR04 using RMT - very fast

Postby uberthoth » Sat Jun 22, 2019 4:14 pm

I tried making the suggested change, which didn't seem to work, so I also changed `rmt_tx` as well. And I also tried changing the double to a float (as I hear there are issues with double math on the esp32), and changed out the 1000 * 1000 * 2 [which I know should taken care of by the compiler but it's still not working so I'll try anything]). I still get an error on this line:

Code: Select all

distance = 340.29 * ITEM_DURATION(item->duration0) / (  2000000 ); // distance in meters
here is the changed code:

Code: Select all

#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "esp_err.h"
#include "esp_log.h"
#include "driver/rmt.h"
#include "driver/periph_ctrl.h"
#include "soc/rmt_reg.h"
#include <sys/time.h>
#include "driver/gpio.h"

#define RMT_TX_CHANNEL 1 /* RMT channel for transmitter */
#define RMT_TX_GPIO_NUM PIN_TRIGGER /* GPIO number for transmitter signal */
#define RMT_RX_CHANNEL 0 /* RMT channel for receiver */
#define RMT_RX_GPIO_NUM PIN_ECHO /* GPIO number for receiver */
#define RMT_CLK_DIV 100 /* RMT counter clock divider */
#define RMT_TX_CARRIER_EN 0 /* Disable carrier */
#define rmt_item32_tIMEOUT_US 9500 /*!< RMT receiver timeout value(us) */

#define RMT_TICK_10_US (80000000/RMT_CLK_DIV/100000) /* RMT counter value for 10 us.(Source clock is APB clock) */
#define ITEM_DURATION(d) ((d & 0x7fff)*10/RMT_TICK_10_US)

#define PIN_TRIGGER 18
#define PIN_ECHO 19

static void HCSR04_tx_init()
{
rmt_config_t rmt_tx={0};
rmt_tx.channel = RMT_TX_CHANNEL;
rmt_tx.gpio_num = RMT_TX_GPIO_NUM;
rmt_tx.mem_block_num = 1;
rmt_tx.clk_div = RMT_CLK_DIV;
rmt_tx.tx_config.loop_en = false;
rmt_tx.tx_config.carrier_duty_percent = 50;
rmt_tx.tx_config.carrier_freq_hz = 3000;
rmt_tx.tx_config.carrier_level = 1;
rmt_tx.tx_config.carrier_en = RMT_TX_CARRIER_EN;
rmt_tx.tx_config.idle_level = 0;
rmt_tx.tx_config.idle_output_en = true;
rmt_tx.rmt_mode = 0;
rmt_config(&rmt_tx);
rmt_driver_install(rmt_tx.channel, 0, 0);
}

static void HCSR04_rx_init()
{
rmt_config_t rmt_rx={0};
rmt_rx.channel = RMT_RX_CHANNEL;
rmt_rx.gpio_num = RMT_RX_GPIO_NUM;
rmt_rx.clk_div = RMT_CLK_DIV;
rmt_rx.mem_block_num = 1;
rmt_rx.rmt_mode = RMT_MODE_RX;
rmt_rx.rx_config.filter_en = true;
rmt_rx.rx_config.filter_ticks_thresh = 100;
rmt_rx.rx_config.idle_threshold = rmt_item32_tIMEOUT_US / 10 * (RMT_TICK_10_US);
rmt_config(&rmt_rx);
rmt_driver_install(rmt_rx.channel, 1000, 0);
}

void app_main()
{
HCSR04_tx_init();
HCSR04_rx_init();

rmt_item32_t item;
item.level0 = 1;
item.duration0 = RMT_TICK_10_US;
item.level1 = 0;
item.duration1 = RMT_TICK_10_US; // for one pulse this doesn't matter

size_t rx_size = 0;
RingbufHandle_t rb = NULL;
rmt_get_ringbuf_handle(RMT_RX_CHANNEL, &rb);
rmt_rx_start(RMT_RX_CHANNEL, 1);

//double distance = 0;
float distance = 0;

for(;;)
{
rmt_write_items(RMT_TX_CHANNEL, &item, 1, true);
rmt_wait_tx_done(RMT_TX_CHANNEL, portMAX_DELAY);

rmt_item32_t* item = (rmt_item32_t*)xRingbufferReceive(rb, &rx_size, 1000);
//distance = 340.29 * ITEM_DURATION(item->duration0) / (1000 * 1000 * 2); // distance in meters
distance = 340.29 * ITEM_DURATION(item->duration0) / (  2000000 ); // distance in meters
printf("Distance is %f cm\n", distance * 100); // distance in centimeters

vRingbufferReturnItem(rb, (void*) item);
vTaskDelay(200 / portTICK_PERIOD_MS);
}

}
and full output:

Code: Select all

I (0) cpu_start: Starting scheduler on APP CPU.
Guru Meditation Error: Core  0 panic'ed (LoadProhibited). Exception was unhandled.
Core 0 register dump:
PC      : 0x400d248d  PS      : 0x00060530  A0      : 0x800d0b09  A1      : 0x3ffb4d10  
0x400d248d: app_main at /home/thoth/git/A9thinker/GPRS_C_SDK/tank_gauge/sr04test/main/bstx03_XiuxinESP32.c:89 (discriminator 1)

A2      : 0x00000000  A3      : 0x00000001  A4      : 0x00000001  A5      : 0x00000001  
A6      : 0x00060021  A7      : 0x00000000  A8      : 0x800d248b  A9      : 0x3ffb4cd0  
A10     : 0x00000000  A11     : 0x3ffb4d14  A12     : 0x000003e8  A13     : 0x00000001  
A14     : 0x00000040  A15     : 0x3ffb699c  SAR     : 0x00000020  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000000  LBEG    : 0x4000c46c  LEND    : 0x4000c477  LCOUNT  : 0x00000000  

ELF file SHA256: 3557e67f93dae1bed9df867b800bd1c138d6258b7677ba69e6fbc3003389d3c1

Backtrace: 0x400d248d:0x3ffb4d10 0x400d0b06:0x3ffb4d40 0x40085625:0x3ffb4d60
0x400d248d: app_main at /home/thoth/git/A9thinker/GPRS_C_SDK/tank_gauge/sr04test/main/bstx03_XiuxinESP32.c:89 (discriminator 1)

0x400d0b06: main_task at /home/thoth/esp/esp-idf/components/esp32/cpu_start.c:527

0x40085625: vPortTaskWrapper at /home/thoth/esp/esp-idf/components/freertos/port.c:403


Rebooting...


uberthoth
Posts: 6
Joined: Tue Jun 11, 2019 4:06 am

Re: HC-SR04 using RMT - very fast

Postby uberthoth » Tue Jun 25, 2019 3:09 pm

I got this working by adding the if clause on item:

Code: Select all

#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "esp_err.h"
#include "esp_log.h"
#include "driver/rmt.h"
#include "driver/periph_ctrl.h"
#include "soc/rmt_reg.h"
#include <sys/time.h>
#include "driver/gpio.h"

#define RMT_TX_CHANNEL 1 /* RMT channel for transmitter */
#define RMT_TX_GPIO_NUM PIN_TRIGGER /* GPIO number for transmitter signal */
#define RMT_RX_CHANNEL 0 /* RMT channel for receiver */
#define RMT_RX_GPIO_NUM PIN_ECHO /* GPIO number for receiver */
#define RMT_CLK_DIV 100 /* RMT counter clock divider */
#define RMT_TX_CARRIER_EN 0 /* Disable carrier */
#define rmt_item32_tIMEOUT_US 9500 /*!< RMT receiver timeout value(us) */

#define RMT_TICK_10_US (80000000/RMT_CLK_DIV/100000) /* RMT counter value for 10 us.(Source clock is APB clock) */
#define ITEM_DURATION(d) ((d & 0x7fff)*10/RMT_TICK_10_US)

#define PIN_TRIGGER 18
#define PIN_ECHO 19

static const char* NEC_TAG = "NEC";

static void HCSR04_tx_init()
{
rmt_config_t rmt_tx={0};
rmt_tx.channel = RMT_TX_CHANNEL;
rmt_tx.gpio_num = RMT_TX_GPIO_NUM;
rmt_tx.mem_block_num = 1;
rmt_tx.clk_div = RMT_CLK_DIV;
rmt_tx.tx_config.loop_en = false;
rmt_tx.tx_config.carrier_duty_percent = 50;
rmt_tx.tx_config.carrier_freq_hz = 3000;
rmt_tx.tx_config.carrier_level = 1;
rmt_tx.tx_config.carrier_en = RMT_TX_CARRIER_EN;
rmt_tx.tx_config.idle_level = 0;
rmt_tx.tx_config.idle_output_en = true;
rmt_tx.rmt_mode = 0;
rmt_config(&rmt_tx);
rmt_driver_install(rmt_tx.channel, 0, 0);
}

static void HCSR04_rx_init()
{
rmt_config_t rmt_rx={0};
rmt_rx.channel = RMT_RX_CHANNEL;
rmt_rx.gpio_num = RMT_RX_GPIO_NUM;
rmt_rx.clk_div = RMT_CLK_DIV;
rmt_rx.mem_block_num = 1;
rmt_rx.rmt_mode = RMT_MODE_RX;
rmt_rx.rx_config.filter_en = true;
rmt_rx.rx_config.filter_ticks_thresh = 100;
rmt_rx.rx_config.idle_threshold = rmt_item32_tIMEOUT_US / 10 * (RMT_TICK_10_US);
rmt_config(&rmt_rx);
rmt_driver_install(rmt_rx.channel, 1000, 0);
}

void app_main()
{
HCSR04_tx_init();
HCSR04_rx_init();

rmt_item32_t item;
item.level0 = 1;
item.duration0 = RMT_TICK_10_US;
item.level1 = 0;
item.duration1 = RMT_TICK_10_US; // for one pulse this doesn't matter

size_t rx_size = 0;
RingbufHandle_t rb = NULL;
rmt_get_ringbuf_handle(RMT_RX_CHANNEL, &rb);
rmt_rx_start(RMT_RX_CHANNEL, 1);

double distance = 0;
//float distance = 0;

for(;;)
{
rmt_write_items(RMT_TX_CHANNEL, &item, 1, true);
rmt_wait_tx_done(RMT_TX_CHANNEL, portMAX_DELAY);

rmt_item32_t* item = (rmt_item32_t*)xRingbufferReceive(rb, &rx_size, 1000);
if(item){
 // distance = 340.29 * ITEM_DURATION(item->duration0) / (  2000000 ); // distance in meters
  distance = 340.29 * ITEM_DURATION(item->duration0) / (1000 * 1000 * 2); // distance in meters
  ESP_LOGI(NEC_TAG, "Distance is %f cm\n", distance * 100); // distance in centimeters
  vRingbufferReturnItem(rb, (void*) item);
} else {
  ESP_LOGI(NEC_TAG, "Distance is not readable");
}

vTaskDelay(20 / portTICK_PERIOD_MS);
}

}

mikronauts
Posts: 23
Joined: Wed Dec 09, 2015 8:11 pm

Re: HC-SR04 using RMT - very fast

Postby mikronauts » Sun Jun 30, 2019 2:33 pm

The time taken to perform that calculation is less than 1/1000 the time to get the distance from the hcsr04.

Insignificant.

uberthoth
Posts: 6
Joined: Tue Jun 11, 2019 4:06 am

Re: HC-SR04 using RMT - very fast

Postby uberthoth » Mon Jul 08, 2019 3:59 pm

mikronauts wrote: The time taken to perform that calculation is less than 1/1000 the time to get the distance from the hcsr04.

Insignificant.
Which calculation are you talking about?

mikronauts
Posts: 23
Joined: Wed Dec 09, 2015 8:11 pm

Re: HC-SR04 using RMT - very fast

Postby mikronauts » Tue Jul 09, 2019 12:29 am

I was pointing out that worrying about the impact of integer vs floating point math (single or double precision) is not worth the effort, as even the slowest method is totally insignificant compared to the meadurement interval.
uberthoth wrote:
Mon Jul 08, 2019 3:59 pm
mikronauts wrote: The time taken to perform that calculation is less than 1/1000 the time to get the distance from the hcsr04.

Insignificant.
Which calculation are you talking about?

AlbertH
Posts: 5
Joined: Wed Feb 03, 2021 3:54 pm

Re: HC-SR04 using RMT - very fast

Postby AlbertH » Thu Feb 04, 2021 10:26 am

First of all, I have very little software experience, I am more a hardware designer (FPGA). I want to measure the with of a tacho pulse with the RMT registers. What I did was placing the code in my Arduino development tool and then started the compiler.

I got a lot of errors which also happens with other examples about the RMT registers.

The error I get is:
...\Arduino\sketch_feb04a\sketch_feb04a\sketch_feb04a.ino: In function 'void HCSR04_tx_init()':
sketch_feb04a:32:16: error: invalid conversion from 'int' to 'rmt_channel_t' [-fpermissive]
rmt_tx.channel = RMT_TX_CHANNEL;


Can someone help to solve this problem?

Thanks in Advance

Who is online

Users browsing this forum: No registered users and 35 guests