Разработка сервопривода с BLDC мотором

dc7dfcb729d1a55f04e977e3c3c5105f.jpeg

Открытый проект серво-контроллера MC50 продолжает развиваться. На этот раз поговорим о создании сервопривода. 

Сервоприводы в умном доме нужны повсеместно:   в запорных кранах, в электрических замках, в моторизированных кронштейнах, столах, жалюзи, в автоматических дверях, калитках, окнах, маркизах, воротах, поворотных видеокамерах, регулируемых креслах, электро-пандусах и проч. Поэтому технология сервоприводов весьма востребована и тут есть где развернуться творчеству.

Предыдущие статьи по теме проекта MC50

В прошлой статье было показано как заставить BLDC мотор крутиться с помощью периферии микроконтроллера S5D9 семейства Renesas Synergy™

Теперь это вращение надо заставить делать полезную работу. Сторонние наблюдатели могут сказать, что работа уже сделана если мотор вращается, цель достигнута. Ставь редуктор и в прод. Но на самом деле проблемы только начинаются.

Конструкция

Конструкция состоит из мотор-редуктора, дополнительного редуктора 29/40, простого узла с серво-потенциометром для контроля за скоростью выходного вала и термистором для контроля за температурой мотора. Как видно, внешний редуктор даёт удобно разместить серво-потенциометр. Дополнительно он увеличивает момент силы  1.3 раза Такая конструкция в разных масштабах встречается во множестве сервоприводов. 

Конструкция сервопривода

Конструкция сервопривода

Схема подключения

Плата серво-контроллера рассчитана на питание от внешнего источника напряжением от 20 до 30 В. Но силовой драйвер продолжает функционировать при понижении напряжения до 7 В. При отсутствии внешнего источника напряжения плата может питаться от USB, но силовой драйвер при этом функционировать не будет.

Схема подключения серво-контроллера MC50

Схема подключения серво-контроллера MC50

О частоте вращения BLDC мотора

Частота вращения BLDC двигателя определяется приложенным к нему напряжением при условии постоянной нагрузки на валу (считаем что 6-шаговая коммутация в это время работает безукоризненно, напряжение меняем ШИМ-ом). Эта частота записывается в даташите на мотор. Если момент силы нагрузки будет больше или меньше, то частота будет разная при неизменном напряжении. Но мы не знаем точно момент силы нагрузки и он скорее всего будет переменным. 

Для идеального двигателя без нагрузки, без трения и без сопротивления обмоток частоту вращения при определенном напряжении можно узнать вращая мотор внешним приводом до достижения заданного напряжения. Частота вращения в этот момент и будет искомой частотой. Но тут важна  форма напряжения. Применив 6-шаговую коммутацию к мотору с синусоидальной обратной ЭДС, не получится получить ту же частоту.

Идеальный BLDC двигатель будет крутиться с бесконечной частотой при подаче на него бесконечного напряжения. У реального же  BLDC двигателя в какой-то момент сначала наступит насыщение магнитопровода, резко повысится ток через обмотки, обмотки раскалятся и спустя некоторое время мотор загорится. Поэтому частота вращения и допустимый момент силы ещё ограничиваются температурой мотора. 

Разработка архитектуры управления.

Если для для управления голым двигателем архитектура достаточно ясна, то для управления сервоприводом с неизвестной динамикой нагрузки все несколько сложнее.

Для начала отметим, что частота вращения ротора не равна частоте вращения сервопривода, а в динамике с реальной механикой с люфтами и упругими реакциями  даже не пропорциональна. 

Для управления частотой вращения самое лёгкое решение — это просто менять скважность широтно-импульсной модуляции (ШИМ). 

Простейшая модель сервопривода в Simulink. Здесь реализована 6-шаговая коммутация и вращение только в одном направлении

Простейшая модель сервопривода в Simulink. Здесь реализована 6-шаговая коммутация и вращение только в одном направлении

Файл модели здесь

При постоянном моменте силы нагрузки на мотор или ручном управлении все довольно хорошо получается. Мы линейно меняем скважность и добиваемся нужной частоты вращения. Коммутация автоматическая с помощью датчиков Холла находящихся в моторе.  Метод отлично работает в самокатах

