Page 1 of 1

RMT Copy Encoder - RMT_ENCODING_MEM_FULL

Posted: Fri Nov 01, 2024 9:48 pm
by nozomiman32
Hi Forum

I am trying to use the ESP32 RMT Perphial to generate a Pulse Code Modulation signal using the "new" copy encoder.

The copy encoder is failing with RMT_ENCODING_MEM_FULL.

In the example below I generate the RMT_ITEMS from HEX values. The RMT_ITEMS appear correct, but the copy encoder fails to encoder the signal and the application crashes on the transmit. Ive tried to encode just a single HEX byte but same issue.

How do I correct this?

Thanks

Code: Select all

	I (952) RMT_PCM: rmt_items[79]: level0=1, duration0=10, level1=0, duration1=10
	I (962) RMT_PCM: Session State = FULL
	I (972) RMT_PCM: Encoded 0 symbols Session State 2
	E (972) rmt: rmt_transmit(530): invalid argument

Code: Select all

    
    #include <stdio.h>
    #include <string.h>
    #include <esp_log.h>
    #include <driver/rmt_tx.h>
    #include <freertos/FreeRTOS.h>
    #include <freertos/task.h>

    #define RESOLUTION_HZ     1000000 // 1MHz resolution, 1 tick = 1us
    #define TX_GPIO_NUM       18

    // Example byte data to be sent as PCM signal
    const uint8_t byte_data[] = {0xaa, 0x55, 0x55, 0x55, 0x55, 0x96, 0x6a, 0x59, 0xa9, 0x65};  // Byte data
    #define BIT_DURATION_US 10   // Duration of each bit in microseconds

    static const char *TAG = "RMT_PCM";

    void send_byte_data(rmt_channel_handle_t tx_channel) {
        size_t byte_data_size = sizeof(byte_data) / sizeof(byte_data[0]);
        size_t total_bits = byte_data_size * 8;
        

        // Create timings to pass to copy encoder
        rmt_symbol_word_t rmt_items[total_bits];   // compile time
        
        for (size_t i = 0; i < byte_data_size; i++) {
            uint8_t byte_value = byte_data[i];
            for (int bit = 7; bit >= 0; bit--) {
                bool bit_value = (byte_value >> bit) & 0x1;
                size_t index = (i * 8) + (7 - bit);
                rmt_items[index].level0 = bit_value ? 1 : 0;
                rmt_items[index].duration0 = BIT_DURATION_US;
                rmt_items[index].level1 = bit_value ? 0 : 1;
                rmt_items[index].duration1 = BIT_DURATION_US;
            }
        }

        // Print rmt_items contents
        for (size_t i = 0; i < total_bits; i++) {
            ESP_LOGI(TAG, "rmt_items[%d]: level0=%d, duration0=%d, level1=%d, duration1=%d",
                    i, rmt_items[i].level0, rmt_items[i].duration0,
                    rmt_items[i].level1, rmt_items[i].duration1);
        }

        // Create copy encoder
        rmt_encoder_handle_t copy_encoder;
        rmt_copy_encoder_config_t copy_encoder_config = {};
        ESP_ERROR_CHECK(rmt_new_copy_encoder(&copy_encoder_config, &copy_encoder));

        // Encode RMT items
        size_t encoded_symbols = 0;
        rmt_encode_state_t session_state = RMT_ENCODING_RESET;
        encoded_symbols = copy_encoder->encode(copy_encoder, tx_channel, &rmt_items, total_bits * sizeof(rmt_symbol_word_t), &session_state);
        
        if (session_state & RMT_ENCODING_MEM_FULL) {
            ESP_LOGI(TAG, "Session State = FULL");   // Should not continue 
        }
        // Log encoded symbols count
        ESP_LOGI(TAG, "Encoded %d symbols Session State %d", encoded_symbols, session_state);

        // Create transmit configuration
        rmt_transmit_config_t transmit_config = {
            .loop_count = 0, // no loop
        };
        
        // Sending transmission
        ESP_ERROR_CHECK(rmt_transmit(tx_channel, copy_encoder, NULL, 0, &transmit_config));
        ESP_ERROR_CHECK(rmt_del_encoder(copy_encoder));
    }


    void app_main(void) {
        ESP_LOGI(TAG, "Creating RMT TX channel");

        rmt_tx_channel_config_t tx_channel_cfg = {
            .clk_src = RMT_CLK_SRC_DEFAULT,
            .resolution_hz = RESOLUTION_HZ,
            .mem_block_symbols = 512, // Amount of RMT symbols that the channel can store at a time
            .trans_queue_depth = 4,    // Number of transactions allowed to be pending in the background
            .gpio_num = TX_GPIO_NUM,
            .flags.with_dma = false   // ESP32 Base model
        };

        rmt_channel_handle_t tx_channel = NULL;
        ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_channel_cfg, &tx_channel));

        ESP_LOGI(TAG, "Enabling RMT TX channel");
        ESP_ERROR_CHECK(rmt_enable(tx_channel));

        while (true) {
            send_byte_data(tx_channel);
            vTaskDelay(pdMS_TO_TICKS(1000));  // Transmit every 1 second
        }
    }

Re: RMT Copy Encoder - RMT_ENCODING_MEM_FULL

Posted: Sat Nov 02, 2024 12:16 pm
by aliarifat794
The ESP32’s RMT memory is limited, so encoding large amounts of data can easily lead to a memory full error. Try to reduce the mem_block_symbols in tx_channel_cfg.

Re: RMT Copy Encoder - RMT_ENCODING_MEM_FULL

Posted: Sat Nov 02, 2024 11:49 pm
by nozomiman32
I dropped it to .mem_block_symbols = 64 and went back to a single byte to encode.

Code: Select all

const uint8_t byte_data[] = {0xaa};
Still the same issue.

Code: Select all

I (322) RMT_PCM: Creating RMT TX channel
I (322) RMT_PCM: rmt_tx_channel_config_t tx_channel_cfg = {
I (322) RMT_PCM:     .gpio_num = 18,
I (332) RMT_PCM:     .clk_src = 4,
I (332) RMT_PCM:     .resolution_hz = 1000000,
I (342) RMT_PCM:     .mem_block_symbols = 64,
I (342) RMT_PCM:     .trans_queue_depth = 4,
I (352) RMT_PCM:     .intr_priority = 0,
I (352) RMT_PCM:     .flags.with_dma = false,
I (362) RMT_PCM: };
I (362) gpio: GPIO[18]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (372) RMT_PCM: Enabling RMT TX channel
I (372) RMT_PCM: rmt_items[0]: level0=1, duration0=10, level1=0, duration1=10
I (382) RMT_PCM: rmt_items[1]: level0=0, duration0=10, level1=1, duration1=10
I (392) RMT_PCM: rmt_items[2]: level0=1, duration0=10, level1=0, duration1=10
I (402) RMT_PCM: rmt_items[3]: level0=0, duration0=10, level1=1, duration1=10
I (402) RMT_PCM: rmt_items[4]: level0=1, duration0=10, level1=0, duration1=10
I (412) RMT_PCM: rmt_items[5]: level0=0, duration0=10, level1=1, duration1=10
I (422) RMT_PCM: rmt_items[6]: level0=1, duration0=10, level1=0, duration1=10
I (432) RMT_PCM: rmt_items[7]: level0=0, duration0=10, level1=1, duration1=10
I (442) RMT_PCM: Session State = FULL
I (442) RMT_PCM: Encoded 0 symbols Session State 2