Pin-Ein­ga­be mit LCD und Servomotor

Lese­zeit: 6 Minu­ten

Lösung
Seite als PDF

Auf einem Tas­ten­feld soll ein zufäl­lig erzeug­ter Pin ein­ge­ge­ben wer­den. Das Pro­gramm soll die­sen Pin abfra­gen. Wur­de der Pin nach Druck auf die Tas­te # rich­tig ein­ge­ge­ben, wird die Mel­dung „kor­rek­ter Pin“ ange­zeigt und der Ser­vo­mo­tor öff­net die Schranke.

So sieht es aus:

Schlie­ße das LCD an:

LCD

Nor­ma­ler­wei­se wäre eine kom­ple­xe Ver­ka­be­lung zum Betrieb eines LCDs nötig. Der ➨I2C-Bus regelt über einen eige­nen Mikro­pro­zes­sor die Kom­mu­ni­ka­ti­on der Daten­lei­tun­gen unter­ein­an­der. Es wer­den des­halb nur vier Anschlüs­se benötigt.

Auf der Rück­sei­te befin­det sich ein Dreh­po­ten­tio­me­ter, mit dem die Hel­lig­keit des LCDs ein­ge­stellt wird.

Ein Ser­vo­mo­tor ist ein spe­zi­el­ler Elek­tro­mo­tor, bei dem die Dreh­ge­schwin­dig­keit und die Beschleu­ni­gung gesteu­ert wer­den kann. Der hier ver­wen­de­te Ser­vo­mo­tor kann aller­dings nur eine 180°-Drehung ausführen.

Benö­tig­te Bibliotheken:

Benö­tig­te Bauteile:

  • LCD 1602
  • Ser­vo­mo­tor
  • Tas­ten­feld 3×4
  • Lei­tungs­dräh­te

Das Tas­ten­feld besteht aus Rei­hen und Spal­ten, die von unten nach oben in einem ➨zwei­di­men­sio­na­len Array ange­ord­net werden:

Baue die Schal­tung auf.
(Fah­re mit der Maus über das Bild, um die Bezeich­nun­gen der Bau­tei­le zu sehen)

Bin­de die Biblio­the­ken ein und defi­nie­re die Variablen:

# include "Adafruit_Keypad.h"
# include "Servo.h"
# include "LiquidCrystal_I2C.h"

LiquidCrystal_I2C lcd(0x27, 20, 4);

// Bezeichnung des Motors
Servo Motor;

// Größe des Tastenfeldes
// 3 Spalten
const byte SPALTEN = 3;

// 4 Zeilen
const byte REIHEN = 4;

// die Ziffern/Zeichen:
// Array 3 x 4
char Tasten[REIHEN][SPALTEN] =
{
  { '#', '0', '*' },
  { '9', '8', '7' },
  { '6', '5', '4' },
  { '3', '2', '1' }
};

// die Pins für die 3 Spalten
byte SpaltenPins[SPALTEN] = { 3, 4, 5 };

// die Pins für die 4 Zeilen
byte ReihenPins[REIHEN] = { 6, 7, 8, 9 };

// TastenFeld → Name des Keypads
// -> Zuordnung der Pins zu den REIHEN und SPALTEN des Arrays
Adafruit_Keypad Tastenfeld = Adafruit_Keypad(makeKeymap(Tasten), ReihenPins, SpaltenPins, REIHEN, SPALTEN);

String Vergleich;
String Pin;

// char-Array für die eingegebenen Zeichen
char Zeichen[5];

// Position im Array Zeichen
int Position = 0;

// Position der angezeigten Spalte LCD
int PositionSpalte = 0;

// Pin des Servos
int ServoPin = 12;

Der set­up-Teil. Beach­te die Kommentare:

void setup()
{
  // Pin dem Servo zuordnen
  Motor.attach(ServoPin);

  // Tastenfeld starten
  Tastenfeld.begin();

  // LCD einschalten
  lcd.init();
  lcd.backlight();

  Serial.begin(9600);

  // auf serielle Verbindung warten
  while (!Serial) { ; }
  delay(500);

  // nur beim Start anzeigen
  Serial.println("Bitte 4-stelligen Pin eingeben:");
  Serial.println("Pin-Eingabe mit # abschlie\u00dfen");
  Serial.println("Korrektur mit * ");

  // Zufallsgenerator starten
  randomSeed(analogRead(0));

  // neuen Pin erstellen
  neuerPin();
  
  // Servo in Ausgangsposition fahren
  Motor.write(0);
}
Download

