LCD Keypad Shield

Ich habe mir chinesische LCD Keypad Shields von DF-Robot zugelegt (steht jedenfalls so drauf). Nach einigem Suchen bin ich dann auf Bibliotheken gestoßen, die aber alle Macken haben. Am übelsten dabei ist eine einzige lapidare “error” Meldung beim Compilieren. Daneben kamen auch schon mal “multiply defined…” Meldungen, mit temp Verzeichnissen - was wollen die mir sagen?

Nun möchte ich eine eigene Bibliothek erzeugen, mit folgenden Erweiterungen gegenüber LiquidCrystal:

  1. feste Pinbelegung (wie vom Shield vorgegeben)
  2. Auswertung der Taster an A0

Falls es sowas schon gibt, kann ich mir den Rest sparen?

Sonst ist mein größtes Problem das Handling von C++ Klassen, mit dem ich zuletzt vor 20 Jahren zu tun hatte, danach bin ich auf Delphi umgestiegen. So etwa sollte das Ergebnis aussehen:

#ifndef LCDKeyPad_h
#define LCDKeyPad_h
#include <Arduino.h>
#include <LiquidCrystal.h>
enum KeyPad_t = {None, Left, …};
LCDKeyPad = class public LiquidCrystal {
void begin(); //kann man das in den Konstruktor verlagern?
KeyPad_t getKey();
}
#endif

Wie sollte das richtig aussehen?
Wo lege ich die Dateien hin? Vermutlich erst mal ins private Sketch-Verzeichnis?

Ich kann Dir hier zwar nicht helfen, aber m.E. sollte es durchaus mindestens eine Lib geben, die das LCD antreiben kann.
Schonmal beim Lieferant angefragt?

Das Display läuft mit LiquidCrystal. Für die Buttons habe ich mehrere Libs gefunden, anscheinend für verschiedene (ältere) IDE Versionen. Eine compiliert garnicht, die andere erkennt nur einen Key, und wenn ich das zugehörige Example ändere, gibt es weitere obskure Fehler (multiple definition...) zur Datei DFR_Key.cpp in verschiedenen Verzeichnissen.

Deshalb möchte ich eine neue Bibliothek bauen, mit anderen Datei- und Klassennamen, um solche Konflikte zu vermeiden. Die Implementierung ist kein Hexenwerk, nur bei der Konstruktion der neuen Klasse fehlen mir ein paar C++ Kenntnisse.

DrDiettrich:
Das Display läuft mit LiquidCrystal.

Ja. Und deshalb braucht es für den Display-Teil des Shields schon mal keine extra Library.
Die vorhandene LiquidCrystal-Library unterstützt auch das Display vom LCD-Keypad-Shield bestens.

DrDiettrich:
Für die Buttons habe ich mehrere Libs gefunden, anscheinend für verschiedene (ältere) IDE Versionen. Eine compiliert garnicht, die andere erkennt nur einen Key, und wenn ich das zugehörige Example ändere, gibt es weitere obskure Fehler (multiple definition...) zur Datei DFR_Key.cpp in verschiedenen Verzeichnissen.

Die Programmierbeispiele für die 5 Buttons des LCD-Keypad-Shields sind bei den beiden Herstellern DFRobot und Sainsmart gleichermaßen bescheiden: Es wird meines Erachtens von beiden ausschließlich Democode gezeigt, der bei der Buttonabfrage nur den momentan gedrückten Button abfragen kann, und ggf. ein Beispielprogramm, das durch Verwendung von mehr oder weniger delay() oder busy-waiting eine Tastenbedienung ermöglicht. Das könnte man wohl in der Tat besser hinbekommen.

Dass aber DFrobot oder Sainsmart komplette Libraries für das LCD-Keypad-Shield zur Verfügung stellen, noch dazu nicht funktionierende, die man nicht mit maximal ein oder zwei kleinen Änderungen für aktuelle IDE-Versionen verwendbar machen könnte, wäre mir neu.

