Задача: быстро сделать датчик линейного перемещения из компьютерной мышки.

В обычных мышках прячется высокочувствительный оптический датчик. Там скрывается своя маленькая «камера» и процессор обработки, который отслеживает передвижения малейших точек на поверхности. В топовых мышках разрешающая способность составляет всего 3 мкм!



С какими подмышиными камнями мы столкнулись, плюс техническая часть, расскажем дальше!

Следующее ТЗ дал заказчик: сделать как можно скорее, с любой мышкой (возможно беспроводной), выводить на 7 сегментный индикатор, обнулять по кнопке, компьютер не подходит, нужна разрешающая способность 0.01 мм, максимальное расстояние 1000 мм.

Для начала как все это делалось:

План:

Считывание координат xy с мышки:
       Реализовать считывание данных можно несколькими способами:
             а) Непосредственно с микросхемы оптического сенсора
                + Можно обойтись простым контроллером
                - Про универсальность можно забыть совсем
             б) Подключить мышку по USB к простым контроллерам (например к ардуино)
                + Простота и дешивизна
                - Надо паять
                - Под рукой была только arduino, а к ней можно подключить мышки совместимые с 
                  PS/2, а они обычно очень неточные. Можно было на stm32, но отладочные платы 
                  сильно подорожали, самому паять не было времени. (но если интересно, то 
                  несколько лет назад был такой похожий проект именно на stm32f4discovery)
              в) Взять какой нибудь простой одно платный компьютер. Под рукой был как раз Raspberri pi.
                  + Подходит для любых USB мышек
                  + Хорошая производительность
                  - Дорого, но может избыточная мощность потребуется потом

В итоге, под нож хирурга легла Малина пи 3. Четыре 64 битных ядра A-53 по 1GHz, 512 МБ оперативки и много других космических для этой задачи циферок.



Задачка: Индикация должна быть на выданных 7-сегментных индикаторах. Получается нам необходимо по 6 цифр на одну координату, итого 12 индикаторов. Каждый индикатор имеет 7 ножек на цифры+ ножка на светодиод точки (dp), общий провод не считаем. Итого после простых расчетов получаем, что мы должны управлять 96 проводниками плюс нужна кнопка. 96 резисторов не очень хотелось тратить.

Послушайте!
Ведь, если светодиод зажигают — значит — это нужно один резистор?

Управлять сразу таким массивом ножек нету возможности. Выход есть! И даже несколько!

1) Использовать дополнительные микросхемы по типу max7219, или сдвиговые регистры, мультплексоры, и т.д.

+ Можно почти бесконечно наращивать количество индикаторов
— Max7219 оказалась с рабочим напряжением 5 В
— Не было под рукой ничего подходящего.

2) Можно сделать динамическую индикацию. В один момент времени зажигать только один светодиодный индикатор. Если индикаторы переключать очень быстро, то человеческий глаз не заметит подставы.
+ Нужно только 8 проводов и резисторов на один индикатор и 12 на переключение индикаторов. Плюс не забываем кнопку. Итого: всего 21 ножка против 96. Берем!
— Так как мы пытаемся управлять целым индикатором через один пин распберри, то максимальный ток у нас ограничен 50 мА. Всегда берем запас, и берем 35 мА на все 8 светодиодов (что не шибко). Еще к этому добавим быстрое переключение индикаторов. В итоге у нас каждый светит в 12 раз меньше положенного. Доработать можно 12 транзисторами, но оставил я это на потом, т.к. яркости в конечном счете хватило.



Теперь начинается софт:

На распберри пи надо поставить linux. Я поставил минимальный дистрибутив
RASPBIAN JESSIE LITE.

Далее через программу putty подключился к IP малинки, и дальше все через командную строку.
Чтобы было проще работать с GPIO(портами ввода и вывода) есть замечательная библиотека WiringPi.

Как устанавливать её и управлять портами, вы сможете найти много информации в сети, поэтому не буду подробно останавливать на этом.

Дальше надо создать папочку нашего проекта:

