Arduino 4x4 Matrix

Hallo miteinander. Ich bin gerade frisch ins Arduino eingestiegen. Hab vom programmieren sehr wenig Erfahrung und schon ein Problem.
Ich hab hier ein Beispielcode und würde den gerne umändern auf eine 4x4 Matrix Keypad.
Schau im Moment aber wie Schweinchen ins Uhrwerk. Über etwas HIlfe würde ich mich sehr feuen,danke.

/* keyPadHiduino Example Code
  by: Jim Lindblom
  date: January 5, 2012
  license: MIT license. If you find this code useful, please
  feel free to use this code however you'd like, commercially 
  or otherwise. Just keep this license on there whatever you do.

  This code implements a 12-key USB keypad. You can type 0-9,
  * is the + sign and the # key is enter. I'm using SparkFun's
  12-button keypad, your pinouts may vary. Multi-touch is
  not supported.

  SparkFun Keypad Pinout:
  Rows and columns are connected as such:
  -------------
  | 1 | 2 | 3 | - 3
  | 4 | 5 | 6 | - 7
  | 7 | 8 | 9 | - 6
  | * | 0 | # | - 1
  -------------
    |   |   |
    2   4   5
*/
// Pins 1-7 of the keypad connected to the Arduino respectively:
int keypadPins[7] = {2, 3, 4, 5, 10, 16, 14};
int keypadStatus;  // Used to monitor which buttons are pressed.
int timeout;  // timeout variable used in loop

void setup()
{
 for (int i=0; i<7; i++)
 {
   pinMode(keypadPins[i], INPUT);  // Set all keypad pins as inputs
   digitalWrite(keypadPins[i], HIGH);  // pull all keypad pins high
 }
}

void loop()
{
 keypadStatus = getKeypadStatus();  // read which buttons are pressed
 if (keypadStatus != 0)  // If a button is pressed go into here
 {
   sendKeyPress(keypadStatus);  // send the button over USB
   timeout = 2000;  // top of the repeat delay
   while ((getKeypadStatus() == keypadStatus) && (--timeout))  // Decrement timeout and check if key is being held down
     delayMicroseconds(1);
   while (getKeypadStatus() == keypadStatus)  // while the same button is held down
   {
     sendKeyPress(keypadStatus);  // continue to send the button over USB
     delay(50);  // 50ms repeat rate
   }
 }
}

/* sendKeyPress(int key): This function sends a single key over USB
  It requires an int, of which the 12 LSbs are used. Each bit in
  key represents a single button on the keypad.
  This function will only send a key press if a single button
  is being pressed */
void sendKeyPress(int key)
{
 switch(key)
 {
   case 1:  // 0x001
     Keyboard.write('1');  // Sends a keyboard '1'
     break;
   case 2:  // 0x002
     Keyboard.write('2');
     break;
   case 4:  // 0x004
     Keyboard.write('3');
     break;
   case 8:  // 0x008
     Keyboard.write('4');
     break;
   case 16:  // 0x010
     Keyboard.write('5');
     break;
   case 32:  // 0x020
     Keyboard.write('6');
     break;
   case 64:  // 0x040
     Keyboard.write('7');
     break;
   case 128:  // 0x080
     Keyboard.write('8');
     break;
   case 256:  // 0x100
     Keyboard.write('9');
     break;
   case 512:  // 0x200
     Keyboard.write('+');
     break;
   case 1024:  // 0x400
     Keyboard.write('0');  // Sends a keyboard '0'
     break;
   case 2048:  // 0x800
     Keyboard.write('\n');  // Sends the 'ENTER' key
     break;
 }
}

/* getKeypadStatus(): This function returns an int that represents
the status of the 12-button keypad. Only the 12 LSb's of the return
value hold any significange. Each bit represents the status of a single
key on the button pad. '1' is bit 0, '2' is bit 1, '3' is bit 2, ..., 
'#' is bit 11.

This function doesn't work for multitouch.
*/
int getKeypadStatus()
{
 int rowPins[4] = {keypadPins[2], keypadPins[6], keypadPins[5], keypadPins[0]};  // row pins are 2, 7, 6, and 1 of the keypad
 int columnPins[3] = {keypadPins[1], keypadPins[3], keypadPins[4]};  // column pins are pins 2, 4, and 5 of the keypad
 int keypadStatus = 0;  // this will be what's returned
 
 /* initialize all pins, inputs w/ pull-ups */
 for (int i=0; i<7; i++)
 {
   pinMode(keypadPins[i], INPUT);
   digitalWrite(keypadPins[i], HIGH);
 }
 
 for (int row=0; row<4; row++)
 {  // initial for loop to check all 4 rows
   pinMode(rowPins[row], OUTPUT);  // set the row pin as an output
   digitalWrite(rowPins[row], LOW);  // pull the row pins low
   for (int col=0; col<3; col++)
   {  // embedded for loop to check all 3 columns of each row
     if (!digitalRead(columnPins[col]))
     {
       keypadStatus |= 1 << ((row+1)*3 + (col+1) - 4);  // set the status bit of the keypad return value
     }
   }
   pinMode(rowPins[row], INPUT);  // reset the row pin as an input
   digitalWrite(rowPins[row], HIGH);  // pull the row pin high
 }
 
 return keypadStatus;
}

Hi und willkommen,

Code bitte immer in Code-Tags setzen. Dafür gibt es im Editor eine extra Schaltfläche.

Und wenn du in sowas noch wie ein Schwein ins Uhrwerk schaust, dann beschäftige dich doch erstmal mit den Basics.

Den Sketch umschreiben wird dir hier keiner und daraus lernen würdest du dann auch nichts.

Gruß

schUk0

Der Beispielkode ist für einen Leonardo, Micro oder Due, welchen davon hast du?

'Normale' Arduinos können kein USB-Keyboard simulieren.

Guten Morgen ardnewbie23,

Schau Dir mal zunächst diesen Code an. Er ist für ein 4x4 Matrix Pad.

Damit kannst Du erst mal Dein Keypad ausgeben via Serial Monitor.

Grüße, Stefan

EDIT. ist für ein 3 * 4 Keypad (Danke Hotsystems)

#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'#','0','*'}
};
byte rowPins[ROWS] = {5, 4, 3, 2}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {8, 7, 6}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){
  Serial.begin(9600);
}

void loop(){
  char key = keypad.getKey();

  if (key != NO_KEY){
    Serial.println(key);
  }
}

Whandall: Der Beispielkode ist für einen Leonardo, Micro oder Due, welchen davon hast du?

'Normale' Arduinos können kein USB-Keyboard simulieren.

Es ist ein Promicro.

stevie72: Schau Dir mal zunächst diesen Code an. Er ist für ein 4x4 Matrix Pad.

Dein Code ist aber auch nur für eine 3x4 Matrix. Falscher Code ?

Wollte ich auch gerade schreiben, kam mir auch so vor. Hatte aber noch Wartezeit.

Was mir überhaupt nicht klar ist:

  case 1:  // 0x001
     Keyboard.write('1');  // Sends a keyboard '1'
     break;
   case 2:  // 0x002
     Keyboard.write('2');
[code]

das ist das case 1, 2, 4, 8, 16 etc. und   0x001, 0x002, 0x004, 0x008, und jetzt 0x010, 0x020 etc.

 Ein Hinweis nach was ich schauen muss.

Ich kenne Micro, Pro Mini und Pro,

was ist ein Promicro?

https://www.sparkfun.com/products/12640

Links erlaubt?

Es ist anscheinend eine Micro Variante (auch mit 32u4), dann sollte das mit den Keys ja klappen.

@Hotsystems:
Huch - da habe ich einen Fehler gemacht… Du hast völlig recht es ist für eine 3*4 Matrix gedacht.

@ardnewbie23: dieses Teil ist evtl. nützlich zum Testen

http://www.ebay.de/itm/142135143207

stevie72: @ardnewbie23: dieses Teil ist evtl. nützlich zum Testen

http://m.ebay.de/itm/USB-2-0-zu-TTL-UART-6Pin-Serial-Converter-Modul-CP2102-STC-Arduino-Pro-Mini-/142135143207?hash=item2117ea2b27%3Ag%3AX5oAAOSw4shX75uD&_trkparms=pageci%253A1d72fad1-04d1-11e7-8dee-74dbd1801482%257Cparentrq%253Ab361543715a0a2a737b99685fffd5b34%257Ciid%253A3