Осциллограмма сигналов  при вращении груза в вертикальной плоскости

Осциллограмма сигналов при вращении груза в вертикальной плоскости

Но как только момент силы начнёт меняться частота вращения начнёт пульсировать, как показано на видео ниже.  

Непостоянство частоты вращения при отсутствии автоматического регулирования

Непостоянство частоты вращения при отсутствии автоматического регулирования

Самое очевидное решение — это применить PID управление с обратной связью по частоте вращения. К сожалению все не так просто. Серво-приводы могут предназначаться для управления угловой скоростью или для управления положением, в обоих случаях нужны разные алгоритмы. И в обоих случаях простой одноконтурный PID очень плохо работает. В случае со стабилизацией положения нужен регулятор с переходной характеристикой не менее третьего  порядка. А PID имеет второй порядок. Т.е. оставаясь в рамках PID нужно две петли управления, вложенные одна в другую.  Нам нужна хорошая, быстрая, оптимизируемая, масштабируемая реализация PID алгоритма. 

Такая реализация есть в среде MATLAB Simulink в виде модели конвертируемой в исходники на C. Ниже представлена модель в виде открытой расширяемой подсистемы.

Файлы модели здесь.

Модель универсального PID регулятора

Модель универсального PID регулятора

Модель повторяет функциональность встроенного PID компонента Simulink, но при этом выводит все коэффициенты PID как входные аргументы в одной шине. Аргументы можно менять и в стандартном компоненте используя символьные обозначения переменных из рабочего пространства, но это влечёт за собой неявные зависимости приводящие к ошибкам. А шина обеспечивает генерацию аргумента как передаваемой структуры. Это уменьшает объем кода при интеграции модели в embedded проект и упрощает рефакторинг моделей.  

Диалог настройки PID регулятора в Simulink

Диалог настройки PID регулятора в Simulink

Для предотвращения бесконечного нарастания интегральной составляющей (anti-windup) применён метод clamping. 

Кроме того, в нашей модели реализован ограничитель скорости нарастания выходного сигнала. Это вносит дополнительную защиту в модель от предельных осцилляций в случае использования некорректных начальных коэффициентов во время тюнинга.  

Сгенерированные из модели исходники находятся в директории MATLAB_PID.

Выбор одноконтурного или двухконтурного управления скоростью вращения серво-привода.

Чтобы сделать выбор архитектуры петли управления проведём эксперимент. Сделаем в среде FreeMaster две записи  сигналов в разных режимах управления мотором. Записывать будем одновременно четыре сигнала:

  • сигнала включения

  • тока протекающего через мотор,  

  • состояния датчиков Холла, отражающих скорость вращения ротора

  • скорость выходного вала привода. 

Первая запись ниже сделана во время скачкообразного включения вращения мотора в режиме 6-step с максимальным напряжением.

cc0636112a66b4a6fe905388147f9f64.gif

Вторая запись ниже сделана во время скачкообразного включения вращения мотора в режиме 6-step с удержанием постоянного тока через мотор с помощью петли управления током. 

b99dfd3fd66f470558425148b1bca7ce.gif

Если посмотреть на реакцию скорости выходного вала на скачок воздействия, то на первой записи видна крайне нелинейная кривая скорости. На второй записи скорость достаточно линейно нарастает, но нарастание начинается с некоторой задержкой.

Очевидно в первом случае практически трудно будет  проводить регулировку скорости регулируя алгоритмом  PID скважность ШИМ. Во всяком случае с интервалом регулирования меньшим 0.1 сек.  Поскольку скорость откликается совершенно не похожим на линейную систему образом. А классический PID хорош только для линейных систем. 

Во втором случае отклик гораздо более линейный и PID здесь подойдёт. Вернее тут подойдёт простой PI контур, поскольку отклик демонстрирует инерциальную нагрузку без упругости (осцилляций).   Но надо помнить — тут уже применён высокоскоростной контур поддержки заданного тока. Т.е. в данном случае у нас получится 2-контурная система: быстрый PI контур управления током через ШИМ и медленный PI для управления скоростью через задание тока.  

В итоге пришли к следующей архитектуре в составе модели Simulink:

Архитектура с двумя петлями управления скоростью вращения сервопривода в среде Simulink

