Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

ESP32 Embedded Rust at the HAL: Remote Control Peripheral

Posted on Jun 22 This blog post is the tenth of a multi-part series of posts where I explore various peripherals in the ESP32C3 using embedded Rust at the HAL level. Please be aware that certain concepts in newer posts could depend on concepts in prior posts.If you find this post useful, and to keep up to date with similar posts, here's the list of channels you can follow/subscribe to:Follow Me on TwitterSubscribe to NewsletterFollow me on GitHubClick Here for Rust SwagThe Remote Control Transceiver (RMT) peripheral in the ESP32C3 microcontroller provides a simple and efficient way to transmit and receive remote control signals. It is commonly used in applications such as infrared (IR) remote control systems. The RMT can produce programmable pulse patterns, has built-in carrier modulation, and supports multiple channels for both transmit and receive.While the RMT peripheral in the ESP32C3 microcontroller is primarily designed for remote control applications, it can also be used for other purposes that involve generating and receiving pulse train signals. This includes but is not limited to applications like; sensor interfacing, LED control, signal generation, and timing and synchronization.In this post, I'm going to build an application that uses the RMT to generate two different waveforms on two different pins. I will also be leveraging the Wokwi logic analyzer to verify/monitor the output of the pins.To understand the content of this post, you need the following:Basic knowledge of coding in Rust.Familiarity with the basic template for creating embedded applications in Rust.All the code presented in this post is available on the apollolabs ESP32C3 git repo. Note that if the code on the git repo is slightly different then it means that it was modified to enhance the code quality or accommodate any HAL/Rust updates.Additionally, the full project (code and simulation) is available on Wokwi here.For this post, you need to download PulseView from the Sigrok website. PulseView is an open-source logic analyzer software that is going to be used to view the output signals. If you are a first-time user of PulseView and the logic analyzer function on Wokwi, I recommend you read my earlier blog post with a step-by-step setup here.Connections include the following:Gpio6 to D0 on the Wokwi logic analyzerGpio5 to D1 on the Wokwi logic analyzerBefore delving into what the software will do, understanding the working of the RMT would be useful to understand how it'll be configured. As such, the figure below extracted from the ESP reference manual shows a block diagram of of a single RMT transmitter channel in the ESP32-C3:In the upper path, known as the data path, an input is provided by the user (in the program) where the RMT transmitter, in turn, will generate the waveforms on the pin. The lower path, known as the control path, generates the carrier signal required for modulation purposes. For the purpose of this post, we are not doing any modulation so the lower path (control path) will be disabled.The RMT hardware employs a pattern known as the RMT symbol to define data shown below. Each symbol comprises two pairs of values. The first value within a pair, spanning 15 bits, represents the duration of the signal in RMT ticks. The second value, encapsulated within a single bit, denotes the signal level, distinguishing between high and low. This arrangement ensures an efficient and concise representation of the signal characteristics, facilitating precise communication and interpretation within the RMT system.📝 *Note*The image above for the RMT symbol comes from the ESP reference, however, you need to be careful as it might be confusing. The numbers on top, do not reflect bit positions like normally expected in many other manuals.In the code introduced in this post, the application will configure two RMT channels and send a different pulse code to each. We will use the logic analyzer to verify that the correct pulses were generated on each pin.In this implementation the crates required are as follows:The esp32c3_hal crate to import the ESP32C3 device hardware abstractions.The esp_backtrace crate to define the panicking behavior.The esp_println crate to provide println! implementation.1️⃣ Obtain a handle for the device peripherals: In embedded Rust, as part of the singleton design pattern, we first have to take the PAC-level device peripherals. This is done using the take() method. Here I create a device peripheral handler named dp as follows:2️⃣ Disable the Watchdogs: The ESP32C3 has watchdogs enabled by default and they need to be disabled. If they are not disabled then the device would keep on resetting. I'm not going to go into much detail, however, watchdogs require the application software to periodically "kick" them to avoid resets. This is out of the scope of this example, though to avoid this issue, the following code needs to be included:3️⃣ Configure and Obtain Handle for the RMT: To create an instance of the RMT, we need to start with creating an instance of the PulseControl peripheral (that's the way the RMT is named in the hal) in the esp32c3-hal. In PulseControl there is a new() instance method that has the following signature:The first three parameters are more or less expected where the RMT would require an instance of the peripheral to be used, a peripheral_clock_control struct, and a clk_source struct. However, for the last three parameters, although the HAL documentation does not provide much detail, it can be found in the reference manual (page 828). Here we aren't going to need any clock division, so all the last three values will remain zero. As such, I create an instance for the pulse handle as follows:Be aware that these settings, mainly to do with clocks, will apply to all the RMT channels within the peripheral. Nevertheless, we will be able to configure individual channel settings in the next step after we divide the channels.4️⃣ Obtain handle and set up the channels: In the ESP32C3 there are two RMT transmitter channels that are encoded as members of the PluseControl struct; channel0 and channel1 . We can create a handle for each separately as follows:At this point, however, the individual channels are not fully configured yet. There are several methods that would enable us to do so. You can find the applicable methods in the Channel0 and Channel1 struct documentation in the esp32c3-hal. Here we use the set_idle_output_level to configure the default output level when the channel is idle, set_carrier_modulation to deactivate the carrier modulation, set_channel_divider to set the channel clock divider value, and set_idle_output to enable the output while the channel is idle:5️⃣ Assign Pins and Obtain Handles for the Configured Channels:All of the methods in the previous step return a Channel0 or Channel1 type. Neither of which is possible to send a sequence to. Instead, we need a ConfiguredChannel0 or ConfiguredChannel1 type. Only the assign_pin method returns a configured channel. As such, we assign the pins and create handles for the configured channels as follows:quite frankly I found this pattern a bit different from what I expected compared to other peripherals.Now that the channels are configured, all we have to do is create the application.In the application, first thing that needs to be done is create the patterns that we want to generate on the pins. In order to do that, we'd have to use the PulseCode type. PulseCode is an object that represents the state of one RMT symbol explained earlier. Here I will create two arrays each with three pulse codes representing a different pattern. The two different patterns will be sent to two different channels:In the seq array three pulse codes will be sent. For each PulseCode, the first level of the symbol is set to high (true) for 10ns and the second part of the symbol to low (false) for 90ns. The seq1 array does the same though with different timings of 50ns for both on and off times.Now we can monitor the outputs with the Wokwi logic analyzer. Looking at the zoomed-out view, with the signals of both channels, you can see that the first channel is generating the three pulse codes followed by the second channel. Exactly like desired in the code.Next, we can zoom in to see the timing. I zoomed in to the second channel and viewed the following:Notice the on and off times are equal like we intended them to be. However, when measuring the timing it is 620ns rather than the 50ns that we expect. This is an issue that I am still investigating and will update this post as soon as it's clear what is occurring.Here is the full code for the implementation described in this post. You can additionally find the full project and others available on the apollolabs ESP32C3 git repo. Also the Wokwi project can be accessed here.In this post, an application was created leveraging the remote control peripheral (RMT) for the ESP32C3 to generate different pulse waveforms. The RMT code was created at the HAL level using the Rust esp32c3-hal. Have any questions/comments? Share your thoughts in the comments below 👇.If you found this post useful, and to keep up to date with similar posts, here's the list of channels you can follow/subscribe to:Follow Me on TwitterSubscribe to NewsletterFollow me on GitHubClick Here for Rust SwagTemplates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well Confirm For further actions, you may consider blocking this person and/or reporting abuse Pierre Chollet - May 26 A.J. Kueterman - Apr 28 Kevin Gilpin - May 22 Ksenia Kondrashova - May 30 Once suspended, apollolabsbin will not be able to comment or publish posts until their suspension is removed. Once unsuspended, apollolabsbin will be able to comment and publish posts again. Once unpublished, all posts by apollolabsbin will become hidden and only accessible to themselves. If apollolabsbin is not suspended, they can still re-publish their posts from their dashboard. Note: Once unpublished, this post will become invisible to the public and only accessible to Omar.unwrap();. They can still re-publish the post if they are not suspended. Thanks for keeping DEV Community safe. Here is what you can do to flag apollolabsbin: apollolabsbin consistently posts content that violates DEV Community's code of conduct because it is harassing, offensive or spammy. Unflagging apollolabsbin will restore default visibility to their posts. DEV Community — A constructive and inclusive social network for software developers. With you every step of your journey. Built on Forem — the open source software that powers DEV and other inclusive communities.Made with love and Ruby on Rails. DEV Community © 2016 - 2023. We're a place where coders share, stay up-to-date and grow their careers.



This post first appeared on VedVyas Articles, please read the originial post: here

Share the post

ESP32 Embedded Rust at the HAL: Remote Control Peripheral

×

Subscribe to Vedvyas Articles

Get updates delivered right to your inbox!

Thank you for your subscription

×