-
Notifications
You must be signed in to change notification settings - Fork 7.6k
RMT - Add capability to set transmitter End Of Transmission/idle state #9235
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@supersebbo - This could the the new API for such the requested RMT feature - let me know if it sound good. /**
Sets the End of Transmission level to be set the <pin> when the RMT transmission ends.
This function affects how rmtWrite(), rmtWriteAsync() or rmtWriteLooping() will set the pin after writing the data.
The default EOT level is LOW, in case this function isn't used before RMT Writing.
This level can be set for each RMT pin and can change between writings to the same pin.
<EOT_Level> shall be Zero (LOW) or non-zero (HIGH) value.
It only affects the transmission process, therefore, it doesn't affect any IDLE LEVEL before starting the RMT transmission.
The pre-transmission idle level can be set manually calling, for instance, digitalWrite(pin, Level).
*/
void rmtSetEOT(int pin, uint8_t EOT_Level); Example:#define MY_RMT_PIN 2
void setup() {
Serial.begin(115200);
if (!rmtInit(MY_RMT_PIN, RMT_TX_MODE, RMT_MEM_NUM_BLOCKS_1, 10000000)) {
Serial.println("init sender failed\n");
}
Serial.println("real tick set to: 100ns");
// sets the End of Transmission Level to HIGH, after writing to the pin. DEFAULT is LOW.
rmtSetEOT(MY_RMT_PIN, HIGH);
// Send the data and wait until it is done - set EOT level to HIGH
rmtWrite(MY_RMT_PIN, led_data, NR_OF_ALL_BITS, RMT_WAIT_FOR_EVER);
} |
This is an example that sets the initial RMT state and then also sets the EOT state: #define BLINK_GPIO 2
#define EOT_INITIAL_STATE_TIME_MS 1000
// BLINK_GPIO shall start at RMT_EOT (HIGH or LOW) as initial state for EOT_INITIAL_STATE_TIME_MS,
// BLINK: 1 second ON, 1 second OFF and then return/stay to RMT_EOT level at the end.
#define RMT_EOT HIGH
// RMT is at 400KHz with a 2.5us tick
// This RMT data sends a 0.5Hz pulse with 1s High and 1s Low signal
rmt_data_t blink_1s_rmt_data[] = {
// 400,000 x 2.5us = 1 second ON
{25000, 1, 25000, 1,},
{25000, 1, 25000, 1,},
{25000, 1, 25000, 1,},
{25000, 1, 25000, 1,},
{25000, 1, 25000, 1,},
{25000, 1, 25000, 1,},
{25000, 1, 25000, 1,},
{25000, 1, 25000, 1,},
// 400,000 x 2.5us = 1 second OFF
{25000, 0, 25000, 0,},
{25000, 0, 25000, 0,},
{25000, 0, 25000, 0,},
{25000, 0, 25000, 0,},
{25000, 0, 25000, 0,},
{25000, 0, 25000, 0,},
{25000, 0, 25000, 0,},
{25000, 0, 25000, 0,},
// Looping mode needs a Zero ending data to mark the EOF
{0, 0, 0, 0}
};
void setup() {
Serial.begin(115200);
Serial.println("Starting Blink testing...");
Serial.flush();
// 1 RMT Block has 64 RMT_SYMBOLS (ESP32|ESP32S2) or 48 RMT_SYMBOLS (ESP32C3|ESP32S3)
if (!rmtInit(BLINK_GPIO, RMT_TX_MODE, RMT_MEM_NUM_BLOCKS_1, 400000)) { //2.5us tick
Serial.println("===> rmtInit Error!");
}
// sets the End of Transmission Level to HIGH, after writing to the pin. DEFAULT is LOW.
rmtSetEOT(BLINK_GPIO, RMT_EOT);
// set initial RMT state by writing a single RMT data
rmt_data_t initStateSetup_rmt_data[] = { {1, RMT_EOT, 0, 0} };
rmtWrite(BLINK_GPIO, initStateSetup_rmt_data, RMT_SYMBOLS_OF(initStateSetup_rmt_data), RMT_WAIT_FOR_EVER);
Serial.printf("\nLED GPIO%d start in the inital level %s\n", BLINK_GPIO, RMT_EOT == LOW ? "LOW" : "HIGH");
delay(EOT_INITIAL_STATE_TIME_MS); // set initial state of the LED is set by RMT_EOT.
// Send the data and wait until it is done - set EOT level to HIGH
Serial.printf("\nLED GPIO%d Blinks 1 second HIGH - 1 second LOW.\n", BLINK_GPIO);
if (!rmtWrite(BLINK_GPIO, blink_1s_rmt_data, RMT_SYMBOLS_OF(blink_1s_rmt_data) - 2, RMT_WAIT_FOR_EVER)) {
Serial.println("===> rmtWrite Blink 1s Error!");
}
Serial.printf("\nLED GPIO%d goes to the EOT level %s\n", BLINK_GPIO, RMT_EOT == LOW ? "LOW" : "HIGH");
}
void loop(){} |
This would be perfect, thanks so much for the quick turn-around. |
While you're in the code could you also add an API to set the RMT clock source to REF_TICK (1MHz) instead of DEFAULT APB? As RMT driven busses are typically slow, using the APB clock results in a huge clock divider to reach kHz speeds, this on it's own is fine but it causes problems when using the Min RX period settings as the register for this value is only 8bit, as described here espressif/esp-idf#11262 (comment) |
I'll work on an API that will allow the user to set the source clock too. This should be ready for Arduino 3.0.0 final release. |
Related area
ESP32 RMT
Hardware specification
ESP32
Is your feature request related to a problem?
It is not possible to set the RMT Transmitter EOT/idle state from the Arduino implementation, making it impossible to drive a bus that requires a logic high idle state.
Describe the solution you'd like
Add a hook to set the EOT state on the RMT init.
The function is available in the Espressif ESP-IDF Implementation as a flag on the RMT TX Config
uint32_t eot_level
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/rmt.html?#_CPPv421rmt_transmit_config_t
Describe alternatives you've considered
No response
Additional context
No response
I have checked existing list of Feature requests and the Contribution Guide
The text was updated successfully, but these errors were encountered: