AVR-USB-MEGA16: управление шаговым двигателем через USB |
Написал Сергей Кухтецкий | |
01.07.2009 | |
В статье описана простая система управления шаговым двигателем на базе персонального компьютера, платы AVR-USB-MEGA16 и простого силового модуля для питания обмоток двигателя. Рассмотрены два варианта программного обеспечения: простой вариант для малых частот вращения двигателя и несколько более сложный, но без ограничений на частоту шагов. Разработка выполнена в лаборатории проблем материаловедения Института химии и химической технологии СО РАН, г. Красноярск (http://www.icct.ru/). Шаговый двигатель – неотъемлемый атрибут многих исполнительных устройств, используемых для позиционирования в пространстве и регулирования материальных расходов. Шаговые двигатели также широко используются в приводах floppy-дисков, HDD, CD-ROM, в бытовых видеомагнитофонах, фотоаппаратах и видеокамерах. Существует множество конструкций шаговых двигателей и способов их питания. В данной статье мы рассмотрим довольно часто встречающийся вариант – униполярный двигатель в полношаговом режиме с одной включенной фазой. При таком питании в каждый момент времени ток подается только на одну обмотку двигателя. Пусть, например, в начальный момент времени ток подан на первую обмотку. В соответствующем положении находится и ротор. Если в следующий момент времени ток будет подан на вторую обмотку и снят с первой, то двигатель сделает один шаг (т.е. ротор повернется на определенный угол). Затем подадим ток только на третью обмотку, потом – на четвертую и опять на первую. И так далее. Ротор будет вращаться по часовой стрелке. Временная диаграмма сигналов показана на Рис.1. Естественно, если запитывать обмотки в обратной последовательности: 1-4-3-2, то двигатель будет вращаться в противоположном направлении.
Рис.1. Схема обмоток и временная диаграмма Несмотря на то, что при таком включении от двигателя нельзя получить полный момент, схема контроллера двигателя получается очень простой. Если же использовать микроконтроллер, то конструкция получается совсем тривиальной – к четырем цифровым выходам микроконтроллера нужно подсоединить усилители тока (простые транзисторные ключи) для питания обмоток двигателя. Далее остается только подавать единички на соответствующие выходы микроконтроллера. Рассмотрим немного подробнее силовой модуль. [Силовой модуль] Схема модуля представлена на Рис.2. При открывании какого-нибудь из транзисторов, ток будет протекать через соответствующую обмотку шагового двигателя. Для управления транзисторами используются свободные выходы PC0, PC1, PC6 и PC7 микроконтроллера платы AVR-USB-MEGA16. Тип транзисторов зависит от мощности подключаемого двигателя, напряжения его питания и, естественно, нагрузочной способности портов микроконтроллера. В данной конструкции я использовал составные транзисторы BD677, обладающие достаточным коэффициентом усиления по току, с допуститимым напряжением коллектор-эммитер до 60В, ток коллектора – до 4 А. Для большинства двигателей, которые используются в лабораторной практике – вполне достаточно. Если не нужна большая мощность, то при питании двигателя от 5В источника можно вообще обойтись без радиаторов.
Рис.2. Схема силового модуля Поскольку нагрузка индуктивная, полезно поставить защитные диоды. Я поставил 1-амперные диоды 1N4001, но можно обойтись и без них. Защитные диоды увеличивают время спада тока в обмотках шагового двигателя (через них ЭДС самоиндукции возвращается в источник питания V+), что уменьшает максимально возможную частоту вращения шагового двигателя. Если убрать диоды, то время спада тока окажется минимальным, двигатель сможет вращаться быстрее, но при этом возникают опасные для транзисторов выбросы ЭДС самоиндукции, которые могут превысить допустимое для них напряжение 60 В. Для первых экспериментов и отладки программного обеспечения взял небольшой шаговый двигатель от старого матричного принтера. Силовая часть разместилась на макетной плате. Питание двигателей производилось от внешнего источника. Напряжение питания – 5В. Вся электроника с двигателем показана на Рис.3, общий вид стенда – на Рис.4.
Рис.3. Электронная часть и шаговый двигатель
Рис.4. Общий вид стенда [Программное обеспечение] Как было отмечено выше, все управление нашим шаговым двигателем сводится к подаче логической единицы последовательно на пины микроконтроллера PC0, PC1, PC6 и PC7. В каждый момент времени единица должна быть только на одном пине. При подаче единицы, откроется соответствующий транзистор в силовом модуле и через одну из обмоток потечет ток. Двигатель сделает шаг. Затем нужно подать единицу на следующий пин, и двигатель сделает следующий шаг. Если не требуется высокая частота шагов, то с такой задачей вполне справится и сам хост. Рассмотрим этот вариант подробнее. Простой вариант Для этого решения можно воспользоваться простой универсальной прошивкой «firmware simple» из статьи «AVR-USB-MEGA16 : Быстрая разработка USB приложений на C# при помощи класса-обертки ATMega16». Эта прошивка позволяет с хоста управлять по USB состоянием регистров ввода/вывода и портами микроконтроллера. Т.е. для данного варианта прошивку можно использовать безо всяких изменений. Единственное что нужно сделать - слегка модифицировать приложение хоста «host simple/LedTest» из этой же статьи. Вместо включения/выключения светодиода, подключенного к порту B, нужно управлять портом четырьмя пинами порта C. Прошивка, исходные файлы firmware и проект приложения хоста (на языке C# для Visual Studio 2008 Express Edition) приведены в папке «01 Простой вариант» архива «090630stepmotor-soft-mega16.zip» к данной статье. Приложение хоста очень простое, поэтому ограничусь только комментариями по общей организации программы.
В массиве ph находятся байты, которые нужно послать в порт C для того, чтобы подать единицу на один из пинов PC0, PC1, PC6 и PC7. Объявление этого массива – в классе Form1:
Таймер timerPulse в приложении хоста задает частоту следования шаговых импульсов (точнее – период этих импульсов). По тику этого таймера вызывается метод timerPulse_Tick(), в котором модифицируется индекс фазы (переменная iPh) на +1 или -1 в зависимости от направления вращения двигателя. Индекс фазы модифицируется циклически в диапазоне 0 – 3. В этом же методе соответствующий байт (ph[iPh]) посылается в порт C командой Период следования импульсов (переменная T) регулируется компонентом NumericUpDown. При изменении T происходит модификация свойства Interval таймера timerPulse (см. метод numericUpDownMs_ValueChanged()). Как уже отмечалось, данная реализация программного обеспечения будет работать только на сравнительно низких частотах следования шаговых импульсов. Для того, чтобы придать более строгий смысл фразе «сравнительно низкие частоты», проведем небольшой эксперимент. Подключим к одному из пинов (PC0, PC1, PC6 или PC7) осциллограф и будем измерять длительность импульсов на этом пине в зависимости от длительности импульсов, задаваемой хостом при помощи компонента NumericUpDown. Мы увидим, что длительность импульсов и период их следования заметно «гуляют» (на десятки миллисекунд). Поэтому будем измерять среднее значение (например, по 10-20 импульсам). На Рис. 5 представлена зависимость этой средней величины от длительности, задаваемой хостом. Шкалы – в логарифмическом масштабе.
Рис.5. Длительность импульсов на пине микроконтроллера в зависимости от длительности, задаваемой хостом Из графика видно, что при больших длительностях (более 100 мс), длительность импульсов на пине микроконтроллера практически совпадает с длительностью, задаваемой хостом. Т.е. в этом режиме хост вполне контролирует частоту вращения двигателя. Для более коротких импульсов (в диапазоне 10-100 мс) наблюдается заметное увеличение средней длительности импульсов (по сравнению с длительностью, задаваемой хостом). Внешне это проявляется как нестабильность вращения и неплавное увеличение скорости вращения при уменьшении длительности импульсов. Наконец, в диапазоне 1-10 мс, скорость вращения двигателя вообще перестает изменяться с изменением длительности импульсов, задаваемых хостом. Для моего компьютера эта величина оказалась равной 15.6 мс, т.е. частота - не более 64 шагов в секунду. Реально – еще меньше. Если учесть, что для типичных двигателей максимальная частота приемистости составляет величину порядка 1000 Гц, то становится ясно, что добиться максимальных скоростей вращения шагового двигателя при управлении шагами непосредственно из хоста нам не удастся. Поэтому (если, конечно, необходимы высокие скорости!) программное обеспечение необходимо модифицировать. Кроме того, возможно придется увеличить напряжение питания (для увеличения скорости нарастания тока в обмотках), применить другой принцип коммутации фаз, убрать защитные диоды и заменить их на специальные защитные цепочки, снижающие выбросы ЭДС самоиндукции до допустимого уровня, применить транзисторы подороже, у которых высокое допуститое напряжение коллектор-эммитер. Быстрый и точный вариант Самый простой выходом из описанной выше ситуации является переход от управления шагами двигателя по таймеру хоста к управлению от аппаратного таймера микроконтроллера. Логика работы программы не меняется, только тактирование шагов двигателя и подача соответствующих байтов в порт C происходит уже не из хоста, а непосредственно в firmware. Некритичные ко времени реакции системы операции (в частности, инициализация таймера, изменение частоты шагов и направления вращения двигателя) можно оставить на хосте. Для реализации этого варианта нам нужно модифицировать как firmware, так и приложение хоста. Исходные файлы и проект можно найти в папке «02 Быстрый вариант» архива «090630stepmotor-soft-mega16.zip». Ниже – небольшие комментарии к этому программному обеспечению. Начнем с firmware (за основу без изменений взято firmware из статьи «AVR-USB-MEGA16: быстрая разработка USB приложений на C# при помощи класса-обертки ATMega16»). Firmware Будем работать с 16-разрядным таймером TIMER1 (чтобы ни в чем себе не отказывать). Основное изменение, которое нам необходимо сделать в firmware, – вставить обработчик прерывания, которое генерируется при достижении счетчиком определенного значения. Это значение как раз будет задавать период шага двигателя. Таймер, естественно, должен работать в режиме со сбросом значения счетчика при достижении этого значения (режим CTC - Clear Timer on Compare).
Модифицируем файл main.c из папки «firmware simple» следующим образом.
2. Как и в предыдущем варианте (но только не в хосте, а в firmware!) объявим массив байтов, посылаемых в порт C и другие рабочие переменные:
3. Напишем две функции (сделать шаг в нужном направлении и обработчик прерывания от таймера):
4. И, наконец, в функцию usbFunctionSetup() вставим еще один case для установки направления вращения двигателя: Это все изменения firmware, которые необходимо сделать. Компилируем, прошиваем микроконтроллер и переходим к хосту. ПО хоста
Сначала модифицируем класс-обертку ATMega (файл ATMega.cs).
2. В секцию «Адреса портов, регистров и пины микроконтроллера ATMega16» добавим константы для работы с регистром масок прерываний TIMSK:
3. Сделаем это в секции «Работа с регистрами TIMER1»:
return buffer[0];
4. Ну и, наконец, свойство smDir, задающее направление вращения двигателя: Все. Модификация класса-обертки закончена. Теперь разберемся с главным файлом приложения (файл Form1.cs). Готовый файл можно найти в проекте хоста (папка «02 Быстрый вариант» архива «090630stepmotor-soft-mega16.zip»). Краткие комментарии ниже. 1. После успешного создания объекта dev класса ATMega16 производится инициализация таймера TIMER1. Выбираем режим 4 – обнуление таймера при совпадении счетчика со значением, находящимся в регистре OCR1A (единичка в бите WGM12 регистра TCCR1B, см. Datasheet на ATMega16). Коэффициент деления тактовой частоты выбираем 1024 (биты CS12 и CS10 в 1, а CS11 – в 0). При этом 16 разрядный счетчик перекроет весь необходимый нам диапазон частот (здесь я ориентировался на свой микродозатор, для которого, собственно говоря, и делалась вся эта разработка).
2. Далее посылаем в регистр OCR1A какое-нибудь значение по умолчанию (здесь оно берется из компонента numericUpDownMs.Value). В конце метода соответствующие биты порта C настраиваются на вывод. 3. При нажатии на кнопку «Старт/Стоп» вызывается метод checkBoxStartStop_CheckedChanged(), в котором, в зависимости от состояния кнопки (нажата или отжата), происходит либо разрешение, либо запрет прерываний от таймера в микроконтроллере (бит OCIE1A регистра TIMSK). Дальше генерацией шаговых импульсов двигателя занимается уже сам микроконтроллер (точнее – его аппаратный таймер TIMER1) независимо от хоста. 4. При переключении направления вращения двигателя (радио кнопки radioButtonForward и radioButtonBack) происходит вызов метода radioButtonForward_CheckedChanged(). В этом методе свойству smDir присваивается значение +1 или -1. При этом по USB производится установка переменной inc (в firmware) в такое же значение. Это сразу же отражается на направлении вращения двигателя. 5. При изменении значения компонента numericUpDownMs, вызывается метод numericUpDownMs_ValueChanged(), в котором происходит вычисление нового значения регистра OCR1A и присваивание ему этого значения. Текущее значение счетчика (TCNT1) при этом обнуляется. Теперь шаговый двигатель будет делать шаги с новой частотой. 6. Чтобы не греть двигатель по окончанию работы программы (таймер микроконтроллера работает независимо от хоста!) в методе Form1_FormClosing(), вызываемом при закрытии формы приложения, происходит запрет прерываний от таймера микроконтроллера и обнуление тока всех обмоток двигателя. Вот, собственно говоря, и все приложение. Компилируем и запускаем. Теперь измерим длительности импульсов на каком-нибудь из пинов (PC0, PC1, PC6 или PC7) микроконтроллера как и в предыдущем (простом) варианте программного обеспечения. Результат такого эксперимента представлен на Рис.6. Видно, что теперь длительность импульсов на пинах микроконтроллера совпадает с длительность импульсов, задаваемых в приложении хоста во всем нужном нам диапазоне.
Рис.6. Теперь можно работать на любых частотах [Микродозатор] Итак, мы решили проблему управления шаговым двигателем на высоких частотах за счет использования периферии микроконтроллера (в данном случае - аппаратного таймера TIMER1). Тем самым нам удалось обойтись без использования какого-либо специализированного контроллера шаговых двигателей. Замечательно и то, что переход от первого варианта системы ко второму происходил только за счет изменения программного обеспечения, без каких либо модернизаций «железа». Расширенный вариант программного обеспечения, описанного выше, используется в реальном прототипе микродозатора жидкостей. В его основе лежит шприцевой насос, приводимый в действие шаговым двигателем. В качестве модели насоса был взят насос от жидкостного хроматографа Милихром. Там используется неплохой отечественный шаговый двигатель ДШИ-200-1. Он работает довольно устойчиво от этого же силового модуля, которое рассмотрено в данной статье выше.
Программное обеспечение было расширено за счет введения следующих дополнительных функций. Рис.7. Общий вид прототипа микродозатора
Рис.8. Вид работающего приложения хоста Байты перемычек (fuse bits) ATmega16 должны быть 0xFF (low) и 0x09 (high).
@ S.V.Kukhtetskiy, 2009 [Ссылки]
1. Исходники проектов этой статьи – firmware и ПО хоста |
|
Последнее обновление ( 10.11.2010 ) |