Auf welche Libraries beziehst Du Dich?

DrDiettrich:
obskure Fehler (multiple definition...) zur Datei DFR_Key.cpp in verschiedenen Verzeichnissen.

Wenn Du eine Library installierst, sollte die Datei nur einmal vorkommen. Warum sollte der Compiler über dieselbe Datei in mehreren verschiedenen Verzeichnissen meckern, wenn Du die Datei tatsächlich nur in einem Verzeichnis installiert hast? Das klingt mir mehr danach, als wenn Du da etwas an den Haaren herbeiziehst, was eigentlich eher ein Fehler beim Installieren der Library auf Deiner Festplatte ist.

jurs:
Ja. Und deshalb braucht es für den Display-Teil des Shields schon mal keine extra Library.
Die vorhandene LiquidCrystal-Library unterstützt auch das Display vom LCD-Keypad-Shield bestens.

Zu diesem Teil möchte ich nur die feste Pinbelegung des Shield hinzufügen, die von der Belegung in sonstigen Beispielen abweicht. Sonst muß man ja jedesmal erst das Datenblatt und LiquidCrystal.begin() studieren, um die Parameter richtig einzutippen.

Die Programmierbeispiele für die 5 Buttons des LCD-Keypad-Shields sind bei den beiden Herstellern DFRobot und Sainsmart gleichermaßen bescheiden: Es wird meines Erachtens von beiden ausschließlich Democode gezeigt, der bei der Buttonabfrage nur den momentan gedrückten Button abfragen kann, und ggf. ein Beispielprogramm, das durch Verwendung von mehr oder weniger delay() oder busy-waiting eine Tastenbedienung ermöglicht. Das könnte man wohl in der Tat besser hinbekommen.

Mir gefallen die Analog-Buttons sowieso nicht, aus verschiedenen Gründen. Aber wenn die Schaltung schon vorgegeben ist, dann möchte ich wenigstens nicht jedesmal ausprobieren müssen, welcher Knopf welchen Wert liefert.

Dass aber DFrobot oder Sainsmart komplette Libraries für das LCD-Keypad-Shield zur Verfügung stellen, noch dazu nicht funktionierende, die man nicht mit maximal ein oder zwei kleinen Änderungen für aktuelle IDE-Versionen verwendbar machen könnte, wäre mir neu.

Auf welche Libraries beziehst Du Dich?

Nochmal nachgeschaut, bei DFR_Key scheint es sich um Bibliotheken für ältere Versionen zu handeln, aktuell wird keine Bibliothek mehr angeboten.

Wenn Du eine Library installierst, sollte die Datei nur einmal vorkommen. Warum sollte der Compiler über dieselbe Datei in mehreren verschiedenen Verzeichnissen meckern, wenn Du die Datei tatsächlich nur in einem Verzeichnis installiert hast? Das klingt mir mehr danach, als wenn Du da etwas an den Haaren herbeiziehst, was eigentlich eher ein Fehler beim Installieren der Library auf Deiner Festplatte ist.

Die zusätzlichen Dateien liegen unter AppData\Local\Temp\build…, und zu jedem compilierten Sketch scheint so ein Verzeichnis angelegt zu werden. Die angehängte Datei enthält die angezeigten Meldungen, anscheinend aus mehreren Compiler-Läufen, auch aus einem Temp Verzeichnis.

Den Sketch konnte ich nur einmal compilieren und hochladen, grunsätzlich scheint also alles erst mal in Ordnung zu sein. Danach kommen aber nur noch Fehler. Deshalb möchte ich eben gerne eine eigene Bibliothek erstellen, aber anscheinend weiß darüber auch hier niemand so richtig Bescheid :frowning:

stderr.txt (3.79 KB)

DrDiettrich:
Nochmal nachgeschaut, bei DFR_Key scheint es sich um Bibliotheken für ältere Versionen zu handeln, aktuell wird keine Bibliothek mehr angeboten.

