Wie ein LCD ansteuern ; LMC 1602 I2C ; Tutorial ; Sketch

Halli Hallo,

ich habe jetzt über 2 Stunden das Web nach Tutorien zum Ansteuern eines LCD's über I2C gesucht - leider vergebens ! :frowning:

Ich besitze ein LCD LCM 1602 I2C von YwRobot.

Ich habe jetzt zwar gefunden, wie es angeschlossen wird und dass die Pins A4/A5 zur Kommunikation genutzt werden, jedoch immer noch kein Tutorial oder eine Erklärung! :frowning:

Vielleicht kann mir ja jemand helfen, oder weiß, wo es ein Tutorial dazu gibt!

Vielen Dank schonmal! :slight_smile:

Liebe Grüße
Aljoscha

Hallo,

ich weis nicht wonach Du gesucht hast, dass hier war fix gefunden. Library mit Beispielen ist vorhanden.

http://www.exp-tech.de/Displays/I2C-LCD-1602-Module.html?XTCsid=8eca025f8ef32f57b0e421b6a4551f62

Zunächst SCL und SDA verbinden über ein Pullup wiederstand falls der nicht schon integriert ist.
Dann musst du dir zunächst mal die LiquidCrystal_I2C lib besorgen und installieren.
Als nächstes musst du rauskriegen mit welcher Adresse das Display angesprochen wird.

Und das LCD einfach über die lib ansprechen.

Habe da mal was gefunden:
http://www.ictcool.com/2013/08/11/how-to-configure-i2c-module-with-lcd-1602-and-arduino-uno/

MfG.
Addi :wink:

Wie Du hier:

http://arduino-info.wikispaces.com/LCD-Blue-I2C

lesen kannst, gibt es von diesem Display mindestens 3 verschiedene Versionen, die unterschiedlich angesteuert werden müssen.

Dies zeigt einmal mehr, wie wichtig es ist, dass Du bei einem Post immer Links zur verwendeten Hardware angibst. Ansonsten bekommst Du unter Umständen Hilfestellung für ein anderes Display, was in gewissen Fällen sogar zur Beschädigung der Hardware führen kann. Auf oben verlinkter Seite ist auch erklärt, wie man herausfindet, welche Version (falls es eine der dort erwähnten drei ist) man hat.

Die aufgewiesenen Seiten hatte ich schon gefunden, aber leider werde ich nicht wirklich schlau daraus. :frowning:

http://arduino-info.wikispaces.com/LCD-Blue-I2C#v1

Da stehen dann Beispielsketche für das LCD!

/* YourDuino.com Example Software Sketch
 16 character 2 line I2C Display
 Backpack Interface labelled "YwRobot Arduino LCM1602 IIC V1"
 terry@yourduino.com */

/*-----( Import needed libraries )-----*/
#include <Wire.h>  // Comes with Arduino IDE
// Get the LCD I2C Library here: 
// https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads
// Move any other LCD libraries to another folder or delete them
// See Library "Docs" folder for possible commands etc.
#include <LiquidCrystal_I2C.h>

/*-----( Declare Constants )-----*/
/*-----( Declare objects )-----*/
// set the LCD address to 0x27 for a 20 chars 4 line display
// Set the pins on the I2C chip used for LCD connections:
//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

/*-----( Declare Variables )-----*/
//NONE

void setup()   /*----( SETUP: RUNS ONCE )----*/
{
  Serial.begin(9600);  // Used to type in characters

  lcd.begin(16,2);   // initialize the lcd for 16 chars 2 lines, turn on backlight

// ------- Quick 3 blinks of backlight  -------------
  for(int i = 0; i< 3; i++)
  {
    lcd.backlight();
    delay(250);
    lcd.noBacklight();
    delay(250);
  }
  lcd.backlight(); // finish with backlight on  

//-------- Write characters on the display ------------------
// NOTE: Cursor Position: (CHAR, LINE) start at 0  
  lcd.setCursor(0,0); //Start at character 4 on line 0
  lcd.print("Hello, world!");
  delay(1000);
  lcd.setCursor(0,1);
  lcd.print("HI!YourDuino.com");
  delay(8000);  

// Wait and then tell user they can start the Serial Monitor and type in characters to
// Display. (Set Serial Monitor option to "No Line Ending")
  lcd.clear();
  lcd.setCursor(0,0); //Start at character 0 on line 0
  lcd.print("Use Serial Mon");
  lcd.setCursor(0,1);
  lcd.print("Type to display");  


}/*--(end setup )---*/


void loop()   /*----( LOOP: RUNS CONSTANTLY )----*/
{
  {
    // when characters arrive over the serial port...
    if (Serial.available()) {
      // wait a bit for the entire message to arrive
      delay(100);
      // clear the screen
      lcd.clear();
      // read all the available characters
      while (Serial.available() > 0) {
        // display each character to the LCD
        lcd.write(Serial.read());
      }
    }
  }

}/* --(end main loop )-- */


/* ( THE END ) */

Wenn ich ihn aber kompilieren will, kommt ne Fehlermeldung:

"sketch_apr15a:19: error: 'POSITIVE' was not declared in this scope"