Архитектура с двумя петлями управления скоростью вращения сервопривода в среде Simulink

Файл модели здесь

Модель включает мотор-редуктор с планетарной передачей и датчиками Холла, внешний редуктор, серво сенсор с моделью измерения скорости включая шумы измерения, 3-фазный инвертер с CMOS транзисторами, ШИМ модулятор и два контура управления: по скорости и по току. Цветами на модели выделяются участки работающие с разной частотой тактирования. Контур тока работает на частоте 16 Кгц, контур скорости на частоте 100 Гц.

Измерения частоты вращения ротора датчиками Холла

В модели показанной выше частота вращения ротора измеряется по датчикам Холла. Но в реальности оказалось, что измерение длительности интервалов между фронтами импульсов с датчиков плохо подходит для определения частоты вращения ротора. Из графика ниже следует, что при постоянной частоте разница в длительностях интервалов может составлять до 30%. Такая погрешность потом выразится в недостаточной точности или быстроте стабилизации частоты вращения.

a0d5f1466ccd55248e9de3cc45611fee.png

В нашей программе мы применяем иной способ измерения частоты вращения. Таймера захватывают время каждого фронта сигнала, но разницу считают не от предыдущего фронта, а от последнего фронта того же полюса.   

Используется логика захвата таймеров GPT3211 и GPT3212 (согласно хидеру из SSP они имеет имена R_GPTB3 и R_GPTB4). Таймера имеют по два модуля захвата, поэтому для сигналов с трех датчиков нужно два таймера. Таймера тактируются абсолютно синхронно благодаря команде одновременного запуска (все таймера в Synergy можно запустить синхронно). 

