Мышь как энкодер ардуино

Arduino.ru

Энкодер из мышки.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Пытаюсь считать кол-во прерываний. Вот время одного препятствия происходит множество ложных срабатываний.

А как заставить программу увеличить переменную на 1 и ОЖИДАТЬ,пока не уберу препятствие?

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Куча значений вывелось во время одного и того же препятствия. Может это аппаратный вопрос?

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Приведённый код можно сократить, убрав ненужные условия:

Теперь, если с этим разобрались — какие именно проблемы? Вам надо, чтобы прерывание срабатывало по изменению фронта? Чтобы срабатывало однократно? Чтобы вообще не срабатывало? Что значит » пока не уберу препятствие «? Постарайтесь донести свою мысль в более понятной форме, пожалуйста.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Куча значений вывелось во время одного и того же препятствия. Может это аппаратный вопрос?

Нет, куча значений вывелось во время многократного срабатывания прерывания по изменению фронта. Почему фронт менялся так часто? Так это уже аппаратный вопрос ;)

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Спасибо! Изменения с High на Low происходили многократно только во время препятствия. Потом отключил пин от Ардуинки,и COM порт стал выдавать значения постоянно,без остановки. Я думаю,что фототранзистор от комп. мышки слишком чувствительный и стоит поискать ему замену.

+ иногда выводятся 2 раза подряд Low или High(а бывает,что и по 10 раз подряд!)

Если есть варианты,посоветуйте пожалуйста,какой приемник подходит для этой задачи.

Источник

Мышь как энкодер ардуино

Энкодер из оптического датчика мыши Logitech

Автор: Хатуль_мадан
Опубликовано 10.06.2022
Создано при помощи КотоРед.

Немного истории.

Началось все с того, что понадобились энкодеры (валкодеры, кому как нравится) для некоторых самоделок. Механические обладают рядом недостатков, таких как: дребезг контактов, быстрый износ и др. Поэтому, для контроля вращения мотора, например, оптимально подходят оптические датчики. Их выбор невелик. Те, которые в составе имеют пару фотоэлементов (два фототранзистора), и те, которые с цифровым выходом, в основном, от мышек фирмы Logitech. Более навороченные, с фотоматрицами и лазерным считыванием, рассматривать не будем, их цена не для самоделок. Так вот, самый популярный вариант — это со сдвоенным фотодатчиком. Включение простое, настройка легкая, иногда требуется небольшое усиление сигнала, или компаратор, т.к. сигнал аналоговый. При медленном вращении вала на выходе плавно меняющееся напряжение. Со всем можно смириться, но такие датчики стояли в очень старых мышках с шариком. Сейчас таких почти не найти. В наше время пока очень популярны дешевые мышки фирмы Logitech, в которых тоже встречаются оптические датчики (но все чаще применяют механические энкодеры). Беда в том, что много лет не мог найти в сети толкового описания протокола обмена с таким датчиком, все заканчивалось на упоминании двух импульсов при опросе. А недавно вновь понадобился энкодер для модернизации одного устройства, пришлось взять рабочую (но подглючивающую) мышку и самому изучить, что же происходит при опросе оптического датчика. Очень подробно описывать не буду, все материалы во вложениях в конце статьи.

Подопытная мышка Logitech B100. Датчик в ней H6z02, сверху EL. Питание подавал от зарядника телефона +5В. Светодиод матрицы при этом не горит. Распайка датчика: вид сзади, ноги вниз: 1-пин общий, 2-пин +5В, 3-пин выход. Так вот, для того, чтобы увидеть, что происходит в шине обмена с датчиком, понадобился двухканальный осциллограф и небольшая тестовая схемка, на МК типа PIC10F322