cd /home/pi
sudo mkdir mouse
cd /home/pi/mouse

Дальше открываем редактор и вставляем код с гита. ВАЖНО! Код писал на очень скорую руку!

sudo nano

для выхода из редактора надо нажать Alt+x и сохранить файл с названием blinker.c. Дальше надо обязательно скомпилировать с указанием wiring pi:

gcc -o mouse mouse.c -l wiringPi

Все! Теперь подключаем мышку, вставляем провода и запускаем!

Подключение проводов

// pin number declarations. We're using the Broadcom chip pin numbers.

const int p21pin = 2;
const int p22pin = 3;
const int p23pin = 4;
const int p24pin = 17;
const int p25pin = 27;
const int p26pin = 22;
const int p11pin = 10;
const int p12pin = 9;
const int p13pin = 11;
const int p14pin = 5;
const int p15pin = 6;
const int p16pin = 13;
const int papin = 8;
const int pbpin = 23;
const int pcpin = 12;
const int pdpin = 20;
const int pepin = 21;
const int pfpin = 24;
const int pgpin = 18;
const int pdppin = 16;

const int butpin = 26;

sudo ./mouse

Автозапуск при загрузке:

sudo nano /etc/rc.local

и перед exit 0 дописать две строчки

cd /home/pi/mouse
sudo ./mouse &

Работать с этой прогой очень просто. по нажатию кнопки мыши или просто кнопки на плате идет обнуление. При долгом нажатии кнопки переходим в режим регулировки DPI. Это важный параметр который задается мышкой и показывает сколько отсчетов мы получим при движении на один дюйм. Соответственно копка на плате и на мышке прибавляет и убавляет DPI. Долго нажимаем, наше значение записалось в файл и надежно хранится до следующей загрузки системы. Для чистоты эксперимента в программе, индикация, получение информации с мышки и кнопка обрабатываются а параллельных процессах.

Дальше самое интересное! Тестирование и результаты!
Какие есть нюансы работы с мышкой:

1. Оси X и Y на моей мышке были не параллельны боковым граням, приходилось для высчитывания реального расстояния пользоваться «пифагоровыми штанами».

2. Разрешающая способность не равно погрешность!

Простым языком — разрешающая способность действительно показывает минимальное перемещение, которое увидит мышка, (отсчеты в компьютере должны быть дискретны минимальной разрешающей способности). А вот что мышка ничего не пропустит, ничем не гарантируется. Можно уменьшить эту величину используя хорошие поверхности (чтобы оптический сенсор мог отслеживать перемещения), использовать небольшие скорости. Но пропуски будут всегда! Для пользователя это означает постоянный уход нуля и непрогнозируемую погрешность измерения.

3. USB HID по которому работает мышь не гарантирует доставку информации в компьютер! То есть неизвестно пропустил ли компьютер какую нибудь информацию с мышки или нет. Вероятность пропажи информации малая, но все же есть.

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

5. Тут я сильно зол! Дело в том, что мышку я брал самую крутую из ассортимента Logitech, это самая продвинутая была на тот день модель logitech performance mx. Но какого было мое удивление, когда мышь давала разные погрешности при движении вперед и назад. ЭТО КАК? Поясню для пользователя. Если постоянно двигать мышку назад и вперед, то курсор ощутимо так все снижается и снижается. Это на любых платформах. Приходится периодически поднимать мышку и ставить на новое место. После того, как я заметил это, моя жизнь превратилась в кошмар! #Logitech logitech объясните существенную разницу в погрешностях измерения вперед и назад!

Видеодемонстрации работы:


В итоге: недостатки перевесили все плюсы мышки как измерительного прибора. Поэтому проект закрыл и выкладываю для дорогих моих читателей на GeekTimes.
Поделиться с друзьями
-->

