- Назначение и возможности,
- Технические характеристики и устройство,
- Подключение, пример использования,
- Применение, достоинства и недостатки,
- Вывод,
- FAQ.
Назначение и возможности
Оптический инкрементный поворотный энкодер - таково полное название с титулами героя данной статьи. Звучит длинно, но каждый термин имеет смысл. “Оптический” - означает, что в качестве датчика используется оптопара, то есть связка светодиод - фотоприемник, вещь весьма точная, надежная и крайне долговечная. “Инкрементальный” - значит увеличивающий (или уменьшающий, смотря в какую сторону), в противовес “абсолютному” не указывает точное текущее положение вала в любой момент, а также сразу после включения, лишь отслеживает, на какой угол от был повернут по или против часовой стрелки с момента начала пристального наблюдения. “Поворотный” - отслеживающий именно поворот, угловое изменение положение вала, что намекает нам на возможность существования еще как минимум “линейных” энкодеров. Наконец, ключевое - “энкодер”, по сути конвертер механического движения в сигнальные импульсы для отслеживания движения в скалярном и векторном выражении. Выглядит весьма солидно, больше похож на какой-нибудь шаговый двигатель, чем на измерительный прибор.
Название звучит отчасти знакомо, как минимум в словах “энкодер” и “инкрементальный”. Да, это дальний родственник известных нам органов управления, широко используемых DIY-мастерами всех уровней начиная с чуть выше начального. Между ними много общего, но не меньше различий.
“Обычные” энкодеры, как было только что замечено, являются типичными HIM-устройствами, интерфейсом взаимодействия человек-машина. Человек крутит ручку, нажимает кнопку, машина воспринимает это как команды для увеличения или уменьшения чего-либо. Герой же нашей статьи больше склонен быть инструментом измерения и/или контроля движения, что предполагает скорее использование в паре с щупом или механизмом, чем с рукой человека. Отсюда вытекает несколько отличительных особенностей: более высокая точность (в десятки и сотни раз), отсутствие фиксированных положений и торцевой кнопки за ненадобностью. Разумеется, сложность такого устройства значительно выше, как и его цена.
Применений можно найти массу, везде где требуется точно знать, на какой угол отклонился тот или иной вал, стержень, балка, рейка, фланец и так далее. Это нужно для контроля работы станков, дозаторов и прочих приспособлений. При помощи нехитрого механизма в виде зубчатого колеса и зубчатой же рейки поворотный энкодер легко превращается в линейный, что дает возможность контролировать небольшие смещения чего угодно в любом направлении, что важно для измерения размеров и движений.
В зависимости от количества шагов на оборот, измеряемые значения могут достигать десятых или даже сотых градуса, а значит десятых и сотых миллиметров при грамотной доработке.
В данной статье мы приведем небольшой пример измерительного устройства, собранного из высокоточного энкодера, но список применений может ограничиваться только потребностями и фантазиями разработчика.
Технические характеристики и устройство
Оптические энкодеры выпускаются великим множеством производителей, но основное принципиальное отличие моделей лишь одно: количество импульсов на один оборот вала. Еще могут быть отличия в размере и форме корпуса, способа подключения, количество проводов и так далее, но все это уже вторично.Количество шагов, от которого зависит точность устройства, выбирается исходя из задачи. Для чего-то достаточно и десяти, а для другого и трех тысяч мало. Разброс наиболее ходовых моделей от 10 до 5000 импульсов на оборот, что покрывает очень большой диапазон возможных применений.
Выбирая энкодер, главное придерживаться принципа разумной достаточности. Слишком высокая чувствительность накладывает на контроллер большую ответственность и вычислительную нагрузку, с которой он не всегда сможет справиться. Вот, к примеру, логика подсказывает, что при вращении вала со скоростью 1 об/сек менее чем среднего энкодера с разрешением 1000 имп/сек мы будем вынуждены отслеживать эту самую тысячу импульсов в секунду, то есть чередующиеся состояния HIGH и LOW продолжительностью 0,5 мс. Кратное увеличение скорости или чувствительности кратно уменьшает это время. В конце концов контроллер может оказаться в ситуации, когда частота опроса перевалит за предельно допустимую, мы получим пропуски, и, как следствие, искаженную картину мира.
Маска для оптопар на примере энкодера 360 им/сек выглядит так, но может отличаться в зависимости от модели и производителя.
Два оптрона традиционно размещены на главной, самой мелкой сетке и смещены на некоторое расстояние относительно друг друга, чтобы импульсы приходили в разное время, сообщая нам о направлении движения. Таким образом, вращая вал мы можем наблюдать привычную для энкодеров картину с двух этих датчиков:
Третий оптрон служит для группировки импульсов в некоторое количество, чаще всего кратное одному обороту. Используется для контроля на отсутствие пропусков, выравнивания, калибровки, плюс ускорения работы при большом количестве оборотов. Все три сигнала при вращении вала туда-обратно более чем на один оборот выглядят так:
На фоне сигнала об одном полном обороте (внизу) два шаговых выглядят как одно сплошное нечто. В данном случае показания снимались с энкодера, попавшего к нам в руки, а значит между оборотами аж 2000 импульсов.
Длина “оборотного” импульса при небольшой скорости вращения составляет менее одной микросекунды! Стоит учитывать при выборе энкодера, контроллера и программных настроек.
В остальном, кроме значительно менее длинных импульсов, с точки зрения контроллера никакой разницы с “обычным” энкодером нет. Как с ним работать мы подробно рассматривали в соответствующей статье с несколькими примерами и вариантами на любой вкус. Останавливаться на этом еще раз смысла не имеет, есть предложение сразу перейти к реальному примеру с реальным энкодером.
Различные датчики, модули, платы управления
Можно купить в нашем онлайн магазине https://3d-diy.ru/catalog/arduino-and-robotics/ с оплатой онлайн и доставкой от 1 дня.
Подключение, пример использования
В нашем распоряжении имеется энкодер фирмы OMRON на 2000 импульсов/оборот, что является золотой серединой по чувствительности в этой линейке относительно недорогих изделий. Вал, вопреки ожиданиям, вращается абсолютно свободно, не оказывая ни малейшего сопротивления, что весьма порадовало и обнадежило.Согласно ярлыку, допустимо питание от 5 до 12В, что нас вполне устраивает, так как работать он будет со стандартной Arduino. Если планируется подключать его к более современным и мощным контроллерам, которые используют напряжение 3,3 В, придется воспользоваться преобразователем уровней и дополнительным питанием.
Провод энкодера делится на 5 цветных проводов плюс оплетку. Воспользуемся даташитом, чтобы разобраться где что и для чего. Что мы тут видим. Оплетка и синий дружно присоединяются к земле (GND). Коричневый к питанию, в нашем случае +5 В. Черный и белый представляют фазы А и Б. Это те самые основные оптопары, меняющие свой уровень в зависимости от того, проходит их свет через решетку с двумя тысячами прорезей или нет. Они нам интересны в первую очередь. Оранжевый отвечает за сигнал полного оборота, штука в перспективе нужная, но обойдемся пока без нее.
Подключаем черный провод к пину 8, белый к 9. Синий и оплетку, как уже озвучивалось, к земле, коричневый к +5 В. На этом подключение энкодера будем считать законченным.
Перед тем как бежать писать программу, определяемся с таймингами, то есть временем, за которое сигнал с оптопар меняет свое значение. Сделать это можно разными способами, в том числе методом последовательного приближения, более известным в народе как “метод тыка”, а можно срезать угол и воспользоваться услугами цифрового анализатора сигналов. К слову, такой девайс просто обязан быть у любого уважающего себя DIY-мастера, хотя бы в минималистичном исполнении. Стоит копейки, экономит кучу времени на настройке, поиске неисправностей и ошибок.
При вращении вала пальцами на скорости, значительно меньше неразумной, снимаем показания. Замеряем и делаем вывод: длина сигнала составляет порядка 100 микросекунд, смещение оптопар порядка трети от этого значения, то есть 30 микросекунд. Стало быть, чтобы достоверно просчитать все сигналы и направление, период опроса должен составлять не менее 20 микросекунд.
Не поверите, но в настройке очень может помочь и упомянутый выше даташит. Знание отношений времени одного события к другому иногда может очень пригодиться. Из описанных в статье про “обычные” энкодеры способов выберем самый очевидный - прерывание по таймеру. Еще раз срезаем угол зайдя на онлайн калькулятор таймеров, чтобы вычислить параметры прерываний.
Согласно полученных данных создаем процедуру запуска прерывания с частотой 20 мкс.
cli(); TCCR1A = 0b00000000; TCCR1B = 0b00001010; // делитель 8, сброс при совпадении 1A OCR1A = 0x0028; // 20mus TIMSK1 = 0b0000010; // прерывание А sei();
Опрос будем проводить непосредственно с порта, это намного быстрее, хоть и слегка сложнее, так как требует знаний бинарной логики и понимания, что такое порт вообще.Пины Atmega328, на которой основано большинство классических Ардуин, с номерами 8 и 9 соответствуют нулевому и первому биту порта B. Записываем их в кольцевой буфер, анализируем на изменение нулевого бита, что означает шаг от энкодера, узнаем, что там в первом бите - это дает нам понимание о направлении поворота вала. В зависимости от результата либо прибавляем, либо убавляем шаг в переменной NUM на один шаг. В NUM у нас будет храниться абсолютное значение состояния вала на данный момент времени.
В итоге, выглядит обработка сигнала так:
ISR(TIMER1_COMPA_vect) { static byte PIN[2]; PIN[0] = PIN[1]; PIN[1] = PINB; if ((!(PIN[0] & 0b00000001)) && (PIN[1] & 0b00000001)) { // изменение на фазе А if (PIN[1] & 0b00000010) { // направление NUM++; } else { NUM--; } } }
Получилось компактно и изящно. В любой момент основной программы берем содержимое NUM и узнаем, в каком положении находится вал в данный момент времени, а если точнее, в каком был в последние 20 микросекунд.Создадим простейший измеритель размеров при помощи энкодера и рычага. Для этого нарисуем в 3D рычаг на вал и фиксатор энкодера, чтобы тот не катался по столу во время работы. Печатаем, собираем на импровизированном стенде.
Для чего? Проводим под рычагом небольшие предметы разного размера, а рычаг будет отклоняться от нулевого значения, и если воспользоваться правилом прямоугольного треугольника, можно вычислить размер этих предметов.
Необходимы комплектующие для 3д принтера?Первые же опыты показали очень высокую чувствительность прибора. Изменения на валу происходили даже от небольшой вибрации стенда, например, от постукивания по ней пальцем. В плоттере порта, с квантизацией состояния NUM в 20 мс, отчетливо видно, как вибрация влияет на результат. Максимально сильно прижав испытательный стенд к столу и проявляя нечеловеческую осторожность, проводим под рычагом первый предмет - жало отвертки диаметром 5 мм. Любуемся результатом. С учетом поправок максимальное значение можно приравнять к 34-35 относительно взятого за ноль значения 1000. Ноль за ноль мы не взяли по причине нежелания “уходить в минус”, однако это вопрос вкуса.
Купить запчасти для 3D принтеров можно в нашем магазине 3DIY https://3d-diy.ru/catalog/spare-parts-3d-printer/ с доставкой по всей России.
Срезаем угол в третий раз и заменяем науку геометрию на простую порцию: 35 имп/5 мм = Х имп/Y мм, то есть взяв 7 имп за 1 мм. Проверяем на практике, проведя под рычагом “мизинчиковую” батарейку диаметром 10 мм. Пик приходится на 70 единиц, делим на 7, получаем 10. Все верно!
Программа для моментальных измерений:
volatile unsigned int NUM = 1000; // нулевое значение (для корректного отображения минусовых значений) void setup() { DDRB = 0b00000100; cli(); TCCR1A = 0b00000000; TCCR1B = 0b00001010; // делитель 8, сброс при совпадении 1A OCR1A = 0x0028; // 20mus TIMSK1 = 0b0000010; // прерывание А sei(); Serial.begin(19200); } void loop() { printer(); // печать результатов в монитор lever(); // выставление нулевого значения (компенсация люфтов и проскальзываний) } void lever() { static unsigned long timer; static int oldNUM[2]; if ((timer + 200) > millis())return; oldNUM[0] = oldNUM[1]; oldNUM[1] = NUM; if (oldNUM[0] == oldNUM[1]) NUM = 1000; timer = millis(); } void printer() { static unsigned long timer; if ((timer + 20) > millis())return; // печатаем каждые 20 мс (можно чаще) Serial.println(NUM); timer = millis(); } ISR(TIMER1_COMPA_vect) { // опрос энкодера static byte PIN[2]; PIN[0] = PIN[1]; PIN[1] = PINB; if ((!(PIN[0] & 0b00000001)) && (PIN[1] & 0b00000001)) { // изменение на фазе А if (PIN[1] & 0b00000010) { // направление NUM++; } else { NUM--; } } }
И, наконец, заставим контроллер перевести результаты на человеческий язык, то есть отчитываться об измерениях в миллиметрах. Для чего, вооружившись уже известными параметрами плюс новыми выводами по итогам серии измерений, с учетом поправок на округление и люфты, получаем следующую цепочку от проведения под датчиком отвертки и батарейки:Отвертка 5 мм, батарейка 10 мм. Все верно.
Итоговая программа:
volatile unsigned int NUM = 1000; // нулевое значение (для корректного отображения минусовых значений) unsigned int MAX; // максимум за отчетный период void setup() { DDRB = 0b00000100; cli(); TCCR1A = 0b00000000; TCCR1B = 0b00001010; // делитель 8, сброс при совпадении 1A OCR1A = 0x0028; // 20mus TIMSK1 = 0b0000010; // прерывание А sei(); Serial.begin(19200); } void loop() { maximum(); // ищем максимум в отчетный период printer(); // печать результатов в монитор lever(); // выставление нулевого значения (компенсация люфтов и проскальзываний) } void lever() { static unsigned long timer; static int oldNUM[2]; if ((timer + 200) > millis())return; oldNUM[0] = oldNUM[1]; oldNUM[1] = NUM; if (oldNUM[0] == oldNUM[1]) NUM = 1000; timer = millis(); } void maximum() { static unsigned long timer; if ((timer + 10) > millis())return; // ищем максимум if (NUM > MAX) MAX = NUM; timer = millis(); } void printer() { static unsigned long timer; if ((timer + 2000) > millis())return; // каждые пару секунд публикуем максимум в мм и обнуляем его Serial.println((MAX-997)/7); // очень грубое округление до целого, в меньшую сторону MAX = 0; timer = millis(); } ISR(TIMER1_COMPA_vect) { // опрос энкодера static byte PIN[2]; PIN[0] = PIN[1]; PIN[1] = PINB; if ((!(PIN[0] & 0b00000001)) && (PIN[1] & 0b00000001)) { // изменение на фазе А if (PIN[1] & 0b00000010) { // направление NUM++; } else { NUM--; } } }
Разумеется, программа несовершенна, она выдает максимальное значение высоты за равные промежутки измерений, вне зависимости от самих измерений. Нужно подгадывать и проводить предметы под рычагом между выводом результатов. Если измерять два и более предмета менее чем за 2 секунды, получим размер наибольшего из них. Если вывод отчета придется на момент прохождения предмета под рычагом, получим максимальное значение на этот момент, даже если рычаг только немного приподнимется. Кроме того, программа не показывает доли миллиметра, хотя могла бы, и не округляет результат до целого, хоть и это не проблема.В идеале, программа должна отслеживать начало и окончание измерения и выдавать данные по факту прохождения предмета, а также показывать цифру с десятыми долями миллиметра. Сделать это не очень сложно и потому оставляем доработку в качестве домашнего задания для заинтересованных в развитии читателей.
Применение, достоинства и недостатки
Измерение любых угловых и линейных размеров. Контроль работы механизмов, а также их калибровка и выравнивание. Проверка качества изделий. Датчики дозаторов. Датчики скоростей вращения и подачи. Даже в качестве органа ручного управления можно использовать, если требуется очень тонкая работа при твердой руке и остром глазе. Как производная - рукоять в игровом автомате и/или квесте и серии “а ну-ка попади”, “попробуй успей” и тому подобных.Применений уже придуманы тысячи и еще столько же ждут своих открывателей.
К несомненным достоинствам энкодеров данного типа отнесем высокую точность (до 14 импульсов на угловой градус), максимальную простоту подключения, долговечность и надежность. Свободное вращение вала, без сопротивления, а значит и помех в измерениях, тоже отнесем к жирным плюсам.
Обнаружен некоторый дрейф, при котором физический возврат вала в исходное положение не сводит сальдо импульсов к нулю. Возможно, это от недостатка жесткости собранного нами образца, но в любом случае можно компенсировать разницу программно за счет фазы Z и прочих ухищрений. Требуется обращать на это внимание в каждом конкретном случае, абсолютное доверие к “железкам”, как и ко всему остальному в жизни, не рекомендуется.
Выводы
Высокоточные энкодеры Omron и им подобные весьма полезная в DIY-хозяйстве вещь, если требуются разнообразные измерения с малой погрешностью. Со своими задачами справляются отлично, подключаются быстро и просто, программирование не вызывает больших трудностей. К изучению, покупке и употреблению рекомендуются.FAQ
Возможно ли использовать несколько подобных энкодеров в одном проекте? Если да, то намного ли увеличится вычислительная нагрузка на контроллер?Да, возможно. Нет, не сильно, если использовать весь порт для энкодеров, то есть до четырех штук без “оборотного” сигнала или два с “оборотным”, функция обработки усилится незначительно.
Если энкодер вращается нечасто, как можно сократить нагрузку на его отслеживание?
Использовать отслеживание прерывания по событию. На Atmega328 для этого имеются два пина, соответственно, можно подключить два энкодера таким способом. Пример есть в статье про HMI-энкодеры.
Возможно ли контролировать скорость вращения пластинки на ретро-проигрывателе или скорость лентопротяга на магнитофоне и прочих подобных устройствах, где точная скорость вращения критично важна?
Конечно можно. Самым сложным вопросом в таких проектах остается лишь: “как надежно присоединить измеряемый вал к валу энкодера”.
Чем могут отличаться модели высокоточных энкодеров помимо количества импульсов на оборот?
Максимальным вольтажом питания, количеством интерфейсных проводов и способом подключения. Как правило, добавляется еще по одному инвертированному выводу на фазу, нужно это или нет - вопрос открытый. Возможно, дополнительные провода требуются для совместимости с некоторыми готовыми разработками.
Какова максимальная скорость вращения вала энкодера, которую он в состоянии обработать?
Согласно даташиту максимальная частота, в зависимости от конкретной модели, может составлять от 50 до 100 КГц. То есть, к примеру, для нашего энкодера 2000 имп/об эта величина составит от 25 до 50 об/мин, для 4000 имп/об вдвое меньше. Следует учитывать, что длительность импульсов при такой скорости составит 10-20 мкс. Для Ардуино задача вполне подъемная, при условии, что нет других мощных параллельных задач, особенно на прерываниях по таймеру.