RMT code migration from ESP-IDF 4.2 to version 5.2.2

orbitcoms
Posts: 149
Joined: Fri Aug 03, 2018 10:08 pm
Location: Sydney, Australia

RMT code migration from ESP-IDF 4.2 to version 5.2.2

Postby orbitcoms » Wed Jul 03, 2024 11:18 pm

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]

User avatar
ok-home
Posts: 78
Joined: Sun May 02, 2021 7:23 pm
Location: Russia Novosibirsk
Contact:

Re: RMT code migration from ESP-IDF 4.2 to version 5.2.2

Postby ok-home » Thu Jul 04, 2024 1:25 am

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)

orbitcoms
Posts: 149
Joined: Fri Aug 03, 2018 10:08 pm
Location: Sydney, Australia

Re: RMT code migration from ESP-IDF 4.2 to version 5.2.2

Postby orbitcoms » Thu Jul 04, 2024 1:37 am

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.

User avatar
ok-home
Posts: 78
Joined: Sun May 02, 2021 7:23 pm
Location: Russia Novosibirsk
Contact:

Re: RMT code migration from ESP-IDF 4.2 to version 5.2.2

Postby ok-home » Thu Jul 04, 2024 1:56 am

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

orbitcoms
Posts: 149
Joined: Fri Aug 03, 2018 10:08 pm
Location: Sydney, Australia

Re: RMT code migration from ESP-IDF 4.2 to version 5.2.2

Postby orbitcoms » 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")

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]

User avatar
ok-home
Posts: 78
Joined: Sun May 02, 2021 7:23 pm
Location: Russia Novosibirsk
Contact:

Re: RMT code migration from ESP-IDF 4.2 to version 5.2.2

Postby ok-home » Fri Jul 05, 2024 7:16 am

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

orbitcoms
Posts: 149
Joined: Fri Aug 03, 2018 10:08 pm
Location: Sydney, Australia

Re: RMT code migration from ESP-IDF 4.2 to version 5.2.2

Postby orbitcoms » Fri Jul 05, 2024 9:14 am

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

orbitcoms
Posts: 149
Joined: Fri Aug 03, 2018 10:08 pm
Location: Sydney, Australia

Re: RMT code migration from ESP-IDF 4.2 to version 5.2.2

Postby orbitcoms » Fri Jul 05, 2024 9:18 am

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));

orbitcoms
Posts: 149
Joined: Fri Aug 03, 2018 10:08 pm
Location: Sydney, Australia

Re: RMT code migration from ESP-IDF 4.2 to version 5.2.2

Postby orbitcoms » 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?

User avatar
ok-home
Posts: 78
Joined: Sun May 02, 2021 7:23 pm
Location: Russia Novosibirsk
Contact:

Re: RMT code migration from ESP-IDF 4.2 to version 5.2.2

Postby ok-home » Fri Jul 05, 2024 11:45 pm

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

Who is online

Users browsing this forum: No registered users and 365 guests