Всем управляет контроллер мыши. Периодически от него подается сигнал, чтобы зажечь светодиод, период 200мкС и длительность импульса 25мкС. Так как у PIC10F322 всего три ноги, работающие на выход, то входную RA3 использовал для синхронизации с контроллером мыши. На двух выходных ножках формируем сигнал традиционного инкрементального энкодера (светодиоды в помощь), а еще одна как раз для обмена с датчиком. Почему именно PIC10F322? Потому, что есть и много, наши друзья китайцы прислали по 33р за штуку. Но полноценный энкодер лучше сделать на 8-и ногом МК, типа PIC12F629, или PIC12F683, или на атини, при изменении программы. Исходники программы тоже прилагаются, там ничего сложного нет, переделка под любой МК не займет много сил. Так вот, кратко: после импульсов на светодиод примерно через 130. 140мкС начинается опрос датчика, ножка МК настраивается на выход и подается высокий уровень на 2. 3мкС, затем на такое же время подается низкий уровень, затем ножка переводится на вход, т.е. этот спад импульса является сигналом датчику на вывод информации, и уже датчик выставляет низкий уровень на шине, если нет вращения, или высокий уровень, если вращение вправо. МК опрашивает шину и фиксирует поворот, если он был. Второй импульс опроса происходит полностью аналогично: МК дает фронт на 2мкС, потом спад на 2мкС, освобождает шину и опрашивает датчик. Если после второго импульса датчик выставил высокий уровень, то вращение влево, если низкий, то вращения нет. Вот и весь протокол обмена. Проверял еще на одной мышке Logitech RX250, и все то же самое, только импульсы с промежутком в 10мкС. Вот картинки, как все проверялось, сам МК на тестовой плате:

И как все цепляется к мышке:

Теперь, некоторые практические размышления. В программе анализируется вращение и преобразуется в код инкрементального энкодера из 4 комбинаций, который выводится на ноги МК, и который, в свою очередь, тоже нужно анализировать еще одним основным МК. Это все отнимает время и усложняет процесс основной программы. Даже если делать полноценную схему на более крупном контроллере (в архиве схема вариант3), то от частого опроса (каждые 200мкС) никто не избавляет. Поэтому появилась идея, раз уж применять маленький МК, то пусть он и занимается сбором информации именно от датчика, а по запросу, например, каждые 10. 100мС, можно скидывать накопленное по упрощенному SPI интерфейсу, тогда и ног у PIC10F322 хватает на все, и основной МК не отвлекается на опрос. Вот схема, ничем не сложнее:

Такой обмен может быть организован, или с запросом от основного МК, выставив низкий уровень на шине CLK, или, если энкодер повернули, то на ноге Data выставляем низкий уровень, что служит сигналом о вращении и необходимости обмена. В модели все работает, упрощенно немного, но если дойдет до практического применения, то доработать не сложно.

В заключении хочу сказать, что сегодня за пару часов был собран вполне применимый на практике энкодер в корпусе переменного резистора, и даже торцевая кнопочка удачно разместилась (фото прилагаются). Работает прекрасно, лучше, чем такой же на аналоговых сдвоенных фотодатчиках. Почему-то с них у меня выходят синусоиды, сдвинутые по фазе (в файле исследований он тоже есть). Эту тему начали обсуждать уже давно, с 2014 года, вот на днях продолжили вот тут:

Как вставлять видео работы я еще не научился. Если есть вопросы, пишите в ту же ветку форума.

Источник

USB-polygon-20: Мышиный энкодер

Исправление ошибки

Перед тем, как перейти к теме выпуска, хочу упомянуть об исправлении, которое пришлось внести в код, а заодно о проявлении ошибки и поиске причин.

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

В общем, нашел ошибку в коде.

В третьем опусе цикла я уже описывал, что сталкивался с подобной проблемой в самом начале работы над проектом, и виноват был сторожевой таймер — «собака». Однако в коде с использованием библиотеки LUFA это вроде бы предусмотрено. В функции SetupHardware() в самом начале есть такой код, отключающий «собаку»:

Сперва предположил, что этот участок не выполняется, потому что макроопределение ARCH не установлено.

Кстати сказать, в makefile переменная ARCH = AVR8 — это совсем другое, она действует только в makefile , и к коду программы отношения не имеет, хотя должна соответствовать одноименному макроопределению в коде, этого требует документация библиотеки LUFA. И в принципе можно бы определить макрос при помощи переменной CC_FLAGS в makefile , прибавив к ней -DARCH=0 ( ARCH_AVR8 определено как 0 ), но это не обязательно. MassStorage.c содержит строчку #include «MassStorage.h» , в данном файле есть #include , который в свою очередь содержит #include «../../Common/Common.h» , где записано #include «Architectures.h» , а там, наконец, есть такой код:

