Здесь приведен перевод апноута [1], описывающего реализацию компактного, высокоскоростного, управляемого прерываниями контроллера шагового мотора. Шаговые двигатели (ШД) обычно используются для приложений наподобие управления фокусом камеры, привода ленты, перемещения печатающей головки, управления движением механики в факсах, принтерах, копировальных аппаратах, 3D-принтерах, станках с ЧПУ, жестких дисках, приводах DVD-ROM и т. п. Высокое быстродействие микроконтроллеров AVR позволяет разработчику реализовать высокоскоростные приложения для управления ШД, причем вычислительное ядро процессора остается слабо нагруженным. Особенности описываемого контроллера:
• Высокоскоростной контроллер ШД • Применяются прерывания • Компактный код (в обработчике прерывания используется около 10 байт) • Низкие требования к вычислительным ресурсам • Можно реализовать на всех микроконтроллерах семейства AVR
[Немного теории: как это работает]
Шаговый мотор (шаговый двигатель, ШД) постоянного тока преобразует импульсы тока во вращение своего ротора. Типичный ШД содержит в своем составе 4 силовые обмотки, на которые подаются эти импульсы тока. Обмотки часто помечены разными цветами как red (красный), yellow/white (желтый/белый), red/white (красный/белый) и yellow (желтый), но могут использоваться и другие цвета. Приложенное напряжение к этим обмоткам приводит к выполнению мотором одного шага.
Во время нормального функционирования (когда ротор ШД вращается) в каждый момент времени напряжение подключено к 2 обмоткам из четырех. ШД поворачивает свой ротор на один шаг по часовой стрелке с каждым переключением пар обмоток в определенном порядке. Если порядок переключения обмоток меняется на противоположный, то ШД будет вращать ротор в обратном направлении. Переключение обмоток иногда называют переключением фаз ШД.
Скорость вращения управляется частотой импульсов переключения фаз ШД. С каждым импульсом (с каждым шагом ШД) ротор поворачивается на фиксированный угол. Обычный угол поворота составляет 1.8 градуса. С таким углом поворота на шаг полный оборот ротора (360 градусов) потребует 200 шагов (циклов переключения фаз).
Путем изменения интервала между прерываниями таймера можно регулировать скорость вращения ШД, а путем подсчета количества шагов можно управлять углом поворота. На рис. 1 показаны диаграммы переключения фаз ШД. В таблице 1 показано соответствие шагов мотора значениям, записываемым в выводы порта микроконтроллера.
Рис. 1. Последовательность переключения фаз.
Таблица 1. Значения фаз ШД.
Шаг
Yellow
Red/White
Yellow/White
Red
Значение (HEX)
0
1
0
0
1
9
1
1
1
1
0
C
2
0
1
1
0
6
3
0
0
1
1
3
[Описание программного обеспечения]
Программа микроконтроллера использует 16-разрядный таймер с функцией захвата для генерирования прерывания каждые 100 мкс. Когда выполняется обработчик прерывания, новое значение для формирования фаз выводится в выходные разряды порта PORTB (они управляют силовыми ключами, которые подают напряжения на обмотки ШД).
Значения для фаз шагового двигателя записаны в память программ (FLASH) микроконтроллера. При включении питания или сбросе эти значения копируются в SRAM, чтобы ускорить к ним доступ со стороны кода программы - этим достигается максимальное быстродействие. В этой реализации подпрограмма обработчика прерывания (interrupt service routine, ISR) занимает 7 циклов процессорного времени + 4 цикла на вход в ISR и 4 цикла на выход из ISR. Всего получается 15 тактовых циклов. Таким образом, на рабочей тактовой частоте 8 МГц один шаг мотора займет меньше 2 мкс. Если запуск ISR потребуется каждые 100 мкс, то обработка управления фазами ШД займет примерно 2% вычислительных ресурсов ядра микроконтроллера.
В этой программе значения для формирования фаз ШД сохраняются в по адресу 0x0100 в памяти RAM. Старший байт адреса RAM всегда постоянный, и используется только младший ниббл младшего байта адреса для получения доступа доступа к значениям (см. рис. 2). Младший ниббл в ячейке памяти (4 бита) содержат действительное значение для управления фазами ШД, старший ниббл содержит адрес следующего значения.
Рис. 2. Использование адресов и значений из таблицы переключения фаз.
При использовании такого метода можно достичь максимальной скорости работы кода и минимального расхода процессорного времени микроконтроллера. В таблицах 2 и 3 показано использование ресурсов микроконтроллера.
Таблица 2. Использование вычислительных ресурсов и памяти.
Функция
Размер кода
Циклов
Использование регистров
Прерывание
Описание
Main
38 слов
-
R16, XL, XH, ZL, ZH
-
Инициализация и пример основной программы.
OC1A
10 слов
13 + возврат
R16, XL, XH
Timer1 Output Compare A
Формирование шагов мотора путем вывода очередных значений в порты управления фазами. Вычисление адреса для следующего значения фаз.
Всего
48 слов
-
R16, XL, XH, ZL, ZH
Таблица 3. Использование периферийных устройств.
Периферийное устройство
Описание
Разрешенные прерывания
4 вывода портов GPIO
Выходы для управления силовыми ключами фаз ШД.
Timer1
Использование прерываний таймера для генерации частоты смены фаз ШД.
;***************************************************************************;* Имя файла: avr360.asm;* Тема: простая реализация высокоскоростного контроллера ШД;* Date :98.07.02;* Version :1.00;* Support telephone :+47 72 88 43 88 (ATMEL Norway);* Support fax :+47 72 88 43 99 (ATMEL Norway);* Support E-mail :avr@atmel.com;* Target MCU :может работать на всех моделях AVR;* : (в этом примере используется ATmega8515);***************************************************************************.include"..\8515def.inc";*************** Используемые глобальные регистры **************************.deftemp = R16;*************** Определение констант ********************************.equc_value = 500;значение сравнения для output compare interrupt; 500 циклов на 5 МГц соответствует 100 мкс;************************************************************************=;*;* Начало программы - с этого места начинается выполнение кода;*;************************************************************************=.cseg;Начало таблицы векторов прерываний.org0x00rjmpmain;Вектор прерывания Output compare A interrupt.orgOC1AaddrrjmpOC1A;************************************************************************=;* OC1A - Обработчик прерывания (ISR) Timer1 Output compare A;*;* Описание:;* Этот ISR загружает новое значение фаз из таблицы, расположенной ; в памяти SRAM. Значения в ячейках таблицы имеют 2 функции: младший;* ниббл содержит значение для вывода в порт, а старший содержит адрес для;* следующего значения. Младший ниббл выводится в порт, а старший ниббл;* помещается в регистр XL.;*;* Количество слов кода : 6 + возврат;* Количество тактовых циклов : 7 + возврат;* Младшие регистры : не используются;* Старшие регистры : 3 (temp, XL, XH);************************************************************************=OC1A:ldtemp,X;Загрузить в temp значение по указателю XmovXL,temp;Поместить это значение в младший байт указателя Xanditemp,0x0F;Сброс старшего ниббла tempoutPORTB,temp;Вывод младшего ниббла в фазы ШДswapXL;Поменять местами старший и младший нибблы XLandiXL,0x0F;Подготовка адреса следующей ячейки: сбросить старший нибблreti;****************************************************************************;* Основная программа;*;* Эта программа инициализирует Timer 1 output compare interrupt, чтобы оно;* срабатывало с интервалом, определенным константой c_value.;* Для достижения максимальной скорости работы таблица преобразования значений;* загружается из памяти программ (FLASH) и сохраняется в SRAM по адресу 0x0100.;****************************************************************************main:ldir16,high(RAMEND) ;Инициализация указателя стекаoutSPH,r16ldir16,low(RAMEND)
outSPL,r16lditemp,0x0F;Настройка выходов порта PORTBoutDDRB,templditemp,0x00outPORTB,temp;Запись начального значения в PORTBlditemp,high(c_value);Загрузка старшего байта величины сравненияoutOCR1AH,templditemp,low(c_value) ;Загрузка младшего байта величины сравненияoutOCR1AL,templditemp,0x00outTCNT1H,temp;Очистка старшего байта таймераoutTCNT1L,temp;Очистка младшего байта таймераoutTCCR1A,temp;Очистка регистра управления таймера A (timer control reg A)lditemp,0x40outTIFR,temp;Очистка ожидающего прерывания таймераoutTIMSK,temp;Разрешение прерывания сравнения таймера (Timer compare interrupt)ldiZH,high(step*2) ;Инициализация указателя Z на таблицу фаз мотора в памяти FLASHldiZL,low(step*2)
ldiXH,high(0x0100) ;Инициализация указателя X на место в оперативной памяти (RAM)ldiXL,low(0x0100)
lditemp,0x04;Загрузка значения счетчикаload:lpm;Загрузка значения шага из FLASHstX+,R0;Сохранение значения шага в RAMadiwZL,0x01;Инкремент указателя на FLASHdectemp;Декремент счетчикаbrneload;Повторить, пока не будет загружена вся таблицаldiXH,high(0x0100) ;Инициализация указателя X на место таблицы в RAMldiXL,low(0x0100)
lditemp,0x9outTCCR1B,temp;Очистка таймера при совпадении значения (compare match), CK/1sei;Общее разрешение прерыванийloop:rjmploop;Бесконечный цикл по метке loop;Таблица преобразований для формирования фаз ШД (Step motor lookup table):step:.db0x19,0x2C,0x36,0x03