AVR - LCD_2004, AM2320, DS3231
-
- 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
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....
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....
MFG
Michael Springwald
Michael Springwald
-
- Beiträge: 6194
- 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
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.
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.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- 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
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
Michael Springwald
-
- 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
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.
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.
-
- 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
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
Michael Springwald
-
- 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
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.
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.
-
- Beiträge: 6194
- 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
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
Mit Java und C/C++ sehe ich rot
-
- 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
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
Michael Springwald
-
- Beiträge: 6194
- 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
Ja bis zu 8 Adressen. Und wen du verschiedene Schieberegister hast, so wie ich es, sind sogar 16 möglich.ja, dass ist klar. Das kann man gut mit einem I2C Scanner von Arduino herausfinden. Ich glaube man kann die Sogar einstellen.
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
Mit Java und C/C++ sehe ich rot
-
- 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
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
Michael Springwald
-
- Beiträge: 6194
- 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
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
Mit Java und C/C++ sehe ich rot
-
- 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
Mit dem kleinen Sleep funktioniert auch der 2-Zeiler nicht.
Probiere doch mal in Zeile drei und Vier was zu schreiben.
MFG
Michael Springwald
Michael Springwald
-
- Beiträge: 6194
- 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
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
Mit Java und C/C++ sehe ich rot
-
- 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
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
Michael Springwald
-
- Beiträge: 6194
- 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
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.
Was ist der Grund, das man diesen Umweg machen muss ?
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
Mit Java und C/C++ sehe ich rot