Ich habe dieses LCD bei Amazon bestellt:

Ich bin aber der Meinung, auf der Rückseite ein "V3" lesen zu können, habe eine Foto angehangen.
Nur zur version 3 finde ich keine Beispiele. :frowning:
Laut Amazons Verkäuferangabe wird es mit 0 x 27 addressiert.

#################################################

EDIT: Habe doch noch was gefunden : http://forum.arduino.cc/index.php/topic,128635.0.html

Habe es jetzt mal hinbekommen, dass das LCD mir was anzeigt, was ich schreibe. Werde jetzt damit mal ausprobieren, wie weit ich damit komme! :slight_smile:

Leider komme ich aber nicht dahinter, wie ich eine beschriebene Zeile wieder richtig überschreibe. :fearful:

Hier mein Sketch!

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

#define I2C_ADDR    0x27                          // <<----- Add your address here.  Find it from I2C Scanner
#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7


LiquidCrystal_I2C	lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);


int Echo = 12 ;
int Trigger = 11 ;

int Abstand ;
int Zeit ;

void setup()
{ 
  
  Serial.begin (9600) ;
  
  
  lcd.begin (16,2); //  <<----- My LCD was 16x2

  
  // Switch on the backlight
  lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.home (); // go home

  pinMode (Echo, INPUT) ;
  pinMode (Trigger, OUTPUT) ;
  
  lcd.setCursor (0,0); 
  lcd.print("Objektabstand");


   
}

void loop()
{ 
  digitalWrite (Trigger, LOW) ;
  delayMicroseconds (2) ;
  digitalWrite (Trigger, HIGH) ;
  delayMicroseconds (5) ;
  digitalWrite (Trigger, LOW) ;
  
  Zeit = pulseIn (Echo, HIGH) ;
  
  Abstand /* in mm */ = (Zeit * 0.343) / 2 ;

  lcd.setCursor (0,1); 
  lcd.print(Abstand);
  
  
  Serial.println (Abstand) ;
  
  
  delay (300) ;
  

}

Wenn der Ultraschallsensor jetzt 3000 mm misst, ich diese am LCD anzeigen lasse und dann 50 mm messe, bleiben die 2 letzten Nullen der 3000 mm aber trotzdem stehen. Es werden dann immer nur die ersten beiden Stellen geändert, messe ich dann wieder eine 3-stellige Zahl bleibt die letze Null der 3000 mm unverändert stehen. :disappointed_relieved: :disappointed_relieved:

Leider komme ich aber nicht dahinter, wie ich eine beschriebene Zeile wieder richtig überschreibe. smiley-eek-blue

Hänge doch einfach an das lcd.print(Abstand) folgendes an:

lcd.print("     ");

Kannst auch einfach lcd.clear() machen ;).
Das löscht einfach jedes Zeichen.

lcd.clear() ist aber auch sehr langsam. Besser man löscht nur das was man wirklich muss.

Die beste Methode ist man schreibt erst mal den neuen Wert drüber und berechnet dann die Differenz in der Länge zwischen der alten und der neuen Zeile. Dann überschreibt man den Rest mit Leerzeichen. Das produziert am wenigsten Flackern.

lcd.clear() habe ich schon versucht, aber dann beschreibt er die obere Zeile in der "Objektabstand" stehen soll, irgendwie nicht mehr und ja, es flackert mehr.

kann man nicht eine bestimmt Zeile löschen? hab was von dem Befehl "lcd.clearLine()" gelesen, aber das funktioniert mit der library oder meinem display irgendwie nicht, dann meckert er.

Aber momentan ist die Variante, die anderen Zeichen mit Leerzeichen zu überschreiben, vielleicht ausreichend.
Dankeschön schonmal! :slight_smile:

Du machst setCursor() auf die Zeile/Spalte und schreibst dann Leerzeichen über den Teil den du Löschen willst. Das ist Standard. Du kannst dir natürlich auch selbst eine Funktion dafür schreiben. Das ist keine große Sache. Eine fertige Funktion würde es auch nicht anders machen, der der Controller keine Befehle hat um Zeichen oder Zeilen zu löschen.

Oder du schreibst einfach anderen Text drüber, wenn nur ein Wert aktualisiert werden soll.

Ich habe das ganze jetzt mal so umgeschrieben!
Falls das nicht gut geschrieben, oder umständlich ist, bin ich für Kritik dankbar! :slight_smile:

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

#define I2C_ADDR    0x27                         
#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7


LiquidCrystal_I2C	lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

// Variablendeklaration

int Echo = 12 ;
int Trigger = 11 ;

int Abstand ;
int Zeit ;

int Starttaster = 10 ;

int Schalterzustand = 0 ;
int Schalterzustand_old = 0 ;
int Start = 0 ;

int interval = 500 ;
int previous_millis = 0 ;

void setup()
{ 
  
  Serial.begin (9600) ;
  
  
  lcd.begin (16,2); 

  
  // Beleuchtung des Displays einschalten
  
  lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.home (); // go home

  pinMode (Echo, INPUT) ;
  pinMode (Trigger, OUTPUT) ;
  



   
}

