Эксперементирую с такой вот клавиатурой. В принципе все с ней понятно, подключил все восемь ножек к Ардуине, последовательно дергаю проводки строк и считываю проводки столбцов. Программка получилась без проблем и работает отлично (см ниже). Вопрос в следующем: можно ли каким либо образом уменьшить количество используемых пинов при этом без использования входного и выходного регистров? Например собрать RC цепь на входящих ножках и искать сигналы по задержке на выходящих? Смутно кажется, что придумать что то можно, я прав? Код (Text): // пины строк const int P[] = {11, 10, 9, 8}; // пины столбцов const int M[] = {7, 6, 5, 4}; // символы на клаве const char k4x4 [4][4] = { {'1', '2', '3', 'A'}, {'4', '5', '6', 'B'}, {'7', '8', '9', 'C'}, {'*', '0', '#', 'D'} }; void setup() { // выставляем пины строк на выход, столбцов на вход for (int i = 0; i <= 3; i++) { pinMode(P[i], OUTPUT); pinMode(M[i], INPUT_PULLUP); digitalWrite(P[i], HIGH); } Serial.begin(9600); } void loop() { GetKey4x4(); // обработку клавы убрал в функцию } void GetKey4x4() { // последовательно выставляем по одной строке в LOW for (int p = 0; p <= 3; p++) { digitalWrite(P[p], LOW); // и считываем столбцы вылавливая где LOW происходит for (int m = 0; m <= 3; m++) { if (!digitalRead(M[m])) { delay(10); // простейшим способом пропускаем дребезг char a = k4x4[p][m]; // считываем соотвествующий символ для комбинации столбца и строки Serial.print(a); while (!digitalRead(M[m])); // ждем отпуска кнопки } } digitalWrite(P[p], HIGH); // возвращем строку в HIGH и крутим дальше } }
Собирайте резистивные цепочки и на аналоговый вход, только нажимать по одной кнопке. При желании, можно вообще все 16 кнопок на один провод повесить. На контроллере считывать аналоговый вход и анализировать значение.
Вроде можно так подобрать резисторы, что будет видно и одновременное нажатие нескольких кнопок. Под степень двойки как-то подбирается.
Народ, я правильно понимаю, что одинаковыми резисторами тут не обойтись? Надо на каждую ножку ставить резистор с разным сопротивлением?
Доделал уже чисто из спортивного интереса, такой мороки не надо больше. ) Мало того что схема сборки сложнее, с четырьмя достаточно разноомными резисторами (подобранными опытным путем), так еще и программа получилась не такая красивая как в цифровом варианте подключения. Но, тем не менее, справился, от чего почувствовал удовлетворение. Есть еще способ сделать все через регистры, но это схема еще на порядок сложнее. Потом. Может быть. Выводы: Все три способа по своему хороши. Цифровой с прямым подключением самый быстрый и простой. Аналоговый заменяет 8 цифровых пинов на 4 аналоговых (экономия). Для работы с несколькими подобными устройствами, которые используют несколько входов и выходов одновременно, подойдет только подключение через регистры. Код (Text): const int A[] = {A0, A1, A2, A3}; int P; // нажатый столбец int M; // нажатая строка int an; // показание активного пина // символы на клаве const char k4x4 [4][4] = { {'1', '2', '3', 'A'}, {'4', '5', '6', 'B'}, {'7', '8', '9', 'C'}, {'*', '0', '#', 'D'} }; void setup() { for (int i = 0; i <= 3; i++) { pinMode(A[i], INPUT); } Serial.begin(9600); } void loop() { // по кругу опрашиваем аналоговые пины (столбцы), если на каком то из них показание менее 1000, значит есть нажатие for (int i = 0; i <= 3; i++) { an = analogRead(A[i]); if (an < 1000) { P = i; // определили номер нажатого столбца // далее по значению напряжения вычисляем номер строки // резисторы на выходящих ножках притянутые к земле установил в порядке убывания: 100кОм, 33кОм, 10кОм и 1КОм, что соответсвтует примерным значениям на пинах 500, 250, 100, 10 // на всех входящих ножках установлены резисторы 100кОм // так как показания немного колеблются, берем диапазон с запасом: if (an > 400) { M = 0; } else if ((an < 300) && (an > 200)) { M = 1; } else if ((an < 150) && (an > 50)) { M = 2; } else if (an < 50) { M = 3; } char a = k4x4[P][M]; // считываем соотвествующий символ для комбинации столбца и строки Serial.print(a); while (analogRead(A[i]) < 1000); // ждем отжатия кнопки } } }
Больше вредных советов слушайте. Можно было обойтись и одним номиналом, соединить в цепочку и к узлам уже кнопки подключать.
Покажите как, я пробовал, получалось что ножки контактируют между собой через резисторы и ничего не работает.
Самый простой способ: Резисторы могут быть одинаковыми. Получается ступеньчатый переменный делитель. Измеряя напряжение делаем вывод о нажатой кнопке. Основной недостаток - нельзя различить две одновременно нажатые кнопки. Есть похожий способ, при котором можно различать одновременно нажатые кнопки, только я его не помню
Я об этом и говорил. Если подобрать номиналы резисторов так, чтобы падение напряжения было пропорционально степени двойки, то можно будет различать несколько кнопок одновременно. Возможно не совсем верно сформулировал, но смысл примерно такой.
Вообще, я вижу, автора сильно волнует проблема мультиплексирования Вот ему: http://easyelectronics.ru/multipleksirovanie.html#more-368
Примерно так я сначала и пробовал сделать, т.к. это самое очевидное. Почему то не получилось. Попробую еще раз вечером, может быть что то напутал.
Вот такая схема: при очень правильном подборе сопротивлений должна дать возможность различать одновременные нажатия...
У меня смутное подозрение, что я не до конца понимаю как работает вольметр вообще и аналоговый пин в частности. Между чем и чем он измеряет вольтаж? Почему в некоторых случаях он вообще не работает, в других показывает ерунду. Объясните кто нибудь на пальцах или дайте ссылку где почитать.
Вольтметр измеряет напряжение между своими щупами Аналоговый вход меряет напряжение между собой и GND. Но значение, которое возвращает analogRead относительное. 0В = 0; 5в = 1023.
Почему то работает не так как хотелось бы. При отжатых кнопках на всех пинах 1024, при нажатии любой кнопки на нижнем ряд 770, 517, 265, 14, при нажатии любой на верхнем - 97, 97, 97, 97. То есть нажатие на любою кнопку влияет на все остальные в клавиатуре. Почему так происходит и как избавиться?
Все, разобрался! Уф. Работает отлично, спасибо за информацию. Мультитач пока не нужен, с ним буду разбираться немного позже. )