Comments 87
angle += increment[AB+ABprev*4];
сильно ли изменит картину замена операции умножения сдвигом?
1. Может влиять вывод в сериал при собственно формировании вывода (они обожают блокировать прерывания) и при собственно передаче (во время прерывания после очередного байта).
2. Дребезг может быть слишком быстрым и к моменту считывания текущего значения в прерывании Вы теряете, к примеру +1 и делаете лишнюю -1.
Посоветовал бы попробовать вариант с отключением прерывания по тому пину, что только что сработал и оставлять второй, и так их постоянно менять — тогда дребезг просто не заметен и таблица инкрементов становится проще — лет 10 назад я так делал с обычными, не настолько быстрыми, энкодерами — получалось неплохо.
А в чем сложность? Туда же вроде тот же код ардуины можно залить, не?
Я сам то с обычной ардуины на ESP перепрыгнул. Там именно код от ардуины «как есть» можно брать, через ту же arduino IDE (хотя я взял VisualStudio). И забыть про нехватку памяти и производительности.
Вроде и для STM так можно, только настроить один раз по инструкции.
Правда как хардверный счётчик цеплять — это отдельно надо думать, но вообще производительности STM может и на софтверном хватить с большим запасом.
А если stm32+Micropython?
Если я правильно понял предложение, то в два раза падает точность. Вместо четырёх отсчётов на прорезь получится два.
Мда… STM32 Blue Pill стоит 1.8$. Ардино 3$. Помоему ардуино просто лишняя трата денег. В stm32 частота выше, а код пишеться за 5 минут не спешего ковыряние STM32CubeMX, одного make, openocd -l stm32f103c8t6.cfg --init
Купите blue pill за 1.8$. Я настолько уверен, что готов сделать перевод денег, хоть сейчас. Но подождите я щас вам статью забацаю :).
на некоторых atmel только 2 прерывания, как быть если надо несколько энкодеров?
даже если есть несколько прерываний не будут ли они конфликтовать при одновременной работе?
на некоторых atmel только 2 прерывания
Я не очень понял, можете пояснить?
The External Interrupts are triggered by the INT0 and INT1
pins or any of the PCINT23...0 pins.
тоесть прерываний таки 2, только они могут быть назначены на другие ножки.
получается можно подключить только один энкодер?
А кто вам чушь про дребезг на плавно меняющихся фронтах рассказал?
Расскажите ему про гистерезис логических уровней.
'дребезг' в данном случае может возникнуть только если энкодер физически вибрирует.
Правда там угол вычислять не требуется, но всё равно вещь неприятная, и аппаратно никак не давится без дополнительной схемы, в отличии от промышленных оптических, где всё уже внутри.
Но в данной конкретной статье, в данном конкретном устройстве, автор использует оптический и героически пытается найти у него дребезг.
ps:
Вы много видели механических энкодеров с разрешением бОльшим нескольких десятков импульсов? А это уже немного другие временнЫе параметры и дребезг там вполне можно давить софтово.
Так ведь можно выход на один из входов кинуть и получить гистерезис с нужными характеристиками. Или там диапазоны напряжений разные?
Ну, тут разница между приличным и неприличным энкодером в один резистор выходит...
Ну и подавляющее большинство тех, кто балуется с ардуино, пришли из программирования в лучшем случае, или вообще со стороны, а не из схемотехники, или тем более, проектирования встраиваемых систем, и не имеют профильного образования. Т.е. это не высокомерие, это констатация факта — многие просто не знают о том, как это делается. И уровень поделок на ардуино весьма низок, как и порог вхождения, кстати.
У высокоточных оптических энкодеров нет перобразования синусоиды в меандр. Вместо этого есть специальные коробочки (умножители), которые анализируют две входны синусоиды A и B и по ним восстанавливают угол с повышенной точностью. Например, 1000 отсчётов на прорезь.
Это я так, для информации, захотелось поделиться.
Про меандр можно пообсуждать и подокапываться до формальных определний, а про синусоиду — можно. То есть y1=sin(t) это гармонический сигнал, синусоида времени, периодическая функция и всё такое. А y2=sin(phi(t)) — это синусоидальная функция с аргументом phi. Про y2 можно говорить "синусоида угла", но не стоит говорить "гармоническая функция".
Вообще, это всё вопрос терминологий и догворённостей. Например, сумму двух гармонических функций уже нельзя называть периодическим сигналом, но все называют. Главное, чтобы люди друг друга понимали. :)
можно посмотреть реализацию в проекте по «автономному контроллеру на stm32»
Есть оптический энкодер ЛИР-158Б, и к нему родной преобразователь ЛИР-917 с выходом на USB. Производитель уверяет что преобразователь тянет частоту запросов до 50Гц, а мне для задачи (оценка ускорений при разрушении маятником образца) требуется суб-миллисекундная точность. Потому тоже пробую приспособить Arduino Uno для чтения энкодера. Поначалу повторил вашу мысль о таблице преобразований, но затем упростил её до следующей логики (упрощенно):
volatile bool StateA, StateB; //глобальные, инициализируются при запуске чтением ножек.
volatile long Coord; //глобальная, при запуске 0
// Прерывание по каналу A датчика угла поворота
void interruptChannelA() {
// меняем состояние канала (чтобы не делать digitalRead())
StateA = !StateA;
// корректируем координату
if (StateA != StateB) Coord++;
else Coord--;
}
// Прерывание по каналу B датчика угла поворота
void interruptChannelB() {
// меняем состояние канала (чтобы не делать digitalRead())
StateB = !StateB;
// корректируем координату
if (StateA == StateB) Coord++;
else Coord--;
}
Собственно скорости вращения небольшие, порядка 5-10 радиан/сек (60-100 rpm).
Проблема в памяти — 2КБ всё-таки маловато для регистрации даже одного маха маятника (я регистрирую число микросекунд, прошедших с предыдущего тика энкодера). Но если верить вашим результатам, хотя бы с быстродействием все будет в порядке.
Проблема в том, что по моим подсчетам получается следующее:
6 радиан/сек дают порядка 9500 тиков энкодера в секунду. Я собираюсь передавать интервалы между тиками в микросекундах, т.е. у меня будет 1 пакет на тик.
Максимальная заявленная скорость виртуального серийного порта для Uno — 115200 бод, что даёт порядка 11КБ/с. Т.е. я успеваю передавать данные быстрее, чем они генерируются, только если каждый тик будет кодироваться 8-10 битами — а такой разрядности мне может не хватить.
Сейчас я планирую использовать ОЗУ ардуины как кольцевой буффер, с таким расчетом чтобы он не успел переполниться за характерный интервал измерения. Но все равно, как-то ненадежно.
И всё это при допущении, что Ардуино реально вытянет эти 11КБ/с. Если завязаться на протокол USB напрямую, наверняка можно выжать куда больше, но это уже сложнее чем написать Serial.begin(115200). =)
Соглашусь, это может быть оверкилл, но сейчас, на этапе прототипирования, простота может оказаться важнее.
Сейчас использую Arduino Mega2560, вот там уже можно жить — со скрипом, но памяти хватает на одно измерение.
Правда, всплыла другая проблема — такое чувство, что меандр там (в ЛИР-158Б) не совсем равномерный. Наблюдаются периодические отклонения от среднего интервалов между фронтами — где-то +-5% от среднего, причем наблюдаются при любой скорости вращения.
P.S.: извините за столь поздний ответ — забыл про тему.
По поводу ЛИР-158. Это довольно точный датчик. В зависимости от исполнения
5 класс ±15" 6 класс ±30" 7 класс ±75" 8 класс ±150"
причем это накопленная погрешность, а не между штрихами.
Хотя может быть между фронтами 5% отклонение возможно.Там число физических штрихов на лимбе 5400 максимум, а для повышения разрешения применяется интерполяция.
прерываниями (фронтами по обоим каналам энкодера) — последовательность dT(X) где X — положение вала энкодера.
Уже тогда стал заметен определённый паттерн — например, на одном энкодере задержки формировали повторяющийся периодический паттерн (значения условные): 110мкс, 105мкс, 105мкс, 95мкс. На другом энкодере той же модели паттерн отличался, но он тоже был повторяющийся и тоже имел период 4 измерения (4 фронта = 1 деление на лимбе).
Этот паттерн наблюдался на всех участках траектории, т.е. при разных скоростях вращения, в том числе и при низких (возле крайних положений маятника). Значит, дело не в производительности МК.
Далее, я нашел относительное отклонение значения каждого измерения от среднего по пяти точкам — это порядка 0,18 градуса дуги, средняя скорость не должна существенно измениться на таком интервале. Величины этого отклонения были в пределах ±5%.
Что самое интересное, характер распределения величины отклонения по положениям вала энкодера сохранялся — то есть, если в каком-то положении вала разброс был меньше, он был меньше и при последующих измерениях. Конкретные значения чуть «гуляли», но картина распределения сохранялась и была уникальной для каждого экземпляра энкодера в моем распоряжении.
Исходя из этого, я сделал вывод, что «гуляющие» интервалы между соседними тиками энкодера вызваны погрешностями изготовления лимба, а не особенностями программы/МК.
P.S.: интервалы в микросекундах измерялись 16битным таймером с предделителем 8, без использования прерываний — просто брал значение счетчика и сдвигал на бит вправо. Однако идентичная картина наблюдалась и при использовании стандартной micros(), с поправкой на её разрешение 4мкс.
www.skbis.ru/index.php?p=14
> интервалы между соседними прерываниями (фронтами по обоим каналам энкодера)
Фронты — это именно фронты, или фронт и спад?
Если фронт и спад, то длительности полуволн наверное могут быть неодинаковы. В этом случае можно попробовать брать прерывания только по [восходящему] фронту или только по спаду.
Максимальная входная частота сигналов преобразователя 5 МГц
Увы, ЛИР-917 не умеет работать в пакетном режиме (сделать N измерений за промежуток времени и отдать их разом). А вручную задержки порядка 1 мс в юзерспейсе обычной ОС с вытесняющей многозадачностью сделать трудно. Вот и пришлось городить огород с ардуино в роли преобразователя — провести пакет измерений, сохранить в ОЗУ, потом неторопливо отдать на комп по виртуальному COM-порту.
Но почему бы не взять Xmega — где вообще аппаратный блок для работы с энкодером.
Причем та же Atmel студия, только библиотеки ASF для удобства.
Я активно работаю над сложным проектом с STM32, но в своих проектах часто использую Atmel Xmega.
Кроме того — у Atmel полно недорогих ARM процессоров, весьма доступных. От 100 руб. за штуку, и там тоже хватает интересной периферии. Те же M0+ — это 32 бита и 48 МГц. И даже в soic корпусе.
А «Ардуино головного мозга» — это когда делают отдельную плату на STM32, которая считает энкодер и передает в Ардуину показания энкодера по UART.
Ардуино головного мозга: импульсный датчик положения