Page 1 of 2
RMT code migration from ESP-IDF 4.2 to version 5.2.2
Posted: Wed Jul 03, 2024 11:18 pm
by orbitcoms
Hi,
I am having trouble understanding how to migrate my RMT driver code from esp-idf version 4.2 to 5.2.2
My application is simple that I want to modulate a 125kHz carrier with data.
In my exisiting code I can simply place my data into an array and call the function to send it on demand. However, the updated driver seems to be using encoder and appears to me to be more complex.
My existing code is below. Would someone be able to help me understand how I can make the changes to compile this using the esp-idf 5.2.2 verison?
[Codebox=c file=Untitled.c]
const rmt_item32_t lf_wake[] ={
{{{WAKEPERIOD,1,BITPERIOD,0}}}
};
const rmt_item32_t lf_preamble[]={
{{{BITPERIOD,1,BITPERIOD,0}}},
{{{BITPERIOD,1,BITPERIOD,0}}},
{{{BITPERIOD,1,BITPERIOD,0}}}
};
void send_lf_byte(uint8_t data_val)
{
uint8_t mask = 0x80;
rmt_item32_t rmt_data[2];
for(uint8_t i = 0; i < 8 ; i++){
if((data_val & mask)==mask){
rmt_data[i].duration0 = BITPERIOD; //encode "1"
rmt_data[i].level0 = 1;
rmt_data[i].duration1 = BITPERIOD;
rmt_data[i].level1 = 0;
}
else{
rmt_data[i].duration0 = BITPERIOD; //encode "0"
rmt_data[i].level0 = 0;
rmt_data[i].duration1 = BITPERIOD;
rmt_data[i].level1 = 1;
}
mask >>= 1;
}
ESP_ERROR_CHECK(rmt_write_items(config.channel, rmt_data,BYTESIZE,true));
void send_packet(uint8_t mydata)
{
ESP_ERROR_CHECK(rmt_write_items(config.channel, lf_wake, WAKESIZE,true));
ESP_ERROR_CHECK(rmt_write_items(config.channel, lf_preamble, PREAMBLESIZE,true));
send_lf_byte(data_msb);
}
}[/Codebox]
Re: RMT code migration from ESP-IDF 4.2 to version 5.2.2
Posted: Thu Jul 04, 2024 1:25 am
by ok-home
Hi
simple way to pass the rmt_item32_t array
Code: Select all
const rmt_item32_t rmt_data_out[]={
{{{BITPERIOD,1,BITPERIOD,0}}},
{{{BITPERIOD,1,BITPERIOD,0}}},
{{{BITPERIOD,1,BITPERIOD,0}}},
{{{0,0,0,0}}}
};
rmt_copy_encoder_config_t tx_encoder_config = {0};
rmt_encoder_handle_t tx_encoder = NULL;
rmt_new_copy_encoder(&tx_encoder_config, &tx_encoder);
rmt_transmit_config_t rmt_tx_config = {0};
rmt_transmit(tx_chan_handle, tx_encoder, rmt_data_out, sizeof(rmt_data_out), &rmt_tx_config));
rmt_tx_wait_all_done(tx_chan_handle, portMAX_DELAY)
Re: RMT code migration from ESP-IDF 4.2 to version 5.2.2
Posted: Thu Jul 04, 2024 1:37 am
by orbitcoms
Thank you for your response. I appreciate your time to answer my question
So, I can do all the loading in my init code then whenever I want to send, I repeat these 2 lines of code?
[Codebox=c file=Untitled.c]
rmt_transmit(tx_chan_handle, tx_encoder, rmt_data_out, sizeof(rmt_data_out), &rmt_tx_config));
rmt_tx_wait_all_done(tx_chan_handle, portMAX_DELAY)
[/Codebox]
Does encoder require a const or can it be a variable array? Most of the packet is fixed except some ID bytes that I were sending in a loop and thinking I could place these all into 1 array at init so each time I send I just use the RMT TX function and wait till done.
Re: RMT code migration from ESP-IDF 4.2 to version 5.2.2
Posted: Thu Jul 04, 2024 1:56 am
by ok-home
orbitcoms wrote: ↑Thu Jul 04, 2024 1:37 am
Does encoder require a const or can it be a variable array? Most of the packet is fixed except some ID bytes that I were sending in a loop and thinking I could place these all into 1 array at init so each time I send I just use the RMT TX function and wait till done.
rmt_transmit
This function constructs a transaction descriptor then pushes to a queue. The transaction will not start immediately if there's another one under processing. Based on the setting of rmt_transmit_config_t::queue_nonblocking, if there're too many transactions pending in the queue, this function can block until it has free slot, otherwise just return quickly.
https://docs.espressif.com/projects/es ... _config_t
if you don't care about intervals between transaction - send in parts
if intervals are critical - create 1 full array (its size is limited by channel memory) and send the whole array
const as far as I understand - not critical.
you can see an example of a complete RMT channel initialization
https://github.com/ok-home/rmt_ws_tool ... md.c#L239
Re: RMT code migration from ESP-IDF 4.2 to version 5.2.2
Posted: Fri Jul 05, 2024 5:27 am
by orbitcoms
Hi,
I have written some code based on your simple example. I am getting a clock error when trying to assign the RMT channel.
assert failed: rmt_ll_tx_set_channel_clock_div /IDF/components/hal/esp32s3/include/hal/rmt_ll.h:181 (div >= 1 && div <= 256 && "divider out of range")
My init code is below...Also, below that I have copied my data packet fill routine, does that look ok?
[code]
void lf_send_packet(uint16_t)
{
ESP_LOGI(TAG,"Set Tx chan handle and TX config");
rmt_channel_handle_t tx_chan_handle = NULL;
rmt_tx_channel_config_t tx_chan_config = {
.clk_src = RMT_CLK_SRC_DEFAULT, // select source clock
.gpio_num = RMT_TX_GPIO,
.mem_block_symbols = 64,
.flags.io_loop_back = 0, // gpio output/input mode
.resolution_hz = 125000,
.trans_queue_depth = 5, // set the maximum number of transactions that can pend in the background
};
ESP_LOGI(TAG,"Assign new channel");
ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_config, &tx_chan_handle));
ESP_LOGI(TAG,"Channel assigned ok");
rmt_encoder_handle_t tx_encoder = NULL;
rmt_copy_encoder_config_t tx_encoder_config = {};
ESP_LOGI(TAG,"Set Encoder handle and config");
ESP_ERROR_CHECK(rmt_enable(tx_chan_handle));
ESP_ERROR_CHECK(rmt_new_copy_encoder(&tx_encoder_config, &tx_encoder));
rmt_transmit_config_t rmt_tx_config = {
.loop_count = 0,
};
lf_packet.data_out_len = 43;
ESP_LOGI(TAG,"Send the packet");
ESP_ERROR_CHECK(rmt_transmit(tx_chan_handle, tx_encoder, lf_packet.lf_data_out, (lf_packet.data_out_len) * sizeof(rmt_symbol_word_t), &rmt_tx_config));
rmt_tx_wait_all_done(tx_chan_handle, RMT_TIMEOUT_MS);
ESP_LOGI(TAG,"All done");
rmt_disable(tx_chan_handle);
rmt_del_encoder(tx_encoder);
rmt_del_channel(tx_chan_handle);
}
[/code]
[Codebox=c file=Untitled.c]
#define RMT_TIMEOUT_MS (10000)
#define TAG "RMT"
typedef struct lf_packet_config
{
rmt_symbol_word_t lf_data_out[50];
int data_out_len;
} lf_packet_config_t;
lf_packet_config_t lf_packet;
uint8_t fill_packet(lf_packet_config_t pkt,uint8_t data, uint8_t pos)
{
uint8_t mask = 0x80;
for(uint8_t i = 0;i<8;i++)
{
if((data&mask)==mask)
{
lf_packet.lf_data_out[pos+i].duration0 = BITPERIOD; //preamble
lf_packet.lf_data_out[pos+i].level0 = 1;
lf_packet.lf_data_out[pos+i].duration1 = BITPERIOD;
lf_packet.lf_data_out[pos+i].level1 = 0;
}
else
{
lf_packet.lf_data_out[pos+i].duration0 = BITPERIOD; //preamble
lf_packet.lf_data_out[pos+i].level0 = 0;
lf_packet.lf_data_out[pos+i].duration1 = BITPERIOD;
lf_packet.lf_data_out[pos+i].level1 = 1;
}
}
return pos+8;
}
void load_lf_data(void)
{
uint8_t pos = 0;
lf_packet.lf_data_out[pos].duration0 = WAKEPERIOD; //wake
lf_packet.lf_data_out[pos].level0 = 1;
lf_packet.lf_data_out[pos].duration1 = BITPERIOD;
lf_packet.lf_data_out[pos].level1 = 0;
pos+=1;
for(uint8_t n = 1; n < 4; n++)
{
lf_packet.lf_data_out[pos].duration0 = BITPERIOD; //preamble
lf_packet.lf_data_out[pos].level0 = 1;
lf_packet.lf_data_out[pos].duration1 = BITPERIOD;
lf_packet.lf_data_out[pos].level1 = 0;
}
pos+=1;
pos = fill_packet(lf_packet, DECODE_PATTERN, pos);
pos = fill_packet(lf_packet, (me.id >> 8), pos);
pos = fill_packet(lf_packet, (me.id), pos);
pos = fill_packet(lf_packet, TAGPOLLCOMMAND, pos);
uint8_t crc = 0;
crc = (me.id >>8) ^ (me.id) ^ (TAGPOLLCOMMAND);
pos = fill_packet(lf_packet, crc, pos);
lf_packet.lf_data_out[pos].val = 0; //stop transfer
}
[/Codebox]
Re: RMT code migration from ESP-IDF 4.2 to version 5.2.2
Posted: Fri Jul 05, 2024 7:16 am
by ok-home
orbitcoms wrote: ↑Fri Jul 05, 2024 5:27 am
Hi,
I have written some code based on your simple example. I am getting a clock error when trying to assign the RMT channel.
assert failed: rmt_ll_tx_set_channel_clock_div /IDF/components/hal/esp32s3/include/hal/rmt_ll.h:181 (div >= 1 && div <= 256 && "divider out of range")
Code: Select all
.clk_src = RMT_CLK_SRC_DEFAULT, // select source clock
.resolution_hz = 125000,
};
RMT_CLK_SRC_DEFAULT = APB CLK
prescaler digitization rmt - 8 bit = 256
Need to change resolution_hz to 1,250,000 or 1,000,000 and change BITPERIOD constants
or change clk_src
Re: RMT code migration from ESP-IDF 4.2 to version 5.2.2
Posted: Fri Jul 05, 2024 9:14 am
by orbitcoms
I'm not quite with you on this yet. If I set resolution to say 1000000 then this is 1us bit time.
So for say the DATA time, I could set the Duration for say 2000 with level 1 to be high for 2ms?
Isn't the data the actual modulating signal?
If so, how do I set the carrier to 125 khz?
ie. I need the carrier of 125kHz being modulated by my data for symbol times -say 0.5ms each
Thanks
Re: RMT code migration from ESP-IDF 4.2 to version 5.2.2
Posted: Fri Jul 05, 2024 9:18 am
by orbitcoms
I think this is what I was missing
ESP_LOGI(TAG, "modulate carrier to TX channel");
rmt_carrier_config_t carrier_cfg = {
.duty_cycle = 0.33,
.frequency_hz = 38000, // 38KHz
};
ESP_ERROR_CHECK(rmt_apply_carrier(tx_channel, &carrier_cfg));
Re: RMT code migration from ESP-IDF 4.2 to version 5.2.2
Posted: Fri Jul 05, 2024 10:01 am
by orbitcoms
I have another question.
Can the config for transmitter, carrier and encoder be done once at start of program and then just activate the tx function each time to send it (ie. Once encloder etc has been loaded with my data, it does not get blanked out for any reason during use but acts like a normal array in memory? All my data is contsant and the only thing that can chage during run time is 2 ID bytes. I assume if I know the location in the rmt symbol array, I can just write to those locations only and then call tx function again?
Re: RMT code migration from ESP-IDF 4.2 to version 5.2.2
Posted: Fri Jul 05, 2024 11:45 pm
by ok-home
orbitcoms wrote: ↑Fri Jul 05, 2024 10:01 am
I have another question.
Can the config for transmitter, carrier and encoder be done once at start of program and then just activate the tx function each time to send it (ie. Once encloder etc has been loaded with my data, it does not get blanked out for any reason during use but acts like a normal array in memory? All my data is contsant and the only thing that can chage during run time is 2 ID bytes. I assume if I know the location in the rmt symbol array, I can just write to those locations only and then call tx function again?
yes