Здесь фрагмент того как производится измерение в обработчике прерываний от АЦП:

  st = R_GPTB3->GTST;  // Читаем флаги состояния capture таймера  GPT3211

  if (st & BIT(0))     // Проверяем флаг TCFA. Input Capture/Compare Match Flag A
  {
    // Здесь если событие захвата произошло

    R_GPTB3->GTST = 0;      // Очищаем флаг захвата и остальные флаги.
                            // За другие флаги захвата не беспокоимся, поскольку они при штатной работе не могут быть взведены в этот момент.

    val = R_GPTB3->GTCCRA;  // Читаем регистр с захваченным состоянием счетчика

    // Здесь рассчитываем разницу по отношению к предыдущему захваченному значению на том же угле поворота ротора, т.е. для полюса с номером в переменной hall_u_cnt
    if (hall_u_prev_arr[hall_u_cnt] > 0)
    {
      if (val > hall_u_prev_arr[hall_u_cnt])
      {
        hall_u_capt_arr[hall_u_cnt] = val - hall_u_prev_arr[hall_u_cnt];
      }
      else
      {
        // Корректируем если было произошло переполнение счетчика между захватами
        hall_u_capt_arr[hall_u_cnt] =  0x7FFFFFFF -(hall_u_prev_arr[hall_u_cnt] - val -1);
      }

      hall_u_capt = hall_u_capt_arr[hall_u_cnt]; // Сохраняем разницу в промежуточную переменную. Эта переменная используется при отладке через FreeMaster
      // .......................................................
      one_turn_period = hall_u_capt;             // Записываем длительность полного оборота ротора в глобальную переменную для дальнейшего использования остальными задачами
      // .......................................................
    }
    hall_u_prev_arr[hall_u_cnt] = val;         // Сохраняем текущее захваченное значение в переменную предыдущего значения
    hall_u_cnt++;                              // Ведем счет полюсов. Для каждого полюса сохраняется своя измеренная величина
    if (hall_u_cnt >= 8) hall_u_cnt = 0;

    // Определяем направление вращения
    h = R_IOPORT5->PCNTR2 & 0x7;  // Читаем сигналы датчиков Холла здесь снова, несмотря на то что они уже были прочитаны в обработчике прерывания
                                  // Это нужно поскольку capture логика может сработать уже после того как в ISR были прочитаны состояния датчиков
    if ((h == 0b100) || (h == 0b011))      rotating_direction = 1; // Направление вращения определяем по паттернам сигнало с датчиков сразу после текущего фронта
    else if ((h == 0b010) || (h == 0b101)) rotating_direction = -1;

    R_GPTB5->GTCLR_b.CCLR13 = 1;  // Сброс счетчика отслеживающего остановку вращения
    R_GPTB5->GTST           = 0;  // Сброс флагов счетчика отслеживающего остановку вращения
  }

  if (st & BIT(1))
  {
    // Input capture/compare match of GTCCRB occurred
    R_GPTB3->GTST = 0;
    val = R_GPTB3->GTCCRB;
    if (hall_v_prev_arr[hall_v_cnt]>0)
    {
      if (val > hall_v_prev_arr[hall_v_cnt])
      {
        hall_v_capt_arr[hall_v_cnt] = val - hall_v_prev_arr[hall_v_cnt];
      }
      else
      {
        hall_v_capt_arr[hall_v_cnt] =  0x7FFFFFFF -(hall_v_prev_arr[hall_v_cnt] - val -1);
      }
      hall_v_capt = hall_v_capt_arr[hall_v_cnt];
      one_turn_period = hall_v_capt;
    }
    hall_v_prev_arr[hall_v_cnt] = val;
    hall_v_cnt++;
    if (hall_v_cnt >= 8) hall_v_cnt = 0;

    h = R_IOPORT5->PCNTR2 & 0x7;  // Читаем сигналы датчиков Холла здесь чтобы они были прочитаны не раньше чем стработает capture логика
    if ((h == 0b110) || (h == 0b001))      rotating_direction = 1;
    else if ((h == 0b011) || (h == 0b100)) rotating_direction = -1;

    R_GPTB5->GTCLR_b.CCLR13 = 1;  // Сброс счетчика отслеживающего остановку вращения
    R_GPTB5->GTST           = 0;
  }


  st = R_GPTB4->GTST;

  if (st & BIT(0))
  {
    // Input capture/compare match of GTCCRA occurred
    R_GPTB4->GTST = 0;
    val = R_GPTB4->GTCCRA;
    if (hall_w_prev_arr[hall_w_cnt]>0)
    {
      if (val > hall_w_prev_arr[hall_w_cnt])
      {
        hall_w_capt_arr[hall_w_cnt] = val - hall_w_prev_arr[hall_w_cnt];
      }
      else
      {
        hall_w_capt_arr[hall_w_cnt] =  0x7FFFFFFF -(hall_w_prev_arr[hall_w_cnt] - val -1);
      }
      hall_w_capt = hall_w_capt_arr[hall_w_cnt];
      one_turn_period = hall_w_capt;
    }
    hall_w_prev_arr[hall_w_cnt] = val;
    hall_w_cnt++;
    if (hall_w_cnt >= 8) hall_w_cnt = 0;

    h = R_IOPORT5->PCNTR2 & 0x7;  // Читаем сигналы датчиков Холла здесь чтобы они были прочитаны не раньше чем стработает capture логика
    if ((h == 0b101) || (h == 0b010))      rotating_direction = 1;
    else if ((h == 0b110) || (h == 0b001)) rotating_direction = -1;

    R_GPTB5->GTCLR_b.CCLR13 = 1;  // Сброс счетчика отслеживающего остановку вращения
    R_GPTB5->GTST           = 0;
  }

Здесь мы получаем значение частоты вращения c девиацией меньшей 0.3%, но с гораздо большей задержкой чем могли бы получить измеряя длительности между соседними фронтами. Но в последнем случае нам пришлось бы применить фильтр, который внёс бы ещё большую задержку.   

Экстраполяция частоты вращения при внезапной остановке

