![](https://habrastorage.org/getpro/habr/upload_files/178/46e/156/17846e156091f4413b4a8e98e8c880cb.png)
Речь о том, как управлять включением и скоростью двигателя постоянного тока на примере сервопривода MC50 так, чтобы сервопривод не сгорел. Несмотря на то, что MC50 был разработан для управления BLDC моторами, он также хорошо подходит и для управления коллекторными двигателями постоянного тока мощностью до 600 Вт. Правда для этого пришлось сделать некоторые незначительные модификации.
Все статьи по открытому проекту MC50 здесь:
Во-первых, сопротивление шунтов в измерителях тока фаз было уменьшено до 1 мОм.
Во-вторых, MOSFET транзисторы CSD18540Q5BT в 3-фазном мосте были заменены на более продвинутые и недавно выпущенные STL320N4LF8. Эти транзисторы отличает уникально низкое сопротивление открытого канала - всего 0.8 мОм, при таком же быстродействии и даже выше чем у CSD18540Q5BT. Благодаря этому на мощностях до 400 Вт и чуть выше сервоприводу не нужен вентилятор. А когда мощность требует вентилятора, то его можно подключить между оставшейся свободной фазой W и клеммой GND.
В текущей версии программы мотор можно включать и выключать в ручном режиме с платы используя ручной энкодер, из управляющей программы Freemaster и по интерфейсу CAN. Для управления скоростью вращения коллекторные двигатели вместо 3-фазных датчиков холла оборудуются 2-фазными датчиками с квадратурным сигналом.
![](https://habrastorage.org/getpro/habr/upload_files/4fb/b15/4a7/4fbb154a765245e664a24a2b23984e51.png)
В программе при выборе типа приложения DC traction motor будет проводится измерение скорости с квадратурного энкодера подключённого к линиям W и V. Сам мотор подключается к клеммам U и V. В данном случае получается полный мост и мотор можно вращать в обоих направлениях.
Осторожно с модуляцией!
Скоростью мотора управляем изменяя коэффициент заполнения ШИМ. Когда хотим получить полную мощность ШИМ отключаем и оставляем статические включённые транзисторы. В традиционных драйверах такое могло привести к падению напряжения в бустерах верхних ключей и их закрытию, поскольку они подзаряжаются только при наличии ШИМ. Но в нашей схеме применена микросхема драйвера 3-фазного моста TMC6200, которая сама создаёт нужное напряжение для верхних ключей без необходимости ШИМ. Это плюс.
Но есть другая проблема - мёртвое время. Мёртвое время обеспечиваемое микросхемой TMC6200 слишком мало для мощных MOSFET применяемых на плате. Дополнительное мёртвое время создаётся в ШИМ генераторах микроконтроллера. Это стандартная фича. Нестандартно здесь будет обеспечить переход из ШИМ в статические сигналы и обратно.
Когда плавно повышаем ШИМ до 100%, то в конце процесса нужно выставить статический сигнал, чтобы в одном плече все время был открыт верхний транзистор, а в другом плече нижний.
Тут может оказаться, что микроконтроллер не справляется с такой задачей без установления на доли микросекунды одновременного высокого уровня на верхнем и нижнем транзисторах использую штатные возможности таймеров. Также следует рассмотреть выход из статических сигналов на формирование ШИМ и ситуации переключения из одной статической конфигурации сигналов к противоположной. Есть опасность коротких (наносекундных), но очень мощных сквозных токов.
![Диаграмма описывающая корректную вставку мёртвого времени при обычной ШИМ модуляции. Но на ней не видно что будет если модуляцию отключить. Диаграмма описывающая корректную вставку мёртвого времени при обычной ШИМ модуляции. Но на ней не видно что будет если модуляцию отключить.](https://habrastorage.org/getpro/habr/upload_files/471/a30/e24/471a30e24e6ba9dda7dae88c830145f5.png)
В случае нашего микроконтроллера Renesas Synergy выход был найден в быстром переключении функции портов с периферийной функции на функцию общего ввода вывода с явной очерёдностью установки уровней сигналов.
Выглядит это так, на примере одной фазы:
/*-----------------------------------------------------------------------------------------------------
Установка состояния на выходе фазы U 3-фазного инвертера
val = 0 - нижний ключ постоянно открыт, верхний постоянно закрыт
val = 100 - нижний ключ постоянно закрыт, верхний постоянно открыт
val = -1 - нижний ключ постоянно закрыт, верхний постоянно закрыт
0 < val < 100 - На выходе сигнал ШИМ с коэфициентом заполнения равным val в процентах
Установка ШИМ буфферизирована, и вступит в действие после окончания текущего цикла ШИМ
-----------------------------------------------------------------------------------------------------*/
void Phase_U_mode(int32_t val)
{
if (val >= 100) gpt0_out_mode = FL_PHASE_PULL_UP;
else if (val == 0) gpt0_out_mode = FL_PHASE_PULL_DOWN;
else if (val < 0) gpt0_out_mode = FL_PHASE_Z_STATE;
else
{
val =(gpt_pwm_cycle_set * (100 - val)) / 100;
// Не даем прекратиться PWM и не даем импульсу стать слишком коротким
if (val < MIN_PWM_COMPARE_VAL)
{
val = MIN_PWM_COMPARE_VAL;
}
else if ((gpt_pwm_cycle_set - val) < MIN_PWM_COMPARE_VAL)
{
val = gpt_pwm_cycle_set - MIN_PWM_COMPARE_VAL;
}
R_GPTA0->GTCCRC = val;
gpt0_out_mode = FL_PHASE_PWM_ON;
}
}
/*-----------------------------------------------------------------------------------------------------
Функция вызываемая из обработчика прерывания для приведения выходов к заданному задачей управления состоянию
\param mode
-----------------------------------------------------------------------------------------------------*/
void Set_output_U(uint8_t mode)
{
uint32_t tmp_H = R_PFS->P415PFS;
uint32_t tmp_L = R_PFS->P414PFS;
switch (mode)
{
case FL_PHASE_PULL_UP :
// Для фазы U устанавливаем P415 (UH) в 1, P414 (UL) в 0
tmp_H = tmp_H & ~(LSHIFT(0x1F,24) | BIT(16));
tmp_H = tmp_H | BIT(2) | BIT(0);
tmp_L = tmp_L & ~(LSHIFT(0x1F,24) | BIT(16) | BIT(0));
tmp_L = tmp_L | BIT(2);
R_PFS->P414PFS = tmp_L; // Записываем состояние выхода в порт данного выхода
__DSB(); // Оператор Data Synchronization Barrier (DSB) необходим для гарантии установления состояния выхода
// до того как начнет выполняться следующая инструкция
R_PFS->P415PFS = tmp_H;
__DSB();
break;
case FL_PHASE_PULL_DOWN :
// Для фазы U устанавливаем P415 (UH) в 0, P414 (UL) в 1
tmp_H = tmp_H & ~(LSHIFT(0x1F,24) | BIT(16) | BIT(0));
tmp_H = tmp_H | BIT(2);
tmp_L = tmp_L & ~(LSHIFT(0x1F,24) | BIT(16));
tmp_L = tmp_L | BIT(2) | BIT(0);
R_PFS->P415PFS = tmp_H;
__DSB();
R_PFS->P414PFS = tmp_L;
__DSB();
break;
case FL_PHASE_Z_STATE :
// Для фазы U устанавливаем P415 (UH) в 0, P414 (UL) в 0
tmp_H = tmp_H & ~(LSHIFT(0x1F,24) | BIT(16) | BIT(0));
tmp_H = tmp_H | BIT(2);
tmp_L = tmp_L & ~(LSHIFT(0x1F,24) | BIT(16) | BIT(0));
tmp_L = tmp_L | BIT(2);
R_PFS->P414PFS = tmp_L;
__DSB();
R_PFS->P415PFS = tmp_H;
__DSB();
break;
case FL_PHASE_PWM_ON :
// Для фазы U переключаем P415 (UH) и P414 (UL) в режим управления периферией
// Перепрограммирвать режим портов только если он не был уже в заданном состоянии
if (((tmp_H >> 24) & 0x1F) != PSEL_03)
{
// Если выход H был установлен в 1, то предварительно установить его в 0
if (tmp_H & BIT(0))
{
tmp_H = tmp_H & ~(LSHIFT(0x1F,24) | BIT(16) | BIT(0));
tmp_H = tmp_H | BIT(2);
R_PFS->P415PFS = tmp_H;
__DSB();
}
// Если выход L был установлен в 1, то предварительно установить его в 0
if (tmp_L & BIT(0))
{
tmp_L = tmp_L & ~(LSHIFT(0x1F,24) | BIT(16) | BIT(0));
tmp_L = tmp_L | BIT(2);
R_PFS->P414PFS = tmp_L;
__DSB();
}
tmp_H = tmp_H & ~(LSHIFT(0x1F,24) | BIT(0));
tmp_H = tmp_H | BIT(16) | BIT(2) | LSHIFT(PSEL_03,24);
tmp_L = tmp_L & ~(LSHIFT(0x1F,24) | BIT(0));
tmp_L = tmp_L | BIT(16) | BIT(2) | LSHIFT(PSEL_03,24);
R_PFS->P414PFS = tmp_L;
__DSB();
R_PFS->P415PFS = tmp_H;
__DSB();
}
break;
}
}
Осторожно с разгоном!
Подавать напряжение на двигатель постоянного тока надо с осторожностью. При резкой подаче даже половинного от номинального напряжения возникает импульс тока через мотор почти в два раза превышающий его максимальный рабочий ток.
![Старт вращения ротора без стадии разгона. Заполнение ШИМ = 50% Старт вращения ротора без стадии разгона. Заполнение ШИМ = 50%](https://habrastorage.org/getpro/habr/upload_files/30f/a7a/333/30fa7a33315e27ab932b4ae135cc2641.png)
Если увеличить напряжение ещё на 10%, то ток уже достигает величины на пределе безопасной работы силовых элементов драйвера.
![Старт вращения ротора без стадии разгона. Заполнение ШИМ = 60% Старт вращения ротора без стадии разгона. Заполнение ШИМ = 60%](https://habrastorage.org/getpro/habr/upload_files/5de/e9d/249/5dee9d249151edf804f9e732e97c303d.png)
Отсюда следует, что запускать мотор постоянного тока следует плавно. Причём даже увеличивая по шагам заполнение ШИМ всего на 1%, можно наблюдать импульсы тока на моторе величиной около 1 А. Поэтому график мощности потребления и тока, показанный ниже, имеет странную пилообразную структуру.
![Старт вращения ротора со стадией разгона. Заполнение ШИМ в конце = 100% Старт вращения ротора со стадией разгона. Заполнение ШИМ в конце = 100%](https://habrastorage.org/getpro/habr/upload_files/f6a/b5c/16e/f6ab5c16e1a0609716f15b8e5ce44a55.png)
Осторожно с торможением!
Если мотор удалось без происшествий разогнать, то теперь задача его остановить. Резкая остановка закорачиванием обмоток работает неплохо, но вызывает сильный удар способствующий ускоренному разрушению ведущего вала при наличии инерционной нагрузки. Поэтому применяют контролируемое замедление снижением напряжения (уменьшая коэффициент заполнение ШИМ). И здесь поджидает обратная ЭДС.
Если мы попытаемся останавливать быстрее чем останавливается мотор при свободном выбеге (когда все транзисторы в драйвере отключаются), то можем получить обратную ЭДС амплитудой превышающей выносливость питающего источника или пробить силовые транзисторы.
![График торможения с уровня ШИМ 40% до 0 за 0.7 сек График торможения с уровня ШИМ 40% до 0 за 0.7 сек](https://habrastorage.org/getpro/habr/upload_files/8ba/bed/ed8/8babeded87e79acc726bccada22fb82a.png)
В нашем случае свободный выбег мотора без нагрузки от максимальной скорости длился чуть менее 3 сек. Поэтому линейное контролируемое замедление длящееся не менее 3 сек. не вызовет перенапряжения в шине питания.
Никогда не забываем о температуре.
На итальянском моторе может быть такая надпись: SERVIZIO S3 25%. На других моторах символы S3 могут встретиться также. Это говорит о том, что мотор не предназначен для постоянной работы. Если его держать с номинальной скоростью в течении, скажем, часа, то он просто сгорит. Поэтому на мотор тоже надо ставить термосенсор. Можно, конечно, следить в программе сколько там процентов времени проработал мотор, но это скорее всего приведёт к недобору ресурса по температуре и более частым отказам в исполнении команд. В нашем сервоконтроллере есть специальный вход для подключения NTC резистора 10 КОм.
Далее можно столкнуться с перегревом самого сервоконтроллера. На плате установлен измерительный термистор рядом с силовыми транзисторами. Кроме этого термосенсор интегрирован в самом микроконтроллере и присутствует защита от перегрева в микросхеме драйвера TMC6200. Следует помнить, что длительный перегрев хуже всего влияет на электролитические конденсаторы, которые быстро теряют свой ресурс при 100 и более град.
Установленные конденсаторы типа EEE-FT1H331AP имеют ресурс 2000 часов при 105 град. С. Несмотря на то, что наш двигатель называется двигателем постоянного тока, его ток потребления при постоянном напряжении все равно импульсный. И амплитуда импульсов достигает десятка ампер. Поэтому импульсная нагрузка на конденсаторы не намного меньше чем в 6-шаговом управлении BLDC моторами. Т.е. конденсаторы греются не только через плату от транзисторов и шунтов, но и сами по себе. В программе реализовано управление вентилятором с клеммы W и задаётся таймаут отключения вентилятора после остановки мотора.
![Положение термистора на плате Положение термистора на плате](https://habrastorage.org/getpro/habr/upload_files/33f/45b/53a/33f45b53a78cf7def9c854252a931a20.png)
Все исходные тексты проекта находятся здесь. В проекте сохранена также функциональность всех предыдущих демонстраций серво управления BLDC и все промежуточное программное обеспечение включая RTOS и сетевые стеки. Переключение между управлением BLDC и DC моторами производится в энергонезависимых настройках. Кроме того добавлено дистанционное управление по CAN с одного сервоконтроллера другим сервоконтроллером.