Start Elkretssimulator Karnaughdiagram Quine McCluskey


Tangentbord 4x4 knappar





Ett litet käckt tangentbord. Ett typiskt tangentbord som fungerar som de flesta tangentbord. Vi hittar dem i portlås eller på maskiner.



Det som varierar mellan olika tangentbord är hur många knapparna är, dvs antalet rader och kolumner. I detta fall 4x4 = 16 knappar.

Schema

Spontant kan man tänka sig att ett tangentbord med t.ex. 16 knappar, helt enkelt består av 16 individuella knappar med vardera 2 anslutningar. Men det är inte alls så det är konstruerat. Tänk dig ett tangentbord till en dator. Det skulle bli väldigt många anslutningar till en processor eller avkodningschip om varje knapp krävde 1 eller 2 anslutningar. Istället arrangerar man knapparna i en matris. Studera nedan.

Till ett typiskt tangentbord med 16 knappar behövs enbart 8 anslutningar. Så hur kan 16 knappar läsas av med 8 anslutningar?



Koncept för att läsa av tangenterna

Vi skapar en 4x4 matris, med kolumner och rader, där knapparna kopplar i skärningspunkterna. Vi kan då läsa av om en knapp är nertryckt genom att vi får en sluten krets i skärningspunkten. Det vi förlorar med detta koncept är att vi måste läsa av tangentbordet med någon typ av algoritm. Men det vi vinner är att vi får ner anslutningar till ett minimum. (dvs √ antal knappar eller något i närheten)

Det fungerar så att vi skickar in en signal (hög nivå) på en kolumn och läser av vilka knappar som är nedtryckta i just den kolumnen.



Vi kan scanna av tangentbordet väldigt snabbt och lagrar sedan i vårt program vilka knappar som är nertryckta. Vi kan t.ex. skapa ett interrupt som körs 10-20 gånger per sekund, som gör denna scanning av tangenterna och för bok över vilka som är nertryckta och inte.

Uppkoppling

Vi tänker oss alltså t.ex. följande uppkoppling.


Vi skriver en kod som kör ut signaler på kolumnerna (C1-C4) i tur och ordning - dvs en i taget - och läser av raderna (R1-R4) för att se om en knapp är nertryckt och detta görs 20 gånger per sekund m.h.a. ett interrupt.

T.ex. som nedan.

Kod


#define C1 8
#define C2 9
#define C3 10
#define C4 11
#define R1 4
#define R2 5
#define R3 6
#define R4 7

int column = C1;
int keyboardp[] = {1, 1, 1, 1, 
                   1, 1, 1, 1, 
                   1, 1, 1, 1, 
                   1, 1, 1, 1};
bool keypressed;

void setup() 
{
  pinMode(C1, OUTPUT);
  pinMode(C2, OUTPUT);
  pinMode(C3, OUTPUT);
  pinMode(C4, OUTPUT);
  pinMode(R1, INPUT_PULLUP);
  pinMode(R2, INPUT_PULLUP);
  pinMode(R3, INPUT_PULLUP);
  pinMode(R4, INPUT_PULLUP);

  Serial.begin(9600);
  Serial.println("Nu har jag initierat seriella monitorn");  

  cli(); // innan vi ändrar något stäng interrupt
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;

  OCR1A = 780;// = (16*10^6) / (20*1024) - 1 dvs 20 ggr per sekund
  // CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS10 and CS12 bits for 1024 prescaler
  TCCR1B |= (1 << CS12) | (1 << CS10);  
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  sei(); // när vi är färdiga dra igång interrupt  
}

// anropas 20 gånger per sekund
ISR(TIMER1_COMPA_vect)
{
  if(++column>C4)
  {
    column=C1;
  }
  digitalWrite(C1, (column==C1)?LOW:HIGH);
  digitalWrite(C2, (column==C2)?LOW:HIGH);
  digitalWrite(C3, (column==C3)?LOW:HIGH);
  digitalWrite(C4, (column==C4)?LOW:HIGH);  
  keypressed=false;
  keypressed|=(LOW==(keyboardp[(column-8)*4+0]=digitalRead(R1)));
  keypressed|=(LOW==(keyboardp[(column-8)*4+1]=digitalRead(R2)));
  keypressed|=(LOW==(keyboardp[(column-8)*4+2]=digitalRead(R3)));
  keypressed|=(LOW==(keyboardp[(column-8)*4+3]=digitalRead(R4)));
}

void printkeyboardvalues()
{
    Serial.println("tangentbord=");
    for(int x=0;x<4;x++)
    {
      for(int y=0;y<4;y++)
      {
        Serial.print(keyboardp[x*4+y]);
      }
      Serial.println();
    }
}

// en evig loop
void loop() 
{
  if(keypressed)
  {
    printkeyboardvalues();
    while(keypressed){delay(500);};
  } 
}


När vi trycker på tangentbordet blir nu respektive position i keyboardp -matrisen noll.



Om man vill se lite tydligare vilken knapp som är nertryckt, så kan vi istället skriva ut numret. Det blir då t.ex. såhär.


#define C1 8
#define C2 9
#define C3 10
#define C4 11
#define R1 4
#define R2 5
#define R3 6
#define R4 7

int column = C1;
int keyboardp[] = {1, 1, 1, 1, 
                   1, 1, 1, 1, 
                   1, 1, 1, 1, 
                   1, 1, 1, 1};
bool keypressed;

void setup() 
{
  pinMode(C1, OUTPUT);
  pinMode(C2, OUTPUT);
  pinMode(C3, OUTPUT);
  pinMode(C4, OUTPUT);
  pinMode(R1, INPUT_PULLUP);
  pinMode(R2, INPUT_PULLUP);
  pinMode(R3, INPUT_PULLUP);
  pinMode(R4, INPUT_PULLUP);

  Serial.begin(9600);
  Serial.println("Nu har jag initierat seriella monitorn");  

  cli(); // innan vi ändrar något stäng interrupt
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;

  OCR1A = 780;// = (16*10^6) / (20*1024) - 1 dvs 20 ggr per sekund
  // CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS10 and CS12 bits for 1024 prescaler
  TCCR1B |= (1 << CS12) | (1 << CS10);  
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  sei(); // när vi är färdiga dra igång interrupt  
}

// anropas 20 gånger per sekund
ISR(TIMER1_COMPA_vect)
{
  if(++column>C4)
  {
    column=C1;
  }
  digitalWrite(C1, (column==C1)?LOW:HIGH);
  digitalWrite(C2, (column==C2)?LOW:HIGH);
  digitalWrite(C3, (column==C3)?LOW:HIGH);
  digitalWrite(C4, (column==C4)?LOW:HIGH);  
  keypressed=false;
  keypressed|=(LOW==(keyboardp[(column-8)*4+0]=digitalRead(R1)));
  keypressed|=(LOW==(keyboardp[(column-8)*4+1]=digitalRead(R2)));
  keypressed|=(LOW==(keyboardp[(column-8)*4+2]=digitalRead(R3)));
  keypressed|=(LOW==(keyboardp[(column-8)*4+3]=digitalRead(R4)));
}

void printkeyboardkey()
{
  for(int x=0;x<16;x++)
    if(keyboardp[x]==LOW)
    {
      Serial.print("key=");
      Serial.println(x);
    }
}

// en evig loop
void loop() 
{
  if(keypressed)
  {
    printkeyboardkey();
    while(keypressed){delay(500);};
  } 
}

Och vi ser lite tydligare vilken knapp vi tryckte på.




Lycka till!