Forum: Mikrocontroller und Digitale Elektronik At Mega 8 Codeabfrage


von Andre (Gast)


Lesenswert?

Anbei erstmal mein Quelltext den ich bisher erstellt habe mit dem myAVR 
Workpad Plus in Verbindung mit dem myAVRMK2 Board .
Daran angeschlossen haben ich eine Tastaturmatrix :
Betrieben wird das ganze mit einem ATMega8 .

main ()            // Hauptprogramm, startet bei Power ON und Reset

{

  DDRD  = 0b10000000;
  PORTD = 0b00000000;
  DDRB  = 0b000011;
  PORTB = 0b111100;
  DDRC  = 0xFF;
  while (true)

  {
    switch(PINB & 0b111100)
    {
      case 0b111000  :
      DDRD  = 0b00000000;
      PORTD = 0b10000000;
      DDRB  = 0b111100;
      PORTB = 0b000011;
      switch(PINB & 0b000011)
      {

        case 0b000001 :
        DDRD  = 0b10000000;
        PORTD = 0b00000000;
        DDRB  = 0b000011;
        PORTB = 0b111100;
        PORTC = 0b100000;
        waitMs(200);     //3
        break;

        case 0b000010 :
        DDRD  = 0b10000000;
        PORTD = 0b00000000;
        DDRB  = 0b000011;
        PORTB = 0b111100;
        PORTC = 0b010000;
        waitMs(200);     //2
        break;

        default :
        DDRD  = 0b10000000;
        PORTD = 0b00000000;
        DDRB  = 0b000011;
        PORTB = 0b111100;
        PORTC = 0b001000;
        waitMs(200);    // 1
        break;

      }
      break;

      case 0b110100  :
      DDRD  = 0b00000000;
      PORTD = 0b10000000;
      DDRB  = 0b111100;
      PORTB = 0b000011;
      switch(PINB & 0b000011)
      {

        case 0b000001 :
        DDRD  = 0b10000000;
        PORTD = 0b00000000;
        DDRB  = 0b000011;
        PORTB = 0b111100;
        PORTC = 0b100000;
        waitMs(200);     // 6
        break;

        case 0b000010 :
        DDRD  = 0b10000000;
        PORTD = 0b00000000;
        DDRB  = 0b000011;
        PORTB = 0b111100;
        PORTC = 0b010000;
        waitMs(200);     // 5
        break;

        default :
        DDRD  = 0b10000000;
        PORTD = 0b00000000;
        DDRB  = 0b000011;
        PORTB = 0b111100;
        PORTC = 0b001000;
        waitMs(200);     // 4
        break;

      }
      break;
      case 0b101100  :
      DDRD  = 0b00000000;
      PORTD = 0b10000000;
      DDRB  = 0b111100;
      PORTB = 0b000011;
      switch(PINB & 0b000011)
      {

        case 0b000001 :
        DDRD  = 0b10000000;
        PORTD = 0b00000000;
        DDRB  = 0b000011;
        PORTB = 0b111100;
        PORTC = 0b100000;
        waitMs(200);      // 9
        break;

        case 0b000010 :
        DDRD  = 0b10000000;
        PORTD = 0b00000000;
        DDRB  = 0b000011;
        PORTB = 0b111100;
        PORTC = 0b010000;
        waitMs(200);     // 8
        break;

        default :
        DDRD  = 0b10000000;
        PORTD = 0b00000000;
        DDRB  = 0b000011;
        PORTB = 0b111100;
        PORTC = 0b001000;
        waitMs(200);     // 7
        break;

      }
      break;

      case 0b011100  :
      DDRD  = 0b00000000;
      PORTD = 0b10000000;
      DDRB  = 0b111100;
      PORTB = 0b000011;
      switch(PINB & 0b000011)
      {

        case 0b000001 :
        DDRD  = 0b10000000;
        PORTD = 0b00000000;
        DDRB  = 0b000011;
        PORTB = 0b111100;
        PORTC = 0b100000;
        waitMs(200);       // #
        break;

        case 0b000010 :
        DDRD  = 0b10000000;
        PORTD = 0b00000000;
        DDRB  = 0b000011;
        PORTB = 0b111100;
        PORTC = 0b010000;
        waitMs(200);     // 0
        break;

        default :
        DDRD  = 0b10000000;
        PORTD = 0b00000000;
        DDRB  = 0b000011;
        PORTB = 0b111100;
        PORTC = 0b001000;
        waitMs(200);     //  *
        break;

      }
      break;

      default :
      PORTC = 0x00;
      break;

    }


  }

}