А так как __DOXYGEN__ у меня нигде не определен, ARCH по умолчанию будет определен как ARCH_AVR8 .

Кстати, анализ файла MassStorage.lss показывает, что таки да, код после условия #if (ARCH == ARCH_AVR8) компилируется. Тогда в чем дело?

А дело банально в том, что перед вызовом SetupHardware() я навставлял кучу кода, связанного с инициализацией экрана от мобильника. И к тому времени, как доходит дело до остановки «собаки», она уже успевает «гавкнуть». И надо всего-навсего поднять вызов SetupHardware() на самый верх функции main() .

Теперь программа запускается после перепрошивки устройства без дополнительных телодвижений кабелем или кнопками. Можно продолжать далее по теме.

Энкодер мыши

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

Можно будет попробовать починить, можно разобрать на детали и использовать корпус, но это все потом. Сначала хочу побаловаться с энкодером.

Ролик (или колесико) мыши — съемный узел. В его состав входят:

  • «Качелька», которая служит для крепления собственно энкодера, а также давит на кнопки. В моем случае таких кнопок три, так как на ролик можно не только нажимать, но и качать вправо – влево;
  • Энкодер с шестигранным отверстием для оси ролика и тремя проводами, которые через разъем подключаются к плате мыши;
  • Пластиковый ролик на оси. Так сказать, колесный диск. Ось с краев круглого сечения для нормального вращения в точках крепления «качельки», а по центру шестигранная для зацепа в энкодере;
  • Резиновая шина (ну, или покрышка, как хотите).

Из мыши этот узел извлекается необычайно просто: отключается от платы разъем и выщелкивается из единственной точки крепления «качелька». Далее узел также легко разбирается на составные детали.

Энкодер сам по себе (без «качельки» и ролика) использовать неудобно. Поэтому буду применять его в сборе, только резинку сниму, ибо проскальзывает. За «качельку» удобно держать, а за ролик удобно крутить.

Итак, у энкодера имеются три провода: белый, желтый и черный. Можно не сомневаться, что белый и желтый — это фазы A и B (не обязательно именно в этом соответствии), а замыкаются они при вращении на черный. Тестер в режиме омметра подтверждает это предположение. Заодно определяем, что при вращении энкодера тактильно ощущаются 18 щелчков, причем, на каждый щелчок приходится две смены общего состояния выводов: по одному перепаду на каждом выводе.

Хотелось применить энкодер вместо кнопок для изменения картинки на подключенном экране мобильника, как в опусе 18. Там было подготовлено 20 кадров в расчете на энкодер KY-040, который предполагалось заказать на Aliexpress. Но побаловаться с запчастями от полудохлой мыши интереснее, особенно в рамках нищебродского проекта с минимальным бюджетом.

Значит, надо переписать файл для SD-карты на 18 кадров, изменив «стрелочки» на каждом кадре для равномерности. Кроме того, в коде программы заменить cnt20 на cnt18 , cnt20old на cnt18old , и проверку переполнения счетчика делать сравнением не с 19, а с 17.

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

Энкодер следует подготовить к подключению. Порты контроллера ожидают логические уровни, а энкодер пока что может только замыкать два провода на третий. Стало быть, подключим черный провод к «корпусу», а белые через подтягивающие резисторы — к +3,3 В. Таким образом, разомкнутый белый провод, подключенный к выводу порта, будет показывать логическую единицу, а замкнутый — логический ноль. При вращении энкодера состояние выводов будет последовательно изменяться.

Теперь о том, куда подключать. На порту B остался всего один свободный вывод, а для энкодера нужно два. Можно задействовать порт C, на котором «сидят» кнопки. Нижние две из них используются для переключения «спецрежима», а точнее, флаговой переменной canDo .

Отныне буду для этой цели использовать одну среднюю кнопку. В блоке, отвечающем за опрос кнопок я заменяю код, который четвертой кнопкой включал canDo , а пятой — выключал:

на код, который третьей кнопкой переключает этот флаг:

