Энкодер на базе HEDR и STM32

в 5:03, , рубрики: diy или сделай сам, stm32, датчики, микроконтроллер, программирование микроконтроллеров, схемотехника, энкодер
Энкодер на базе HEDR и STM32 - 1

Всем привет!

В данной статье я хочу Вам рассказать про датчик HEDR(от компании avago technologies) - это двухканальный инкрементальный оптический датчик, предназначен для измерения пройденного пути, линейной скорости, угловой скорости и направлении вращения вала.
С помощью данного датчика будет реализован энкодер на базе микроконтроллера STM32, который будет производить вычисление пройденного пути.

В данной статье будет рассмотрено:

  • Принцип работы датчика HEDR-5420-ES214;

  • Схема подключения к микроконтроллеру STM32;

  • Программная реализация (расчет пройденного пути и вывод информации на дисплей).

Технические характеристики датчика HEDR-5420-ES214

Документация на датчик[https://www.alldatasheet.com/datasheet-pdf/pdf/509439/AVAGO/HEDR-5420-ES214.html?gad_source=1&gad_campaignid=22850169015&gbraid=0AAAAADcdDU-9Yb_iV4NBRyTas8sz4w3rS&gclid=Cj0KCQjwmYzIBhC6ARIsAHA3IkRXgZnMIlPCRRWeMRAt0Jsj4grqSN8YuCEhqdnXAyeqnuLWPlW31hoaAlbcEALw_wcB]

  • Напряжение питания [ 4.5 - 5.5В ];

  • Тип выхода [ квадратурный ];

  • Диаметр вала [ 5 мм ];

  • Разрешение [ 200 отсчетов на оборот ];

  • Рабочая температура [ от -10°C до +85°C ].

Принцип работы датчика HEDR-5420-ES214

Устройство состоит из трех основных компонентов:

  • Источник света (светодиод, формирующий поток света);

  • Оптическая система (линза, обеспечивает фокусировку и отражение света);

  • Фотодетектор.

Энкодер на базе HEDR и STM32 - 2

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

Эти изменения интенсивности света преобразуются в внутренние сигналы А и В, которые проходят через компараторы в составе обработки сигналов, на выходе формируются два цифровых прямоугольных сигнала - канал А и В, находящиеся в квадратурной фазе на 90°, что позволяет микроконтроллеру определять направление вращения вала, к примеру:

  • если канал А опережает канал B - вращение происходит в одну сторону;

  • если канал B опережает канал А - вращение происходит в противоположную сторону.

Для своей задачи применяется следующая последовательность, если канал А опережает канал B - движение энкодера считается положительным, если на оборот, то движение будет отрицательным.

Осциллограмма данных полученных с датчика HEDR-5420-ES214

Осциллограмма данных полученных с датчика HEDR-5420-ES214

Схема подключения к микроконтроллеру STM32

Схема подключения HEDR и дисплея к микроконтроллеру STM32F030CCT6

Схема подключения HEDR и дисплея к микроконтроллеру STM32F030CCT6
Макет STM32F030CCTx и HEDR

Макет STM32F030CCTx и HEDR

В данной схеме используются преобразователь напряжения DA1 (+12V +5V) и стабилизатор напряжения DA2, дисплей подключается к выводам МК 21_SCL_I2C2 и 22_SDA_I2C2, датчик HEDR подключается к выводам МК 29_CH.A и 30_CH.B, данные сигналы сначала проходят через делители, R17-R18-[CH.A] и R15-R16-[CH.B], так как датчик работает от +5V, сигналы соответственно тоже у него +5V, я всегда стараюсь дополнительно защитить МК, после делителя амплитуда сигналов снизится до +3.3V, копипастить информацию по описанию узлов преобразователя, стабилизатора, узла обвязки напряжения питания и резонатора для МК не особо хочется, поэтому кому интересно можно почитать статью [https://habr.com/ru/articles/950818/].

Настройка микроконтроллера STM32F030CCTx в CubeIDE 

Энкодер на базе HEDR и STM32 - 6

Настройка RCC и SYS (в RCC выбираю Crystal/Ceramic Resonator, так как у меня внешний кварц на 8 МГц)

Энкодер на базе HEDR и STM32 - 7

Настройка дисплея

Взаимодействие дисплея с МК будет через I2C2

Энкодер на базе HEDR и STM32 - 8

Настройка выводов узла подключения датчика HEDR

  • TIM1_CH1 (к данному выводу будет подключаться сигнал CH.A);

  • TIM1_CH2 (к данному выводу будет подключаться сигнал CH.B).

Энкодер на базе HEDR и STM32 - 9
Энкодер на базе HEDR и STM32 - 10

Таймер используется в режиме Encoder mode - это специальный аппаратный режим, который позволяет микроконтроллеру автоматически подсчитывать импульсы от инкрементального датчика и определять направление вращения, данная конфигурация освобождает МК от необходимости программно обрабатывать прерывания по каждому импульсу.

Encoder Mode TI1 and TI2 данный параметр указывает, что используется оба канала датчика (A и B), это дает разрешение X4 - т.е. счетчик будет увеличиваться на 4 шага за один полный оборот.

Описание режимов

TI1 - подсчет ведется по фронту одного канала А, направление определяется по уровню В, разрешение 1.8 градусов;

TI2 - аналогично логике TI1, но базируется на канале В;

TI1 and TI2 - подсчет ведется на каждом фронте обоих каналов (А+, А-, В+, В-), направление определяется автоматически, т.е. количеством импульсов на оборот 200, я получаю 800 шагов на оборот, разрешение будет 0.45 градусов.

Input Filter - включает цифровую фильтрацию входного сигнала, помогает убрать дребезг и шум, значения от 0 до 15, чем выше значение, тем надежнее фильтрация, но будет повышаться задержка.

Polarity (Rising Edge) - счетчик реагирует на восходящие фронты сигнала.

Настройка Clock

Энкодер на базе HEDR и STM32 - 11

Программная реализация ведомого устройства

Ссылка на скачивание исходного кода [ https://t.me/ChipCraft В закрепленном сообщении [ #исскуствомк_исходный_код — Исходный код для Encoder_HEDR_5420_STM32F030CCTx].

Модуль process_Encoder

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

  • Количество импульсов на оборот;

  • Пройденную дистанцию;

  • Отображение данных на дисплее.

#define ENCODER_MODE_X4 4

Данный параметр отражает режим подсчета импульсов, привожу формулу

N_{шагов}=PPR  cdot 4=200 cdot 4=800 O_{шаг}=frac{360}{800}=0.45

Этот режим обеспечивает максимальную точность - 0.45 на один шаг.

#define WHEEL_DIAMETR_M 0.230f // 230 мм
#define WHEEL_RADIUS_M (WHEEL_DIAMETR_M / 2.0f)

Здесь я задаю геометрические размеры колеса, на валу которого установлен датчик%

Диаметр колеса 230 мм (0.230м);

Радиус вычисляется так:

R=frac{ D}{2}=frac{ 0.230}{2}=0.115 м

#define STEPS_PER_REV (ENCODER_PPR * ENCODER_MODE_X4)

Максимальное количество шагов за один оборот

#define CIRCUMFERENCE_M (2.0f *M_PI * WHEEL_RADIUS_M)

Длина окружности колеса - это путь, который проходит колесо за один оборот

C=2pi RC=2 cdot 3.1416 cdot 0.115=0.722 м

т.е. при моем радиусе 0.115, получится за один полный оборот 0.72 м.

Энкодер на базе HEDR и STM32 - 17

Функция display_init() - инициализация дисплея

  • Инициализируется драйвер дисплея;

  • Выполняется заливка экрана черным цветом;

  • На дисплее на 2 секунды отображается стартовый экран с надписью ''ChipCraft";

  • После задержки экран очищается для дальнейшей работы.

библиотеку для работы с дисплеем я взял с [https://github.com/afiskon/stm32-ssd1306/tree/master]

Функция display_update()

Отвечает за визуализацию информации на дисплее:

  • Экран предварительно очищается с помощью ssd1306_Fill(Black);

  • В верхней части по центру отображается надпись «Encoder»;

  • Ниже последовательно выводятся:

    • количество импульсов;

    • дистанция;

  • Буфер графики передается на дисплей вызовом ssd1306_UpdateScreen()

Функция encoder_Handler()

Логика работы:

  • считывание текущего значения таймера;

  • определение разницы (delta) между текущим и предыдущим значениями;

  • накопление общего счетчика enocoder_position;

  • вызов функций для вычисления дистанции и обновление дисплея.

Функция get_distance_m() - вычисление пройденной дистанции

Переводит количество импульсов датчика в физическую длину пути в (метрах).

process_Encoder.c
#include "./Project/process_Encoder.h"
#include "./Project/shared.h"
#include "./Project/ssd1306.h"
#include "./Project/ssd1306_fonts.h"
#include "main.h"
#include <stdlib.h>//abs
#include <string.h>//memset
#include <stdio.h>
#include <stdint.h>
#include <math.h>

#define ENCODER_PPR 200 // импульсов на оборот
#define ENCODER_MODE_X4 4

#define WHEEL_DIAMETR_M 0.230f // 230 мм
#define WHEEL_RADIUS_M (WHEEL_DIAMETR_M / 2.0f)

#define STEPS_PER_REV (ENCODER_PPR * ENCODER_MODE_X4)
#define CIRCUMFERENCE_M (2.0f *M_PI * WHEEL_RADIUS_M)

uint16_t current_count= 0;
int16_t delta = 0;
float distance = 0.0f;
int32_t encoder_position = 0;

uint8_t ssd1306_buffer[SSD1306_BUFFER_SIZE];


void display_init(void) {
	ssd1306_Init();

	ssd1306_Fill(Black);
	ssd1306_SetCursor(20, 25);
	ssd1306_WriteString("ChipCraft", Font_11x18, White);
	ssd1306_UpdateScreen();

	HAL_Delay(2000);

	ssd1306_Fill(Black);
	ssd1306_UpdateScreen();
}

void encoder_Handler(void) {

	static uint16_t last_count = 0;
	current_count = __HAL_TIM_GET_COUNTER(&htim1);

	delta = (int16_t)(current_count - last_count);
	encoder_position += delta;

	last_count = current_count;

	get_distance_m();

	display_update(encoder_position, distance);

}
void display_update(int32_t pulses, float distance) {

	char buf[32];

	ssd1306_Fill(Black);

	ssd1306_SetCursor(25, 2);
	ssd1306_WriteString("Encoder" ,Font_11x18, White);

	sprintf(buf, "Pulses: %ld", pulses);
	ssd1306_SetCursor(2, 22);
	ssd1306_WriteString(buf, Font_7x10, White);

	sprintf(buf, "Dist: %.2f m", distance);
	ssd1306_SetCursor(2, 36);
	ssd1306_WriteString(buf, Font_7x10, White);

	ssd1306_UpdateScreen();
}

float get_distance_m(void){

	distance = ((float) encoder_position / STEPS_PER_REV) * CIRCUMFERENCE_M;

	return distance;
}

Модуль proj_main() - главный метод

  • Выполняется инициализация дисплея;

  • Запуск таймера;

  • Запуск функции encoder_Handler().

proj_main.c
#include "./Project/shared.h"
#include "./Project/proj_main.h"
#include "./Project/process_Encoder.h"
#include "./Project/process_Encoder.h"

void proj_main()
{
	volatile const char *ch = ";V-F-BIN;ver: "VER_PROG(VER_a,VER_b,VER_c);(void)ch;//0x8008b00

	display_init();

	HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL);

	while (1){

		//хэндлеры
		encoder_Handler();

	}//while (1)
}

Если статья показалась Вам интересной, буду рад выпустить для Вас еще множество статей исследований по всевозможным видам устройств, так что, если не хотите их пропустить — буду благодарен за подписку на мой ТГ-канал.

Автор: DM_ChipCraft

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js