void loop()
{ 
  
  // Kontrolle ob Änderung des Eingangs
  
  Schalterzustand = digitalRead (Starttaster) ;
  
  if ((Schalterzustand == 1) && (Schalterzustand_old == 0))
    {
      Start = 1 - Start ;
      delay (30) ;
    }
  
  // Messung starten
  
  if (Start ==1)
    {
      
      digitalWrite (Trigger, LOW) ;
      delayMicroseconds (2) ;
      digitalWrite (Trigger, HIGH) ;
      delayMicroseconds (5) ;
      digitalWrite (Trigger, LOW) ;
  
      Zeit = pulseIn (Echo, HIGH) ;
       
      // Abstandswert in mm berechnen
      
      Abstand = (Zeit * 0.343) / 2 ;
      
      lcd.setCursor (0,0); 
      lcd.print("Abstand in mm");
      
      // Wert auf LCD alle 500 ms aktualisieren
      
      if ((millis() - previous_millis >= interval))
        {
          previous_millis = millis() ;
          
          lcd.setCursor (0,1); 
          lcd.print("               ");

          
          lcd.setCursor (0,1); 
          lcd.print(Abstand);
          
          Serial.println (Abstand) ;
          
        }


    }
    
  else
    {

      lcd.setCursor (0,0) ;
      lcd.print ("Fuer Messung                 ") ;
      lcd.setCursor (0,1) ;
      lcd.print ("Start druecken               ") ;
    }
    
  Schalterzustand_old = Schalterzustand ;
  

}

Das ganze funktioniert auch, jedoch fängt das Display nach ca. 40 Sekunden an zu flackern und die Werte ändern sich viel schneller, als sie sollten. Habe mal ein Video angehangen!

IMG_0136.avi (1.97 MB)

int previous_millis

Es sind nicht 40 sekunden sondern 32,7 !

aaaaaaaaaaaaaaah :smiley: ich müsste da eine long variable nehmen ?!?!?! :smiley: :fearful: :blush:

unsigned long. Mit long verschwendest du wieder die Hälfte des Wertebereichs für negative Zahlen die du nicht hast.

Ähm ja richtig, meinte ich ja auch :slight_smile:

Unsigend long kann keine negativen, aber daüfr das doppelte im positiven zahlenbereich.
und hier brauche ich ja keine negativen zahlen ! :slight_smile:

Vielen Dank mal an dieser Stell, bin jetzt schon nen schönen Schritt weiter! :slight_smile:

Aber abgesehn davon, dass ich die Bibliotheken einbinden muss, habe ich das hier noch nicht ganz verstanden! :blush: :blush:

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

#define I2C_ADDR 0x27
#define BACKLIGHT_PIN 3
#define En_pin 2
#define Rw_pin 1
#define Rs_pin 0
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7

LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

Kann mir das vielleicht mal jemand erklären? :blush: :blush:

Du definierst da ein Objekt namens lcd vom Typ LiquidCrystal_I2C.
Dieser Typ ist in der Library ( #include <LiquidCrystal_I2C.h> ) definiert.
Zum Erzeugen eines solchen Objekts gibst du ihm an, wie es per I2C adressiert wird ( 0x27 ) und wie die Verbindungen zwischen dem I2C-Device und dem eigentlichen Display sind.

Ob es andere Möglichkeiten gibt ( für fertige I2C-Display - Kombinationen ), müsstest du in LiquidCrystal_I2C.h nachlesen ...

Das lcd - Objekt kann bestimmte Sachen machen, die als Funktionen z.B. so aufgerufen werden: lcd.clear( ) ;
( welche Funktionen (auch Methoden genannt) das sind, und was für Parameter die brauchen, siehst du auch in LiquidCrystal_I2C.h , nach der Zeile public: )

Ich bin mir da nicht sicher, korrigiert mich da bitte falls ich falsch liege,
aber ich denke, dass dieses LCD Display einfach ein ganz normales LCD ist, wo einfach bloß ein I2C Portexpander
(oder sowas in der Art) dran ist.

Wenn das so ist, dann lässt sich das auch ganz einfach erklären, warum du diese Variablen definieren und übergeben musst.
Damit sagst du der Lib dann quasie welcher Expander Input/Output Pin mit welchem Eingang/Ausgang des LCD verbunden ist, damit sie weiß wie das gesammte Teil angesprochen werden muss.

Ich bin mir da nicht sicher, korrigiert mich da bitte falls ich falsch liege,
aber ich denke, dass dieses LCD Display einfach ein ganz normales LCD ist, wo einfach bloß ein I2C Portexpander
(oder sowas in der Art) dran ist.

Das ist genau so. Da aber die Verdrahtung vom I2C Portexpander zum Display von Modul zu Modul etwas unterschiedlich gehandhabt wird, hat der Bibliotheksprogrammierer einfach diese Art der Festlegung gewählt. Man muss dann für das eigene Modul herausfinden (gut wenn der Verkäufer auch ein Datenblatt bereithält), welcher Ausgang des I2C Portexpanders auf welchen Display-Pin geht.