Вчера приобрёл такую клавиатуру, и пытаюсь подключить и заставить её работать. Испольую следующий скетч: Код (C): void setup() { // put your setup code here, to run once: pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, OUTPUT); pinMode(6, INPUT); pinMode(7, INPUT); pinMode(8, INPUT); pinMode(9, INPUT); Serial.begin(9600); } void loop() { // put your main code here, to run repeatedly: for(int i = 0; i > 3; i++) { digitalWrite(i, HIGH); for(int j = 4; j > 7; j++) { if (digitalRead(j) == HIGH) { bouton(i,j); } } digitalWrite(i, LOW); } delay(100); } void bouton (int i, int j) { char msg[2]; if (i == 0) { if (j == 4) sprintf(msg, "1"); else if (j == 5) sprintf(msg, "2"); else if (j == 6) sprintf(msg, "3"); else if (j == 7) sprintf(msg, "A"); else sprintf(msg, "E"); } else if (i == 1) { if (j == 4) sprintf(msg, "4"); else if (j == 5) sprintf(msg, "5"); else if (j == 6) sprintf(msg, "6"); else if (j == 7) sprintf(msg, "B"); else sprintf(msg, "E"); } else if (i == 2) { if (j == 4) sprintf(msg, "7"); else if (j == 5) sprintf(msg, "8"); else if (j == 6) sprintf(msg, "9"); else if (j == 7) sprintf(msg, "C"); else sprintf(msg, "E"); } else if (i == 3) { if (j == 4) sprintf(msg, "*"); else if (j == 5) sprintf(msg, "0"); else if (j == 6) sprintf(msg, "#"); else if (j == 7) sprintf(msg, "D"); else sprintf(msg, "E"); } while (digitalRead(j) == HIGH) Serial.println(msg); } Собственно я ничего не получаю в мониторе serial порта, как это пофиксить? И как лучше идентифицировать какая кнопка была нажата?
а где ты такой скетч надыбал for(int i = 0; i > 3; i++) это как так (цикл работает когда условие истинно!)? кстати в твоем случаи так for(int i = 2; i <= 5; i++) то есть устанавливаем выходы от 2 до 5 функцией digitalWrite() в высокий уровень! дальше проверяем нажатие for(int j = 6; j < =9; j++) соответственно входы 6-9 !
Сам написал. Спасибо за исправления, хоть что то начало выводиться в монитор. Но до сих пор не понятно на какие провода надо подавать напряжение, а на каких проводах надо искать.
Разумеется, я понимаю что, нужно подавать питание на один из проводов первой четвёрки, и искать это питание, на одном из второй четвёрки. Но блин, как понять где на шлейфе от клавиатуре первая четвёрка, а где вторая?
это кнопки и разницы нет к тому же и клавиатура у тебя 4х4, от того что ты подашь напряжение на 1-ю четверку а со 2-й снимешь или наоборот, разницы не будет!
Я джва дня хочу подключить эту клавиатуру к Arduino mega и имею сказать следующее: если цеплять её на 8 пинов, и делать примерно как в первом сообщении, то это НЕ работает. Из-за наводок 4 пина которые INPUT выдают пр-ревосходный белый шум. Ну натурально, бесконтактное управление - рукой проводишь над проводками - результат опроса клавы меняется. Пытался извращаться с Input_Pullup - та же петрушка, вид сбоку. Надо ставить подтягивающие резисторы, как в схеме 1 по ссылке из 4 сообщения. 10 кОм слишком мало, с ним всё сваливается в LOW, а других у меня пока нет. Беда, печаль, не повторяйте моих ошибок. Может Ардуино само как-нибудь может в подтягивающие резисторы, а? Или какой-нибудь shield или что-то такое есть, не знаете?
Там как раз не советуют пользоваться внутренней подтяжкой. И Di Halt тоже не советовал (говорит, внутренняя подтяжка дохнет от любого чиха), а ему можно верить. Лучше не пожалеть внешнего резистора.
Изложенная там, в частности, идея о многократном опросе кнопки для удаления "дребезга" проста, но великолепна. Непременно использую.
Читал код, мучительно пытался понять. Комменты на французском - это хорошо, это полезно. Убедил себя в том, что функция bounсe::update() то ли занимает время процессора в течение interval_millis от момента previous_millis, то ли в этот промежуток времени отвечает только FALSE. То есть на опрос 16 кнопок с её использованием я потрачу (16*interval_millis) времени. Хм... ну посмотрим. Внезапно обнаружил что читал вторую версию кода (bounce2). Прочитал первую (bounce), частично понял .
Попробовал. В соответствии с предупреждением , внутренняя подтяжка не помогла или вовсе не сработала: на всех INPUT pin'ах непоколебимо стоит HIGH. Ну, почти: при замыкании 2 или 3 или 4 OUTPUT pin'ов на 4-й INPUT pin, первый INPUT pin падает в LOW, зато 2-й по-прежнему HIGH. (номера условны, в реальности это были 30-37 pins) Да и pin с ними. Буду паять внешние резисторы.
Здравствуйте! Коротко о клавном: всё работает, и работает хорошо. Кнопки у клавы хорошие, шума дают мало, он легко давится. Подробности: Подключил клавиатуру следующим образом: входы 1-4 к пинам Pin1-Pin4, входы 5-8 к пинам Pin5-Pin6 и через резистор 10 кОм к земле. ( при сопротивлении резистора 40 кОм есть ложный HIGH на Pin5-8, при 30 кОм - нормально, при 10 - тоже). Не паял пока, всё через макетку. Для работы с клавой сделал следующий класс (см в нём инструкцию про применению): keyb4x4.h: Код (Text): #include <Arduino.h> /* Как пользоваться классом: 0) Создайте экземпляр класса. Сообщите конструктору номера пинов, к которым подключена ваша клавиатура, в порядке увеличения номера на разъеме клавы. Там есть нумерация, есличо. 2) в setup() выполните begin() 3) в loop() вставьте process() Он выполняется за 230-250 микросекунд (не милли-, а микро) + MicrosToAskOnePin (440-450 мкс всего) иногда ... Используйте get() чтобы извлечь нажатый юзером PROFIT в виде char'a. */ // keyb4h4.h class Keyb4x4 { public: // constructor: give it number of pins connected to keyboard; three last values have reasonable defaults and usually should be omitted. // Pin numbering is printed on keyb's jack. Keyb4x4(int pin1, int pin2, int pin3, int pin4, int pin5, int pin6, int pin7, int pin8, int NumberConsequentRepeats=7, int MicrosToAskOnePin=200, int UnknownValuePresumedAs=LOW); //Run it in Setup() //Keyb4x4::begin() Initiates pins, run this function in Setup void begin (boolean UseInternalPullingResistors=false); //default=false because they don't work ha-ha-ha. // Run it in loop() //Keyb4x4::process() Checks keyboard every loop() cycle, adding keys to buffer. Only _pressed and then released_ keys are added! void process(); //Keyb4x4::ask() Basic function. Quickly asks keyboard and returns: char '\0' if nothing pressed or char of KeyTable set if button is pressed. char ask(void); //should be used not itself but in some wrap function like process() //Main function - use it to... //Keyb4x4::get(). ...get one char from buffer. Or '\0' if it is empty. char get(void); boolean KeyPressed; //true if user have pressed something... void SetParameteres(int NumberConsequentRepeats, int MicrosToAskOnePin, int UnknownValuePresumedAs); //if you need to change it from defaults. To change just one param, omit others - they will be ignored int version(void); //для понтов private: int cols[4]; //here I store numbers of pins connected to one side of keyb matrix (let's call its "columns") int rows[4]; //here I store numbers of pins connected to other side of keyb matrix (let's call its "rows") long NumberConsequentRepeats; // Function Ask will DigitalRead a pin form rows[] array until get "NumberConsequentRepeats" of the same consequent values, OR unsigned long MicrosToAskOnePin; // until "MicrosToAskOnePin" time will pass. In this case it will ensure the pin is Unknown and int UnknownValuePresumedAs; // presume it is HIGH or LOW (default) according to UnknownValuePresumedAs variable boolean UseInternalPullingResistors; // use only external 10 kOm resistors and you'll get no problems. static const char KeyTable44[4][4]; //key values, see initialisation below char buffer[256]; //keyboard buffer for process() and get() int UsedBuffer; // pointer to last used place in buffer. char CurrentPressedKey; // for process() }; keyb4x4.cpp: Код (Text): // keyb4x4.cpp #include "keyb4x4.h" #include "Arduino.h" //here we fill array of keyboard values. You can modify it if necessary. const char Keyb4x4::KeyTable44[][4]={{'1','2','3','A'},{'4','5','6','B'},{'7','8','9','C'},{'*','0','#','D'}}; Keyb4x4::Keyb4x4(int pin1, int pin2, int pin3, int pin4, int pin5, int pin6, int pin7, int pin8, int NumberConsequentRepeats, int MicrosToAskOnePin, int UnknownValuePresumedAs) { this->cols[0] = pin1; // pins keyboard connected to this->cols[1] = pin2; // pins keyboard connected to this->cols[2] = pin3; // pins keyboard connected to this->cols[3] = pin4; // pins keyboard connected to this->rows[0] = pin5; // pins keyboard connected to this->rows[1] = pin6; // pins keyboard connected to this->rows[2] = pin7; // pins keyboard connected to this->rows[3] = pin8; // pins keyboard connected to this->NumberConsequentRepeats=NumberConsequentRepeats; this->MicrosToAskOnePin=MicrosToAskOnePin; this->UnknownValuePresumedAs=UnknownValuePresumedAs; this->UsedBuffer=-1; KeyPressed=false; } void Keyb4x4::begin(boolean UseInternalPullingResistors) { // setup the pins on the microcontroller: for (int i=0; i<4; i++) { pinMode(cols[i], OUTPUT); // to send voltage, pinMode(rows[i], INPUT); // and to read results. //prepare OUTPUT pins: digitalWrite(cols[i], LOW); //prepare INPUT pins: if (UseInternalPullingResistors) { digitalWrite(rows[i], HIGH); // Here we enable internal pulling resistors between INPUT pins to ground. On my Arduino Mega they don't work at all :-(. } else { digitalWrite(rows[i], LOW); // and here disable them: it's preferable if you already have external pulling resistors in your scheme. } } //cycle end } char Keyb4x4::ask(void) { // char r='-'; for (int i=0; i<4; i++) { for (int j=0; j<4;j++) digitalWrite(cols[j], LOW); //set OUTPUT pin's to zero. Don't remove or you'll get false positives digitalWrite(cols[i], HIGH); //set +5V to pin from column and for (int j=0; j<4;j++){ //check is it visible on any row? if (digitalRead(rows[j])==HIGH) { // OK, if we got circuit so take several repeats to ensure it is not false positive because of induction, statics or other long counter=1; // we already have 1 answer unsigned long TimeToStop=micros()+MicrosToAskOnePin; //don't gonna fall to infifnite cycle if pin "free-float" while ((counter<NumberConsequentRepeats) && (micros()<TimeToStop)) { //the investigation if (digitalRead(rows[j])==HIGH) { counter++; } else{ // negativ answer? counter=0; //begin collect from zero! } } //here investigation over and we check it's result if (counter>=NumberConsequentRepeats) { //Yes! col[i] and row[j] connected! пришёл к успеху return KeyTable44[3-j][3-i]; } else{ //Unknown result if (UnknownValuePresumedAs==HIGH) { //считать гуся карасём return KeyTable44[3-j][3-i]; } else if (UnknownValuePresumedAs==LOW) {}//do nothing не свезло, не пофартило } } //end of first If(DigitalRead...) statement }//end of rows cycle }//end columns cycle return '\0'; } void Keyb4x4::process(void) { char t; t=ask(); if (CurrentPressedKey==t) {return;} //key is still pressed from previous run else if ((t=='\0') && (CurrentPressedKey!='\0')) { // key pressed now released - add it to buffer ранее нажатая кнопка отпущена - добавляем UsedBuffer++; buffer[UsedBuffer]=CurrentPressedKey; CurrentPressedKey='\0'; if (UsedBuffer>255) UsedBuffer=-1; //BTW if overflow - just start from beginning. KeyPressed=true; return; } else if ((t!='\0') && (CurrentPressedKey=='\0')) { // key just pressed right now CurrentPressedKey=t; //и подождём while it releases return; } else if ((t!='\0') && (CurrentPressedKey!='\0')) { //other key pressed while first don't released. It's bad. It's undefinite situation because of matrix keyb structure. Don't do so! //do nothing как-нибудь так! } } char Keyb4x4::get(void) { char t='\0'; if (UsedBuffer>=0) { t=buffer[0]; for (int i=0; i<UsedBuffer;i++) buffer[i]=buffer[i+1]; UsedBuffer--; if (UsedBuffer<0) KeyPressed=false; } return t; } void Keyb4x4::SetParameteres(int NumberConsequentRepeats=0, int MicrosToAskOnePin=0, int UnknownValuePresumedAs=LOW) { if (NumberConsequentRepeats!=0) this->NumberConsequentRepeats=NumberConsequentRepeats; if (MicrosToAskOnePin!=0) this->MicrosToAskOnePin=MicrosToAskOnePin; if (UnknownValuePresumedAs!=0) this->UnknownValuePresumedAs=UnknownValuePresumedAs; } int Keyb4x4::version(void) { return 3; } Для подавления шума в вышеприведенной функции ask после получения замыкания двух пинов оно проверяется до тех пор, пока не обнаружится NumberConsequentRepeats последовательных положительных результатов. Всё это проверяется за время не более чем MicrosToAskOnePin. Если не получено нужного числа последовательных результатов за это время, то для пинов принимается состояние UnknownValuePresumedAs. Программа для демонстрации работы клавы использует LCD 4х20 строчек, правьте под себя: Код (Text): #include <keyb4x4.h> #include <Arduino.h> // подключаем библиотеку для работы с LCD #include <LiquidCrystal.h> //создаем объект клавиатуры Keyb4x4 myKeyb (40,41,42,43,44,45,46,47); // сосздаем объект LCD, указывая контакты данных LiquidCrystal lcd(48, 49, 50, 51, 52, 53); int line=0; int column=0; unsigned long t=0; void setup() { // указываем размерность экрана и начинаем работать lcd.begin(20, 4); lcd.clear(); lcd.print("Keyb input below:"); lcd.setCursor(0, 1); //иниц. клав. myKeyb.begin(true); } void loop() { char k='\0'; //вспомогательное - засечка времени t=micros(); //мне надо быстро, мне ещё много чего крутить в realtime //Опрос клавиатуры myKeyb.process(); //вспомогательное - засечка времени t=micros()-t; if (myKeyb.KeyPressed) { k=myKeyb.get(); lcd.setCursor(column, 1); lcd.print(k); column++; if (column>19) column=0; lcd.setCursor(0, 2); lcd.print("Run time, mcs: "); lcd.print(t); } } Буду рад, если кому-нибудь пригодится.