А вот измененный фрагмент схемы:

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

Перемычки JP3 и JP5, соответствующие портам 6 и 7, снимаю, таким образом, порты нижних кнопок освободились, и к их контактным площадкам можно подпаять выводы энкодера. Но не просто так, а с джамперными пинами, которые воткну в разъемчик энкодера. Добавлю кошмара к устройству. Сплошной навесной монтаж, куча проводов. «Пудель», одним словом. Но это ненадолго, скоро все разберу, а для отладочной времянки допустимо. На фото виднеются емкости, о которых расскажу несколько ниже.

Обработка событий энкодера

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

Допустим, изначально на обоих проводах «0». При вращении сначала изменится состояние одного провода, будет «1» и «0». Потом изменится состояние второго провода, получим «1» и «1». Затем снова будет изменение на первом: «0» и «1». И, наконец, все вернется в исходное: два нолика.

Если рассматривать два провода, как двухразрядное число, получается такое изменение: 0 -> 2 -> 3 -> 1 -> 0 -> … при вращении в одну сторону, или 0 -> 1 -> 3 -> 2 -> 0 -> … в другую.

При обсуждении этого дела на форумах в этом месте обязательно кто-нибудь начинает кричать: «Это же код Грея!» Ну да, код Грея. По определению и исходя из принципа действия энкодера. Это код, в котором последовательно расположенные числа отличаются друг от друга на один разряд. Ну и что? Да, код Грея легко привести к последовательности натуральных чисел. Буквально в пару операций. Но зачем? Совершенно спокойно можно его использовать в прямом виде.

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

Итак, в произвольный момент времени можно опросить энкодер и узнать состояние его проводов. Но само по себе состояние не интересно, потому что вращение — это процесс, протекающий во времени. Состояние важно в сравнении с предыдущим состоянием. Если оно не изменилось, то скорее всего и вращения не было (хотя, есть возможность, что было ровно на два щелчка, но это вряд ли). А если изменилось, то можно определить не только факт поворота, но и направление.

Составлю табличку зависимости текущего состояния от предыдущего:

\ 0 2 3 1
0 0 + x
2 0 + x
3 x 0 +
1 + x 0

Таблица симметричная, так что можно текущим состоянием считать хоть первую строку, хоть первый столбец, это индифферентно.

«0» означает, что вращения не было. Оно и понятно: если текущее состояние равно предыдущему… «+» означает вращение в прямом направлении, «-» — в обратном. Понятия «прямой» и «обратный» довольно-таки относительны и еще зависят от того, какой провод мы выберем фазой А, а какой — Б. «x» соответствует ошибке: такой переход в нормальной ситуации возникнуть не может, значит, ошибка вызвана либо дребезгом контактов, либо слишком быстрым поворотом вала энкодера, либо сбоем программы (например,вызвавшим аномальную задержку между последовательными опросами), либо метафизическими причинами.

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

старое
состояние
новое
состояние
код
(hex)
действие
0 0 0 0
0 2 2 +
0 3 3 x
0 1 1
2 0 8
2 2 A 0
2 3 B +
2 1 9 x
3 0 C x
3 2 E
3 3 F 0
3 1 D +
1 0 4 +
1 2 6 x
1 3 7
1 1 5 0

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

В первой младшие 4 разряда будут содержать текущее и предыдущее состояние энкодера, а вторая будет реагировать на изменения. Соответственно, первая — беззнаковая, а вторая — знаковая, чтобы нормально реагировать на вращение вперед, назад и в другие стороны.

Далее, сразу после обработки нажатия на третью кнопку (упомянутого чуть выше) добавляю такой код:

Два замечания помимо комментариев в коде: во-первых, код избыточен, достаточно восьми case (четыре плюса и четыре минуса), но так нагляднее; во-вторых, счетчик энкодера переписывается в счетчик cnt18 , вывод которого на экран мобильника в виде «циферблата» уже реализован.

Компилирую, прошиваю, запускаю. На экране мобильника появляется логотип, на светодиодах — счетчик. Нажимаю третью кнопку. Счетчик на светодиодах пропадает, на экране появляется «циферблат» с нулями и «стрелкой» вверху.

