Pages: [1] 2   Go Down
Author Topic: Probleme mit Programmcode für Türschloßprojekt  (Read 2683 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
***
Karma: 1
Posts: 166
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo,

ich habe eine Frage zu einem Code für ein Türschlossprojekt. Es handelt sich um diesen Code:

Quote
#include <MyAnalogKeyPad.h>
#include <LiquidCrystal.h>
#define analogPinKeyPad 0                                 // Definition des analogen Pins
#define RS 12                                             // Register Select
#define E 11                                              // Enable
#define D4 5                                              // Datenleitung 4
#define D5 4                                              // Datenleitung 5
#define D6 3                                              // Datenleitung 6
#define D7 2                                              // Datenleitung 7
#define COLS 16                                           // Anzahl der Spalten
#define ROWS 2                                            // Anzahl der Zeilen
int CODE = 9200;                                // Die generierte Zahl, Anzahl der Versuche
char Eingabe[5];                                        // max. 5 stellige Zahl generieren
byte stelle;   

MyAnalogKeyPad myOwnKeyPad (analogPinKeyPad);             // KeyPad Instanziieren
LiquidCrystal lcd ( RS,E,D4,D5,D6,D7);                    // LCD Instanziieren

void setup(){
  myOwnKeyPad.setDebounceTime(500);                       // Prellzeit auf 500ms setzen
  lcd.begin(COLS, ROWS);                                  // Anzahl der Spalten und Zeilen
  startSequence();                                        // Aufruf der Startsequenz
}

void loop(){
  char myKey = myOwnKeyPad.readKey();                    // Abfragen des gedrückten Tasters
  if (myKey != KEY_NOT_PRESSED){                         // Abfragen ob irgendein Taster gedrückt ist
  Eingabe[stelle] = myKey;
  stelle++;
  lcd.print(myKey);                                      // Taste im LCD anzeigen
  }
  if (stelle == int(log10(CODE))+1){
    int a = atoi(Eingabe);
    if ( a == CODE){
      lcd.clear();                                      // LCD Anzeige löschen
      lcd.print("Code zugelassen");                          // Ausgabe an das LCD Display
      delay(2000);                                      // 2 Sekunden warten
      stelle = 0;
      startSequence();                                  // Startsequenz aufrufen
    }
    else if( a != CODE){
      lcd.setCursor(0,1);                               // Cursor in die 1. Zeile positionieren
      lcd.print("Code verweigert");                            // Ausgabe an das LCD Display
      lcd.setCursor(0,0);       
    }
    else{
      lcd.setCursor(0,1);                               // Cursor in die 2. Zeile positionieren
      lcd.print("Code verweigert");                            // Ausgabe an das LCD Display
      lcd.setCursor(0,0);
    }
    lcd.setCursor(2,0);                                 // Cursor an die 3. Stelle in der 1. Zeile positionieren
   
    stelle = 0;
  }
}

void startSequence(){
    lcd.clear();                                         // Display Anzeige löschen
  lcd.print("TEST FUER");                        // Ausgabe an das LCD Display
  lcd.setCursor(0,1);                                  // Cursor in die 2. Zeile positionieren
  lcd.print("   AUSBILDUNG");
  delay(2000);                                         // 4 Sekunden warten
  lcd.clear();                                         // LCD Anzeige löschen
}

Die Library für das Keypad liefert mir folgende Werte zurück je nachdem welche Taste gedrückt ist:

nichts gedrückt - KEY_NOT_PRESSED
0 - KEY_0
1 - KEY_1
2 - KEY_2
3 - KEY_3
4 - KEY_4
5 - KEY_5
6 - KEY_6
7 - KEY_7
8 - KEY_8
9 - KEY_9
# - KEY_hash
* - KEY_star

Wie man nun mit den eingelesenen Werten arbeitet, bzw. sie mit dem vorgegebenen Kennwort zu vergleichen ist mir soweit eigentlich schon gelungen (zumindest einigermaßen). Jetzt möchte ich das wenn die Eingabe:  #100 ist das man in eine bestimmte andere Menüebene kommt. Die Ebene erstellen und so klappt auch alles. Ich habe nur an folgender Stelle ein Problem:

Wie kann ich die beiden Zeichen: # , * einlesen? Wenn ich zum Beispiel oben in dem Programmcode meinen CODE von der aktuellen Zahl 9200 zum Beispiel in #100 ändere kommt eine Fehlermeldung. Ich kenn mich mit der Materie noch nicht richtig aus deshalb kann ich mir nicht so richtig helfen. Ich vermute es hat was mit dem Datentyp der Variablen CODE zu tun. Wenn ja welchen Datentyp müsste ich nehmen?

Gruß,

Tobias
Logged

Nobody is perfect but - impossible is nothing

Germany
Offline Offline
Faraday Member
**
Karma: 59
Posts: 3072
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

CODE ist ein int, und es ist auch nicht vorgesehen, dies zu ändern. ( Ohne alles über den Haufen zu werfen)
# und * sind eher als Begrenzungszeichen zu sehen
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 166
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hmm, schonmal danke aber ich hab das nicht ganz verstanden.
Wenn ich auf dem KeyPad die Tasten # und * drücke bekomme ich die auch so auf dem LCD Display angezeigt. Nun muss es doch möglich sein eine Variable zu deklarieren die anstatt der CODE Variable 9200 eben #100 als Wert hat. Und dann auf die selbe Art wie bei der CODE Abfrage sagen wenn die Eingabe ( myKey) #100 ist dann mache das.......  Geht das nicht ohne viel Aufwand?

Gruß
Logged

Nobody is perfect but - impossible is nothing

Germany
Offline Offline
Faraday Member
**
Karma: 59
Posts: 3072
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Geht das nicht ohne viel Aufwand?
Na ja, schon, aber von deinem Beispiel-Code bleibt nicht viel übrig.

Die gedrückten Tasten findest du in char myKey und char Eingabe[5];

Um Sachen wie

   if (stelle == int(log10(CODE))+1) {

wäre es nicht schade, meiner Meinung nach...
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 166
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

danke für die Antwort. Was meinst du mit "wäre es nicht schade meiner Meinung nach" ? Hmm dann wirft das halt meine Pläne durcheinander bzw. schränkt die Auswahl des Passwortes ein, aber wenn es sonst den ganzen Sketch umwirft muss ich es dann wohl lassen ;-)
Logged

Nobody is perfect but - impossible is nothing

Germany
Offline Offline
Faraday Member
**
Karma: 59
Posts: 3072
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Um Sachen wie
   if (stelle == int(log10(CODE))+1) {
wäre es nicht schade, meiner Meinung nach...
... weil die log10 Funktion, zumal wenn CODE nicht als const deklariert wurde, eine aufwändige float Operation ist, und das nur, um rauszukriegen, wie viele Stellen dein konstanter Schlüssel-Code hat.

Na ja konstant ist er ja nur erstmal in diesem Beispiel, aber trotzdem ...


Dass der eigentliche Code nur aus Ziffern besteht und * und # als Trennzeichen verwendet werden, würde mich nicht stören. Das erleichtert eher die Kommunikation bei Fehleingaben. ( So machen es zumindest andere Zahlenschlösser mit einer solchen Tastatur ).
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 166
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey,
Danke für die Rückmeldung.

Mir ging es halt wegen den Sonderzeichen darum das man z.B. mit der Eingabe #100 in die Menüebene kommt, da das einlesen der Zeichen halt doch nicht so geht muss mann z.B. 1000 eintippen um in das Menü zu kommen. Dann fällt halt 1000 als mögliches Kennwort was man sich einstellen kann raus. So dachte ich halt. Aber da das ganze ein überschaubares Projekt ist gibt es nicht so viele Sonderkombinationen.

Gruß und danke für die Infos,

Tobi
Logged

Nobody is perfect but - impossible is nothing

Germany
Offline Offline
Faraday Member
**
Karma: 59
Posts: 3072
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ob man grade einen Schlüssel eintippt oder ein Menü steuert, sollte doch dem Benutzer angezeigt werden, und also auch dem Programm klar sein, oder?

Ich verstehe wohl dein Problem nicht...
Ich würde z.B. als Ende des Schlüssels die '*' - Taste nehmen, danach bist du wieder im Menü - Modus,
z.B. mit den Funktionen 0 .. 9, oder # für neue Schlüsseleingabe

( Sollte ja auch alles auf deinem 16x2 Display darstellbar sein )

Ein reines "Türschloss-Projekt" hat ja auch kein großes Menu: Schlüssel eingeben, falls offen: Schliessen, Schlüssel ändern, Bestätigen.
Was noch ? ( mehrere Schlüssel ?)
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 82
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mich wundert, dass der Code überhaupt häuft.

Code:
char myKey = myOwnKeyPad.readKey();

du definierst myKey als einzelnen char obwohl deine Funktion eine Zeichenkette liefert  (KEY_X). Ich würde MyAnalogKeyPad.h so ändern, dass mir die Lib auch nur einen char zurückgibt.
Logged

Germany
Offline Offline
Faraday Member
**
Karma: 59
Posts: 3072
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
obwohl deine Funktion eine Zeichenkette liefert  (KEY_X).

Und welche Library verwendest du ?
Tobias' in
#include <MyAnalogKeyPad.h>
verwendete scheint immerhin zu kompilieren, auch wenn er nicht verrät was er da nimmt...

Und dass eine Funktion namens keyPressed() einen Buchstaben zurückliefert, ist doch recht sinnvoll, oder.
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 82
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich verwende meine eigene Subroutine die liefert ein byte zurück:

0 -> 0
...
9 -> 9
* -> 10
# -> 11
nichts -> 12
Fehler -> 13

Ich vermute durch die Zuweisung gibt es einen Überlauf und in myKey wird nur das letzte Zeichen des Strings gespeichert. Das Funktioniert auch bei Key_0 bis Key_9. Nur bei # = KEY_hash steht dann in myKey ein h und bei * = KEY_star ein r.  Dann funktioniert die Funktion atoi() aber nicht mehr. Das ganze ist keine saubere Lösung und dass es funktioniert ist ehr ein Zufall.
Logged

Germany
Offline Offline
Faraday Member
**
Karma: 59
Posts: 3072
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Nur bei # = KEY_hash steht dann in myKey ein h und bei * = KEY_star ein r.

???
Ich weiss nicht wo bei
#define KEY_hash '#' 
der Buchstabe 'h'  ( 0x68 ) vorkommt
???

Da es bei Tobias schon ziemlich funktionert, ist mir klar, dass sein keyPressed() bei der Taste 0 ein '0' liefert, usw.
Eingabe[4] bleibt immer 0, damit geht dann auch atoi(Eingabe). sobald man genau 4 Ziffern eingetippt hat.


Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 82
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Ich weiss nicht wo bei
#define KEY_hash '#' 
der Buchstabe 'h'  ( 0x68 ) vorkommt
???

Da es bei Tobias schon ziemlich funktionert, ist mir klar, dass sein keyPressed() bei der Taste 0 ein '0' liefert, usw.
Eingabe[4] bleibt immer 0, damit geht dann auch atoi(Eingabe). sobald man genau 4 Ziffern eingetippt hat.

ich weiß jetzt nicht wo du dass #define KEY_hash '#' her hast. Tobias93 hat das ganze so beschrieben: Taste - Rückgabewert

Quote
Die Library für das Keypad liefert mir folgende Werte zurück je nachdem welche Taste gedrückt ist:

nichts gedrückt - KEY_NOT_PRESSED
0 - KEY_0
1 - KEY_1
2 - KEY_2
3 - KEY_3
4 - KEY_4
5 - KEY_5
6 - KEY_6
7 - KEY_7
8 - KEY_8
9 - KEY_9
# - KEY_hash
* - KEY_star

Ich persönlich versuche alles was mit strings zu tun hat in C zu vermeiden. Strings brauchen viel speicher und lassen sich unkomfortabel verarbeiten. Z.B hat Eingabe im Sketch eine Größe von 5 * 8 bit = 40 bit für 5 stellen. Mit einem long mit 32 bit kannst du einen 9-stelligen code eingeben.
Logged

Germany
Offline Offline
Faraday Member
**
Karma: 59
Posts: 3072
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Ich persönlich versuche alles was mit strings zu tun hat in C zu vermeiden
Genau, ich auch.

Daher war ich gar nicht auf die Idee gekommen, dass
Quote
...
9 - KEY_9
# - KEY_hash
* - KEY_star
irgendwas mit Strings zu tun haben könnte. Hat's ja auch nicht smiley-wink

Quote
ich weiß jetzt nicht wo du das
#define KEY_hash '#'
her hast.

Geraten.
Ist auch eigentlich egal, jedenfalls im Beispielcode dieses Threads.
"KEY_hash" als string ist auf jeden Fall Unsinn. Und sicher nicht der Rückgabewert von keyPressed().
 
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 166
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok. Wie ich oben ganz am Anfang geschrieben habe: Ich bin Anfänger auf dem Gebiet, dass heißt so ziemlich 50% der letzten Posts sind für mich Böhmsche Dörfer :-(
Ich versuchs mal zu erklären. Der Sketch und die dafür benötigten Librarys habe ich mittels des Lehrbuchs: "Die elektronische Welt mit Arduino entdecken" geschrieben, dass heißt was da steht hab ich eingetippt und die Sktech Erklärung dazu habe ich versucht zu verstehen.

Ich versuche jetzt mal mein Problem genau wie möglich in Worte zu fassen:

Die Header Datei die für das Projekt angelegt wurde:

Quote
#ifndef MYKEYPAD_H
#define MYKEYPAD_H

#if ARDUINO < 100
#include <WProgram.h>
#else
#include <Arduino.h>
#endif

#define KEY_NOT_PRESSED '-'
#define KEY_1 '1'
#define KEY_2 '2'
#define KEY_3 '3'
#define KEY_4 '4'
#define KEY_5 '5'
#define KEY_6 '6'
#define KEY_7 '7'
#define KEY_8 '8'
#define KEY_9 '9'
#define KEY_0 '0'
#define KEY_star 'stern'
#define KEY_hash 'raute'

class MyAnalogKeyPad{
public:
MyAnalogKeyPad (byte analogPin);                           // Parametrisierter Konstruktor
void setDebounceTime(unsigned int debounceTime);               // setzen der Prellzeit
void setThresholdValue(byte tv);                           // setzen der Threshold (Grenzwert)
char readKey();                                          // Ermitteln des gedrückten Tasters auf Keypad
private:
byte analogPin;                                          // analoger Pin zur Messwertaufnahme
unsigned long debounceTime;                                 // private Variable für die Prellzeit
long lastValue;                                          // letzte Zeit der millis-Funktion
byte threshold;                                          // Toleranzwert
};
#endif


nun poste ich die cpp Datei:

Quote
#include "MyAnalogKeyPad.h"                                 // Parametrisierter Konstruktor

MyAnalogKeyPad::MyAnalogKeyPad(byte ap){
   analogPin = ap;                                      // Analog Pin für Messwertaufnahme
   debounceTime= 300;                                    // Initialwert für DebounceTime festlegen
   threshold = 5;                                       // Toleranzwert festlegen
}

void MyAnalogKeyPad::setDebounceTime(unsigned int time){         // Methode zum Setzen der Prellzeit
   debounceTime = time;
}

void MyAnalogKeyPad::setThresholdValue(byte tv){               // Methode zum Setzen der Tolleranz
   threshold = tv;
}

char MyAnalogKeyPad::readKey(){                              // Methode zum Ermitteln des gedrückten Tasters auf dem Keypad
   char key = KEY_NOT_PRESSED;                              // Initialwert von key ist "KEY_NOT_PRESSED" (nichts ist gedrückt)
   byte aValue = analogRead(analogPin);
   if((aValue > 0)&&(millis()- lastValue >= debounceTime)){
      if((aValue > (176 - threshold))&&(aValue < (176 + threshold)))
         key = KEY_1;
      if((aValue > (163 - threshold))&&(aValue < (163 + threshold)))
         key = KEY_2;
      if((aValue > (149 - threshold))&&(aValue < (149 + threshold)))
         key = KEY_3;
      if((aValue > (136 - threshold))&&(aValue < (136 + threshold)))
         key = KEY_4;
      if((aValue > (122 - threshold))&&(aValue < (122 + threshold)))
         key = KEY_5;
      if((aValue > (108 - threshold))&&(aValue < (108 + threshold)))
         key = KEY_6;
      if((aValue > (94 - threshold))&&(aValue < (94 + threshold)))
         key = KEY_7;
      if((aValue > (79 - threshold))&&(aValue < (79 + threshold)))
         key = KEY_8;
      if((aValue > (64 - threshold))&&(aValue < (64 + threshold)))
         key = KEY_9;
      if((aValue > (48 - threshold))&&(aValue < (48 + threshold)))
         key = KEY_star;
      if((aValue > (32 - threshold))&&(aValue < (32 + threshold)))
         key = KEY_0;
      if((aValue > (15 - threshold))&&(aValue < (15 + threshold)))
         key = KEY_hash;
         
      lastValue = millis();
      }
   return key;
}

Der passende Sketch wurde ja schon zu Anfang gepostet.

Nun beschreibe ich euch mal meinen aktuellen Standpunkt:

Das Programm funktioniert in sofern das ich wenn die Zahlen 9200, also der in CODE gespeicherte Wert eingegeben wird ein I/O Port geschaltet wird... Tür geht auf.
Wenn die Falschen Zahlen eingegeben werden geht die Tür nicht auf. Die beiden Zeichen will ich mal rauslassen weil da läuft´s nicht so richtig wenn die eingetippt werden spielt der Sketch irgendwie die Reise nach Jerusalem smiley

Ok hab ich mir gedacht dann überbrückst du die beiden Schalter halt und dann hat sichs. Nun möchte ich aber das man mit der Kombination #100 oder *100 oder irgend einer Kombination mit den Zeichen in eine Menüeebene kommt um da z.B. das Kennwort zu ändern. Jetzt steh ich vor dem Problem das die Sonderzeichen ja nicht funktionieren... das is ja schonmal schlecht. Hab ich mir gedacht, komm egal, nimmste als Kombination die dich ins Menü bringt eben 0000, dann fällt die Kombination eben als mögliche Kennwortkombination weg.... bleiben ja immer noch genug.

Jetzt geb ich also 0000 ein und komme in das Menü - bis dahin klappts.
Nun lasse ich am Display anzeigen :
Auswahl:
1 = Code aendern

Jetzt will ich das ich wenn ich eine 1 eintippe (nur eine 1 nicht 0001) das ich dann in die Ebene zum Menü ändern komme. Tippe ich nun 1 ein, passiert nichts... Da bin ich aber glaube ich selbst auf das Problem gestoßen. Ich müsste ein Array anlegen was nur eine Zahl speichert und nicht [5] oder ? Whatever gebe ich nun halt 0001 ein bekomme ich angezeigt Coder verweigert und er springt wider an den Anfang. Das heißt er scheint nicht zu verstehen das er nun eine Ebene höher ist und die Eingaben hier nicht mit den Vorgaben der Ebene für die Codeeingabe verglichen werden sollen.

Könnt ihr mir hier eine Tipp geben wie man das Problem lösen kann, vielleicht auch mit Begründung, damit ich es verstehe?

Schonmal vielen Dank,

Tobias
Logged

Nobody is perfect but - impossible is nothing

Pages: [1] 2   Go Up
Jump to: