Здравствуйте, как сделать чтоб ардуино повторяла нажатие клавиш в точности как на HID-клавиатуре. имею такой код: Код (C++): uint8_t buf[8] = { 0 }; /* Keyboard report buffer */ #define PIN_X 2 int state = 1; void setup() { Serial.begin(9600); pinMode(PIN_X, INPUT); // Enable internal pull-ups digitalWrite(PIN_X, 1); delay(200); } void loop() { state = digitalRead(PIN_X); if (state != 1) { buf[2] = 27; // Letter X Serial.write(buf, 8); // Ssend keypress releaseKey(); } } void releaseKey() { buf[2] = 0; Serial.write(buf, 8); // Release key delay(500); } взял с этого сайта. У меня получается при зажатии кнопки на длительное время на ардуино, аналогично многократному нажатию клавиши на клавиатуре. Допустим если нажать и удерживать кнопку "Х" на клавиатуре то она пошлет код кнопки "27" и когда отпустишь то пошлет код "0". А если нажать и удерживать кнопку на ардуино то она сразу отправит код "27" и "0" не смотря на то что я кнопку ещё не отпустил, и при длительном удерживании кнопки, будет просто слать "27" и "0".
Да так и сделать - по возрастающему фронту отправлять 27, по фронту на спад - 0. Вот тут ловят высокий фронт, для примера. http://wiki.amperka.ru/конспект-arduino:кнопочный-переключатель
Переписал код так, но теперь кнопка не "отжимается" обратно т.е. код "27" идет бесконечно, как сделать чтоб он шёл пока клавиша нажата, а при отпускании приходил "0". Я не силен в программировании Код (C++): /* Arduino USB Keyboard HID demo * Cut/Copy/Paste Keys */ uint8_t buf[8] = { 0 }; /* Keyboard report buffer */ #define PIN_X 2 boolean buttonWasUp = true; // была ли кнопка отпущена? int state = 1; void setup() { Serial.begin(9600); pinMode(PIN_X, INPUT_PULLUP); // Enable internal pull-ups digitalWrite(PIN_X, 1); delay(200); } void loop() { // определить момент «клика» несколько сложнее, чем факт того, // что кнопка сейчас просто нажата. Для определения клика мы // сначала понимаем, отпущена ли кнопка прямо сейчас... boolean buttonIsUp = digitalRead(PIN_X); // ...если «кнопка была отпущена и (&&) не отпущена сейчас»... if (buttonWasUp && !buttonIsUp){ // ...может это «клик», а может и ложный сигнал (дребезг), // возникающий в момент замыкания/размыкания пластин кнопки, // поэтому даём кнопке полностью «успокоиться»... delay(10); // ...и считываем сигнал снова buttonIsUp = digitalRead(PIN_X); if (!buttonIsUp) { // если она всё ещё нажата... buf[2] = 27; // Letter X Serial.write(buf, 8); // Ssend keypress } } buttonWasUp = buttonIsUp; }
Сделал так. Если кнопка одна то всё хорошо работает, но как добавляется ещё кнопки то снова работает не правильно. Код (C++): void loop() { if(digitalRead(PIN_X)==HIGH) //если кнопка нажата ... { buf[2] = 27; //Letter X Serial.write(buf, 8); //Ssend keypress digitalWrite(LED_RED,HIGH); //включаем светодиод } else if (digitalRead(PIN_X)==LOW) //если не нажата... { buf[2] = 0; Serial.write(buf, 8); //Release key digitalWrite(LED_RED,LOW); //выключаем } if(digitalRead(PIN_L)==HIGH) //если кнопка нажата ... { buf[2] = 6; //Letter C Serial.write(buf, 8); //Ssend keypress digitalWrite(LED_YELLOW,HIGH); //включаем светодиод } else if (digitalRead(PIN_L)==LOW) { buf[2] = 0; Serial.write(buf, 8); //Release key digitalWrite(LED_YELLOW,LOW); //выключаем } if(digitalRead(PIN_V)==HIGH) //если кнопка нажата ... { buf[2] = 25; //Letter V Serial.write(buf, 8); //Ssend keypress digitalWrite(LED_GREEN,HIGH); //включаем светодиод } else if (digitalRead(PIN_V)==LOW) { buf[2] = 0; Serial.write(buf, 8); //Release key digitalWrite(LED_GREEN,LOW); //выключаем } }
Я так понимаю просто else if все срабатывают поэтому при появлении высокого уровня например на "PIN_X" он тут же сбрасывается от низких "PIN_L" и "PIN_V" как с эти бороться я не знаю.
Код (C++): word button[] = { 10, 11, 12 }; word buttonCode[] = { 27, 6, 25 }; #define ARRAY_SIZE sizeof(button) / sizeof(word) bool buttonWas[ARRAY_SIZE]; bool buttonIs[ARRAY_SIZE]; long unbounce[ARRAY_SIZE]; long unbounceInterval = 50; uint8_t buf[8] = { 0 }; void setup() { Serial.begin(9600); for(word i = 0; i < ARRAY_SIZE; i++) { buttonWas[i] = buttonIs[i] = unbounce[i] = 1; pinMode(button[i], INPUT_PULLUP); } } void loop() { long curTime = millis(); for(word i = 0; i < ARRAY_SIZE; i++) { buttonIs[i] = digitalRead(button[i]); if (unbounce[i] + unbounceInterval > curTime) continue; if (buttonIs[i] != buttonWas[i]){ unbounce[i] = curTime; buttonWas[i] = buttonIs[i]; if (!buttonIs[i]){ buf[2] = buttonCode[i]; Serial.write(buf, 8); } else { buf[2] = 0; Serial.write(buf, 8); } } } }
Большое спасибо!!! Где можно почитать по подробнее про sizeof и word, чтоб представлять что происходит в скетче?
В ваш код я хочу добавить джойстик hw-504, где по оси x angle >= 45 && angle <= 135 будет срабатывать 'w' и angle <= -45 && angle >= -135 срабатывать 's'. По оси y angle < 45 && angle > -45 будет срабатывать 'd' и (angle < -135 && angle >= -180) || (angle <= 180 && angle > 135) срабатывать 'a'. И соответственно в положении по осям 500 не чего не должно срабатывать. Вот что я сделал, но не работает, как сделать по другому. Этот код работает через ком порт как отладчик из проета azeron_gamepad.ino: Код (C++): word button[] = { 13, 12, 11, 10, 9, 8, 7, 6, 5, A5, A4, A0 }; word buttonCode[] = { 10, 29, 30, 9, 27, 31, 224, 6, 32, 21, 8, 44 }; #define ARRAY_SIZE sizeof(button) / sizeof(word) bool buttonWas[ARRAY_SIZE]; bool buttonIs[ARRAY_SIZE]; long unbounce[ARRAY_SIZE]; long unbounceInterval = 50; uint8_t buf[8] = { 0 }; //------------------------------------- // добавил из azeron_gamepad.ino #define KEY_RELEASE(x) #define KEY_PRESS(x) //Globals const int xCenter = 250; // Tweak for your D-pad's center values, should be 250 const int yCenter = 250; const int xDeadband = 150; // Sets the size of the center deadband const int yDeadband = 150; // D-pad: UP = w, RIGHT = d, DOWN = s, LEFT = a, DPadNone is "center value" const char dPadUp = 26; //'w'; const char dPadRt = 7; //'d'; const char dPadDn = 22; //'s'; const char dPadLt = 4; //'a'; const char dPadNone = 0; //'0'; //------------------------------------- void setup() { Serial.begin(9600); for(word i = 0; i < ARRAY_SIZE; i++) { buttonWas[i] = buttonIs[i] = unbounce[i] = 1; pinMode(button[i], INPUT_PULLUP); } } //------------------------------------- // добавил из azeron_gamepad.ino void loop() { readJoystick(); readKeys(); } void readJoystick() { float angle = 0.0; static char lastKeyPressed = dPadNone; int joyX = analogRead(A2); // Or A3, rotates 0 angle (0 degrees is full right by default) int joyY = analogRead(A3); // Or A2, rotates 0 angle double mapJoyX = map(joyX, 0, 1023, 0, 500); double mapJoyY = map(joyY, 0, 1023, 0, 500); if ((mapJoyX <= xCenter + xDeadband && mapJoyX >= xCenter - xDeadband) && (mapJoyY <= yCenter + yDeadband && mapJoyY >= yCenter - yDeadband)) { angle = 1000.0; if (lastKeyPressed != dPadNone) { KEY_RELEASE(lastKeyPressed); lastKeyPressed = dPadNone; } } else { // Else determine its angle angle = atan2(mapJoyY - yCenter , mapJoyX - xCenter) * 57.2957795; } if ((angle >= 45 && angle <= 135)) { // UP if (lastKeyPressed != dPadUp) { if (lastKeyPressed != dPadNone) { KEY_RELEASE(lastKeyPressed); } lastKeyPressed = dPadUp; KEY_PRESS(dPadUp) } } else if (angle < 45 && angle > -45) { // RIGHT if (lastKeyPressed != dPadRt) { if (lastKeyPressed != dPadNone) { KEY_RELEASE(lastKeyPressed); } lastKeyPressed = dPadRt; KEY_PRESS(dPadRt) } } else if (angle <= -45 && angle >= -135) { // DOWN if (lastKeyPressed != dPadDn) { if (lastKeyPressed != dPadNone) { KEY_RELEASE(lastKeyPressed); } lastKeyPressed = dPadDn; KEY_PRESS(dPadDn) } } else if ((angle < -135 && angle >= -180) || (angle <= 180 && angle > 135)) { // LEFT if (lastKeyPressed != dPadLt) { if (lastKeyPressed != dPadNone) { KEY_RELEASE(lastKeyPressed); } lastKeyPressed = dPadLt; KEY_PRESS(dPadLt) } } } //------------------------------------- void readKeys()// добавил из azeron_gamepad.ino { long curTime = millis(); for(word i = 0; i < ARRAY_SIZE; i++) { buttonIs[i] = digitalRead(button[i]); if (unbounce[i] + unbounceInterval > curTime) continue; if (buttonIs[i] != buttonWas[i]){ unbounce[i] = curTime; buttonWas[i] = buttonIs[i]; if (!buttonIs[i]){ buf[2] = buttonCode[i]; Serial.write(buf, 8); } else { buf[2] = 0; Serial.write(buf, 8); } } } }