im currently programming a robot arm with stepper and servomotors.
I have trouble coding the software for 3 steppermotors. Id like to control the steps with RMT. In order to do that I have to detect the Moment, when the RMT-Modula has generated all Symbols. After finishing the transmition I have to change the direction of the stppers by toggeling the GPIO. There is an ISR-Callback to detect the exact Moment, that triggers after finishing a RMT-Transmition. Here I have problems to get the ISR every time. To change the direction of the steppers, all transmitions have to be done, but sometimes there are not all ISRs generated. Sometimes only one cycle workes, sometims multiple like two, or three.
This is my init:
Code: Select all
esp_err_t stepper_rmt_init() {
for(int i = 0; i < 3; i++) {
// --- RMT TX Channel ---
rmt_tx_channel_config_t tx_chan_cfg = {
.gpio_num = MOTOR_STEP_PIN[i],
.clk_src = RMT_CLK_SRC_DEFAULT, // Use default clock source
.mem_block_symbols = 48, //amount of symbols in memory block
.resolution_hz = RMT_RESOLUTION_HZ, // 1MHz resolution for 1us timing
.trans_queue_depth = 10,
};
ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_cfg, &stepper[i].channel));
// --- Encoder ---
rmt_copy_encoder_config_t enc_cfg = {};
ESP_ERROR_CHECK(rmt_new_copy_encoder(&enc_cfg, &stepper[i].copy_encoder));
rmt_tx_event_callbacks_t cbs = {
.on_trans_done = rmt_tx_done_callback,
};
ESP_ERROR_CHECK(rmt_tx_register_event_callbacks(stepper[i].channel, &cbs, (void *)i));
// Channel aktivieren
ESP_ERROR_CHECK(rmt_enable(stepper[i].channel));
}
ESP_LOGI("RMT_SETUP", "Stepper RMT channels initialized successfully.");
return ESP_OK;
}Code: Select all
static bool rmt_tx_done_callback(rmt_channel_handle_t channel, const rmt_tx_done_event_data_t *edata, void *user_ctx) {
int motor_id = (int)user_ctx;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
getriggert++;
rmt_stepper_done |= (1 << motor_id);
if (rmt_stepper_done == 0b111)
{
rmt_stepper_done = 0;
vTaskNotifyGiveFromISR(calculate_next_pose_timer_handle, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken)
{
portYIELD_FROM_ISR();
}
}
return xHigherPriorityTaskWoken;
}Code: Select all
for (int i = 0; i < 3; i++)
{
new_motor_settings.steps_to_go[i] = 300;
new_motor_settings.new_motor_speed[i] = 5000.0f;
if (new_motor_settings.steps_to_go[i] > MAX_SEGMENT_STEPS)
go_interpolated = false;
float period_us = RMT_RESOLUTION_HZ / new_motor_settings.new_motor_speed[i]; // wenn fehler wieder auf int setzen
high_period[i] = period_us / 2;
low_period[i] = period_us - high_period[i];
step_symbol[i] = (rmt_symbol_word_t){
.level0 = 1,
.duration0 = high_period[i],
.level1 = 0,
.duration1 = low_period[i]};
}
for (int i = 0; i < 3; i++)
{
rmt_disable(stepper[i].channel);
rmt_enable(stepper[i].channel);
if(new_motor_settings.steps_to_go[i] <= 0){
rmt_stepper_done |= (1 << i);
}
else{
rmt_transmit_config_t tx_cfg = {
.loop_count = new_motor_settings.steps_to_go[i],
.flags.eot_level = 0,
};
esp_err_t ret = rmt_transmit(
stepper[i].channel,
stepper[i].copy_encoder,
segment_symbols[i],
sizeof(rmt_symbol_word_t),
&tx_cfg
);
if (ret == ESP_OK) {
ESP_LOGI("RMT", "Motor %d Transmit started – %d Steps", i, new_motor_settings.steps_to_go[i]);
} else {
ESP_LOGE("RMT", "Motor %d Transmit ERROR: %s", i, esp_err_to_name(ret));
// Optional: Zähler trotzdem hochzählen, damit Task nicht hängen bleibt
rmt_stepper_done |= (1 << i);
}
}
}That only workes a few times, than not all ISRs are generated. In the following there is an example of the output:
Code: Select all
I (6097) I2C_SETUP: I2C master initialized successfully.
I (6147) UART2_SETUP: STS UART (2) initialized successfully.
I (6147) Partition Init: Partition for path poses initialized successfully.
I (6197) UART0_SETUP: User UART (1) initialized successfully.
I (6197) RMT_SETUP: Stepper RMT channels initialized successfully.
I (7337) TIMER_SETUP: Timer initialized successfully.
Called ISR: 0
I (7337) DIR: Motor 0 DIR=0 (Ziel 29218 > Ist 27877)
I (7337) DIR: Motor 1 DIR=1 (Ziel 40718 > Ist 30093)
I (7337) DIR: Motor 2 DIR=0 (Ziel 95375 > Ist 97656)
I (7347) RMT: Motor 0 Transmit started – 300 Steps
I (7347) RMT: Motor 1 Transmit started – 300 Steps
I (7357) RMT: Motor 2 Transmit started – 300 Steps
Motor 0 Transmit DONE
Motor 1 Transmit DONE
Motor 2 Transmit DONE
Called ISR: 3
I (7377) DIR: Motor 0 DIR=0 (Ziel 28607 > Ist 27877)
I (7377) DIR: Motor 1 DIR=1 (Ziel 40718 > Ist 30093)
I (7387) DIR: Motor 2 DIR=0 (Ziel 94750 > Ist 97656)
I (7387) RMT: Motor 0 Transmit started – 300 Steps
I (7397) RMT: Motor 1 Transmit started – 300 Steps
I (7397) RMT: Motor 2 Transmit started – 300 Steps
Motor 0 Transmit DONE
Motor 1 Transmit DONE
Motor 2 Transmit DONE
Called ISR: 5If somebody knows a solution for my Problem or knows if the ISR is bugged, id be very grateful
Thanks a lot, Felix