AVR - LCD_2004, AM2320, DS3231

Vorstellungen von Programmen, welche mit Lazarus erstellt wurden.
pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

AVR - LCD_2004, AM2320, DS3231

Beitrag von pluto »

Hallo

In den letzten Tagen ist ein Programm für ein atMega328 bzw. ein Arduino Nano entstanden.

Das ist mein erstes Programm mit Lazarus für AVR. Neu für mich war direkt mit den einzelnen Modulen wie z.b. AM2320 zu Arbeiten. Am Ende hat es aber geklappt.

Vielleicht nützt es jemanden...

Ich hoffe in der Zip sind alle nötigen Dateien drin....

Ein erstes Foto(aber nicht aktuelle)
Ein erstes Foto(aber nicht aktuelle)

LCD2004Test.zip
Kleinen Fehler behoben
(138.66 KiB) 194-mal heruntergeladen
MFG
Michael Springwald

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: AVR - LCD_2004, AM2320, DS3231

Beitrag von Mathias »

Du schreibst, das nur 4-Zeilen LCD funktionieren, hat der 2-Zeiler mit dem original Code nicht funktioniert ?

So wie ich sehe, ist die grösste Änderung bei dir die Funktion SetCursor(); Oder hast du hier nur ein Überlaufschutz eingebaut ?
Und ein paar Sleep hat es noch gegeben.

Ich habe mir auch ein LCE2004 bestellt.

Wen ich diesen bekomme, werde ich gucken, das mein Code mit dem 2 und 4 Zeiler funktioniert.
Wen dann beide laufen werde ich mich hinter ein Tutorial machen. Das selbe mit den Sensoren wen ich sie in ca. 3 Wochen bekomme. :wink:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: AVR - LCD_2004, AM2320, DS3231

Beitrag von pluto »

Du schreibst, das nur 4-Zeilen LCD funktionieren, hat der 2-Zeiler mit dem original Code nicht funktioniert ?

Im Prinzip schon, aber nur mit 2 Zeilen und das mit dem Enabled passte nicht. Der Wert war einfach zu Kurz.
Ich musste nur ein wenig anpassen, dass könnte ich aber auch Dynamischer gestalten.... werde ich mal machen....

So wie ich sehe, ist die grösste Änderung bei dir die Funktion SetCursor(); Oder hast du hier nur ein Überlaufschutz eingebaut ?

Da habe ich NICHTS gemacht, ich wollte, aber das war jemand anders....

Und ein paar Sleep hat es noch gegeben.

Richtig, die sind auch wichtig.

Die größte Änderung habe ich hier gemacht:

Code: Alles auswählen

 
procedure TLCD.write4Bits(Value: byte);
const
  ENABLE_MASK: byte = $04;
 
  procedure Sleep;
  var
    i: Integer;
  begin
    for i := 1 to 1000 do asm nop end; // 450
  end;
 
begin
  TWIwriteByte(Device_Addr, Value or ENABLE_MASK or backlightStsMask);
  Sleep;
  TWIwriteByte(Device_Addr, (Value and not ENABLE_MASK) or backlightStsMask);
  Sleep;
end;
 

Der Enebaled PIn vom LCD muss für ca 450 Nanosekunden(Irgendwie so war es) auf High geschaltet sein, sonst ist es zu schnell.... größer kann er glaube ich aber durchaus sein.
Wichtig: Bei 450 geht es auch, aber 1000 ist besser, ich weiß jetzt nicht ob es Millisekunden sind oder wie auch immer, so klappt es jedenfalls recht gut.

Wen ich diesen bekomme, werde ich gucken, das mein Code mit dem 2 und 4 Zeiler funktioniert.

Meine Unit, basiert ja komplett auf DEIN Code, ich habe auch Create erweitert, wie du gesehen hast:
displayFunction:=LCD_4BITMODE or LCD_1LINE or LCD_5x8DOTS or LCD_2LINE;
das ist z.b. für ein 4 Zeilen LCD nötig....

Wen dann beide laufen werde ich mich hinter ein Tutorial machen. Das selbe mit den Sensoren wen ich sie in ca. 3 Wochen bekomme.

Bin gespannt... Dann würde es auch gleich ein Praktische Anwendung geben: Die Werte auf ein LCD anzeigen....
MFG
Michael Springwald

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: AVR - LCD_2004, AM2320, DS3231

Beitrag von Timm Thaler »

Ahhhh! Jetzt nimm Dir doch bitte mal Dein Tafelwerk raus und geh die Einheitenvorsätze nochmal durch.

Dein Arduino läuft mit 16MHz. Ein Takt, üblicherweise ein einfacher Befehl, dauert damit 1/16 Millionstel Sekunde. Das sind 0,0625usec* oder 62nsec. 450nsec sind also etwa 8 AVR Takte, oder 8 einfache Assemblerbefehle wie NOP. Eine for-Schleife von 0 bis 2 ist schon länger als 8 Takte.

Nun sprichst Du das Display aber über einen I2C Portexpander an. Ein I2C Bus läuft üblicherweise mit 100 bis 400kHz. Sprich ein Datenbit dauert 10 bis 2,5usec. 1! Datenbit. Um ein Byte zu übertragen brauchst Du also schon 80 bis 20usec, oder mindestens 20 000 nsec. Und dann werden immer mehrere Byte übertragen, Adressbyte und Start+Stop Kondition.

Die Datenübertragung für das Setzen der Ports dauert also um Größenordnungen länger als die nötige Enable-Zeit. Du kannst also problemlos das Enable sofort nach dem Setzen wieder abschalten.

Allerdings fällt mir was anderes auf. Die Displays übernehmen üblicherweise die Daten sofort nach dem Anlegen des Enable. Das heisst aber auch, die Daten müssen beim Setzen des Enable sicher am Port anliegen und dann noch für mindestens 450nsec weiter anliegen.

Richtig wäre es eigentlich so: Daten senden, Daten und Enable high senden, Daten löschen und Enable low.

Wenn ich am WE zurück bin, kann ich eine funktionierende Routine posten.



*) u steht für Mikro, ich hab kein my Zeichen auf der Tablet Tastatur.

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: AVR - LCD_2004, AM2320, DS3231

Beitrag von pluto »

Dein Arduino läuft mit 16MHz. Ein Takt, üblicherweise ein einfacher Befehl, dauert damit 1/16 Millionstel Sekunde. Das sind 0,0625usec* oder 62nsec. 450nsec sind also etwa 8 AVR Takte, oder 8 einfache Assemblerbefehle wie NOP. Eine for-Schleife von 0 bis 2 ist schon länger als 8 Takte.

Wenn ich deine Aussage richtig verstehe: Wäre eine for schleife bis 1000 schon viel zu lange - eigentlich. Aber damit geht es. Werte unter 450 gehen nicht bzw. sind nicht "stabil".

Dazu habe ich eine passende Geschichte:
Im Verein ist jemand dabei ein altes 3KV Netzteil zu Reparieren. Dort wurde ebenfalls ein 2004 verbaut. Das Problem: Das es ging ist reiner Zufall. Laut Datenblatt und Analyse das Signals dürfte es nicht gehen. Jedenfalls war das alte Display Kaputt. Es wurde ein neues gekauft. Problem: Das neue reagierte anders als das "alte".... Lösung: Das Signal musste verlangsamt werden. Es ging hier um das Enabled Signal. Das Display hatte nicht genügend Zeit darauf zu reagieren.

Die Datenübertragung für das Setzen der Ports dauert also um Größenordnungen länger als die nötige Enable-Zeit. Du kannst also problemlos das Enable sofort nach dem Setzen wieder abschalten.

Tatsache ist jedoch: wenn ich das gemacht habe, kamen nur schmierzeichen am LCD an. und auch das setzten vom Cursor klappte nicht.
Erst als ich die for schleife auf ein wert über 450 gesetzt hat, klappte es. Es kann gut sein, dass der Eigentliche Fehler wo anders liegt...
Mit meiner Lösung klappt es jedoch recht gut und läuft Stabil.

Allerdings fällt mir was anderes auf. Die Displays übernehmen üblicherweise die Daten sofort nach dem Anlegen des Enable. Das heisst aber auch, die Daten müssen beim Setzen des Enable sicher am Port anliegen und dann noch für mindestens 450nsec weiter anliegen.

Genau. Aber nur wenn der Enabled Pin für eine Gewisse Zeit anliegt.

Wenn ich am WE zurück bin, kann ich eine funktionierende Routine posten.

Bin gespannt. Meine klappt ja soweit....
MFG
Michael Springwald

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: AVR - LCD_2004, AM2320, DS3231

Beitrag von Timm Thaler »

Nein, Du legst mit dem ersten TWIwrite das Enable gleichzeitig mit den Daten an. Die Daten müssen aber beim Enable bereits sicher anliegen, das kannst Du so nicht gewährleisten.

Ich vermute, beim gleichzeitigen Anlegen der Daten mit Enable liest das Enable die noch nicht stabilen Daten falsch ein. Da aber beim Disable die Daten weiter anliegen, liest das nächste Enable die vorherigen Daten dann richtig ein.

Ist aber nur eine Vermutung, ich schau mir das am WE nochmal an.

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: AVR - LCD_2004, AM2320, DS3231

Beitrag von Mathias »

Ich habe mir auch ein LCE2004 bestellt.

Ich habe heute das LCD bekommen.

Ich musste dies auch anpassen, ich weis nicht, wieso ich so einen kleinen wert bei Sleep eingetragen hatte.

Noch etwas wichtiges, mein LCD hat nicht die I²C Adresse $3F, sondern $27. Das liegt daran, das es verschiedene Steuerplatinen gibt, obwohl sie gleich aussehen. Aber es sind verschiedene Schieberegister verbaut, der kleiner Unterschied macht das "A".
PCF8574AT und PCF8574T