Auch ich habe gerade mal nachgeschaut und eine Library dieses Namens auf dieser Seite unter "Old libraries for V1:" verlinkt gefunden.

Download-Link der ZIP-Datei.

Die Library kann bei mir sogar unter der IDE Version 1.6.4 völlig einwandfrei installiert werden.
Danach kann das Beispielprogramm "Key Grab v0.2" ebenfalls völlig einwandfrei geöffnet, kompiliert und hochgeladen werden.

Dabei handelt es sich um ein etwas gruseliges Programm, das auf flimmerndem Display die Nummer der gedrückten Taste anzeigt.

Sehr bescheiden und eher ein abschreckendes Beispiel für Programmierung, aber funktioniert im Prinzip.

DrDiettrich:
Die zusätzlichen Dateien liegen unter AppData\Local\Temp\build..., und zu jedem compilierten Sketch scheint so ein Verzeichnis angelegt zu werden. Die angehängte Datei enthält die angezeigten Meldungen, anscheinend aus mehreren Compiler-Läufen, auch aus einem Temp Verzeichnis.

Ich würde die IDE mal beenden, das Temp-Verzeichnis löschen und dann die IDE neu starten.

Und ansonsten müßtest Du bei der Entwicklung von Funktionen und C++-Klassen so vorgehen, dass Du diese erstmal in einem Arduino-Sketch entwickelst und testest. Und wenn die Funktionen und C++-Klassen dann im Sketch einwandfrei und narrensicher funktionieren, kannst Du dann die Deklarationen in eine .h Datei und den Code in eine .cpp Datei packen, als externe Library, die dann per #include eingebunden werden kann.

Hast Du auch schon mal versucht, den Sketch (unwesentlich) zu ändern und dann nochmal zu compilieren?

DrDiettrich:
Hast Du auch schon mal versucht, den Sketch (unwesentlich) zu ändern und dann nochmal zu compilieren?

OK, ich habe die bereits in den Windows-Papierkorb entsorgte Library also nochmal über "Wiederherstellen" aus dem Windows-Papierkorb gefischt, die IDE 1.6.4 nochmal neu gestartet, das Beispiel neu geladen und ein wenig abgeändert.

Ich habe mich dazu entschlossen, das an der Stelle völlig bescheuerte "lcd.clear();" im Beispielsketch auszukommentieren:

  if (localKey != SAMPLE_WAIT)
  {
//    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Current Key:");
    lcd.setCursor(0, 1);
    lcd.print(localKey);
  }

Ergebnis:
Der Beispielsketch läßt sich nach dieser kleinen Änderung genau so problemlos kompilieren und auf einen Arduino UNO mit LCD Keypad Sketch hochladen wie vorher.

Einziger Unterschied: Die LCD-Anzeige flimmert nicht mehr so dämlich wie vorher.

Also sind auch kleinere Änderungen kein Problem.

Vielleicht solltest Du auch auf die IDE Version 1.6.4 updaten?
Und die DFR_Key Library-Installation dann mit Hilfe der ZIP-Datei ruhig über die Funktion
"Sketch - Library - Add .ZIP library" machen.

Ich verwende bereits die 1.6.4, und hatte die schon im Verdacht. Vielleicht beißt sie sich ja auch mit der vorherigen Version, oder die Installation ist fehlerhaft. Als mir 59 Minuten Download für die MSI angedroht wurde, habe ich das ZIP heruntergeladen und ausgepackt. Vielleicht starte ich nochmal ganz von vorn...

DrDiettrich:
Ich verwende bereits die 1.6.4, und hatte die schon im Verdacht. Vielleicht beißt sie sich ja auch mit der vorherigen Version, oder die Installation ist fehlerhaft. Als mir 59 Minuten Download für die MSI angedroht wurde, habe ich das ZIP heruntergeladen und ausgepackt. Vielleicht starte ich nochmal ganz von vorn...

