Внимание - много текста
Задумал поставить управление мышкой в подрулевой переключатель.
У меня ВАЗ-2111 с подрулевым от Калины (Приоры, Шеви-Нивы).
Правый подрулевой переключатель пустотелый, легко разбирается.
Решил туда воткнуть маленький трекбол.
Далее излагаю по порядку.
Для реализации проекта приобрел:
- Arduino Pro Micro;
- Трекбол от BlackBerry Bold 9000.
Выбор обусловлен тем, что оба компонента очень компактны. Arduino Pro Micro умеет прикидываться HID мышкой.
Плата (и корпус) трекбола с 4-мя датчиками Холла и кнопкой, с выводами для пайки (Размеры 16мм х 12мм).
К нему шарик с магнитами на осях (можно выбирать цвет:желтый, синий, розовый, черный, зеленый, оранжевый, фиолетовый)
И все это накрывается крышкой.
И вот тут я уперся в скетч.
Пытался использовать стандартный Button Mouse Control из примеров с офф. сайта.
С кнопками все замечательно работает - курсор мыши ползает, меня устраивает. Правда нет правой кнопки (а она удобна и под Win и под Android). Ну да ничего, решаемо.
Дальше вместо 4х кнопок подключил трекбол (схему подглядел на Sparkfun)
Подключил так (кликабельно):
Все прекрасно, курсор ползает в нужных направлениях, все хорошо.
Кроме того, что иногда, после того как перестаешь крутить шарик, курсор мыши продолжает ползти в последнем направлении.
Начал разбираться почему.
Однозначно проблема в Механизме трекбола и Датчиках Холла (далее ДХ).
Вот Datasheet на датчики - ссылка.
Вот так работает механизм трекбола (вид сбоку):
Шар не крутится, он поджат снизу пружиной (красная) к крышке трекбола.
Магнитные поля осевых магнитов направлены перпендикулярно ДХ. С ДХ нет никаких сигналов на Arduino. Курсор мыши неподвижен.
Начинаем пальцем вращать шар вправо.
Шар смещается и прижимается к оси RIGHT, начиная вращать ее (и магнит) относительно ДХ.
При изменении направления магнитного поля Датчик Холла выдает "1", Arduino её видит и курсор мыши движется вправо.
Если продолжить вращение, то за один оборот шара, ось (и магнит) провернутся 9 раз (т.е. на 360° шара - 9 оборотов оси).
Проскочит 9 раз "1" и курсор продвинется дальше.
Убираем палец, прекращая вращение. Шар отводится пружиной от оси прекращая ее вращение.
"1" перестают поступать на вход Arduino, курсор мыши остановился. Это в идеале.
Однако в реальности, после того как шар перестал крутить ось, магнит может остаться в положении,
когда датчик постоянно выдает "1". На рисунке видно, что ось (и магнит) справа осталась повернута перпендикулярно относительно исходного положения.
Соответственно Arduino видит постоянно "1" на своем порту и курсор мыши ползет по экрану.
Такая ситуаци может быть и сразу после включения мыши. И после загрузки курсор мыши начинает свое "независимое путешествие" в одном ей известном направлении.
Получается, что Arduino надо реагировать не на высокий уровень на входе, а на фронт импульса или на изменение логического состояния входа. Если состояние входа статично, постоянно "0" или "1", то контроллер должен это игнорировать.
Как сделать этакий программный XOR, дополнить скетч, я пока понять не могу. Если у кого есть мысли на этот счет - прошу поделиться, буду крайне признателен.
Сейчас скетч выглядит так (кнопки работают, добавлена правая клавиша мыши):
Прошу прощения за обилие текста. Реально уперся в скетч, нужна помощь опытных коллег.Код:// set pin numbers for the five input: const int upButton = 2; const int downButton = 5; const int leftButton = 4; const int rightButton = 3; const int mouseButton = 6; const int mouseRightButton = 7; int range = 1; // output range of X or Y movement; affects movement speed int responseDelay = 20; // response delay of the mouse, in ms void setup() { // initialize the buttons' inputs: pinMode(upButton, INPUT); pinMode(downButton, INPUT); pinMode(leftButton, INPUT); pinMode(rightButton, INPUT); pinMode(mouseButton, INPUT); pinMode(mouseRightButton, INPUT); // initialize mouse control: Mouse.begin(); } void loop() { // read the buttons: int upState = digitalRead(upButton); int downState = digitalRead(downButton); int rightState = digitalRead(rightButton); int leftState = digitalRead(leftButton); int clickState = digitalRead(mouseButton); int mouseRightState = digitalRead(mouseRightButton); // calculate the movement distance based on the button states: int xDistance = (rightState - leftState) * range; int yDistance = (downState - upState) * range; // if X or Y is non-zero, move: if ((xDistance != 0) || (yDistance != 0)) { Mouse.move(xDistance, yDistance, 0); } // if the mouse button is pressed: if (clickState == HIGH) { // if the mouse is not pressed, press it: if (!Mouse.isPressed(MOUSE_LEFT)) { Mouse.press(MOUSE_LEFT); } } // else the mouse button is not pressed: else { // if the mouse is pressed, release it: if (Mouse.isPressed(MOUSE_LEFT)) { Mouse.release(MOUSE_LEFT); } } // if the mouse button is pressed: if (mouseRightState == HIGH) { // if the mouse is not pressed, press it: if (!Mouse.isPressed(MOUSE_RIGHT)) { Mouse.press(MOUSE_RIGHT); } } // else the mouse button is not pressed: else { // if the mouse is pressed, release it: if (Mouse.isPressed(MOUSE_RIGHT)) { Mouse.release(MOUSE_RIGHT); } } // a delay so the mouse doesn't move too fast: delay(responseDelay); }














Ответить с цитированием