Продолжаю описание электрофокусера с блоком управления на базе Arduino. Третья часть посвящена коду микроконтроллера, а так же некоторым тонкостям сборки и настройки.
Первая часть тут, вторая часть тут.
Данный текст ориентирован на тех, кто будет разбираться в коде с целью его частичного или полного использования и на тех, кто решает подобные задачи и может почерпнуть что-то полезное. Код прокомментирован, так что ограничусь описанием структуры и общей логики, плюс отмечу важные детали.
Код микроконтроллера
Код микроконтроллера разрабатывался и отлаживался в среде Arduino 1.0.5-r2, последняя версия доступна на githab`е.
Так как изначально ставилась задача управления только одним фокусером, я не стал пользоваться возможностями ООП. Только управление шаговым двигателем выделено в отдельный класс в библиотеку StepperClass.
Исходя из поставленой задачи, микроконтроллер должен выполнять следующие основные функции:
- Инициализировать фокусер — Setup();
- Периодически снимать состояние кнопок и потенциометра с пульта ДУ, управлять индикацией состояния светодиодами;
- Общаться с ПО на ноутбуке по RS232 — serialEvent() и SendCmd();
- И управлять шаговым двигателем, вращая его с заданной скоростью в заданном направлении, считая шаги с учетом режима микрошага, при необходимости контролирую выход за заданные границы — StepperClass;
Пару слов о Loop()
Опрос потенциометра производиться с интервалом, заданным в CheckSpeedTime (по умолчанию 100 мс). Кнопки опрашивают каждый раз, хотя это конечно избыточно, можно так же привязать к CheckSpeedTime .
Вращение мотора осуществляется через вызов глобальной функции Roll(), которая транслирует его далее на StepperClass.Roll(), мигая при этом светодиодом на пине motorled.
При изменении текущей скорости любым способом меняется яркость светодиода на пине speedled.
При достаточно долгом бездействии (задается в ReleaseTime) снимается напряжение с двигателя (ШД имеют свойство активно кушать ток и греться). Безусловна, эта опция «на любителя». По-хорошему, после точной фокусировки фокусер трогать нельзя. В идеале — его необходимо механически зафиксировать, если это предусмотрено конструкцией фокусера. Если этого не сделать, то сняв ток с ШД, мы можем получить небольшое смещение положения фокусера, то есть небольшую расфокусировку. В каждом конкретном случае нужно проверять, приводит ли снятие напряжение к смещению фокусера, и если да – отключать автоматическое снятие напряжения в скетче и, либо снимать его вручную (предварительно заблокировав фокусер фиксатором), либо вообще не снимать.
Но и у нее есть недостатки. Главный из них — нет поддержки микрошага. В ряде задач это крайне неудобно. Скорости в библиотеке задаются в оборотах в секунду, а позиция в шагах. Очевидно, что сменив режим микрошага, мы получим иную скорость, и неправильное положение. Если режим микрошага не меняется — ничего страшного, единожды вводим поправочные коэффициенты. Но если режим микрошага динамически переключается, ситуация сильно усложняется. Один из вариантов — делать обертку (wrapper), которая запоминает режим и автоматически пересчитывает координаты и скорости. Что я и делал до поры до времени.
В данном проекте использование AccelStepper вполне приемлемо и оправдано. Я столкнулся с некоторыми странностями и как минимум с одним багом (если поставить скорость в 0 и шагнуть — управление не возвращается, зависаем), но в целом — рекомендую к использованию.
Разработка собственного класса для управления ШД — вынужденный шаг. В другом проекте работа с микрошагом для меня это стала критически важной и промучившись какое время я написал свою библиотеку, существенно более простую, но зато с поддержкой микрошага и ориентированную на работу с линейкой драйверов от Polulu (A4988, DRV8825). Библиотека очень маленькая, выложена на github, текст заголовочника содержит комментарии.
Библиотека будет дорабатываться и обновляться. В честности, есть планы по существенной доработке функции Roll() с целью повышения точности и плавности хода (учет пропущенных по времени шагов, режим «догоняем»).
Использовать разные библиотеки в близких проектах мне не хотелось, поэтому фокусер так же был переведен на StepperClass.
В этом проекте я решил не усложнять жизнь и придерживаться этого же принципа. Как таковая скорость вообще не рассчитывается. Слева быстро, справа — медленно. В то время как код микроконтроллера везде оперирует не скоростью, а интервалом между шагами двигателя, что на практике несколько удобнее.
Протокол управления фокусером по RS232
Ничего стандартного или общепринятого в деле управления фокусировочными устройствами я не нашел (хотя честно признаться, рыл не глубоко). В будущем планирую написать ASCOM-драйвер и использовать с BackyardEOS, а с чем-то еще мне вряд ли придется интегрироваться. Поэтому решил использовать свой очень простой протокол:
168 | ID команды (1 байт) | параметр команды | 13 | 10 |
Контрольной суммы нет, размер команды не ограничивается (только разумным размером буфера приема — 255 байт) и в посылке не предопределен. При приеме команды происходит накопление буфере до тех пор, пока не придет идентификатор конца команды #13#10. После этого идентификатор команды и параметр команды выделяются из буфера и команда выполнятся. Пропуск идентификатора начала или конца команды может привести к пропуску одной команды. На практике это не критично. Более подробно команды и параметры опишу в следующей части, тут это не так важно.
Любая полученная команда обязательно подтверждается либо ответом (например, если это был запрос скорости, тогда используется тот же идентификатор команды), либо подтверждением выполнения действия (тогда может посылок может быть несколько с разными идентификаторами).
Все команды, кроме FOCUSER_GO_TO_POSITION выполняются сразу. Переход на заданную позицию выполняется в главном цикле, так эта операция может выполняться долго, а нам нужно сохранить возможность отмены операции.
Фактически, протокол полностью имитирует работу пульта ДУ и даже чуть больше.
Тонкости адаптации и настройки, а так же некоторые грабли
Регулировка тока на А4988 и пропуск шагов
Драйвер ШД А4988 имеет встроенный ограничитель тока, подаваемого на ШД. Штука очень полезная и важная. Как ей пользоваться описано на сайте разработчика. Но у нее есть один интересный эффект. Как мы знаем, при снижении силы тока падает крутящий момент. Как ни странно, конкретно на А4988 в режиме микрошага это может выражаться в регулярном 100% пропуске шагов на определенной фазе. Поэтому в режиме 1/16 запросто можно получить вместе 16 шагов, только 4, или 8. Добавляем тока – и все хорошо.
Подключение ШД
При подключении ШД к драйверу желательно не перепутать отводы между парами (см. схемы подключения биполярных ШД). Перепутать отводы внутри пары не страшно, получите вращение в другую сторону. Рекомендую первым делом прозвонить пары отводов и проверить сопротивление обмоток, соответствует ли оно тому, что вам обещали.
Один раз мне продали ШД под номинальное напряжение 12В, а оказалось, что на самом деле он рассчитан на 2.8В. А я удивлялся — почему он у меня как-то странно ходит, драйвер греется, ардуинка иногда выключается…
Максимальная скорость вращения, пауза между шагами и микрошаг
У любого ШД есть максимальная скорость вращения. Обычно — это сотни оборотов в секунду. С точки зрения управления ШД это значит, что существует некий минимальный интервал времени между шагами. Пытаться делать шаги чащи не только бесполезно, но даже вредно — ШД будет дергаться, свистеть, гудеть, но нормально ходить не будет. Это еще одна возможность получить ШД, не желающий ходить нормально. Максимальную скорость производитель указывает тоже далеко не всегда, так что вполне вероятно ее придется определять опытным путем.
Важный и интересный момент, о котором обычно не пишут — как использование режима микрошага влияет на максимальную скорость и минимальную длительность паузы между шагами соответственно. Отвечаю – использование микрошага практически никак не влияет на максимальную скорость вращения. По крайней мере, несущественно в рамках данной работы. А вот на длительность паузы между шагами — очень даже влияет. Чем более мелкий шаг мы используем, тем чаще нужно давать команду на следующий шаг. В качестве эксперимента я провел тестирование одного из своих двигателей и получил вот такую вот картину:
По горизонтали – величина паузы между шагами в микросекундах, по вертикали – режим микрошага. В ячейках соответствующая заданному режиму и заданной величине паузы скорость вращения в угловой мере за единицу времени, полученная опытным путем. Абсолютная величина скорости в данном случае не важна (измерялась скорость на валу, присоединенном к мотору через червячную передачу и редуктор), важно соотношение между разными ячейками.
Легко заметить, что максимальная скорость 0,161 была достигнута в режиме 1/8 микрошага с интервалом между шагами в 125 микросекунд (чистая удача, на полном шаге ее тоже наверняка удалось бы получить с интервалом где-то около 1200). Чуть меньшая скорость 0,139 была получена дважды, в режиме полного шага с интервалом1250 микросекунд, и в режиме 1/16 шага с интервалом 50 микросекунд. Близкая скорость 0,135 была получена в режиме 1/4 микрошага с интервалом 300 микросекунд. Получается, что при переходе от полного шага к 1/16 шага для сохранения текущей скорости интервал между шагами нужно сократить ровно в 25 раз (но не в 16! ).
Так же видно, что в режиме 1/32 микрошага максимальную скорость получить было бы невозможно. В этом случае нас ограничивается время выполнения loop(), которое на Arduino Uno составляет порядка 30 микросекунд на пустом цикле (по крайней мере так было на «китайце», где я проводил эксперименты).
Из всего это следует один простой вывод – в нашем случае разумно выбирать режим микрошага на сколько это возможно более мелкий, но учитывая возможную потерю крутящего момента. В максимальной скорости мы не потеряем, плавность хода и точность на низких скоростях увеличим.
Что нужно поменять в скетче для адаптации под другой двигатель
- Максимальное и минимальное значение скорости. Задается в MIN_SPEED_DELAY и MAX_SPEED_DELAY как интервал между шагами в микросекундах. Можно нащупать опытным путем;
- Микрошаг. Задается исходя из возможностей двигателя в DEFAULT_MS. Если крутящего момента хватает — лучше оставить 1/16;
- Кол-во шагов на оборот, задается в STEP_PER_REVOLUTION;
- Нужно ли снимать напряжение с мотора при простое и время бездействия в IsRelease и ReleaseTime соответственно.
На этом пожалуй все. Совершенно не освещенным осталось приложение под Windows для удаленного управления — программная панель управления фокусером. Возможно изложу в 4-ой части, но пока есть сомнения в целесообразности.
Автор: alex_flyeye