HC-SR04 using RMT - very fast

Deouss
Posts: 386
Joined: Tue Mar 20, 2018 11:36 am

HC-SR04 using RMT - very fast

Postby Deouss » Mon May 21, 2018 5:51 am

I was testing RMT and it turned out to be excellent tool )

Here is a code for ultrasonic sensor HC-SR04 using full hardware capabilities of ESP hardware Remote Control module


[code]
#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;
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;
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;

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
printf("Distance is %f cm\n", distance * 100); // distance in centimeters

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

}
[/code]

BeWaterMyFriend
Posts: 1
Joined: Wed Oct 17, 2018 4:27 pm

Re: HC-SR04 using RMT - very fast

Postby BeWaterMyFriend » Wed Oct 17, 2018 4:31 pm

Great Example. Thanks for sharing !

oussama
Posts: 1
Joined: Tue Jan 29, 2019 3:33 pm

Re: HC-SR04 using RMT - very fast

Postby oussama » Mon Feb 04, 2019 1:47 pm

Hello,

First of all thank you for your code it works perfectly. now i'm traing to simplify the ligne:
distance = 340.29 * ITEM_DURATION(item->duration0) / (1000 * 1000 * 2);
Because the μC works for nothing if we break down in number of instructions. The sensor being linear, it is necessary to simplify this calculation with a constant, so any suggestions :roll:

Regards,

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

Re: HC-SR04 using RMT - very fast

Postby mikronauts » Mon Mar 25, 2019 6:49 pm

I would be VERY surprised if the compiler did not perform constant folding by default.
oussama wrote:
Mon Feb 04, 2019 1:47 pm
Hello,

First of all thank you for your code it works perfectly. now i'm traing to simplify the ligne:
distance = 340.29 * ITEM_DURATION(item->duration0) / (1000 * 1000 * 2);
Because the μC works for nothing if we break down in number of instructions. The sensor being linear, it is necessary to simplify this calculation with a constant, so any suggestions :roll:

Regards,

ESP_Angus
Posts: 1703
Joined: Sun May 08, 2016 4:11 am

Re: HC-SR04 using RMT - very fast

Postby ESP_Angus » Tue Mar 26, 2019 12:13 am

The compiler will indeed optimise out all the constant calculations.

If you want the very best performance, probably the only other optimisation would be not to use floats and to "think big" in the integer domain instead (ie have the calculation output integer centimeters or millimeters so all the math can be faster integer math not floating point.)

But I can't imagine this infrequent single FP calculation is a large bottleneck, either.

Deouss
Posts: 386
Joined: Tue Mar 20, 2018 11:36 am

Re: HC-SR04 using RMT - very fast

Postby Deouss » Tue Mar 26, 2019 1:42 am

I'm not sure if this is FP32 or maybe better to use FP64 e.g. double.
Maybe optimized FP16 (manual calc?) would work fine as well

ESP_Angus
Posts: 1703
Joined: Sun May 08, 2016 4:11 am

Re: HC-SR04 using RMT - very fast

Postby ESP_Angus » Tue Mar 26, 2019 3:31 am

Deouss wrote:
Tue Mar 26, 2019 1:42 am
I'm not sure if this is FP32 or maybe better to use FP64 e.g. double.
Maybe optimized FP16 (manual calc?) would work fine as well
Single precision floating point (ie float not double) on the ESP32 will use the FPU. Double precision will use software so is much slower.

Integer will always be faster, so if you only care about X digits of precision then just pick an integer base large enough to capture all those digits, and divide down later into a float if you need to. Or use a fixed point math library.

In this case I don't think this calculation happens often enough for the choice of math type to make any difference to overall performance.

Deouss
Posts: 386
Joined: Tue Mar 20, 2018 11:36 am

Re: HC-SR04 using RMT - very fast

Postby Deouss » Tue Mar 26, 2019 11:41 am

I would like to know how many cycles a single float FPU operations take.
Why is this such a big case? I don't think it should be slower than software but I see all the time people saying it is a performance issue.
Could you please elaborate on that?

ESP_Angus
Posts: 1703
Joined: Sun May 08, 2016 4:11 am

Re: HC-SR04 using RMT - very fast

Postby ESP_Angus » Tue Mar 26, 2019 11:14 pm

Deouss wrote:
Tue Mar 26, 2019 11:41 am
I would like to know how many cycles a single float FPU operations take.
Why is this such a big case? I don't think it should be slower than software but I see all the time people saying it is a performance issue.
I don't think we actually publish statistics for ESP32, although we probably should. The answer is "it depends" a bit, because of things like the CPU pipeline.

There are some user benchmarks here measuring 170MOPS for float multiply, which sounds about right. Their integer multiplication result is bad for some reason (they mark it as a problem case), in ideal conditions I believe integer multiplication should take one cycle so maximum 240MOPS.

As a rule of thumb: integer math is always faster than hardware floating point math (on any CPU), and software floating point math is always much slower than either of the other two (on any CPU, note the results for "double" in the linked post).

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

Re: HC-SR04 using RMT - very fast

Postby uberthoth » Thu Jun 20, 2019 3:01 am

Has anyone tried this code lately? All I get is this Guru meditation about core panic:

Code: Select all

I (114) cpu_start: App cpu up.                                                                                                                       [10/13182]
I (132) heap_init: Initializing. RAM available for dynamic allocation:                                                                                         
I (139) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM                                                                                                      
I (145) heap_init: At 3FFB2F80 len 0002D080 (180 KiB): DRAM                                                                                                    
I (151) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM                                                                                                   
I (158) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM                                                                                                  
I (164) heap_init: At 400892B4 len 00016D4C (91 KiB): IRAM                                                                                                     
I (170) cpu_start: Pro cpu start user code                                                                                                                     
I (188) cpu_start: Starting scheduler on PRO CPU.                                                                                                              
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      : 0x400d2491  PS      : 0x00060730  A0      : 0x800d0b0d  A1      : 0x3ffb4d10  
0x400d2491: app_main at /home/thoth/git/A9thinker/GPRS_C_SDK/tank_gauge/sr04test/main/bstx03_XiuxinESP32.c:92 (discriminator 1)

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

ELF file SHA256: f72eba0ee73b704e70e2cb3c46cc43357e7349cb9aa64dfb4204213e1d20c7f5

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

0x400d0b0a: 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...

Who is online

Users browsing this forum: No registered users and 1 guest