Leider bin ich noch recht unerfahren im Programmieren von 
Mikrocontrollern .
Der Quelltext kann bereits genau unterscheiden welche Taste genau 
gedrückt wird auch wenn ich denke das ich das ziemlich umständlich 
umgesetzt habe .
Soweit so gut allerdings kommt mir keine Idee wie ich jetzt einen Code 
einprogrammieren könnte der nach richtiger Eingabe beispielsweise eine 
LED schaltet .
Vielleicht kann mir hier jemand mal einen Ansatz bzw ein Stichwort geben 
wie ich das umsetzten könnte .

Lieben Dank schonmal und Gruß

von Flo (Gast)


Lesenswert?

du speicherst die Werte (ich nehme mal Zahlen von 0-9 an) in einer 
Variable.
Dabei kannst du die Zahlen entweder verschieben oder mit einem Faktor 
multiplizieren:

z.B.
Wert = 0;
Taste 2 gedrückt
-> Wert *= 10;     //"verschoben" um 10, hier egal, da 0
-> Wert += 2;      // Wert ist 2
Taste 4 gedrückt
-> Wert * 10;
-> Wert += 4;      //Wert ist jetzt 24

Taste bestätigen
-> if Wert == Code
-> Piepen

von Karl H. (kbuchegg)


Lesenswert?

Andre schrieb:
> Anbei erstmal mein Quelltext den ich bisher erstellt habe mit dem myAVR
> Workpad Plus in Verbindung mit dem myAVRMK2 Board .
> Daran angeschlossen haben ich eine Tastaturmatrix :

Wie ist die angeschlossen (Schaltplan)

Der Code schreit förmlich danach mit ein paar Schleifen und sonstigen 
Sachen drastisch vereinfacht zu werden.

> Soweit so gut allerdings kommt mir keine Idee wie ich jetzt einen Code
> einprogrammieren könnte der nach richtiger Eingabe beispielsweise eine
> LED schaltet .

Warte noch.
Sieh erst mal zu, dass die Matrixabfrage einfacher wird

Letztenendes willst du bei einer Funktion landen, die dir sagt welche 
Taste gedrückt ist. Das ist dein erstes Zwischenziel. Aber der jetzige 
Code ist mit seinen vielen Port Zugriffen und Binärkonstanten soweit 
undurchschaubar, dass sich diese Funktion nicht wirkich aufdrängt.

Der Code agiert so ähnlich wie in einer Analogie jemand der nicht 
Multiplizeren kann und 3 * 4 bestimmt indem er 3 + 3 + 3 + 3 ausrechnet. 
Nicht wirklich falsch aber deutlich zu kompliziert.

von Andre (Gast)


Lesenswert?

Ich habe mal etwas überlegt allerdings fällt mir einfach nichts anderes 
ein .
Am besten wären natürlich Befehle bzw Abfragen die direkt aus der 
Binärkombination der Matrix erkennt welche Taste genau gedrückt ist .
Ich wollte ja zb auch einen Lernmodus einbauen mit dem ich dann einen 
neuen Code einprogrammieren kann .
Ich brächte da echt Hilfe von euch zumindest ein Stichwort womit ich es 
umsetzen kann .
Ich wurschtel mich dann irgendwie durch wenn ich die grobe Richtung 
kenne .
Kann man sowas nicht am besten mit Interrups realisieren ? .
So würden die Tastenabfragen nicht in der ständig wiederholenden 
Programmschleife liegen .

