En este proyecto pretendo crear un teclado auxiliar de 16 teclas para todas aquellas personas, que como yo mismo, solo podemos usar una mano para manejar los ordenadores y ciertas teclas se nos hace complicado usarlas y no podemos prescindir de ellas, ya que las usamos habitualmente para escribir correos electrónicos o los que nos dedicamos al mundillo de la programación.
En esta ocasión veréis que he utilizado un Arduino Nano. Para el fin de crear este teclado la condición indispensable es que la placa sea una Atmega32U4 ya que si lo probáis con cualquier otra no os funcionara.
Junto a este escrito os dejare un fichero comprimido con el código fuente de la aplicación y las dos librerías modificadas para que reconozca al teclado español, estos tres ficheros han de estar en la misma carpeta.
Cabe comentar que, si lo vais a usar en Mac, la primera tecla que habéis de presionar a la hora de que el sistema reconozca el teclado, es el símbolo “<”; de esta manera no perderéis la configuración del teclado principal.

Materiales:





Esquema de conexión:


Aplicación:
#include <Keypad.h> #include "Keyboard.h" // This is a "built-in" library no need to install #include <Mouse.h> #include <SoftwareSerial.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 20 chars and 4 line display #define RxD 0 // Usado para conexion rs232 virtual. #define TxD 1 // Usado para conexion rs232 virtual. const byte filas = 4; //Numero de filas del teclado const byte columnas = 4; //Numero de columnas del teclado //Defino una matriz 4x4 con la posicion de las filas y columnas char matriz[filas][columnas] = { { '@', '<', '>', 'A'}, { '#', '{', '}', 'B'}, { '(', ')', '/', 'C'}, { '*', '0', '#', 'D'}, }; byte pinesFilas[filas] = {5, 6, 7, 8}; //Pines donde van conectadas las filas del teclado byte pinesColumnas[columnas] = {9, 10, 11, 12}; //Pines donde van conectadas las columnas del teclado /* * byte pinesFilas[filas] = {12, 11, 10, 9}; //Pines donde van conectadas las filas del teclado * byte pinesColumnas[columnas] = {8, 7, 6, 5}; //Pines donde van conectadas las columnas del teclado */ //Inicializo el teclado con el numero de filas, columnas, los pines del Arduino utilizados y la matriz Keypad teclado = Keypad( makeKeymap(matriz), pinesFilas, pinesColumnas, filas, columnas); SoftwareSerial comVirtual(RxD, TxD); void setup() { Serial.begin(9600); //Inicializo el puerto serie lcd.init(); // initialize the lcd lcd.backlight(); lcd.setCursor(0, 0); lcd.clear(); lcd.setCursor(2, 0); lcd.print("Hola Teclat"); lcd.setCursor(1, 1); lcd.print("joseprommy.com"); delay(1000); lcd.setCursor(0, 0); lcd.clear(); lcd.setCursor(0, 0); lcd.print("@<> #{} []& ()/"); lcd.setCursor(1, 1); lcd.print("joseprommy.com"); } void loop() { char tecla_presionada = teclado.getKey(); //Almaceno en una variable la tecla presionada if (tecla_presionada) { Serial.println(tecla_presionada); //Muestra la tecla presionada en el monitor serie Keyboard.begin(); //begin keyboard // if (digitalRead(4) == 0){ //Si el boto 4 es pressionat Keyboard.write(tecla_presionada); //Envia "@" delay(200); //} } }
/* Keyboard.h Copyright (c) 2015, Arduino LLC Original code (pre-library): Copyright (c) 2011, Peter Barrett This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef KEYBOARD_h #define KEYBOARD_h #include "HID.h" #if !defined(_USING_HID) #warning "Using legacy HID core (non pluggable)" #else //================================================================================ //================================================================================ // Keyboard #define KEY_LEFT_CTRL 0x80 #define KEY_LEFT_SHIFT 0x81 #define KEY_LEFT_ALT 0x82 #define KEY_LEFT_GUI 0x83 #define KEY_RIGHT_CTRL 0x84 #define KEY_RIGHT_SHIFT 0x85 #define KEY_RIGHT_ALT 0x86 #define KEY_RIGHT_GUI 0x87 #define KEY_UP_ARROW 0xDA #define KEY_DOWN_ARROW 0xD9 #define KEY_LEFT_ARROW 0xD8 #define KEY_RIGHT_ARROW 0xD7 #define KEY_BACKSPACE 0xB2 #define KEY_TAB 0xB3 #define KEY_RETURN 0xB0 #define KEY_ESC 0xB1 #define KEY_INSERT 0xD1 #define KEY_DELETE 0xD4 #define KEY_PAGE_UP 0xD3 #define KEY_PAGE_DOWN 0xD6 #define KEY_HOME 0xD2 #define KEY_END 0xD5 #define KEY_CAPS_LOCK 0xC1 #define KEY_F1 0xC2 #define KEY_F2 0xC3 #define KEY_F3 0xC4 #define KEY_F4 0xC5 #define KEY_F5 0xC6 #define KEY_F6 0xC7 #define KEY_F7 0xC8 #define KEY_F8 0xC9 #define KEY_F9 0xCA #define KEY_F10 0xCB #define KEY_F11 0xCC #define KEY_F12 0xCD // Low level key report: up to 6 keys and shift, ctrl etc at once typedef struct { uint8_t modifiers; uint8_t reserved; uint8_t keys[6]; } KeyReport; class Keyboard_ : public Print { private: KeyReport _keyReport; void sendReport(KeyReport* keys); public: Keyboard_(void); void begin(void); void end(void); size_t write(uint8_t k); size_t press(uint8_t k); size_t release(uint8_t k); void releaseAll(void); }; extern Keyboard_ Keyboard; #endif #endif
/* Keyboard.cpp Copyright (c) 2015, Arduino LLC Original code (pre-library): Copyright (c) 2011, Peter Barrett This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "Keyboard.h" #if defined(_USING_HID) //================================================================================ //================================================================================ // Keyboard static const uint8_t _hidReportDescriptor[] PROGMEM = { // Keyboard 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 47 0x09, 0x06, // USAGE (Keyboard) 0xa1, 0x01, // COLLECTION (Application) 0x85, 0x02, // REPORT_ID (2) 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x08, // REPORT_COUNT (8) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x95, 0x01, // REPORT_COUNT (1) 0x75, 0x08, // REPORT_SIZE (8) 0x81, 0x03, // INPUT (Cnst,Var,Abs) 0x95, 0x06, // REPORT_COUNT (6) 0x75, 0x08, // REPORT_SIZE (8) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x65, // LOGICAL_MAXIMUM (101) 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) 0x81, 0x00, // INPUT (Data,Ary,Abs) 0xc0, // END_COLLECTION }; Keyboard_::Keyboard_(void) { static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor)); HID().AppendDescriptor(&node); } void Keyboard_::begin(void) { } void Keyboard_::end(void) { } void Keyboard_::sendReport(KeyReport* keys) { HID().SendReport(2,keys,sizeof(KeyReport)); } extern const uint8_t _asciimap[128] PROGMEM; /* * _asciimap took from Keyboard.cpp, * need somebody to test with spansih layout. */ #define SHIFT 0x80 const uint8_t _asciimap[128] = { 0x00, // NUL 0 0x00, // SOH 0x00, // STX 0x00, // ETX 0x00, // EOT 0x00, // ENQ 0x00, // ACK 0x00, // BEL 0x2a, // BS Backspace 0x2b, // TAB Tab 0x28, // LF Enter 10 0x00, // VT 0x00, // FF 0x00, // CR 0x00, // SO 0x00, // SI 0x00, // DEL 0x00, // DC1 0x00, // DC2 0x00, // DC3 0x00, // DC4 20 0x00, // NAK 0x00, // SYN 0x00, // ETB 0x00, // CAN 0x00, // EM 0x00, // SUB 0x00, // ESC 0x00, // FS 0x00, // GS 0x00, // RS 30 0x00, // US 0x2c, // ' ' 0x1e|SHIFT, // ! 0x1f|SHIFT, // " 0x20, // # 0x21|SHIFT, // $ 0x22|SHIFT, // % 0x23|SHIFT, // & 0x2d, // ' 0x25|SHIFT, // ( 40 0x26|SHIFT, // ) 0x30|SHIFT, // * 0x30, // + 0x36, // , 0x38, // - 0x37, // . 0x24|SHIFT, // / 0x27, // 0 0x1e, // 1 0x1f, // 2 50 0x20, // 3 0x21, // 4 0x22, // 5 0x23, // 6 0x24, // 7 0x25, // 8 0x26, // 9 0x37|SHIFT, // : 0x36|SHIFT, // ; 0x64, // < 60 0x27|SHIFT, // = 0x64|SHIFT, // > 0x64|SHIFT, 0x2d|SHIFT, // ? 0x1f, // @ 0x04|SHIFT, // A 0x05|SHIFT, // B 0x06|SHIFT, // C 0x07|SHIFT, // D 0x08|SHIFT, // E 0x09|SHIFT, // F 70 0x0a|SHIFT, // G 0x0b|SHIFT, // H 0x0c|SHIFT, // I 0x0d|SHIFT, // J 0x0e|SHIFT, // K 0x0f|SHIFT, // L 0x10|SHIFT, // M 0x11|SHIFT, // N 0x12|SHIFT, // O 0x13|SHIFT, // P 80 0x14|SHIFT, // Q 0x15|SHIFT, // R 0x16|SHIFT, // S 0x17|SHIFT, // T 0x18|SHIFT, // U 0x19|SHIFT, // V 0x1a|SHIFT, // W 0x1b|SHIFT, // X 0x1c|SHIFT, // Y 0x1d|SHIFT, // Z 90 0x2f, // [ 0x31, // bslash 0x30, // ] 0x94|SHIFT, // ^ 0x38|SHIFT, // _ 0x2e|SHIFT, // ` 0x04, // a 0x05, // b 0x06, // c 0x07, // d 100 0x08, // e 0x09, // f 0x0a, // g 0x0b, // h 0x0c, // i 0x0d, // j 0x0e, // k 0x0f, // l 0x10, // m 0x11, // n 110 0x12, // o 0x13, // p 0x14, // q 0x15, // r 0x16, // s 0x17, // t 0x18, // u 0x19, // v 0x1a, // w 0x1b, // x 120 0x1c, // y 0x1d, // z 0x34, // { 0x38|SHIFT, // | 0x32, // } 0x21, // ~ 0 // DEL 127 }; // Init var bool _altGrMap[128]; bool _altFine = false; // Individually define all needed char void initAltGr() { _altFine = true; _altGrMap[126] = true; // ~ _altGrMap[123] = true; // { _altGrMap[91] = true; // [ _altGrMap[93] = true; // ] _altGrMap[125] = true; // } _altGrMap[92] = true; // bslash _altGrMap[124] = true; // | _altGrMap[64] = true; // @ _altGrMap[35] = true; // # 35 _altGrMap[94] = true; // ^ _altGrMap[96] = true; // ` } uint8_t USBPutChar(uint8_t c); // press() adds the specified key (printing, non-printing, or modifier) // to the persistent key report and sends the report. Because of the way // USB HID works, the host acts like the key remains pressed until we // call release(), releaseAll(), or otherwise clear the report and resend. size_t Keyboard_::press(uint8_t k) { uint8_t i; if (k >= 136) { // it's a non-printing key (not a modifier) k = k - 136; } else if (k >= 128) { // it's a modifier key _keyReport.modifiers |= (1<<(k-128)); k = 0; } else { // it's a printing key int oldKey = k; k = pgm_read_byte(_asciimap + k); if (!k) { setWriteError(); return 0; } if (k & 0x80) { // it's a capital letter or other character reached with shift _keyReport.modifiers |= 0x02; // the left shift modifier k &= 0x7F; } if (!_altFine) initAltGr(); if (_altGrMap[oldKey]) _keyReport.modifiers |= 0x40; } // Add k to the key report only if it's not already present // and if there is an empty slot. if (_keyReport.keys[0] != k && _keyReport.keys[1] != k && _keyReport.keys[2] != k && _keyReport.keys[3] != k && _keyReport.keys[4] != k && _keyReport.keys[5] != k) { for (i=0; i<6; i++) { if (_keyReport.keys[i] == 0x00) { _keyReport.keys[i] = k; break; } } if (i == 6) { setWriteError(); return 0; } } sendReport(&_keyReport); return 1; } // release() takes the specified key out of the persistent key report and // sends the report. This tells the OS the key is no longer pressed and that // it shouldn't be repeated any more. size_t Keyboard_::release(uint8_t k) { uint8_t i; if (k >= 136) { // it's a non-printing key (not a modifier) k = k - 136; } else if (k >= 128) { // it's a modifier key _keyReport.modifiers &= ~(1<<(k-128)); k = 0; } else { // it's a printing key int oldKey = k; k = pgm_read_byte(_asciimap + k); if (!k) { return 0; } if (k & 0x80) { // it's a capital letter or other character reached with shift _keyReport.modifiers &= ~(0x02); // the left shift modifier k &= 0x7F; } if (_altGrMap[oldKey]) _keyReport.modifiers &= ~(0x40); } // Test the key report to see if k is present. Clear it if it exists. // Check all positions in case the key is present more than once (which it shouldn't be) for (i=0; i<6; i++) { if (0 != k && _keyReport.keys[i] == k) { _keyReport.keys[i] = 0x00; } } sendReport(&_keyReport); return 1; } void Keyboard_::releaseAll(void) { _keyReport.keys[0] = 0; _keyReport.keys[1] = 0; _keyReport.keys[2] = 0; _keyReport.keys[3] = 0; _keyReport.keys[4] = 0; _keyReport.keys[5] = 0; _keyReport.modifiers = 0; sendReport(&_keyReport); } size_t Keyboard_::write(uint8_t c) { uint8_t p = press(c); // Keydown release(c); // Keyup return p; // just return the result of press() since release() almost always returns 1 } Keyboard_ Keyboard; #endif

Descarga de los ficheros:
No debes olvidar de incluir los tres ficheros en la misma carpeta.