Arduino Zero - управление шаговым двигателем (прерывание)?

У меня есть плата контроллера шагового двигателя, которая должна пульсировать каждые 40 мкс или около того.

У меня также есть датчики I2C и последовательная запись в преформу.

В настоящее время я запускаю вызов обновления в тесном цикле, но датчики I2C и последовательные записи вызывают значительные задержки, из-за которых моторы заикаются и останавливаются.

Я хотел бы использовать ISR для периодического вызова метода обновления мотора.

Однако я ни за что не могу разобраться с этим таймером.

Вот моя текущая попытка:

void TC4_Handler() {
  Stepper::updateAll();
}

void setup() {

  // Таймеры
  // Настраиваем общие часы (GCLK4), используемые для тактирования таймеров
  REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) |          // Делим источник тактовой частоты 48 МГц на делитель 1: 48 МГц/1=48 МГц
                    GCLK_GENDIV_ID(4);            // Выбор общих часов (GCLK) 4
  while (GCLK->STATUS.bit.SYNCBUSY);              // Ждем синхронизации

  REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC |           // Установите рабочий цикл на 50/50 ВЫСОКИЙ/НИЗКИЙ
                     GCLK_GENCTRL_GENEN |         // Включить GCLK4
                     GCLK_GENCTRL_SRC_DFLL48M |   // Установите источник тактовой частоты 48 МГц
                     GCLK_GENCTRL_ID(4);          // Выбираем GCLK4
  while (GCLK->STATUS.bit.SYNCBUSY);              // Ждем синхронизации

  // Подача GCLK4 на TC4 и TC5
  REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |         // Включить GCLK4 для TC4 и TC5
                     GCLK_CLKCTRL_GEN_GCLK4 |     // Выбираем GCLK4
                     GCLK_CLKCTRL_ID_TC4_TC5;     // Подача GCLK4 на TC4 и TC5
  while (GCLK->STATUS.bit.SYNCBUSY);              // Ждем синхронизации

  REG_TC4_COUNT16_CC0 = 0x000F;                      // Установить регистр TC4 CC0 в качестве значения TOP в режиме совпадения частот
  while (TC4->COUNT16.STATUS.bit.SYNCBUSY);       // Ждем синхронизации

  //NVIC_DisableIRQ(TC4_IRQn);
  //NVIC_ClearPendingIRQ(TC4_IRQn);
  NVIC_SetPriority(TC4_IRQn, 0);    // Установите приоритет Nested Vector Interrupt Controller (NVIC) для TC4 на 0 (самый высокий)
  NVIC_EnableIRQ(TC4_IRQn);         // Подключаем TC4 к вложенному контроллеру векторных прерываний (NVIC)

  REG_TC4_INTFLAG |= TC_INTFLAG_OVF;              // Сбрасываем флаги прерывания
  REG_TC4_INTENSET = TC_INTENSET_OVF;             // Разрешить прерывания TC4
  // REG_TC4_INTENCLR = TC_INTENCLR_OVF; // Отключить прерывания TC4

  REG_TC4_CTRLA |= TC_CTRLA_PRESCALER_DIV1024 |   // Установите прескалер на 1024, 48 МГц/1024 = 46,875 кГц
                   TC_CTRLA_WAVEGEN_MFRQ |        // Переводим таймер TC4 в режим согласования частоты (MFRQ)
                   TC_CTRLA_ENABLE;               // Включить TC4
  while (TC4->COUNT16.STATUS.bit.SYNCBUSY);       // Ждем синхронизации
  // ...
}

, 👍0


1 ответ


1

Поскольку Stepper::updateAll(); не отображается, я не знаю, что он делает. Для точной синхронизации имеет смысл использовать аппаратно управляемые выходные контакты сравнения вывода, такие как TIOAx и TIOBx, вместо того, чтобы запускать какой-либо код для управления выводами при возникновении прерывания.

Если вам нужно управлять несколькими проводами на двигатель, так что импульса на одной выходной линии недостаточно, вы можете рассмотреть возможность использования 74HC595 (или другого регистра сдвига) для передачи битов. Таким образом, каждый раз, когда происходит сравнение выходных данных, линии TIOAx и TIOBx будут посылать импульсы на линию ST_CLK (хранение-часы) SR для передачи битов с триггеров цепочки сдвига на выходные триггеры; затем, на досуге, процедура прерывания может сместить следующий набор битов в '595, готовый к передаче в нужный момент, когда произойдет следующее сравнение выходных данных.

Во время шагового ускорения или замедления лимит счетчика таймера также необходимо обновить в ISR.

,

Я использую этот драйвер https://www.pololu.com/product/2975, все, что делает Stepper::updateAll(), это проверяет, нужно ли импульсировать шаговый штифт., @Cody Smith

В этом случае вы должны использовать линию TIOAx или TIOBx для подачи импульса на A4988 и должны рассчитать ограничения счетчика таймера для установки ISR. Другими словами, не «проверяйте, нужно ли импульсировать шаговый штифт», что равносильно попытке запустить шаговый двигатель с использованием опроса, что является плохой идеей, а вместо этого вычислите, когда шаговый штифт должен быть импульсным, установите таймер. соответственно и есть таймер импульса А4988., @James Waldby - jwpat7