Подключение магнитного энкодера AS5048 к микроконтроллеру.

Приветствую всех на нашем сайте! У меня лежит комплект датчиков с AliExpress, так вот я решил сделать своего рода обзор и пример программы для работы с ними. Речь идет о магнитных энкодерах AS5048. Задача определения угла в различных проектах встречается довольно часто, а эти датчики себя проявили с наилучшей стороны, поэтому нельзя обойти их вниманием 🙂 И для примера подключения энкодера мы будем использовать контроллер STM32.

Классификация энкодеров как таковых достаточно обширна. Например, различают два больших класса:

  • Инкрементальный энкодер – позволяет отследить изменение положения относительно некой начальной точки. Эта начальная точка соответствует положению датчика в момент подачи на него питания.
  • Абсолютный энкодер – в любой момент времени позволяет получить точную однозначную информацию о своем положении в определенном диапазоне и конкретных единицах.

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

Два других крупных класса энкодеров определяют их внутреннее устройство и принцип действия:

  • Оптические энкодеры – состоят из источника света, специального оптического диска и фотоприемника. Диск содержит прозрачные и непрозрачные области, что позволяет по данным фотоприемника получить информацию об изменении положения.
  • Магнитные энкодеры – как уже понятно из названия, в этих устройствах определение положения происходит путем отслеживания изменений магнитного поля. Ключевым элементом таких энкодеров является датчик Холла.

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

Подключение энкодера AS5048.

Итак, наш датчик является абсолютным магнитным энкодером, позволяющим отследить изменение угла в пределах от 0 до 360 градусов. То есть нам доступен полный оборот! Разрешающая способность энкодера – 14 бит, что соответствует:

\frac{360\degree}{16384} = 0,02197\degree

По моему опыту использования и подключения энкодера AS5048 этого обычно хватает с запасом 🙂

Для того, чтобы получить данные о положении доступны несколько вариантов:

  • Интерфейс SPI – для AS5048A.
  • Подключение энкодера по I2C – для AS5048B.
  • Выход PWM – этот вариант доступен для всех модификаций. Но для PWM разрешающая способность не 14, а 12 бит.

Именно на третьем способе мы и остановимся. Во-первых, это зачастую удобнее, не надо отправлять никаких команд для запроса данных, ШИМ-сигнал генерируется постоянно, и нам требуется только измерять его параметры. И, во-вторых, для считывания сигнала таким образом требуется меньше сигнальных линий, в некоторых случаях это оказывается ключевым аспектом при выборе интерфейса.

Принцип использования датчика максимально прост – постоянный магнит (идет в комплекте с платой энкодера) закрепляется на подвижном валу, а сам энкодер – на неподвижной части. При вращении происходит изменение магнитного поля, которое фиксируется датчиками Холла и впоследствии преобразуется в электрический сигнал. А с этим сигналом мы уже можем работать.

Магниты.

Минус использования PWM-выхода заключается в том, что функция установки нулевого положения датчика в этом случае недоступна. Идея тут в том, что при установке платы энкодера и магнита их положение друг относительно друга будет, в общем-то, случайным. Из-за этого нулевое положение датчика будет всегда разным, что обычно недопустимо. И поэтому в AS5048 добавлена возможность установить нулевое положение специальной командой, отправляемой по SPI или I2C.

Но, с другой стороны, у этой проблемы есть очень простое и доступное решение, которое даже не требует использования этой функции. Мы можем просто добавить смещение в код нашей программы. То есть, рассчитав в ПО для микроконтроллера абсолютное положение энкодера, мы добавляем к нему определенную величину. Значение это всегда одинаковое (при постоянстве монтажа), поскольку определяется только взаимным положением магнита и датчика.

С этим разобрались, переходим к формату выходных данных, точнее к механизму, который позволит нам из ШИМ-сигнала получить положение в пространстве. Выходной сигнал выглядит так:

ШИМ-сигнал энкодера.

Возьмем за основу наш пример из статьи про режим таймера Input Capture и будем измерять период сигнала и длительность импульса. Кстати по даташиту частота PWM равна 1 КГц, то есть период – 1 мс. На практике, период оказывается несколько другим, по моим наблюдениям, может быть отклонение до 10%. В связи с этим измерение периода позволит нам значительно повысить точность (относительно случая, если бы мы просто приняли его равным 1 мс).

Алгоритм действия будет таким:

1). Измеряем период и длительность импульса ШИМ-сигнала, получаем значения в микросекундах.

2). Пересчитаем длительность в отсчеты энкодера (clocks на картинке выше):

t_{clocks} = 4119 * \frac{t}{T}

Здесь 4119 отсчетов – это весь период – 16 + 4095 + 8.

3). Из формы выходного сигнала видим, что в случае, если не возникло никакой ошибки длительность импульса составит минимум 16 отсчетов. Это число получается из длительности поля Init (12 отсчетов) и поля Error (4). Максимальная же длительность импульса равна разности между длительностью всего периода и поля Exit, что равно 4119 – 8 = 4111 отсчетов.

4). Если значение длительности удовлетворяет требованиям из пункта 3, то есть лежит в промежутке от 16 до 4111, то определяем из него текущую ширину поля Data в отсчетах:

t_{data\medspace clocks} = t_{clocks} – 16

5). И, наконец, ничего нам не мешает рассчитать значение угла:

\alpha = \frac{t_{data\medspace clocks}}{4095} * 360\degree

Давайте реализуем все эти шаги в программе и для начала определим константы:

#define PERIOD_CLOCKS                                                   4119
#define ANGLE_MAX                                                       360
#define PULSE_CLOCKS_MIN                                                16
#define PULSE_CLOCKS_MAX                                                4111
#define DATA_CLOCKS_MAX                                                 4095

Дополняем код прерывания таймера и все готово!

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if (htim->Instance == TIM2)
	{
		if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
		{
			period = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_1);
			pulseWidth = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_2);

			TIM2->CNT = 0;

			if (pulseWidth < period)
			{
				uint16_t pulseWidthClocks = PERIOD_CLOCKS * pulseWidth / period;

				if ((pulseWidthClocks >= PULSE_CLOCKS_MIN) && (pulseWidthClocks <= PULSE_CLOCKS_MAX))
				{
					uint16_t dataClocks = pulseWidthClocks - PULSE_CLOCKS_MIN;
					angle = ((float)dataClocks) / DATA_CLOCKS_MAX * ANGLE_MAX;
				}
			}
		}
	}
}

И в завершение статьи несколько осциллограмм с выхода энкодера и соответствующие им результаты работы нашей программы (значения здесь в отсчетах таймера, в нашем примере один отсчет – 1 мкс):

Подключение энкодера к микроконтроллеру.

На этом заканчиваем сегодняшний обзор, всем большое спасибо за внимание, надеюсь материал окажется вам полезен!

Ссылка на проект – MT_Encoder_AS5048.

Поделиться!

Подписаться
Уведомление о
guest
0 Комментарий
Inline Feedbacks
View all comments

Присоединяйтесь!

Profile Profile Profile Profile Profile
Vkontakte
Twitter

Язык сайта

Август 2020
Пн Вт Ср Чт Пт Сб Вс
 12
3456789
10111213141516
17181920212223
24252627282930
31  

© 2013-2020 MicroTechnics.ru