
Комментарии 55
Я прям как в универ попал снова. Спасибо за статью!
Посмотрел исходники.
20 файлов для для библиотеки работы с энкодером - не многовато ли?
При этом, честно сказать, сам конечный автомат я с ходу найти и не смог...
Драйвер написан согласно вот этой методичке.
Архитектура Хорошо Поддерживаемого Программного Компонента
https://habr.com/ru/articles/683762/
Если коротко, то много файлов нужны для выборочной компиляции в зависимости от располагаемых в MCU ресурсами.
Ядро драйвера в файле incremental_encoder_mcal.c
20 файлов для для библиотеки работы с энкодером - не многовато ли?
Если проводить аналогию из медицины, то это как центрифугирование крови. Кровь делится на плазму, эритроциты , тромбоциты, красные кровяные тельца и прочее. Так и программный компонент тоже делится на свои фракции. Это ядро, константы, типы данных, диагностика, параметры для NVRAM, файл скрипта сборки, зависимости, конфиги, CLI и тесты. Вот как-то так.
Хз, я на pic16 обошолся всего 2мя функциями и графиком в 2D пространстве S0*S1:
/*
rotation encoder
10<-11
V ^
00->01
00 01 11 10 -> 10110100 0xB4
input: s=[ any:4 cur:2 prev:2 ]
output: [ trash:4 res:2 cur:2 ]
00 01 10 11 cur
00 00 01 10 11 11100100 0xE4
01 10 00 11 01 01110010 0x72
10 01 11 00 10 10001101 0x8D
11 11 10 01 00 00011011 0x1B
prev
*/
enum { renc_inc=4, renc_dec=8 };
char renc_pos(char pos) { return (0xB4>>((pos&3)<<1))&3; }
char renc_upd(char s) { static const char t[4]={ 0xE4,0x72,0x8D,0x1B };
return ((t[s&3]>>((s>>1)&6))<<2)|((s>>2)&3);
}
/* 4bits state usage:
char pos=0, enc=(S1<<1) | S0;
...
enc=renc_upd( (S1<<3) | (S0<<2) | (enc&3) );
if (enc & renc_inc) pos++;
if (enc & renc_dec) pos--;
code=renc_pos(pos);
*/
renc_upd просто обновляет состояние enc, у которого можно узнать увеличиваем положение или уменьшаем. если оба одновременно 1 то недопустимое значение и pos не изменяется. а renc_pos позволяет по положению генерировать S0 и S1 (это если надо эмулировать энкодер)
Я и график не понимаю зачем нужен, одной строчкой считал:
int32_t delta = pin_a_changed ^ pin_a ^ pin_b ? -1 : 1;
об этом ни статью, не методичку не напишешь! Оказывается задача решается с помощью элементарной арифметики полей Галуа.
элементарной арифметики полей Галуа.
У нас в ВУЗе нам поля Галуа не преподавали.
Как заполнять переменную pin_a_changed?
с отсутсвием в убогих МК barrel shifterов вот это вот 0xB4>>x будет ужОс во что скомпилировано(циклы с побитовым сдвигом), проще 16байт флэша на полную таблицу потратить.
int delta(bool a, bool b){
static bool pa=0, pb=0;
bool pos = a^pb, neg = b^pa, moved = pos^neg;
pa=a; pb=b;
return (moved&pos) - (moved&neg);
}Во первых даже в убогих мк есть подпрограммы, которые вызываются командой call. Во вторых renc_pos нужен только для эмуляции экодера, а для определения используется только renc_upd. В третьих renc_upd может обновлять состояние и сообщать об изменении и направление поворота экодера, храня состояние в 1 байте, при желании 2 сотояния в байте. В четвёртых функция чистая (не имеет внутренних состояний) и может обрабатывать сколько угодно энкодеров. В пятых обработка опроса и фильтрации дребезга отделены от функции определения вращения. В шестых никто не мешает ограничивать диапазон допустимых положенией. И потом нафига вы пытаетесь оптимизировать раньше времения, особенно если ресурсов еще с запасом? Более того это эти экодеры не требуется опрашивать слишком быстро и когда их много они опрашиваются как клавиатура (матрица например 8*8) по последовательной шине (RST,CLK,DAT), перебирая столбцы и колонки, просто на каждый энкодер еще по 2 диода вешается.
// load S0,S1, enc, pos, pos_min, pos_max
enc=renc_upd( S1S0<<2 | (enc&3) );
if (enc & renc_inc) pos++;
if (enc & renc_dec) pos--;
// handle range
if (pos<pos_min) pos=pos_min; if (pos>pos_max) pos=pos_max;
// store enc, pos
Не всё так просто.
В драйвер энкодера еще надо заложить ограничители.
Чтобы не позволять увеличивать счетчик выше конкретного порога.
Чтобы не позволять уменьшать счетчик ниже конкретного порога.
Сами пороги прописывать в конфиг- файле.
Недавно натыкался на специализированный МК для управления мотором - Nuvoton NM1520, так у него целый отдельный периферийный модуль интерфейса экнодера оказался, фильтрует дребезг, определяет направление вращения (и его смену), отсчитывает время от сигнала нулевого положения итд, красота!
В stm32 тоже некоторые аппаратные таймеры обладают режимом энкодера.
Но что бы будете делать если надо к одному МК подключить 30 энкодеров?
У богатых свои причуды.. Скорее всего у каждого енкодера будет свой драйвер с подключением к can.
Скорее всего, для такой разработки вместо МК будет использован DSP или PLA/FPGA - соответственно, программно-аппаратная реализация, если делать её по уму, не будет отъедать ресурсы вычислительного ядра для решаемых аппаратно задач.
А на уровне обработки МК - число энкодеров в реальных задачах вряд ли превысит 8 (не, ну натягивать сову на глобус или забивать гвозди зубочисткой, конечно, "можно - но зачем?"), которые перекрываются таймерами серии STM32F4. Тем паче, что для потребительских устройств и вовсе редко нужно больше 1-2 энкодеров, которые реализуемы и на более простых МК (и не только STM32). Но, согласен, если энкодеры низкоскоростные - типа колесика мыши или регулятора громкости - то программное решение вполне оправдано (но нужен ли тогда полноценный конечный автомат с такими наворотами? сомневаюсь!)...
Статья из серии как из простого сделать сложное. То, что вы описали, как способы применения энкодера (в данном случае фазного) :
1) Можно сделать фазовый детектор для SDR обработки сигналов. Если сигналы симфазные, то энкодер будет показывать ноль. Если A опережает по фазе B , то будет нарастать счетчик, если A отстает от B, то счетчик будет убывать.
А в чем смысл данного детектора? Что вы собрались здесь инкрементировать? Обычно вычисляется разность фаз, а не наличие того, какая фаза раньше или позже. Не понимаю целесообразность применения. Если это на СВЧ, то алгоритм конечного автомата будет работать только в теории, на практике совсем другой подход. И вряд ли он сможет показать ноль, если сигналы симфазные. У него задача определить, какая фаза была раньше. И любой программный код имеет последовательность считывания сигнала с пинов. Прерывание с одного пина в любом случае прочитается или раньше или позже, в зависимости от того, что сработало первым. Микроконтроллер - последовательная система обработки данныз. Отличие может быть в наносекундах, но оно будет. Или же вы сами будете выставлять тайминги, в которые сигналы будут считаться синфазными.
2) Регулировать громкость проигрывателей, яркость светильников.
Тут вообще все примитивно и обрабатывается банальным алгоритмом. Даже прерывания можно не трогать. И с кодом тоже нет смысла заморачиваться и соответственно тратить ресурсы микроконтроллера на сложную обработку простого решения. Даже пропуск одного такта не сыграет роли.
3) Оснащать обратной связью электрические моторы и сервоприводы.
Здесь посложнее и все зависит от того, что именно вы хотите обработать. Если сервопривод, то да, нужен очень качественный энкодер, а не то, что вы привели в пример. Я бы сказал не просто качественный, а совсем другого принципа абсолютный энкодер (оптический, магнитный, емкостный) с цифровым интерфейсом и знающий свое положение на момент включения (абсолютную позицию, угол, сдвиг и так далее) .
Если это электродвигатель, то там либо оптический, либо магнитный, либо трансформаторный (аналоговый). И ни в случае с сервоприводом ни с электродвигателем, простой фазный энкодер типа А/В ставиться не будет! И работать он там не сможет! Ну и стоит учесть, что при больших оборотах двигателя, изменение направления вращения быстрым не будет. Да, отчасти все эти энкодеры будут работать как фазовые, но на таких частотах, что длительность имнульсов будет измеряться в наносекундах. При этом магнитный энкодер эмулирует фазовый сдвиг, а оптический имеет собственную систему обработки данных. И все они передают информацию в цифровых интерфейсах.
4) Одометры, датчики скорости оборотов или измерители поступательного движения.
Тоже спорный момент. Там тоже используется не совсем энкодер, потому как это не те сферы где необходимо отслеживать разность фаз. Там направление вращения чаще всего в одну сторону и на высоких оборотах. Поэтому нет смысла использовать фазовый энкодер. Достаточно отслеживать импульсы одного канала, а контроль изменения направления вращения осуществляется другими датчиками.
По сути, фазный энкодер - это вчерашний день. Да он имеет место быть и применяется, но обладает рядом недостатков, поэтому его применение ограничено простыми и не особо ответственными системами. Выбор пункта меню, регулирование громкости и прочие моменты.
А вообще, для разных задач необходимо подбирать датчики персонально, и прежде чем считать, что математикой можно решить ряд задач для "всего", как вы считаете в этой статье, то спешу разочаровать вас. Так не работает в реальной жизни и вам стоит разобраться в теме более серьёзно.
Вы очень грамотный человек и написали много статей, это очень круто, но прежде чем заявлять то, что вы описали в этой статье, подумайте над тем, что это теория и она в вашей голове, практика и реальность чаще всего отличается. Да, частично ваши наработки можно использовать и даже нужно, но стоит понимать где, насколько это будет эффективно и ресурсозатратно.
Автору удачи и успехов!
Конечные автоматы - дело хорошее, но необходимо рассмотреть их применение более тщательно. Мы это проходили в конце 90х и тогда это было актуально и проектировали мы это на бинарной логике.
Конечные автоматы - дело хорошее, но необходимо рассмотреть их применение более тщательно.
Конечный автомат золотой шаблон проектирования системного ПО.
Выручал много раз при решении прикладных задач.
Декодирование BPSK Модуляции из Звука (или передача данных по воздуху) https://habr.com/ru/articles/848068/
Задача про две ёмкости для жидкости
https://habr.com/ru/articles/662561/
Запуск I2S Трансивера на Artery [часть 2] (DMA, FSM, PipeLine) https://habr.com/ru/articles/834304/
Квантование на Триггерах Шмитта
https://habr.com/ru/articles/1003262/
Конечный Aвтомат Аппаратного I2C-Трансивера
https://habr.com/ru/articles/856548/
Обзор Протокола ISO-TP [ISO 15765-2]
https://habr.com/ru/articles/798489/
ПасТильда: ещё одна прошивка
https://habr.com/ru/articles/706470/
Передача и прием данных по лазерному лучу (SDR декодирование BPSK в реальном времени)
https://habr.com/ru/articles/1023062/
Принцип Определения Дальности Между UWB Трансиверами (Конечный Автомат Для DS-TWR)
https://habr.com/ru/articles/723822/
Протокол TBFP
https://habr.com/ru/articles/969948/
Пуск Беспроводной CLI на Микроконтроллере
https://habr.com/ru/articles/929086/
Синтаксический разбор CSV строчек
https://habr.com/ru/articles/765066/
Теория управления шаговым двигателем (или как вертеть PTZ камеру) https://habr.com/ru/articles/709500/
Техникум: Конечный Aвтомат Обработки Сигнала с Кнопки https://habr.com/ru/articles/760088/
Техникум: Распознавание Вещественного Числа из Строчки https://habr.com/ru/articles/757122/
Cross-Detect для Проверки Качества Пайки в Электронных Цепях https://habr.com/ru/articles/762142/
H-мост: Load Detect (или как выявлять вандализм)
https://habr.com/ru/articles/709374/
Load-Detect для Проверки Качества Пайки
https://habr.com/ru/articles/756572/
При разработке электронных устройств порой надо подключить инкрементный энкодер.
Может все таки НЕ надо - энкодеры помоему худшее что могло произойти с железными интерфейсами...
Приходиться... еще можно понять и простить старые полулюбительский вещи только с 1 энкодером...
- энкодеры помоему худшее что могло произойти с железными интерфейсами
Почему тогда осциллографы и блоки питания все еще настраиваются энкодерами?
Взрослые БП клавиатура или клавиатура+энкодер, в осликах энкодеры заменили только переключатели/переменники каждый под конкретную функцию. В этом направлении к счастью только самый ширпотреб пытается на 1 энкодере собрать миллион функции которыми невозможно пользоваться.
Скрытый текст


