in the past i used the RMT Peripheral for measuring a Pulse length, change this Value and transmit a new Pulse (with new Length).
All this has to be very fast and in IRAM.
Now i wanted to update everything the the actual IDF Version. But nothing is working any more.
Why i cant register a custom ISR?
Why i have to use queues?
Why i cant acces RMTMEM directly?
here is my Code:
ISR
Code: Select all
void IRAM_ATTR rmt_isr_handler(void* arg) {
uint32_t intr_st = RMT.int_st.val; // get RMT Status -> Interrupt source (kann nur RMT CH1 receive sein)
RMT.int_clr.val = intr_st; // Clear the Int-Flag which is set
RMT.conf_ch[1].conf1.rx_en = 0; // disable receiver
RMT.conf_ch[1].conf1.mem_owner = RMT_MEM_OWNER_TX; // sonst wird Servo länge nie geändert
uint32_t servo_tmp = RMTMEM.chan[1].data32[0].duration0; // lese die Input Dauer -> 1 = 1µs
//uint32_t servo_tmp = RMTMEM.chan[1].data32[0].duration1; // lese die Input Dauer -> 1 = 1µs
/*if(servo_tmp > throttle){
RMTMEM.chan[2].data32[0].duration0 = throttle; // throttle ist der aktuelle Limit wert
throttle_output = throttle; // der neue Output wert
}
else{
RMTMEM.chan[2].data32[0].duration0 = servo_tmp; // servo_tmp ist der Input wert (kein Limit)
throttle_output = servo_tmp; // der neue Output wert
}*/
throttle_input = servo_tmp; // last throttle input
if (servo_tmp > Current_throttle_limit) {
servo_tmp = Current_throttle_limit; // neuer Wert für servo_tmp
}
if (servo_tmp > Temperature_throttle_limit) {
servo_tmp = Temperature_throttle_limit; // neuer Wert für servo_tmp
}
if (servo_tmp > Voltage_throttle_limit) {
servo_tmp = Voltage_throttle_limit; // neuer Wert für servo_tmp
}
if (servo_tmp > RPM_throttle_limit) {
servo_tmp = RPM_throttle_limit; // neuer Wert für servo_tmp
}
RMTMEM.chan[2].data32[0].duration0 = servo_tmp; // servo_tmp ist der Input wert inkl. Limit
throttle_output = servo_tmp; // der neue Output wert
RMT.conf_ch[2].conf1.mem_rd_rst = 1; // resette Output
RMT.conf_ch[2].conf1.mem_rd_rst = 0; // resette Output
//RMT.int_clr.ch2_tx_end = 1; // Clear Interrupt Flag -> bereits oben erledigt (sollte auch garnicht aktiv sein)
RMT.conf_ch[2].conf1.tx_start = 1; // Starte Output
//rmt_tx_start(rmt_tx_channel.channel, 1); // IDF funktion zum resetten und starten
if (servo_tmp != 0) {
timerWrite(timer, 0);
//gptimer_set_raw_count(timer,0);
//TIMERG0.hw_timer[1].load_high = 0;
//TIMERG0.hw_timer[1].load_low = 0;
raw_analog_input = true;
failsafe_bool = false;
if (!timerAlarmEnabled(timer)) {
timerAlarmEnable(timer);
}
/*if (TIMERG0.hw_timer[3].config.alarm_en == 0) {
TIMERG0.hw_timer[3].config.alarm_en = 1;
}*/
}
RMT.conf_ch[1].conf1.mem_wr_rst = 1; // resette Input
RMT.conf_ch[1].conf1.mem_owner = RMT_MEM_OWNER_RX; // sonst wird Servo länge nie geändert
RMT.conf_ch[1].conf1.rx_en = 1; // Enable Input
}
Code: Select all
#define RMT_CLK_DIV 80
// time before receiver goes idle
#define RMT_RX_MAX_US 2500
#define SERVO_IN 26
#define SERVO_OUT 18
rmt_config_t rmt_rx_channel;
rmt_config_t rmt_tx_channel;
rmt_rx_channel.channel = RMT_CHANNEL_1; // RMT Channel 1
rmt_rx_channel.gpio_num = (gpio_num_t) SERVO_IN; // RMT Mapped GPIO
rmt_rx_channel.clk_div = RMT_CLK_DIV; // RMT_Clock auf 1us?
rmt_rx_channel.mem_block_num = 1;
rmt_rx_channel.rmt_mode = RMT_MODE_RX; // RMT Mode RX
rmt_rx_channel.rx_config.filter_en = true; // Filter aktiv
rmt_rx_channel.rx_config.filter_ticks_thresh = 250; // Pulse unter 250 werden ignoriert (0...255)
rmt_rx_channel.rx_config.idle_threshold = RMT_RX_MAX_US; // Pulse über 2500 werden ignoriert -> Gleichzeitig die Verzögerung zw. Puls und ausführung der ISR
rmt_config(&rmt_rx_channel);
rmt_set_rx_intr_en(rmt_rx_channel.channel, true);
rmt_rx_start(rmt_rx_channel.channel, 1);
rmt_tx_channel.channel = RMT_CHANNEL_2; // RMT Channel 2
rmt_tx_channel.gpio_num = (gpio_num_t) SERVO_OUT; // RMT Mapped GPIO
rmt_tx_channel.clk_div = RMT_CLK_DIV; // RMT_Clock auf 1us
rmt_tx_channel.mem_block_num = 1;
rmt_tx_channel.rmt_mode = RMT_MODE_TX; // RMT Mode TX
rmt_tx_channel.tx_config.loop_en = 0; // disable loop
rmt_tx_channel.tx_config.carrier_en = 0; // disable carrier
rmt_tx_channel.tx_config.idle_output_en = 0; // activate output while idle
//rmt_tx_channel.tx_config.idle_level = RMT_IDLE_LEVEL_LOW; // output level to 0 when idle
//rmt_tx_channel.tx_config.carrier_duty_percent = 50; // must be set to prevent errors - not used
//rmt_tx_channel.tx_config.carrier_freq_hz = 5000; // must be set to prevent errors - not used
//rmt_tx_channel.tx_config.carrier_level = RMT_CARRIER_LEVEL_HIGH; // must be set to prevent errors - not used
rmt_config(&rmt_tx_channel); // set Config
//rmt_tx_start(rmt_tx_channel.channel, 1); // Output wird in ISR gestartet
//rmt_set_tx_intr_en(rmt_tx_channel.channel, true); // Output Interrupt unnötig
rmt_isr_register(rmt_isr_handler, NULL, ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL2, NULL); // ESP_INTR_FLAG_IRAM
RMTMEM.chan[2].data32[0].duration0 = 0; // Output Idle/Default value
RMTMEM.chan[2].data32[0].level0 = 1; // Output Idle/Default value
RMTMEM.chan[2].data32[0].duration1 = 0; // Output Idle/Default value
RMTMEM.chan[2].data32[0].level1 = 0; // Output Idle/Default value