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(©_encoder_config, ©_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
}
}