Медленно проворачиваю ролик энкодера — «циферблат» изменяется, циферки увеличиваются или уменьшаются, «стрелочка» поворачивается в соответствии с направлением, как в опусе 18. Но есть небольшие сбои: часть щелчков энкодера пропускается, а иногда «стрелочка» дергается назад. На быстрое вращение реакция вообще странная: то «циферблат» не изменяется, то сразу прыгает на несколько значений в произвольном направлении.

Некоторое время думал над кодом. Попробовал увеличить время опроса, перепрограммировав таймер, сначала в 256 раз, потом еще в 8 — не помогло. Попробовал сделать проверку состояния по прерываниям, несколько изменив логику защиты от дребезга — тоже нисколько не улучшилось. Я догадывался, что дело в дребезге, но осциллографа дома нету, а до ближайшего прибора тащить далеко и неудобно. Но все-таки добрался я до средств измерения и малость ужаснулся.

При медленном повороте порой все почти в порядке:

Однако чаще всего даже при медленном вращении есть заметный дребезг, который хорошо отсеивается программой:

А вот при быстрой прокрутке вообще кошмар:

Короткие импульсы сплошняком заполнены дребезгом! Это невозможно обработать программно никаким автоматом. И наверхосытку такая одиночная прокрутка:

И укрупненно отдельный срез:

В общем, только программными методами это победить нереально. Надо ставить фильтр. Резистор стоит и так — подтягивающий, на 12 килоом, — добавлю емкость, и получится RC-цепочка, «сливающая» короткие импульсы на корпус. Вот измененный фрагмент схемы с добавкой конденсаторов:

Вот только какую емкость поставить? Правильный подход — выяснить длительность самого длинного всплеска дребезга и самого короткого импульса при быстрой прокрутке вала, и рассчитать емкость для такой постоянной времени RC-цепочки, чтобы фильтр как можно меньше портил импульсы и как можно больше портил дребезг.

Но суровая реальность ограничивает мой выбор пары конденсаторов тремя вариантами (если отбросить то, что меньше единиц нанофарад и больше десятков микрофарад, которые не подойдут даже по беглой прикидке). Есть 2,2 мкФ, 10 нФ и 100 нФ. Как настоящий радиолюбитель, буду сначала паять, потом считать.

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

Ну, теперь можно и посчитать. 12 kilo * 2.2 micro = 0.0264 За это время (в секундах) фронт импульса достигнет 1 — 1/e от единицы, это около 63%. А в три раза позже, через 0,0792 с, фронт достигнет 95%. То есть, импульсы длительностью 80 мс до напряжения питания дойдут, хоть и некрасивые, а то, что покороче — под вопросом. А при быстрой прокрутке импульсы имеют длительность около 10 мс.

Возьмем самый маленький номинал из трех. 12 kilo * 10 nano * 3 = 0.00036 . Импульсы длительностью 360 мкс будут пропускаться. Да и 100 мкс могут быть замечены выше уровня логической единицы. Практика показала, что дребезг почти весь остается.

Ставлю 100 нФ, постоянная времени 1,2 мс. Картинка на медленном вращении такая:

Дребезг на фронтах отсеен совсем, а на срезе либо подавлен, либо доведен до такого состояния, что программный автомат легко с ним справляется. А вот быстрый проворот:

Картина примерно такая же, дребезг в рамках допустимого, работе не мешает.

Эпилог

Подключить энкодер получилось более-менее успешно. Ни одно животное при этом не пострадало: мышь была восстановлена. Энкодер вернул на место, предварительно вымыв колесный диск и шину с мылом и капнув немного суперклея. Теперь ролик не проскальзывает. И заменил дохлую кнопку на исправную, снятую с каких-то мышиных обломков. В качестве бонуса оказалось, что «новая» кнопка еще и тихая. Короче, мышь снова в строю. И при проверке оказалось, что ее ролик в составе мыши работает даже хуже, чем в составе моего устройства: медленная прокуртка длинных страниц иногда отпрыгивает на шаг назад, а быстрая не работает. Так что не вполне качественная работа энкодера — это не кривой код и не кривые руки. Иногда так бывает — и вправду деталь виновата.

Источник