Wenn Du unter Windows verschiedene Versionen der IDE parallel installiert haben möchtest, so ist dass nur in diesem Fall problemlos möglich:

  • niemals die MSI Installer-Version installieren (falls vorhanden, löschen)
  • immer die ZIP-Version der IDE herunterladen, in ein unabhängiges Verzeichnis entpacken

Hallo,
ich nutze für das LCD KeyPad Shield immer die Standard LCD Lib und ein Funktion zum Auslesen der KeyPads.
Hier ein Beispiel mit Quellangaben

/*
  Modification of 
 LiquidCrystal Library - Hello World
 for LCD Keypad Shield (http://www.icstation.com/product_info.php?products_id=1471#.UrbSAqFK_LA)
 
 Demonstrates the use a 16x2 LCD display.  The LiquidCrystal
 library works with all LCD displays that are compatible with the 
 Hitachi HD44780 driver. There are many of them out there, and you
 can usually tell them by the 16-pin interface.
 
 This sketch prints "Hello World!" to the LCD
 and shows the time.
 
 The circuit for the shield:
 * LCD RS pin to digital pin 8
 * LCD Enable pin to digital pin 9
 * LCD D4 pin to digital pin 4
 * LCD D5 pin to digital pin 5
 * LCD D6 pin to digital pin 6
 * LCD D7 pin to digital pin 7
 * LCD R/W conencted to pin 11, but not used (to be checked)
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)
 
 Library originally added 18 Apr 2008
 by David A. Mellis
 library modified 5 Jul 2009
 by Limor Fried (http://www.ladyada.net)
 example added 9 Jul 2009
 by Tom Igoe
 modified 22 Nov 2010
 by Tom Igoe
 
 This example code is in the public domain.
 
 http://www.arduino.cc/en/Tutorial/LiquidCrystal
 */
// modified with content of the https://github.com/stanleyhuangyc/ArduinoOBD/tree/master/libraries/MultiLCD LCD4Bit_mod

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
#define BL 10
//Key message
char msgs[5][15] = {
  "Right Key OK ", 
  "Up Key OK    ", 
  "Down Key OK  ", 
  "Left Key OK  ", 
  "Select Key OK" };
int  adc_key_val[5] ={
  30, 150, 360, 535, 760 };
int NUM_KEYS = 5;
int adc_key_in;
int key=-1;
int oldkey=-1;

void setup() {
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  lcd.blink();
  // Print a message to the LCD.
  lcd.print("hello, world!");
  pinMode(BL,OUTPUT);   // for backlight control
  analogWrite(BL,199);   //
//  digitalWrite(BL, HIGH);}    // or switch
}

void loop() {
  adc_key_in = analogRead(0);    // read the value from the sensor  
  digitalWrite(13, HIGH);  
  key = get_key(adc_key_in);		        // convert into key press
  if (key != oldkey) {				    // if keypress is detected
    delay(50);		// wait for debounce time
    adc_key_in = analogRead(0);    // read the value from the sensor  
    key = get_key(adc_key_in);		        // convert into key press
    if (key != oldkey) {			
      oldkey = key;
      if (key >=0){
        lcd.setCursor(0, 0);  //
        lcd.print(msgs[key]);
      }  
    }
  }
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(0, 1);
  // print the number of seconds since reset:
  lcd.print(millis()/1000);
}

// Convert ADC value to key number
int get_key(unsigned int input)
{
  int k;
  for (k = 0; k < NUM_KEYS; k++)
  {
    if (input < adc_key_val[k])
    {
      return k;
    }
  }
  if (k >= NUM_KEYS)
    k = -1;     // No valid key pressed
  return k;
}

So langsam lichtet sich der Nebel :slight_smile:

Nachdem ich 3 überflüssige Dateien aus dem Sketch-Verzeichnis gelöscht habe, compiliert alles anstandslos. Eine Datei hatte einen völlig kaputten (non-ASCII) Namen, die beiden anderen waren Kopien der KeyGrab Bibliothek. Letzere wurden wohl von der IDE angelegt, als ich die Bibliotheksdateien in der IDE geöffnet habe :frowning: