Mein Arduino Programm für einen Tresor funktioniert nicht?
Ich muss für die Schule einen Tresor mit einem 3x4Keypad , einem Servo und einem Lcd Display programmieren. Dafür habe ich einen Arduino UNO. Das Programm funktioniert aber nicht so wie ich es will.
Wenn ich eine Taste drücke, die nicht # oder * ist soll sie auf dem Display angezeigt werden und auf der Variable inputPasswort gespeichert werden. Diese sollen aber nicht immer in der ersten Spalte stehen, sondern sollen nebeneinander in einer Zeile angezeigt werden. Wenn ich # drücke soll der Arduino prüfen ob das eingegebene Passwort richtig ist. Wenn das der Fall ist, soll sich der Servo öffnen und das Display "Passwort richtig" anzeigen. Wenn nicht soll der Servo geschlossen bleiben und das Display soll "Passwort falsch" anzeigen. Wenn * gedrückt wird soll das Programm alle bisher eingegebenen Zahlen von der Variable inputPasswort löschen.
Das Display zeigt die Zahlen aber nur kurz und immer an verschiedenen Stellen an. Der Arduino erkennt auch nicht wenn das Passwort richtig ist. Kann mir bitte jemand helfen?
So sieht mein Programm bisher aus:
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Servo.h>
#include <Keypad.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
int cursorPosition = 0; // Variable für die Position des Cursors
Servo IHateThis; // Servo heißt jetzt "IHateThis"
const int ROW_NUM = 4; // Anzahl der Tastenfeld Reihen
const int COLUMN_NUM = 3; // Anzahl der Tastenfeld Zeilen
byte pin_rows[ROW_NUM] = { 9, 8, 7, 6 }; //die Pins für die Reihen des Tastenfelds
byte pin_column[COLUMN_NUM] = { 5, 4, 3 }; //die Pins für die Zeilen des Tastenfelds
char keys[ROW_NUM][COLUMN_NUM] = {
{ '1', '2', '3' },
{ '4', '5', '6' },
{ '7', '8', '9' },
{ '*', '0', '#' }
};
Keypad keypad = Keypad(makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM);
char Passwort[5] = { '0', '1', '2', '3', '#' }; //Array mit Länge des Passworts (4 + #) und dem Passwort selbst (0123)
String inputPasswort; // Variable um die eingegebenen Tasten abzuspeichern
void setup() {
inputPasswort.reserve(4);
lcd.init();
lcd.clear();
lcd.backlight(); //Das Display soll beleuchtet sein
IHateThis.attach(12); //Servo ist an Pin 12 angeschlossen
IHateThis.write(140); //Servo ist anfangs in der Position 140 (Tresor ist zu)
}
void loop() {
char Taste = keypad.getKey(); //Variable "Taste" ist hier definiert
if (Taste != '*' && Taste != '#') {
lcd.setCursor(cursorPosition, 0); // Cursor position at position 0 of the first row of the LCD.
lcd.print(Taste); //Wenn eine Taste außer * und # gedrückt wird, wird diese auf dem Display angezeigt
cursorPosition = cursorPosition + 1;
}
if (Taste == '#') { //Nachdem # gedrückt wurde, wird überprüft ob das eingegebene Passwort dem tatsächlichen Passwort entspricht
if (inputPasswort == Passwort) { //Wenn das eingegebene Passwort dem tatsächlichen Passwort entspricht, wird für 3 Sekunden "Passwort richtig" angezeigt. Danach wird der inhalt der Variable inputPasswort gelöscht, der Servo geöffnet, die Variable cursorPosition auf 0 zurückgesetzt und das Display geleert.
lcd.setCursor(0, 0);
lcd.print("Passwort richtig");
delay(3000);
inputPasswort = "";
lcd.clear();
cursorPosition = 0;
lcd.setCursor(cursorPosition, 0);
IHateThis.write(30);
}
if (inputPasswort != Passwort) { //Wenn das eingegebene Passwort nicht dem eingegebenen Passwort entspricht, wird "Passwort falsch" für 3 Sekunden angezeigt, und danach die reset schleife ausgeführt
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Passwort falsch");
delay(3000);
reset();
}
}
if (Taste == '*') { //Wenn * gedrückt wird, wird die reset Schleife ausgeführt
reset();
}
}
void reset() {
inputPasswort = ""; //Alles was auf der Variable inputPasswort gespeichert war, wird gelöscht
lcd.clear(); //Display wird geleert
cursorPosition = 0; //Die Variable cursorPosition wird auf 0 gesetzt
IHateThis.write(140); //Der Servo wird geschlossen
}
1 Antwort
Die inputPasswort-Variable wird von dir nicht verändert. Du musst das eingegebene Zeichen schon noch anhängen.
inputPasswort += Taste;
Im Übrigen sehe ich keinen Grund, wieso du Eingabe und Passwort mit jeweils unterschiedlichen Datentypen darstellst. Entweder du verwendest für beide char-Arrays oder für beide String-Objekte.
Prinzipiell wäre es ratsam, den Code zu überarbeiten:
1) Orientiere dich an den gängigen C/C++-Namenskonventionen: Variablennamen beginnen immer mit einem Kleinbuchstaben. Entscheide dich zudem für eine Sprache (Deutsch oder Englisch, kein Mix) und benenne deine Variablen sinnvoll, sodass ihr Zweck beim Lesen des Codes sofort ersichtlich ist. Du erschwerst es dir (und Lesern) sonst nur, Überblick über den Code zu behalten.
2) Aktuell gehst du in deinem Code immer davon aus, dass mehrere Fälle gleichzeitig erfüllt werden könnten, was aber nicht möglich ist. Wenn der Nutzer # drückt, hat Taste nur den Wert '#', nicht auch gleichzeitig '*'. Wenn das Passwort richtig ist, braucht es im Anschluss keine Prüfung auf das Gegenteil.
Verwende if-else if-else, um unnötige Prüfungen zu vermeiden.
if (Taste != '*' && Taste != '#') {
/* ... */
}
else if (Taste == '#') {
if (inputPasswort == Passwort) {
/* ... */
}
else {
/* ... */
}
}
else {
/* ... */
}
3) Es gibt einige doppelte Anweisungen in deinem Code.
Die reset-Funktion würde ich umgestalten. Dann kann sie in mehreren Fällen genutzt werden.
void reset()
{
inputPasswort = "";
lcd.clear();
cursorPosition = 0;
lcd.setCursor(cursorPosition, 0);
}
Funktionen sind übrigens keine Schleifen. Deine dazugehörigen Kommentare sind also inhaltlich falsch.
Schleifen sind Strukturen, die ihren Rumpf beliebig oft wiederholen können, je nachdem, wie lange ihre Schleifenbedingung zutrifft. In Arduino gehören for, do-while und while zu dieser Kategorie.
Die Ausgabe der Prüfung lässt sich ebenso auslagern:
void printResult(char* message)
{
lcd.setCursor(0, 0);
lcd.print(message);
delay(3000);
}
// invocation example:
printResult("Passwort richtig");
Der Vergleich wird aus zwei Gründen fehlschlagen.
Zum einen hängst du vor dem Vergleich die Raute nicht an das Ende von inputPassword (andersherum könnte man es bei password natürlich auch einfach weglassen).
Zum anderen vergleichst du zwei unterschiedliche Datentypen (inputPassword ist ein String und password ist ein char-Array). Meines Erachtens sollte das eigentlich auch zu einem Compilerfehler führen.
Entweder du entscheidest dich für nur einen Datentyp bei beiden Variablen oder du führst eine Konversion durch.
Beispiel char[]-Vergleich:
#include <string.h>
// ...
char password[] = { '0', '1', '2', '3', '#' };
char inputPassword[] = "0123#";
if (strncmp(password, inputPassword, sizeof(password)) == 0) {
// equal
}
Beispiel String-Vergleich:
String password = "0123#";
String inputPassword = "0123#";
if (password == inputPassword) {
// equal
}
Beispiel char[]-String-Vergleich:
char password[] = { '0', '1', '2', '3', '#' };
String inputPassword = "0123#";
if (inputPassword == String(password)) {
// equal
}
Danke für deine Hilfe. Ich hoffe ich hab das so gemacht, wie du gemeint hast, aber es hat sich am Problem nichts geändert.
Hier ist das geänderte Programm:
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Servo.h>
#include <Keypad.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
int cursorPosition = 0; // Variable für die Position des Cursors
Servo iHateThis; // Servo heißt jetzt "iHateThis"
const int ROW_NUM = 4; // Anzahl der Tastenfeld Reihen
const int COLUMN_NUM = 3; // Anzahl der Tastenfeld Zeilen
byte pin_rows[ROW_NUM] = { 9, 8, 7, 6 }; //die Pins für die Reihen des Tastenfelds
byte pin_column[COLUMN_NUM] = { 5, 4, 3 }; //die Pins für die Zeilen des Tastenfelds
char keys[ROW_NUM][COLUMN_NUM] = {
{ '1', '2', '3' },
{ '4', '5', '6' },
{ '7', '8', '9' },
{ '*', '0', '#' }
};
Keypad keypad = Keypad(makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM);
char password[5] = { '0', '1', '2', '3', '#' }; //Array mit Länge des Passworts (4 + #) und dem Passwort selbst (0123)
String inputPassword; // Variable um die eingegebenen Tasten abzuspeichern
void setup() {
inputPassword.reserve(4);
lcd.init();
lcd.clear();
lcd.backlight(); //Das Display soll beleuchtet sein
iHateThis.attach(12); //Servo ist an Pin 12 angeschlossen
iHateThis.write(140); //Servo ist anfangs in der Position 140 (Tresor ist zu)
}
void loop() {
char key = keypad.getKey(); //Variable "Taste" ist hier definiert
if (key != '*' && key != '#') {
lcd.setCursor(cursorPosition, 0); // Cursor position at position 0 of the first row of the LCD.
lcd.print(key); //Wenn eine Taste außer * und # gedrückt wird, wird diese auf dem Display angezeigt
cursorPosition = cursorPosition + 1;
inputPassword += key;
}
else if (key == '#') { //Nachdem # gedrückt wurde, wird überprüft ob das eingegebene Passwort dem tatsächlichen Passwort entspricht
if (inputPassword == password) { //Wenn das eingegebene Passwort dem tatsächlichen Passwort entspricht, wird für 3 Sekunden "Passwort richtig" angezeigt. Danach wird der inhalt der Variable inputPasswort gelöscht, der Servo geöffnet, die Variable cursorPosition auf 0 zurückgesetzt und das Display geleert.
printResult("Passwort richtig");
reset();
iHateThis.write(30);
}
else { //Wenn das eingegebene Passwort nicht dem eingegebenen Passwort entspricht, wird "Passwort falsch" für 3 Sekunden angezeigt, und danach die reset schleife ausgeführt
printResult("Passwort falsch");
reset();
iHateThis.write(140);
}
}
else { //Wenn * gedrückt wird, wird die reset Funktion ausgeführt
reset();
}
}
void reset() {
inputPassword = ""; //Alles was auf der Variable inputPasswort gespeichert war, wird gelöscht
lcd.clear(); //Display wird geleert
cursorPosition = 0; //Die Variable cursorPosition wird auf 0 gesetzt
lcd.setCursor(cursorPosition, 0);
}
void printResult(char* message) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(message);
delay(3000);
}