Вращение ротора может внезапно прекратится при встрече сервопривода с препятствием. Но тогда блок расчёта частоты вращения по датчикам Холла просто не будет выполняться. В результате показания частоты застынут, а алгоритм 6-шаговой коммутации застынет на постоянном включении одной ветви обмотки. Поэтому нужно реализовать блок экстраполяции частоты вращения при отсутствии сигналов с датчиков Холла. Пример реализации показан ниже.   

  // Блок линейно понижающий скорость в случает отсутствия сигналов с датчиков Холла
  if (one_turn_period != 0)
  {
    if (R_GPTB5->GTST & BIT(6))  // Проверяем флаг TCFPO. Overflow Flag
    {
      // В случае переполения тамера сразу отмечаем скорость как нулевую.
      // Поскольку переполение таймера происходит с периодом в две секунды, то такую низкую скрость принимаем как нулевую
      one_turn_period = 0;
    }
    else
    {
      // За один оброт мотора мы имеем 8 полюсов * 3 датчика = 24 события сброса таймера R_GPTB5
      // И если таймер R_GPTB5 смог набрать 2/3 (16/24) длительности одного оборота и не был сброшен значит скорость упала
      // и можно начинать снижать оценку текущей скорости
      uint32_t no_edge_period = R_GPTB5->GTCNT*16;
      if (no_edge_period > one_turn_period)
      {
        one_turn_period = no_edge_period;
      }
    }
  }

57a820adece90da0c08da27ff3f679bf.gif

Через некоторое время показатель частоты вращения упадёт до нуля и алгоритм управления скоростью примет решение об отключении тока.

Влияние способа коммутации силовых транзисторов на качество управления и энергопотребление

В прошлой статье о 6-шаговом управлении коммутацией были показаны несколько способов переключения транзисторов при ШИМ модуляции. В нашей программе оставлено два способа. Между ними  можно выбирать с помощью настройки параметра Enable soft commutation.  

4ce19c2482f535903a4f7a74ace7c53c.gif

На нашем мотор-редукторе эти два способа показали только незначительные различия. При одинаковой частоте вращения ток потребления был идентичным. Но при мягкой коммутации вращение мотора начиналось при меньшем значении коэффициенте заполнения. Дело в том, что мотор из-за трения не начинает крутиться до того момента как коэффициент заполнения ШИМ не превысит некий порог.  Этот порог в случае жёсткой коммутации в нашем случае был в районе 55%, а в случае мягкой коммутации в районе 30%. Т.е. мягкая коммутация даёт больший диапазон регулирования ШИМ — 70%, в противовес жёсткой — 45%. Это отражается потом и на качестве управления частотой вращения. При мягкой коммутации качество управления несколько лучше.  

Способ коммутации выбирается параметром en_soft_commutation.

Регулировка тока затворов силовых транзисторов

На плате серво-контроллера используется микросхема драйвера TMC6200. Микросхема получает сигналы от микроконтроллера и управляет затворами силовых транзисторов. Микроконтроллер не может напрямую управлять затворами поскольку там нужны высокие напряжения и довольно большие импульсные токи. 

Типичная схема драйвера на TMC6200

Типичная схема драйвера на TMC6200

У этой микросхемы есть возможность через интерфейс SPI задавать уровень выходных токов на затворы. Есть 4 уровня: от самого слабого 400…600 мА до самого сильного  1200…1800 мА.

Как показали испытания всех возможных уровней, на ток потребления они практически не влияют. Измерения мощности при работе двигателя весьма зашумлены, и с учётом этого шума возможно допустить наличие некоторой разницы в пределах 100 мВт. 

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

Управлять настройками драйвера TMC6200 можно с помощью ряда параметров. Настройки загружаются при старте основной задачи управления мотором.

Калибровка смещения токовых усилителей драйвера TMC6200

Микросхема TMC6200 имеет встроенные усилители напряжения с токовых шунтов расположенных в фазах серво драйвера. Наличие встроенных усилителей упрощает схему. Есть возможность менять коэффициент усиления через интерфейс SPI.

b760f993fa87a23833a42e1216375b50.png

Однако недостатком этих усилителей является довольно большое напряжение смещения. Ещё хуже, то что оно сильно зависит от температуры микросхемы. Но мало того, оно разное для каждого из 3 усилителей и может меняться во времени даже при постоянной внешней температуре. В нашей программе используется самый чувствительный режим с усилением в 20 раз. При таком усилении смещение на выходе усилителей достигает 240 мВ и более.

Решение проблемы найдено в том что перед каждым включением мотора производится перекалибровка смещения нуля для каждого из 3 усилителей. Перекалибровка длится около 15 мсек и существенного влияния на быстродействие не оказывает.

Что делать с обратной ЭДС?  