Der loop-Teil. Beach­te die Kommentare.

void loop()
{
  // gedrückte Taste lesen
  Tastenfeld.tick();

  while (Tastenfeld.available())
  {
    keypadEvent Taste = Tastenfeld.read();

    // wenn die Taste losgelassen wurde
    // Wert abgefragter Taste zu char umwandeln
    if (Taste.bit.EVENT == KEY_JUST_RELEASED)
    {
      lcd.setCursor(0, 0);
      lcd.print("Pin eingeben:      ");

      // Zeilen LCD löschen
      ZeileLoeschen(1);
      ZeileLoeschen(3);

      Motor.write(0);

      // eingegebenes Zeichen an der aktuellen Position speichern
      Zeichen[Position] = (char)Taste.bit.KEY;

      // Zeichen anzeigen
      Serial.print(Zeichen[Position]);

      lcd.setCursor(PositionSpalte, 2);
      lcd.print(Zeichen[Position]);

      // nächstes Zeichen -> Position erhöhen
      // Position Spalte LCD erhöhen
      Position++;
      PositionSpalte++;

      // Korrektur ASCII-Wert 42 = *
      if (Taste.bit.KEY == 42)
      {
        // char-Array Zeichen leeren
        for (int i = 0; i < sizeof(Zeichen); i++)
        {
          Zeichen[i] = NULL;
        }

        // Variablen zurücksetzen, Zeilen LCD löschen
        Position = 0;
        PositionSpalte = 0;
        ZeileLoeschen(0);
        ZeileLoeschen(2);

        Serial.println("\tKorrektur: ");
        lcd.setCursor(0, 0);

        lcd.print("Korrektur: ");
      }

      // Zeichen ASCII-Wert 35 = #
      if (Taste.bit.KEY == 35)
      {
        // char-Array in String umwandeln
        Vergleich = String(Zeichen);

        // letzte Zeichen des Strings sind 0 und # -> müssen entfernt werden
        Vergleich = Vergleich.substring(0, Vergleich.length() - 2);

        Serial.println();
        Serial.print(Vergleich);

        // Zeilen LCD löschen
        ZeileLoeschen(0);
        ZeileLoeschen(2);

        lcd.setCursor(0, 0);
        lcd.print("Pin: " + Vergleich + " ");

        // Eingabe mit Pin vergleichen
        if (Vergleich == Pin)
        {
          Serial.println("\korrekter Pin - Schranke \u00f6ffnen!");
          lcd.setCursor(0, 1);
          lcd.print("-> korrekter Pin!");
          delay(2000);
          lcd.setCursor(0, 1);
          lcd.print("Schranke \357ffnen!");
          Motor.write(90);
        }
        else
        {
          Serial.println("\tFalscher Pin - kein Zugriff");

          lcd.setCursor(0, 1);
          lcd.print("-> falscher Pin!");
        }

        // Variable zurücksetzen
        Position = 0;
        PositionSpalte = 0;

        // neuen Pin erstellen
        neuerPin();
      }
    }
  }
}

Die Funk­ti­on neu­er­Pin() erzeugt einen neu­en, zufäl­li­gen Pin und zeigt ihn an..

String neuerPin()
{
  // zufälligen PIN bestimmen
  Pin = "";
  Serial.println("---------------------------------------");

  for (int i = 0; i < sizeof(Zeichen) - 1; i++)
  {
    int Zahl = random(0, 10);
    Pin = Pin + String(Zahl);
  }

  // Pin anzeigen
  Serial.println("neuer Pin: " + Pin);
  lcd.setCursor(0, 3);
  lcd.print("neuer Pin: " + Pin);
  return Pin;
}

Die Funk­ti­on Zei­leLoe­schen() löscht ein­zel­ne Zei­len auf dem LCD.

void ZeileLoeschen(int Zeile)
{
  for (int i = 0; i < 20; i ++)
  {
    lcd.setCursor(i, Zeile);

    lcd.print(" ");
  }
}

Startseite
Aufgaben A-Z
Suchen
Downloads
Fehlermeldungen
Seite als PDF

Ver­wand­te Aufgaben:


Letzte Aktualisierung: 4. Okt 2023 @ 10:26