Publicidade:

segunda-feira, 23 de novembro de 2015

Arduino - Teclado PS2 com Keypad 4x4

Nesse post vou mostrar como reutilizar uma placa de teclado PS2 de PC para usarmos com um teclado 4x4 no Arduino. Mas qual a vantagem disso? Primeiro que se formos utilizar o teclado 4x4 diretamente no Arduino, precisaríamos de 8 pinos e dependendo da forma de montagem mais alguns resistores e até diodos. Com uma placa de teclado, reduzimos para apenas 2 pinos.

Na imagem abaixo temos a demonstração dos pinos de um conector PS2, tanto macho quanto fêmea.



No exemplo mostrado no vídeo utilizo apenas o conector macho, ligando :

GND-3 ao gnd do Arduino,
4-+5V ao Vcc do Arduino,
CLK-5 ao pino 2 (INT.0); e o
DATA-1 ao pino 3 do Arduino.


Vídeo:



Código-fonte:



 /*
  2015 - Fabiano A. Arndt
  fabianoallex@gmail.com
  www.facebook.com/dicasarduino
  Alterado para ser utilizado com teclados matriciais 3x4, 4x4 ou outros
  
  originalmente desenvolvida para ser utilizado através de teclado ps2, conforme descrição abaixo:

  PS2Keyboard.h - PS2Keyboard library
  Copyright (c) 2007 Free Software Foundation.  All right reserved.
  Written by Christian Weichel <info@32leaves.net>

  ** Mostly rewritten Paul Stoffregen <paul@pjrc.com>, June 2010
  ** Modified for use with Arduino 13 by L. Abraham Smith, <n3bah@microcompdesign.com> * 
  ** Modified for easy interrup pin assignement on method begin(datapin,irq_pin). Cuningan <cuninganreset@gmail.com> **

  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
*/

#define PS2_KEYPAD_BREAK     0x01
#define PS2_KEYPAD_MODIFIER  0x02
#define PS2_KEYPAD_SHIFT_L   0x04
#define PS2_KEYPAD_SHIFT_R   0x08
#define PS2_KEYPAD_ALTGR     0x10
#define PS2_KEYPAD_BUFFER_SIZE 45

#define makeKeymapChar(x) ((char*)x)
#define makeKeymapByte(x) ((byte*)x)

class PS2Keypad {
  private:
    volatile byte buffer[PS2_KEYPAD_BUFFER_SIZE];
    volatile byte head, tail;
    byte DataPin;
    byte CharBuffer = 0;
    byte UTF8next   = 0;
    char * _chars;
    byte * _codes;
    byte _cols;
    byte _rows;
    inline byte get_scan_code(void) {
      byte c, i;
      i = tail;
      if (i == head)          { return 0; }
      if (++i >= PS2_KEYPAD_BUFFER_SIZE) { i = 0;    }
      c = buffer[i];
      tail = i;
      return c;
    }
    char get_iso8859_code(void) {
      static byte state=0;
      byte s;
      while (1) {
        s = get_scan_code();
        if (!s) return 0;
        if (s == 0xF0) { state |= PS2_KEYPAD_BREAK;    } else 
        if (s == 0xE0) { state |= PS2_KEYPAD_MODIFIER; } else {
          if (state & PS2_KEYPAD_BREAK) {
            if (s == 0x12)                                  { state &= ~PS2_KEYPAD_SHIFT_L; } else 
            if (s == 0x59)                                  { state &= ~PS2_KEYPAD_SHIFT_R; } else 
            if (s == 0x11 && (state & PS2_KEYPAD_MODIFIER)) { state &= ~PS2_KEYPAD_ALTGR;   }
            state &= ~(PS2_KEYPAD_BREAK | PS2_KEYPAD_MODIFIER); continue;
          }
          if (s == 0x12)                                  { state |= PS2_KEYPAD_SHIFT_L; continue; } else 
          if (s == 0x59)                                  { state |= PS2_KEYPAD_SHIFT_R; continue; } else 
          if (s == 0x11 && (state & PS2_KEYPAD_MODIFIER)) { state |= PS2_KEYPAD_ALTGR; }
          return s;
        }
      }
    }
  public:
    PS2Keypad(byte dataPin, byte rows, byte cols, char * chars, byte * codes) {
      DataPin = dataPin;
      digitalWrite(DataPin, HIGH);
      head = 0;
      tail = 0;
      _chars = chars;
      _codes = codes;
      _cols = cols;
      _rows = rows;
    }
    
    bool available(){
      if (CharBuffer || UTF8next) return true;
      CharBuffer = get_iso8859_code();
      if (CharBuffer) return true;
      return false;
    }
    
    int read(){
      byte result = UTF8next;
      if (result) { UTF8next = 0; } 
      else {
        result = CharBuffer;
        if (result) { CharBuffer = 0; } 
        else        { result = get_iso8859_code(); }
        if (result >= 128) {
          UTF8next = (result & 0x3F) | 0x80;
          result = ((result >> 6) & 0x1F) | 0xC0;
        }
      }
      if (!result) { return -1; }
      return result;
    }
    
    char readChar(){
      byte code = read();
      for (int i=0; i<_rows;i++){
        for (int j=0; j<_cols;j++){
          if (  *(_codes+ i*_rows + j)  == code) { return *(_chars+ i*_rows + j); }
        }
      }
      return ' ';
    }
    
    void execInterrupt(void) {
      static byte bitcount = 0;
      static byte incoming = 0;
      static unsigned long prev_ms = 0;
      unsigned long now_ms;
      byte n, val;
    
      val = digitalRead(DataPin);
      now_ms = millis();
      if (now_ms - prev_ms > 250) {
        bitcount = 0;
        incoming = 0;
      }
      prev_ms = now_ms;
      n = bitcount - 1;
      if (n <= 7) { incoming |= (val << n); }
      bitcount++;
      if (bitcount == 11) {
        byte i = head + 1;
        if (i >= PS2_KEYPAD_BUFFER_SIZE) { i = 0; }
        if (i != tail)                   { buffer[i] = incoming; head = i; }
        bitcount = 0;
        incoming = 0;
      }
    }
};






/*****daqui pra baixo é mostrado como usar a classe PS2Keypad***************/



#define PIN_DATA 3
#define ROWS 4
#define COLS 4

char keys_chars[ROWS][COLS] = {  {'1','2','3', 'A'}, {'4','5','6','B'}, {'7','8','9', 'C'}, {'*','0','#','D'}  };
byte keys_codes[ROWS][COLS] = {  {58, 49, 54,  61},  {26, 103,14, 22},  {33, 19, 6,   38},  {34,  100,5, 30}   };  //esse código será diferente de acordo com as linhas e colunas escolhidas

PS2Keypad keypad(PIN_DATA, ROWS, COLS, makeKeymapChar(keys_chars), makeKeymapByte(keys_codes));

void interrupt_keypad(){ keypad.execInterrupt(); }

void setup() {
  Serial.begin(9600);
  Serial.println("Keypad Test:");
  attachInterrupt(INT0, interrupt_keypad, FALLING);  //atacha a interrupção que trata o recebimento dos dados. SEMPRE FALLING deve ser usado
}

void loop() {
  if (keypad.available()) {
    //int c = keypad.read();
    char c = keypad.readChar();
    Serial.print(c);
  }
}




Nenhum comentário:

Postar um comentário