von Karl H. (kbuchegg)


Lesenswert?

Andre schrieb:

> Kann man sowas nicht am besten mit Interrups realisieren ? .

Ja.
Aber erst mal eins nach dem anderen.

Also: Wie ist die Matrix verschaltet?

von Andre (Gast)


Lesenswert?

Also die Spalten liegen jeweils an PIN 1..3 und die Zeilen an 4..7 .
Daher habe ich quasi in den case Abfragen erst ausgelesen welche Zeile 
gedrückt wurde und innerhalb dessen dann welche Spalte genau damit ich 
am Ende die Zuordnung für exakt eine Zahl bekomme .

von Andre (Gast)


Lesenswert?

Ich bin jetzt soweit das ich mir Gedanken mache wie ich den Code den nun 
wirklich "vergleichen" kann .
Ich habe zwar schon mit Rechnungen versucht aber z.B. wenn ich 1234 
nehme und es rückwärts eingebe wird es auch als richtig erkannt .

Wie könnte man sowas denn umsetzen ? Die Lösung von "Flo" habe ich nicht 
ganz verstanden bzw wenn ich sie richtig verstanden habe komme ich zum 
selben Problem .
Es darf einfach nur ein einziger Code auch richtig sein .

Habe es mal mit Strings versucht da denn der Code an sich verglichen 
wird bin dann aber daran gescheitert das ich mein tmpCode = "0" nicht 
ausführen konnte weil irgendwas mit char und const char nicht passt ?!.

Wäre für jede Idee dankbar

von Karl H. (kbuchegg)


Lesenswert?

Andre schrieb:

> Wie könnte man sowas denn umsetzen ?

Du könntest zb so etwas machen:

Du hast eine Funktion, die dir einen Tastendruck liefert. Das ist 
schon mal einer der wichtigen Punkte: Wird eine Taste gedrückt, dann 
liefert dir die Funktion den Code für diese Taste nur ein einziges mal.

OK. Ich gehe davon aus, dass du so etwas hast.
Vergiss auch erst mal die Werte, die auf den Tasten stehen. Jede Taste 
hat einen Code, nur der ist wichtig (damit man die Ziffern von den 
restlichen Tasten unterscheiden kann)

Die Frage lautet daher:
Dein Benutzer drückt nacheinander Tasten. Wie kannst du feststellen, 
dass zb die letzten 4 Tastendrücke genau einer vorgegebenen Sequenz 
entsprechen?

In der Fragestellung ist in einem gewissen Umfang auch schon die Lösung 
enthalten. 'die letzten 4 Tastendrücke'
Die wird man sich zwischenspeichern müssen. Bei jedem Tastendruck wird 
die älteste entfernt, dafür kommt die neu gedrückte Taste dazu. Und dann 
schaut man einfach, ob die 4 Tastendrücke der vorgegebenen Sequenz 
entsprechen. Wenn ja: Bingo

Lösungsansatz 1:
Du hast ein Array von 4 Werten. Nennen wir es
1
  unsigned char Input[4];
Input[0] sei dabei der 'älteste' Tastendruck (ausgedrückt als der dieser 
Taste zugeordnete Code). Input[3] sie die zuletzt gedrückte.

Drückt der Benutzer eine Taste, dann wird sie 'hinten im Array 
angehängt'. Dies geschieht, indem der älteste Tastendruck verworfen 
wird, alle anderen um 1 Stelle im Array nach vorne rutschen und der neue 
Tastendruck an die Position Input[3] kommt
1
  for( i = 1; i < 4; ++i )
2
    Input[i-1] = Input[i];
3
  Input[3] = neuer_Tasten_Code;

Dann hat man natürlich noch ein 2-tes Array, in dem die korrekte 
Tastenkombination drinnensteht
1
  unsigned char Code[4] = { 1, 8, 5, 3 };

und nachdem die neu gedrückte Taste im Input Array gelandet ist, 
vergleicht man einfach, ob alle Stellen in Input damit mit Code 
übereinstimmen. Das macht man in einer Schleife indem man jeweils 
korrespondierende Arrayelemente miteinander vergeleicht. Ausgansgpunkt 
ist die Annahme: der Code ist korrekt und sobald man ein Pärchen 
gefunden hat, welches nicht übereinstimmt revidiert man diese Annahme: 
der eingegebene Code ist nicht korrekt. Nach der Schleife prüft man 
einfach, ob die ursprüngliche Annahme gehalten hat oder nicht.
1
  for( i = 1; i < 4; ++i )
2
    Input[i-1] = Input[i];
3
  Input[3] = neuer_Tasten_Code;
4
5
  korrekt = TRUE;
6
  for( i = 0; i < 4; ++i ) {
7
    if( Input[i] != Code[i] )
8
      korrekt = FALSE;
9
  }
10
11
  if( korrekt )
12
    öffne_Tür

Das ist eine Möglichkeit.
Eine andere sieht so aus, das man sich die bisher eingegebenen Tasten 
nicht merkt, sondern nur wieviele Stellen bisher korrekt waren. Kommt 
ein neuer Tastendruck der stimmt (mit dem Code vergleichen), dann hat 
man wieder eine korrekte Taste mehr. Stimmen sie nicht überein, dann 
wird die Anzahl der korrekten Tasten wieder auf 0 gesetzt
1
unsigned char bisher_korrekt;
2
...
3
4
  while( 1 ) {
5
6
    ....
7
8
    if( neuer_Tasten_Code == Code[ bisher_korrekt ] )
9
      bisher_korrekt++;
10
    else
11
      bisher_korrekt = 0;
12
13
    if( bisher_korrekt == 4 ) 
14
      öffne_Tür
15
16
  }

Die zweite Variante ist signifikant kürzer und auch ein wenig 
trickreicher als die erste. Hat man aber das Prinzip erst mal so 
einigermassen, ist sie aber denk ich auch nicht schwieriger als die 
erste.

von Andre (Gast)


Lesenswert?

Naja habe jetzt wieder das ganze über den Haufen geworfen .
Die Abfrage der einzelnen Tasten ist immernoch totaler Mist .
Zb dürfte die Taste ja auch nicht mehrfach gezählt werden wenn man sie 
länger hält .
Den Abgleich vom Code habe ich insofern erstmal gelöst gehabt als das 
ich strcat bei Tastendruck immer ein Zeichen also z.B. eine 1,2 etc in 
einen Leerstring schreiben lassen habe .
Am Ende wurde dann immer der String mit dem eingespeicherten String 
verglichen usw.
Hat super geklappt aber wie gesagt diese Tastenmatrix macht mir doch zu 
schaffen weil man sie ja in erster Linie nichtmal direkt ansprechen kann 
.

Gibt es nicht irgendeine Möglichkeit ausser zB. ADC die Tasten auf 
Anhieb zu erkennen .Bzw eine Funktion die nur die Taste annimmt wenn man 
sie auch wieder losgelassen hat würde ja meiner Meinung nach schon 
helfen .

von Karl H. (kbuchegg)


Lesenswert?

Andre schrieb:
> Naja habe jetzt wieder das ganze über den Haufen geworfen .
> Die Abfrage der einzelnen Tasten ist immernoch totaler Mist .
> Zb dürfte die Taste ja auch nicht mehrfach gezählt werden wenn man sie
> länger hält .

Richtig.

Schau dir mal diesen Artikel an. Der stammt zwar aus dem Assembler 
Tutorial, die Gedankengänge sind aber hoffentlich gut genug beschrieben 
um die Ideen nachvollziehen zu können.

http://www.mikrocontroller.net/articles/AVR-Tutorial:_Tasten

Solange du dieses Teilproblem nicht zufriedenstellend gelöst hast, hat 
es keinen Sinn darauf aufbeuend weiterzuarbeiten.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.