Code: Alles auswählen

procedure TLCD.write4Bits(Value: byte);
const
  ENABLE_MASK: byte = $04;
 
  procedure Sleep;
  var
    i: Integer;
  begin
    for i := 1 to 1000 do asm nop end; // 450
  end;
 
begin
  TWIwriteByte(Device_Addr, Value or ENABLE_MASK or backlightStsMask);
  Sleep;
  TWIwriteByte(Device_Addr, (Value and not ENABLE_MASK) or backlightStsMask);
  Sleep;
end;


PS: Das ich jetzt 2 unterschiedliche LCD habe, kann ich beide parallel betreiben, mit dem Object kein Problem.

Code: Alles auswählen

  Mylcd2.Create($3F);
  Mylcd2.Clear;
 
  Mylcd2.setCursor(0, 0);
  Mylcd2.Write('Hello LCD klein ! ');
  Mylcd2.setCursor(0, 1);
  Mylcd2.Write('Hello World !');
 
 
  Mylcd4.Create($27);
  Mylcd4.Clear;
  Mylcd4.createChar(3, herz);
 
  Mylcd4.cursor(True);
  Mylcd4.blink(True);
 
  Mylcd4.setCursor(0, 0);
  Mylcd4.Write(#3 + ' Hello LCD gross ! ' + #3);
  Mylcd4.setCursor(0, 1);
  Mylcd4.Write('Hello World !');
  Mylcd4.setCursor(0, 2);
  Mylcd4.Write('Hello Lazarus !');
  Mylcd4.setCursor(0, 3);
  Mylcd4.Write('Hello AVR !');
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: AVR - LCD_2004, AM2320, DS3231

Beitrag von pluto »

Noch etwas wichtiges, mein LCD hat nicht die I²C Adresse $3F, sondern $27. Das liegt daran, das es verschiedene Steuerplatinen gibt, obwohl sie gleich aussehen. Aber es sind verschiedene Schieberegister verbaut, der kleiner Unterschied macht das "A".

ja, dass ist klar. Das kann man gut mit einem I2C Scanner von Arduino herausfinden. Ich glaube man kann die Sogar einstellen.

Edit:
PS: Das ich jetzt 2 unterschiedliche LCD habe, kann ich beide parallel betreiben, mit dem Object kein Problem.

Müsste ich auch noch mal testen, habe aber nur die 2004 LCD'S .... aber dafür ein paar mehr...
MFG
Michael Springwald

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: AVR - LCD_2004, AM2320, DS3231

Beitrag von Mathias »

ja, dass ist klar. Das kann man gut mit einem I2C Scanner von Arduino herausfinden. Ich glaube man kann die Sogar einstellen.
Ja bis zu 8 Adressen. Und wen du verschiedene Schieberegister hast, so wie ich es, sind sogar 16 möglich.

Die Adresse einstellen, kann man mit den Lötpunkten, welche von 1-3 durchnummeriert sind.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: AVR - LCD_2004, AM2320, DS3231

Beitrag von pluto »

Die Adresse einstellen, kann man mit den Lötpunkten, welche von 1-3 durchnummeriert sind.

Hast du jetzt deine Klasse erweitert? Das es auch mit einem 2004 geht?
MFG
Michael Springwald

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: AVR - LCD_2004, AM2320, DS3231

Beitrag von Mathias »

Hast du jetzt deine Klasse erweitert? Das es auch mit einem 2004 geht?

Ausser dem Sleep habe ich nichts geändert. Die 4 Zeilen habe auf Anhieb funktioniert..
Mit dem kleinen Sleep funktioniert auch der 2-Zeiler nicht.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: AVR - LCD_2004, AM2320, DS3231

Beitrag von pluto »

Mit dem kleinen Sleep funktioniert auch der 2-Zeiler nicht.

Probiere doch mal in Zeile drei und Vier was zu schreiben.
MFG
Michael Springwald

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: AVR - LCD_2004, AM2320, DS3231

Beitrag von Mathias »

Habe ich gemacht, hast du mein Post writer oben mit den 2 lcd nicht gesehen ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: AVR - LCD_2004, AM2320, DS3231

Beitrag von pluto »

Habe ich gemacht, hast du mein Post writer oben mit den 2 lcd nicht gesehen ?

OK. Dann teste ich noch mal deine Version und ändere nur den sleep... vielleicht war das das Problem oder die fehlenden PullUp Widerstände.
Ich habe das Create geändert und ein paar Zeilen hinzugefügt... vielleicht braucht man das gar nicht....
MFG
Michael Springwald

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: AVR - LCD_2004, AM2320, DS3231

Beitrag von Mathias »

Ich habe mir gerade die Sourcen von einem Arduino-Code für den DS3231 angeguckt.
Dort wird mit folgenden Fuctionen die Zeit-Werte vor dem schreiben und lesen in den DS3231 umgewandelt.

Code: Alles auswählen

static uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); }
static uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); }


Was ist der Grund, das man diesen Umweg machen muss ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten