16ти кнопочная клавиатура

Тема в разделе "Обсуждение магазина", создана пользователем L_off, 18 янв 2013.

  1. L_off

    L_off Нерд

    http://amperka.ru/collection/Sensory/product/klaviatura-na-16-knopok

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

    hibiki Гик

    а в чем проблема? просто опрашиваете линии последовательно, на одну, скажем, 1, на другие 0 - и у вас в один момент времени будет пара "строка - от одного до четырех столбцов".
     
    nailxx нравится это.
  3. Unixon

    Unixon Оракул Модератор

    Код (Text):

    const byte PIN_KB_ROW_BASE = 2;
    const byte PIN_KB_COL_BASE = 6;
    const byte KB_KEYS = 16;
     
    unsigned int get_keymap()
    {
     unsigned int keys;
     for (byte i = 3; i >= 0; i--)
     {
      digitalWrite(PIN_KB_ROW_BASE+i,HIGH);
      for (byte j = 3; j >= 0; j--)
      {
      keys = keys*2 + digitalRead(PIN_KB_COL_BASE+j);
      }
      digitalWrite(PIN_KB_ROW_BASE+i,LOW);
     }
     return keys;
    }
     
    byte get_key()
    {
     for (byte i = 3, k = KB_KEYS; i >= 0; i--)
     {
      digitalWrite(PIN_KB_ROW_BASE+i,HIGH);
      for (byte j = 3; j >= 0; j--, k--)
      {
      if (digitalRead(PIN_KB_COL_BASE+j)) return k;
      }
      digitalWrite(PIN_KB_ROW_BASE+i,LOW);
     }
     return 0;
    }
     
    void setup()
    {
     for (byte i = 0; i < 4; i++)
     {
      pinMode(PIN_KB_ROW_BASE+i,OUTPUT);
      digitalWrite(PIN_KB_ROW_BASE+i,LOW);
     }
     for (byte i = 0; i < 4; i++)
     {
      pinMode(PIN_KB_COL_BASE+i,INPUT);
     }
    }
     
    void loop()
    {
     // ... insert some useful code here ...
    }
     
  4. L_off

    L_off Нерд

    так...не понял, можно подробно...очень подробно пожалуйста как это работает:(
     
  5. Unixon

    Unixon Оракул Модератор

    Клавитатура состоит из двух рядов проводников, одни идут вдоль строк, другие вдоль столбцов, кнопки располагаются в местах пересечения. Когда кнопка нажимается, одна из строк замыкается на один из столбцов. Как узнать какая, даже если она одна? Просто. Соединяем все строки - "входы" клавиатуры с выходами ардуины, а столбцы - "выходы" клавиатуры - с входами ардуины. Подаем напряжение на строки, а снимаем его с рядов. Подали на первую строку "1", а на все остальные строки "0". Если в первой строке нажаты кнопки, на соответствующих кнопкам рядах тоже появятся "1", а там где кнопки не нажаты останутся "0". Прочитали все входы и узнали нажата ли в данном ряду, на который только что поставили "1" какая то кнопка или несколько кнопок. Потом убираем с первой строки "1" и ставим на вторую, потом со второй убираем и ставим на третью и т.д. проверяем все строки по очереди. Поскольку строки и столбцы совершенно равноправны, их можно поменять местами, смотря как вам удобнее, "входы" и "выходы" у матричной клавиатуры - понятия условные.

    Не забудьте притянуть "выходы" клавиатуры к земле резисторами!

    В общем, см. пример кода выше.
     
    L_off нравится это.
  6. L_off

    L_off Нерд

    большое спасибо, действительно помогло :)
     
  7. L_off

    L_off Нерд

    а зачем переменная keys домножается на два?
    второй цикл как я понял возвращает номер нажатой кнопки?
     
  8. Unixon

    Unixon Оракул Модератор

    get_key() возвращает номер только первой нажатой кнопки,
    get_keymap() возвращает битовую карту всей клавиатуры, т.е. если в возвращаемом 16-битном числе типа unsigned int установлен i-ый бит, значит на клавиатуре нажата i-тая кнопка. Так очень легко проверять нажание сразу нескольких кнопок, всего лишь сравнивая возвращаемое значение с константой. А умножение на 2 это то же самое, что сдвиг всего числа влево на 1 бит. В цикле состояние всей клавиатуры копируется в биты одного числа начиная со старших кразрядов к младшим. Чтобы записать младший разряд 0 или 1, сначала нужно сдвинуть все записанные ранее, а сдвиг можно записать это либо как "keys<<1", либо как "keys*2", но умножение иногда удобнее, если тип знаковый или большой разрядности.
     
  9. L_off

    L_off Нерд

    но ведь keys - это просто число, как он может возвращать карту?
     
  10. Unixon

    Unixon Оракул Модератор

    Но ведь число состоит из нескольких бит, верно? А для того, чтобы передать нажатие одной кнопки достаточно всего лишь одного бита. В байте (char , usigned char = byte) их 8, в слове (int, unsigned int = word) их 16, в двойном слове (long int, unsigned long = longword) 32, в long long int 64.

    Вот, смотрите: допустим, у нас есть всего 8 кнопок один байт для карты, тогда
    0x00h [0 0 0 0 0 0 0 0] - ни одна кнопка не нажата,
    0x01h [0 0 0 0 0 0 0 1] - нажата кнопка №1,
    0x02h [0 0 0 0 0 0 1 0] - нажата кнопка №2,
    0x03h [0 0 0 0 0 0 1 1] - нажаты кнопки №1 и №2,
    0x8ch [1 0 0 0 1 1 0 0] - нажаты кнопки №3, №4, №8.

    Если клавиатура больше, можно взять число подлиннее или несколько чисел, но это уже не так красиво.
     
  11. L_off

    L_off Нерд

    я все равно не понимаю как одно число может отображать целую карту нажатий, извините:(
     
  12. L_off

    L_off Нерд

    что означают слова "0x00h"?
    получается, надо число на биты разбивать?
     
  13. Unixon

    Unixon Оракул Модератор

    Это шестнадтеричные числа. Сюда загляните. Ну и еще вот сюда тоже.

    Можно, но не обязательно нужно.

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

    Кажется, я знаю, что вам еще может пригодиться - функция типа get_key(), для определения, нажата ли какая то одна заранее известная кнопка.
     
  14. Unixon

    Unixon Оракул Модератор

    Код (Text):

    boolean is_key_pressed(const byte row, const byte column)
    {
     boolean key_pressed = false;
     digitalWrite(PIN_KB_ROW_BASE+row,HIGH);
     key_pressed = digitalRead(PIN_KB_COL_BASE+column);
     digitalWrite(PIN_KB_ROW_BASE+row,LOW);
     return key_pressed;
    }
     
    boolean is_key_pressed(const byte key)
    {
     byte k = key-1;
     return is_key_pressed(k/KB_ROWS, k%KB_ROWS);
    }
     
    Нумерация кнопок начинается с 1 для совместимости с get_key(), у которой 0 означает отсутствие нажатых кнопок.
     
  15. L_off

    L_off Нерд

    мне вынесло мозг вторым циклом
    но ведь клавиш 16. получается нужно 32 битное число, так ведь?
     
  16. L_off

    L_off Нерд

    всмысле принципом работы, для чего он нужен понятно
     
  17. Unixon

    Unixon Оракул Модератор

    С чего бы это? Одна кнопка - один бит.
     
  18. Unixon

    Unixon Оракул Модератор

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

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

    L_off Нерд

    ааааааа точно :)
    0 или 1
     
  20. L_off

    L_off Нерд

    массив проще понять