Была вещица, где одна крутилка использовалась для всего. "Аналоговые" параметры вводить удобно, а вот перемещаться по меню (тоже этим же способом) уже не очень. Может, я конечно недостаточно ловок был
И многие дорогие приборы. Хотя видел в очень дорогой промштуковине имитацию: бульб, имитирующий крутилку, и в торце уложено сенсорное колечко - по нему палец по кругу водишь, и он как крутилка плавно меняет параметр. А кнопки, которые перемещают по многуровневому меню, ужасны. Хуже только сенсорный экран с многуровневым меню.
Энкодер дает "интуитивно понятный интерфейс" при необходимости регулирования изначально аналогового (или эквивалентного ему) параметра. Тех же громкости, положения на линейной или круговой шкале, скорости и т.п. В немалой степени за счет пропорциональности получаемого результата приложенному воздействию (поворота вала энкодера) и неизменности результата от темпа приложения воздействия. Особенно когда настройка производится по субъективным ощущениям оператора (громкость), а не по заранее известным числам (частота УКВ-радиостанции).
Кнопочные интерфейсы же идеальны для изначально дискретных параметров - типа включено/выключено, синий/зеленый и т.д. Однако попытка регулировать кнопками аналоговый параметр приводит либо к затруднениям со значительными изменениями параметра (нажать кнопку 300 раз), либо к анти-интуитивному и неточному способу воздействия (как настройка минут в часах удержанием кнопки).
Так вы теряете половину или даже больше функционала - у вас нет начала и конца, нет текущего положения, по этому тот же звук в каком-нибудь профессиональном пульте -фейдеры или обычные переменные резисторы. Есть абсолютные энкодеры, цифровые магнитные системы, но это из другой оперы и в интерфейсах подобного не встречал.
В любом mcu есть куча таймеров, и несколько из них аппаратно поддерживают энкодеры
В любом mcu есть куча таймеров, и несколько из них аппаратно поддерживают энкодеры
А как быть если нужен не просто энкодер, а энкодер с ограничением?
Чтобы упершись в максимум можно было крутить только назад CCW.
И напротив, упершись в минимум, можно было крутить только вперед CW.
Вернее крутить можно всегда, а софт должен программно накладывать пределы.
Ведь это основа любого HMI.
Настоящее "искусство" начинается там, где надо устанавливать энкодером довольно большой интервал значений, скажем в случае рентгеновской трубки с максимальным напряжением 450 кВ мы можем устанавливать инкремент один вольт, но заставлять юзера накручивать четыреста пятьдесят тысяч инкрементов - ну, такое, жестоко как минимум, так что приращение должно зависеть от скорости вращения колёсика, а вкупе с тем, что частота опроса ограничена, кроме того подключённое устройство несколько инерционно, всё это приводит к тому, что код приходится обложить кучей условий, чтобы всё это заставить работать комфортно для пользователя, и все ещё и крутят с разной скоростью.
Настоящее "искусство" начинается там, где надо устанавливать энкодером довольно большой интервал значений,
Для этого энкодеры HMI делают с кнопкой, чтобы нажатием переключать десятичный разряд, который надо устанавливать.
По крайней мере так сделано на лабораторных блоках питания (AC-DC).
В механических микроскопах мне нравится как сделано - там две крутилки (с разным передаточным числом) и одна внутри другой, как пирамидка. Очень удобно. Если электронно такое реализовать, вообще будет хорошо
Ширпотребный енкодер с кнопкой - с нажатой кнопкой можно крутить быстро, например так.
Есть энкодеры с кнопкой - переключать быстро/точно (можно и злее - вращаешь удерживая нажатым - крутишь сотни или полусотни, просто вращая - единицы).
Или более интуитивно-понятные - где вместо кнопки выключатель (разница в положениях обычно 6-8 мм по вылету вала). Нажал - быстро, отжал - точно.
Но когда нужно менять больше 2-4 десятичных разрядов - тут лучшим вариантом будет нажатием переключать разряды "по кругу", а вращением - менять значения.
Не лучше а дешевле в реализации. А лучше составной энкодер. Кнопки вообще не лучше. Это неудобно и неизбежно приводит к ошибкам. Это просто и дешево, но плохо и неудобно для аналогового ввода. Говорю, как пользователь. Как разработчик вам конечно лучше кнопки и желательно поменьше, а контроль переложить на мозги пользователя. Мне наоборот, эти мозги как можно сильнее разгрузить. Очень неудобно, когда одно и тоже действие приводит к разным результатам в зависимости от того, что ты раньше нажимал. И следить за отдельными индикаторами этих нажатий тоже не очень. Энкодер хорош тем, что можно обойтись тактильной чувствительностью. Для грубо/точно удобно два энкодера в одном. Это проверенное решение.
В рентген аппарате изменение напряжения с точностью в десятые доли процента практически никак на качестве контроля не скажется. В данном конкретном случае это избыточная точность. Это если предположить, что высоковольтный генератор может такую точность обеспечить. Скорее всего, у вас точность один вольт будет только на экране, а на трубку пойдет хорошо если +/- 5 кВ, да еще и с дрейфом в процессе излучения.
Стопитсоттысячная реализация... Зачем?
Можно гораздо проще сделать, без конечного автомата.
Положительный фронт на основном канале это всегда инкремент или декремент в зависимости от состояния второго канала. Все, весь алгоритм.
Step/dir по сути. Можно по отрицательному фронту, без разницы.
Это если модель как у вас, ECW1J-C28-BC0024L, а то бывают разные диаграммы работы у энкодеров.
Скрытый текст
Положительный фронт на основном канале это всегда инкремент или декремент в зависимости от состояния второго канала. Все, весь алгоритм.
Тогда у Вас за один период энкодера будет изменение на 1, вметосо 4х.
Разрешение ухудшится в 4 раза. (
Все верно, за 1 щелчок энкодера будет инкремент или декремент ровно 1 раз. Как раз это и нужно.
ECW1J-C28-BC0024L

ECW1J-C28-BC0024L
Но есть еще и инкрементные энкодеры непрерывного вращения (которые ставят на валы моторов).
И там желательно улучшить разрешение.
Поэтому конечный автомат предпочтительнее.
Так и в чем разница, поменяйте местами A и B или обозначте положительное направление не CCW а CW. Вообще фазовую диаграмму, лучше смотреть в фазовом пространстве. И после изменения можно фильтровать дребизг и читать данные. Более того некоторые одарённый умудрились в осцилографе смазать все энкодеры что бы лучше скользило (возможно для увеличения ресурса). В результате сигнал получился рандомизированным и никакие фильтрации сигнала не справлялись. Пришлось поменять все такие энкодеры на нормальные.


Конечный автомат инкрементного энкодера