Glaube ich eher nicht. Das ist eher hilfreich bei einem Arduino Mini oder Pro Mini. Der Pro Micro ist so etwas wie der Leonardo, oder der Micro, hat also einen ATmega32u4 drauf und der kümmert sich auch selbst um die USB-Verbindung und kann sich auch als USB-Keyboard oder Maus "ausgeben".

Ein USB-Serial-Adapter hilft da nicht allzu viel - obwohl so etwas natürlich in keinem Microkontroller-Bastellabor fehlen sollte - im vorliegenden konkreten Fall aber wenig sinnvoll. :)

4x4 Code

Hallo, eine kurze Anmerkung: Bitte darauf achten, dass beim Drücken mehrerer Tasten gleichzeitig, auch Spalten und Zeilen zusätzlich miteinander verbunden werden. Deshalb ist es zwingend erforderlich, die Ansteuersignale über "Open Collectoren" zu realisieren. Gruß Manfred

Sollte nix machen, die Tasten werden doch sequentiell abgefragt.

Hallo, nochmals zur Tastatur Matrix:
in der Anlage ist der Fall dargestellt, dass die Tasten 4 und 5 gleichzeitig gedrückt werden. Um die Tastatur abfragen zu können, müssen die Ausgänge des ATmega ja zwangsläufig auf unterschiedlichen Logikpegel liegen. Wenn man den E-Technikverstand nicht gänzlich dem Softwareverstand opfert, sieht man, dass die zwei Ausgangsstufen miteinander kurzgeschlossen sind. Also “OpenCollectoren” zwingend erforderlich. Sonst würde nur helfen, die inaktiven Ausgänge als Eingänge zu schalten und dann erst den für die Sequenz notwendigen Pin von Eingang aus Ausgang umzuschalten…
Gruß Manfred

3x4matrix_mtg.JPG

Das stimmt - daher schalte ich bei meiner Scanmatrix immer nur 1 Linie HIGH und die anderen als Input = hochohmig.

Danke für die Antworten. Ich bin jetzt ein Stück weiter, d.h. es funktioniert soweit gut, bis auf die case Anweisung lässt sich nicht erweitern.

#include <Keypad.h>
#include <Keyboard.h>
/* keyPadHiduino Example Code
   by: Jim Lindblom
   date: January 5, 2012
   license: MIT license - feel free to use this code in any way
   you see fit. If you go on to use it in another project, please
   keep this 

   This code turns your ProMicro, with an ATmega32U4, into an
   HID USB Keypad. Buttons 0-9 enter their respective number,
   The * button enters a '+' and the # button enters a 'Enter'.
   
   Keypad Pinout:
   Rows and columns are connected as such on the keypad:
   -------------
   | 1 | 2 | 3 | - 3
   | 4 | 5 | 6 | - 7
   | 7 | 8 | 9 | - 6
   | * | 0 | # | - 1
   -------------
     |   |   |
     2   4   5
     
   This is how they're connected to the ProMicro:
   Keypad Pin ------ Pro Micro Pin
      1 ------------------ 2
      2 ------------------ 3
      3 ------------------ 4
      4 ------------------ 5
      5 ------------------ 6
      6 ------------------ 7
      7 ------------------ 8
      8 ------------------ 9
*/
// Pins 1-8 of the keypad connected to the Arduino respectively:
int keypadPins[8] = {2, 3, 4, 5, 6, 7, 8, 9};
int keypadStatus;  // Used to monitor which buttons are pressed.
int timeout;  // timeout variable used in loop

void setup()
{
  for (int i=0; i<9; i++)
  {
    pinMode(keypadPins[i], INPUT);  // Set all keypad pins as inputs
    digitalWrite(keypadPins[i], HIGH);  // pull all keypad pins high
  }
}

void loop()
{
  keypadStatus = getKeypadStatus();  // read which buttons are pressed
  if (keypadStatus != 0)  // If a button is pressed go into here
  {
    sendKeyPress(keypadStatus);  // send the button over USB
    timeout = 2000;  // top of the repeat delay
    while ((getKeypadStatus() == keypadStatus) && (--timeout))  // Decrement timeout and check if key is being held down
      delayMicroseconds(1);
    while (getKeypadStatus() == keypadStatus)  // while the same button is held down
    {
      sendKeyPress(keypadStatus);  // continue to send the button over USB
      delay(50);  // 50ms repeat rate
    }
  }
}

/* sendKeyPress(int key): This function sends a single key over USB
   It requires an int, of which the 12 LSbs are used. Each bit in
   key represents a single button on the keypad.
   This function will only send a key press if a single button
   is being pressed */
void sendKeyPress(int key)
{
  switch(key)
  {
    case 1:  // 0x001
      Keyboard.write('1');  // Sends a keyboard '1'
      break;
    case 2:  // 0x002
      Keyboard.write('2');
      break;
    case 4:  // 0x004
      Keyboard.write('3');
      break;
    case 8:  // 0x008
      Keyboard.write('4');
      break;
    case 16:  // 0x010
      Keyboard.write('5');
      break;
    case 32:  // 0x020
      Keyboard.write('6');
      break;
    case 64:  // 0x040
      Keyboard.write('7');
      break;
    case 128:  // 0x080
      Keyboard.write('8');
      break;
    case 256:  // 0x100
      Keyboard.write('9');
      break;
    case 512:  // 0x200
      Keyboard.write('U');
      break;
    case 1024:  // 0x400
      Keyboard.write('0');  // Sends a keyboard '0'
      break;
    case 2048:  // 0x800
      Keyboard.write('\n');  // Sends the 'ENTER' key
      break;
    case 4096:  // 0x800
      Keyboard.write('t');  // Sends the 't' key
      break;
    case 8192:  // 0x800
      Keyboard.write('B');  // Ab hier keine Funktion
      break;
  }
  
}

/* getKeypadStatus(): This function returns an int that represents
the status of the 12-button keypad. Only the 12 LSb's of the return
value hold any significange. Each bit represents the status of a single
key on the button pad. '1' is bit 0, '2' is bit 1, '3' is bit 2, ..., 
'#' is bit 11.

This function doesn't work for multitouch.
*/
int getKeypadStatus()
{
  int rowPins[4] = {2,3,4,5};  // row pins are 1, 2, 3, and 4 of the keypad
  int columnPins[4] = {6,7,8,9};  // column pins are pins 5, 6, 7, and 8 of the keypad
  int keypadStatus = 0;  // this will be what's returned
  
  /* initialize all pins, inputs w/ pull-ups */
  for (int i=0; i<9; i++)
  {
    pinMode(keypadPins[i], INPUT);
    digitalWrite(keypadPins[i], HIGH);
  }
  
  for (int row=0; row<4; row++)
  {  // initial for loop to check all 4 rows
    pinMode(rowPins[row], OUTPUT);  // set the row pin as an output
    digitalWrite(rowPins[row], LOW);  // pull the row pins low
    for (int col=0; col<4; col++)
    {  // embedded for loop to check all 3 columns of each row
      if (!digitalRead(columnPins[col]))
      {
        keypadStatus |= 1 << ((row+1)*3 + (col+1) - 4);  // set the status bit of the keypad return value
      }
    }
    pinMode(rowPins[row], INPUT);  // reset the row pin as an input
    digitalWrite(rowPins[row], HIGH);  // pull the row pin high
  }
  
  return keypadStatus;
}

It requires an int, of which the 12 LSbs are used.

schau dir deine Kommentare an

    case 1024:  // 0x400
    case 2048:  // 0x800
    case 4096:  // 0x800
    case 8192:  // 0x800

richtiger wäre wohl

    case 1024:  // 0x400
    case 2048:  // 0x800
    case 4096:  // 0x1000 // 2^12
    case 8192:  // 0x2000 // 2^13

da sieht man, dass du auf das 13. und 14. Bit testest.

Whandall: schau dir deine Kommentare an

    case 1024:  // 0x400
    case 2048:  // 0x800
    case 4096:  // 0x800
    case 8192:  // 0x800

richtiger wäre wohl

    case 1024:  // 0x400
    case 2048:  // 0x800
    case 4096:  // 0x1000 // 2^12
    case 8192:  // 0x2000 // 2^13

da sieht man, dass du auf das 13. und 14. Bit testest.

Da hast Du ja recht, nur wie kann ich weitere bits nutzen? Wo sind die 12bits denn deklariert. Wie gesagt, ich bin ziemlich neu in der programmierung und schon froh, dass es soweit funktioniert. Evt. kannst Du mir das ändern oder einen link zum nachlesen geben.