Комментарии (42)


  1. basilbasilbasil
    18.07.2017 15:47

    1. почему не выбрали другую мыжь?
    2. почему бы на поверхность не нанести контрастные микронасечки?


    1. SergeySavkin
      18.07.2017 15:49

      1.В итоге другую мышь и взяли, но она просто на расстоянии 100мм дает погрешность 1 мм, а нам нужна 0.01мм
      2. Микронасчеки можно, но за нас это сделала природа, например дерево или бумага.


      1. basilbasilbasil
        18.07.2017 16:12

        да, но насечки природного происхождения неупорядоченные.


        1. SergeySavkin
          18.07.2017 17:31

          Тут правильно ответил Gryphon88 «волокна работают как chaotic test target»


  1. lingvo
    18.07.2017 15:55
    +2

    Мда. Совсем неправильный метод решения задачи вы выбрали. Ну ничего — многому научились зато. Ну и, надеюсь, мышь и Распберри не пропали даром?


    1. SergeySavkin
      18.07.2017 17:14

      Все живо и готово к новым проектам


  1. barbanel
    18.07.2017 15:57
    +1

    По поводу пункта 5, чисто мои домыслы в порядке возрастания бредовости:
    — Обычно когда двигаешь мышку, ее координаты меняются с учетом ускорения движения, т.е. резкий рывок мышью даст большее значение чем медленный но на то же самое расстояние. Возможно незаметно для себя вы движете мышь вперед со скоростью, отличной от движения мыши назад.
    — Это фичереквест менеджеров, чтобы в будущем выпустить мышь с еще более тонкой батареей с увеличенной точностью всего за 99.99$
    — Некий инженер со склонностью петь и танцевать в любой непонятной ситуации, написал в коде:

    if ( device_move_direction.to_string = g_move_backward.to_string )
    {
    // it's about time to sing and dance now
    g_error_rate = g_error_rate * random();
    }


    1. nmi77
      18.07.2017 18:38
      +4

      Первый вариант скорее всего верный — для измерительных целей в драйвере нужно выключить аксселерацию.


    1. edge790
      19.07.2017 15:16

      Возможно, я не прав, но акселерация — это фича аппаратного уровня.
      + Интересует вопрос: а стелко увеличительное с сенсора сняли?(Если оно было)

      На данный момент все производители мышей гонятся за DPI, из-за чего прибегают к «грязным трюкам» типа увеличительных стекол.
      Идея простая — жертвуем максимальным ускорением мыши (G) но увеличиваем DPI (т.е. передвижение курсора на X точек за Y дюймов)


    1. Soul_in_Gun
      20.07.2017 06:58

      Данная мышка использует лазеро-оптический тип сенсора, а не «просто оптический», которые грешат положительной акселерацией. В среде геймеров данные параметры (как негативно влияющие на производительность игрока) подробно отслеживаются, созданы списки сенсоров-вендоров где данные погрешности указаны.
      Соответственно просто скорость движения вверх и вниз неравномерны отчего и создаётся данная проблема.

      Решение — использовать мышь с сенсором не имеющим акселерацию, помимо конечно отключения софтварной акселерации


  1. golf2109
    18.07.2017 16:06

    объясните существенную разницу в погрешностях измерения вперед и назад

    разные фронты сигналов


    1. basilbasilbasil
      18.07.2017 16:08

      датчик оптический, какие фронты?


      1. golf2109
        18.07.2017 19:48

        при чем тут «датчик оптический»?
        Вы оптический сигнал напрямую в процессор заводите?
        На выходе датчика сигнал все-таки электрический.
        Фронты электрические передние и задние могут отличаться


        1. Red_Lion
          19.07.2017 07:52

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


        1. Andy_Big
          19.07.2017 08:07
          +1

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


    1. Dmitry_5
      19.07.2017 07:40
      +1

      Скорее датчик под углом стоит


  1. Mulin
    18.07.2017 16:43

    А если использовать тот же принцип что и в оптических мышах, но в качестве «датчика» заюзать вебку и считать перемещение софтом?
    PS Столкнулся с той же проблемой, когда делал датчик перемещения для 3D принтера. Но я там оптическую головку крепил прямо на экструдер, а объектив смотрел на потолок корпуса, таким образом я одним датчиком читал и X и Y.


  1. Gryphon88
    18.07.2017 16:58
    +10

    Задача уже решалась на ГТ (там, кстати неплохие комментарии). Я тоже, как додавлю разрешение, напишу. В конце сообщения под спойлером ссылки, во всех есть код и схема, но сначала несколько ремарок:
    1. Лучше брать проводную мышь постарше, года так 2010-2015, у них пристойное разрешение и они отдают картинку, и подпаяться просто. Я работал на чипе ADNS-2051 (даташит)
    2. С чипом мыши можно общаться двумя способами: через серийный порт (просто, но медленно, не больше 30 fps) или читать квадратурные выходы (до 1500 fps, там вроде по сдвигу генерится прерывание и дергается нога)
    3. Чипы среднехреновые, в том числе по шуму и расстоянию между пикселами… По шуму можно откалиброваться, но геморно.
    4. Разрешение указывают маркетологи, более точной оценкой является расстояние между центрами пикселов делить на 2,5. Можно улучшить разрешение постпроцессингом, в первую очередь через обработку subpixel shift.
    5. Оптическая система важна. Или ставьте на прототип вместе с пластиковой родной линзой, или пересчитывайте фокусное расстояние и увеличение
    6. Чтобы уменьшить «плытие» и улучшить результаты постпроцессинга используйте подложку с фактурой. Идеал — диффракционная решетка с шагом в 1/2 пиксела сенсора, но и плотная (ок 80 г/м) матовая немелованная бумага подойдёт, волокна работают каак chaotic test target

    Ссылки
    1. Сурово: только мышиный сенсор и LPT-порт. Картинки к статье
    2. Ардуино и мышь, одна из первых попыток
    3. Ардуино и мышь-2, более подробно
    4. Ардуино, мышь и JS Хипстота, зато сразу в браузер
    5. Арудиновская библиотека для работы с мышиными сенсорами
    6. ATMega8 и сенсор
    7. AVRовская библиотека AVRCam, чтение мышиного сенсора, постобработка, трекинг. Можно скачать бесплатно, там просто ссылка незаметная


  1. rstepanov
    18.07.2017 17:26

    При использовании энкодера ошибка будет всегда накапливаться, достаточно подергать взад-вперед раз сто — и точность будет уже не доли миллиметра, а скорее десятки сантиметров :) Для таких задач лучше применять что-то типа этого:

    https://sensing.honeywell.com/honeywell-sensing-longfellow2-linear-position-transducer-productsheet.pdf


    1. rstepanov
      18.07.2017 17:28

      Или китайчатина подешевле: https://ru.aliexpress.com/store/product/Free-shipping-Rational-WTB5-0-001mm-600mm-dro-linear-scale-Lathe-accessories-absolute-position-encoder-for/1021179_32386818977.html


    1. SergeySavkin
      18.07.2017 17:28

      В итоге, к похожему и пришли


    1. lingvo
      18.07.2017 18:03

      Датчик холла и магнитная лента с полюсами.


  1. dlinyj
    18.07.2017 18:46
    +1

    Очень много мыслей, но нет толкового описания работы с мышью.


    1. SergeySavkin
      19.07.2017 12:37

      Мышь подключается по USB. Дальше идет работа со стандартными драйверами.


  1. VBKesha
    18.07.2017 18:48

    — max7219 оказалась с рабочим напряжением 5 В

    Я проверял два модуля на этих чипах, никаких проблем они не испытывали пари работе от 3,3В и питание и сигналы, и спокойно работали при 5В питании, и 3.3 логике управления.


  1. VBKesha
    18.07.2017 18:54
    +1

    По поводу результатов, А что если поставить несколько сенсоров, разнонаправленых, и потом сводить с них результат воедино?


    1. Gryphon88
      18.07.2017 21:52
      +2

      В смысле — разнонаправленных? В мыши квадратная матрица, от 15*15 до 128*128


      1. VBKesha
        18.07.2017 23:11
        +1

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


        1. VerdOrr
          18.07.2017 23:17
          +2

          Чего уж мелочиться — 3 шт., направление 0 и ±120гр., и усреднять показания


      1. VerdOrr
        18.07.2017 23:12

        Тянитолкай из двух грызунов, наверное =)


    1. rPman
      20.07.2017 23:09

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


  1. iG0Lka
    18.07.2017 19:26
    +1

    Из решения аналогичных задач в свое время родился проект w-mouse.
    Его автор — Walkie, как раз использует мышиные сенсоры, на производстве, для определения перемещения.
    Если нужен реальный результат советую Вам с ним связатся.
    Кстати w-mouse имеет счетчик посланных отсчетов по X и Y, зная текущее дпи легко подсчитывать смещение.
    скрин экрана настройки


  1. longtolik
    18.07.2017 19:33
    +1

    Здравствуйте, можете попробовать ещё датчик от электронного штангенциркуля, (digital caliper). Он работает по IIC, в основном.
    На датчике мыши я делал энкодеры, и они меня не разочаровали. Посмотреть можно здесь:
    http://www.rlocman.ru/shem/schematics.html?di=162625 там же и ссылки на некоторые чипы.


    1. andersong
      19.07.2017 08:57

      У простых электронных штангетов данные относительные, те требуется установка нуля при каждом включении, но читал про штангеты (марку забыл), где данные абсолютные, те штангет после включения сразу выдает показания, в каком бы месте каретка ни находилась. Как это реализовано? На шкалу нанесены кодирующиие метки?


      1. longtolik
        19.07.2017 09:34

        Насколько я понимаю, питание на чип подаётся постоянно, кнопка отключает ЖКИ. Поэтому батарейка и «садится», независимо от того, работает ли он в режиме измерения или просто лежит в футляре. Те, с которыми я работал, все «помнили» показания, но если вытащить батарейку, то «сбрасывались». У всех был разъем для подключения, но вот протокол может быть нескольких типов.

        Если это критично, то можно сделать так: микроконтроллер считывает показания в ОЗУ (регистр), цепь питания двухступенчатая, то есть, присутствует ещё что-то вроде конденсатора или ионистора. Напряжение от блока или элементов питания подаётся на один из входов микроконтроллера, и когда оно падает ниже критического уровня, наступает прерывание, в ходе обработки которого показания быстро переписываются в энергонезависимую память. После включения, если они не пусты, то считываются в ОЗУ.

        P.S. Раньше микро-ЭВМ успевали всю свою память записывать на диск, когда напряжение 220 Вольт пропадало, но постоянное напряжение ещё держалось на конденсаторах блока питания.


      1. nafikovr
        19.07.2017 13:46

        вариант с мышкой тоже относительный. промышленный линейные датчики тоже относительные, но имеют реперные метки.


        1. andersong
          19.07.2017 13:59

          В промышленности есть и абсолютные датчики, оперирующие кодом Грея.


          1. nafikovr
            19.07.2017 14:30

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


  1. x893
    18.07.2017 19:40

    А если поставить два сенсора с противоположной ориентацией?
    И корректировать вперед-назад с двух? И то же самое сделать по второй координате?
    И не нашел подключение мыши в картинке названия контактов на RPi.


    1. SergeySavkin
      19.07.2017 12:36

      Мышь подключается по USB


  1. lonelymyp
    18.07.2017 21:58
    +4

    Неужели не захотелось погуглить прежде чем пробовать?
    Все многочисленные проекты использующие мышиный сенсор испытывают примерно одинаковые проблемы, мышиный сенсор пропускает движение.
    За последние лет 10-15 ничего особо в этом плане не изменилось.


  1. avf1906
    19.07.2017 15:18

    насчет индикаторов — на али искать по слову tm1637 — два провода = 6 цифр + 16 кнопок (на кнопки ограничение, не поддерживаются одновременные нажатия). хотя наиболее массовые с 4 цифрами, может на будущее пригодится