Как только мотор начинают крутить внешние силы вместо нашего драйвера он превращается в генератор. В генератор мотор также превращается на короткие промежутки времени когда происходит торможение. Если частота вращения вызванная  внешними силами превышает частоту вращения на номинальном напряжении при холостом ходе,   то повышается напряжение на шине питания. Ниже на осциллограмме показаны скачки напряжения на шине питания когда сервопривод вращает груз на рычаге с постоянным значением ШИМ. В моменты опускания груза напряжение на шине питания повышается на 5.5 В. Это происходит потому что частота вращения ротора в эти моменты превышает максимальную частоту вращения на номинальном напряжении по даташиту.  

Осциллограмма выброса обратной ЭДС на шине питания

Осциллограмма выброса обратной ЭДС на шине питания

Если бы мы управляли скоростью и не давали разгоняться сервоприводу, то таких выбросов напряжения не было бы. Однако скачки напряжения могут возникнуть и при выключенном состоянии сервопривода. Тогда стратегия такая. Когда напряжение достигнет уровня достаточного для включения процессора, он сразу подаёт сигнал включения на все нижние транзисторы. Транзисторы закорачивают обмотки мотора и напряжение спадает.  

Проблема определения скорости вращения серво-потенциометра

Если внимательно посмотреть на сигнал приходящий с серво-потенциометра установленного на выходном валу, то можно заметить, что он содержит довольно существенный шум.
Чтобы найти скорость надо получить функцию дифференциала  угла поворота от времени. При цифровом управлении это будет просто разница между текущим и предыдущим положением. Как видно из скриншота, после такой операции получается абсолютно зашумлённый сигнал. В этом случае применяем глубокую двухступенчатую фильтрацию.  Фильтрацию выполняем с частотой ШИМ т.е. 16 КГц

Вид сигнала с серво-потенциометра

Вид сигнала с серво-потенциометра

Модель Simulink для тестирования вариантов фильтрации сигнала скорости вращения выходного вала сервопривода.

Модель Simulink для тестирования вариантов фильтрации сигнала скорости вращения выходного вала сервопривода.

7904fa5186033c98d93f7869374c2a19.gif

Поскольку фильтр вносит фазовую задержку мы не можем на основе такого отфильтрованного сигнала управлять как угодно быстро и точно. 

Нужно узнать частоту на которой фаза на выходе фильтра станет инверсной по отношению к фазе на входе.  Для этого конструируем вспомогательную модель для тестирования нашего эвристического фильтра

Модель для поиска критической фазовой задержки

Модель для поиска критической фазовой задержки

Здесь не прибегаем к сложным анализаторам и эквалайзерам, а просто смотрим очерёдность переходов через ноль. Как только очерёдность нарушается, значит есть сильное смещение фаз между сравниваемыми сигналами. 

Результат работы модели

Результат работы модели

В точке времени 11.4 сек видим первую аномалию. Это и будет место первой инверсии фазы. Легко понять,   что частота в этой точке будет равняться 1140 Гц.  Следовательно после нашего фильтра мы не можем PID регулятором корректировать скоростью быстрее чем 1000 раз в секунду, иначе может возникнуть возбуждение в петле управления. Увеличение длины фильтра бегущего среднего в два раза также в два раза уменьшает предельную частоту управления. 

Разработка приложений для MC50

Программный фреймворк  серво контроллера MC50 выполнен на базе Azure RTOS. На данном этапе он содержит в себе практически весь состав промежуточного программного обеспечения Azure RTOS с драйверами периферии. Поверх слоя промежуточного ПО находится несколько прикладных задач: управления мотором, управления микросхемой 3-фазного драйвера мотора, измерения , GUI, управление выходами и другие. 

Грубая структура программного обеспечения

Грубая структура программного обеспечения

В текущей версии софта реализовано управление рычагом на заданные углы с заданной скоростью. С помощью ручного энкодера производится калибровка углов, настройка скорости поворота и номер узла на шине CAN. Все остальные параметры можно настроить через терминал VT100 через USB VCOM или через интернет, как это было показано в предыдущих статьях. Команды сервоприводу могут подаваться с ручного энкодера, по шине CAN и через протокол FreeMaster через USB.

0ba7dfb72d20b870ac2047beb8c971d0.gif

Разработка продолжается…

© Habrahabr.ru