Hallo liebe Gemeinde,
bei meinem aktuellen Projekt geht es darum, ein Display (4x20) mit
I2C-Anschluß mit einem Arduino Nano zu verbinden. Für mich geht es bei
diesem Projekt um einen Einblick in die Abläufe zum Ansprechen eines
Displays. Es ist ein Teilprojekt und später soll dieses Display durch
ein DOGM128x64 ersetzt werden.
Das Display habe ich von Aliexpress
(http://www.aliexpress.com/snapshot/6049640235.html) und funktioniert
über I2C, wenn ich über die Arduino-IDE gehe und es mit einem Sketch
anspreche.
Mein Problem ist, das es unter dem Atmel Studio 6.1.2730-SP2 nicht geht.
Anbei habe ich die Dateien, die ich verwendet habe, angefügt.
Ausgangspunkt ist die Seite von Nico Eichelmann, Thomas Eichelmann
(http://computerheld.de/i2clcd/), von welchen ich die Files habe.
Die Anschlüsse SCL und SCA vom Arduino Nano habe wie folgt verwendet:
SCL = A5 (PC5)
SCA = A4 (PC4)
Meine Vermutung ist, das ich in den Files (wo auch immer), ich die
beiden Anschlüsse SCL und SCA nirgends definieren konnte. Zumindest habe
ich nirgends eine Definition dazu gefunden (ich kann aber auch Blind
sein).
Die Compelierung läuft ohne Fehler:
------ Build started: Project: Display-Test (6.1), Configuration: Debug
AVR ------
Build started.
Project "Display-Test (6.1).cproj" (default targets):
Target "PreBuildEvent" skipped, due to false condition;
('$(PreBuildEvent)'!='') was evaluated as (''!='').
Target "CoreBuild" in file "C:\Program Files\Atmel\Atmel Studio
6.1\Vs\Compiler.targets" from project "C:\Users\XXXX\Documents\Atmel
Studio\6.1\Display-Test (6.1)\Display-Test (6.1)\Display-Test
(6.1).cproj" (target "Build" depends on it):
Task "RunCompilerTask"
C:\Program Files\Atmel\Atmel Studio 6.1\shellUtils\make.exe all
make: Nothing to be done for `all'.
Done executing task "RunCompilerTask".
Task "RunOutputFileVerifyTask"
Program Memory Usage : 740 bytes 2,3 % Full
Data Memory Usage : 10 bytes 0,5 % Full
Done executing task "RunOutputFileVerifyTask".
Done building target "CoreBuild" in project "Display-Test (6.1).cproj".
Target "PostBuildEvent" skipped, due to false condition;
('$(PostBuildEvent)' != '') was evaluated as ('' != '').
Target "Build" in file "C:\Program Files\Atmel\Atmel Studio
6.1\Vs\Avr.common.targets" from project "C:\Users\XXXX\Documents\Atmel
Studio\6.1\Display-Test (6.1)\Display-Test (6.1)\Display-Test
(6.1).cproj" (entry point):
Done building target "Build" in project "Display-Test (6.1).cproj".
Done building project "Display-Test (6.1).cproj".
Build succeeded.
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped
==========
Die Übertragung auf den Nano verlief ohne Probleme. Wie auch bisher,
habe ich F5 (Start Debugging) verwendet, so wie ich auch bisher meine
Übertragungen gemacht hatte, wo auch die Testprogramme liefen. Ich
verwende das Atmel Studio so wie es installiert wurde, ohne irgendwelche
Extras oder Erweiterungen.
Meine Anzeige jedoch zeigt nur den in der ersten und dritten Zeile
jeweils ausgefüllte Zeichen an. Kontrast passt.
Ich stehe vor einem Rätsel. Okay, ich bin jetzt nicht die super
Informatikerin, aber es sollte mehr zu sehen sein als das. Wichtig ist
mir, das ich nicht die Arduino-IDE verwenden will, sondern später
komplett in C++ schreiben möchte. Das hängt mit den zukünftigen
Projekten zusammen. Mir ist bewusst, das C nicht gleich C++ ist und ich
hier in C schreibe. Für mich soll dies ein Anfang sein, um das eine oder
andere zu verstehen.
Es wäre schön, wenn sich jemand dies mal anschaut und mir sagen kann,
was ich falsch gemacht habe und wie es richtig sein soll/muss. Ich bin
sicher, das es nur etwas banales sein kann.
Alles liebe,
Sarah
> Ich stehe vor einem Rätsel.
Du rufst nirgends i2c_init() auf
> Meine Vermutung ist, das ich in den Files (wo auch immer), ich> die beiden Anschlüsse SCL und SCA nirgends definieren konnte.
Die kannst und brauchst du auch nicht definieren. Das ist Hardware-TWI
und als solches fix an bestimmte Pins gebunden. Da kannst du sowieso
nicht aus.
Servus Karl Heiz,
Karl Heinz schrieb:>> Du rufst nirgends i2c_init() auf>
Stimmt. Habe jetzt in der Display-Test.c vor der Initialisierung des LCD
die Initialisierung der I2C gesetzt:
1
...
2
intmain(void)
3
{
4
i2c_init();//- I2C initialization
5
lcd_init();//- Display initialization
6
...
Ergebnis bleibt aber das selbe. Das Display zeigt nichts an, ausser die
beiden Zeilen mit den gefüllten Feldern.
>> Die kannst und brauchst du auch nicht definieren. Das ist Hardware-TWI> und als solches fix an bestimmte Pins gebunden. Da kannst du sowieso> nicht aus.
Das klingt super, denn dann habe ich den Vorteil für später, wenn das
DOGM128 dran kommt. Spart ne Menge an Zeit und Kapazität.
Laut dem Datenblatt von Atmel sind an diesen Pins SCL und SCA
rausgeführt, welche ja an A4 und A5 beim Nano sind. Sollte also passen.
dir ist aber schon klar, dass diese Angabe hier sich nicht bei der
Compilierung von twimaster.c auswirken wird?
In twimaster.c steht:
1
/* define CPU frequency in Mhz here if not defined in Makefile */
2
#ifndef F_CPU
3
#define F_CPU 4000000UL
4
#endif
d.h. dort wird mit 4 Mhz gerechnet.
Schmeiss aus allen C Files zumindest die #ifndef raus. Aus
1
...
2
/* define CPU frequency in Mhz here if not defined in Makefile */
3
#ifndef F_CPU
4
#define F_CPU 4000000UL
5
#endif
6
...
wird dann
1
...
2
#define F_CPU 4000000UL
3
...
Noch besser wäre es, F_CPU projektübergreifend in den Projekt-Settings
zu definieren. Dann hat man die Gewissheit, dass in allen C Files mit
dem gleichen Wert gerechnet wird. Aber diese 'Absicherung' mit einem
#ifndef und Annahme eines Default Wertes erweits sich immer öfter zum
Boomerang. Wenn F_CPU nicht definiert ist, dann sollte man das als
Fehler werten und nicht irgendeinen windigen Default annehmen. Vor allen
Dingen dann nicht, wenn dieser Default dann auch noch kleiner als die
Realität ist, und damit alle Warteschleifen zu kurz berechnet werden.
Ebenfalls:
Gib dem LCD nach dem Anlegen der SPannung mal etwas Zeit. Sprich: mach
am Anfang in main() eine kleine Wartezeit rein, bis du das LCD das erste
mal ansprichst. Größenordnung: so 50 bis 100ms
Puh, das sind ja gleich drei Beiträge auf einmal, das geht nun wirklich
nicht - doch mit Kinderüberraschung * ggggg *
Okay, ich habe mir das jetzt mal durchgelesen.
Karl Heinz schrieb:> Display-Test.c>
1
>#defineF_CPU16000000
2
>
>> dir ist aber schon klar, dass diese Angabe hier sich nicht bei der> Compilierung von twimaster.c auswirken wird?>
Stimmt, da sich der Compiler bei jeder .c neu sortiert. Ich habe im
twimaster.c das auf 16MHz geändert. Verändert aber an der Situation
nichts.
> Schmeiss aus allen C Files zumindest die #ifndef raus.
Bis auf die i2clcd.h habe ich das machen können. Wenn ich das in der
i2clcd.h mache, meldet er, das es bereit Deklariert wurde in der
Display-Test.c Habe das in der Datei ausgeklammert, da ja bereits
definiert.
> Ebenfalls:> Gib dem LCD nach dem Anlegen der SPannung mal etwas Zeit. Sprich: mach> am Anfang in main() eine kleine Wartezeit rein, bis du das LCD das erste> mal ansprichst. Größenordnung: so 50 bis 100ms
Gemacht, habe ich auf 1000ms gesetzt per delay.h
>> die LCD Adresse kann nicht 0x27 sein.>
Doch, leider. In der Arduino-IDE, wo ich das bisher ausprobiert hatte,
wollte er mit 0x20 nicht, sondern erst als ich auf 0x27 umgestellt
hatte.
>> Probier mal 0x4E>
1
>#defineLCD_I2C_DEVICE0x4E
2
>
> oder (was dasselbe ist)>
1
>#defineLCD_I2C_DEVICE(0x27<<1)
2
>
>>> Also auch mal 0x20 bzw. 0x40 als Adresse ausprobieren.>
Auch ausprobiert, wie immer ohne Erfolg. Auch hatte ich noch mal
versucht, auf 0x20 oder 0x40zu setzten - Fehlanzeige.
>> Welcher Sketch?>
Diesen hier (Arduino-IDE), inkl. der aktuellen LiquidCrystal_I2C.h:
// Move any other LCD libraries to another folder or delete them
11
// See Library "Docs" folder for possible commands etc.
12
#include<LiquidCrystal_I2C.h>
13
/*-----( Declare Constants )-----*/
14
//none
15
/*-----( Declare objects )-----*/
16
// set the LCD address to 0x27 for a 20 chars 4 line display
17
// Set the pins on the I2C chip used for LCD connections:
18
// addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
19
LiquidCrystal_I2Clcd(0x27,2,1,0,4,5,6,7,3,POSITIVE);// Set the LCD I2C address
20
21
22
/*-----( Declare Variables )-----*/
23
//none
24
25
voidsetup()/*----( SETUP: RUNS ONCE )----*/
26
{
27
Serial.begin(9600);// Used to type in characters
28
29
lcd.begin(20,4);// initialize the lcd for 20 chars 4 lines and turn on backlight
30
31
// ------- Quick 3 blinks of backlight -------------
32
for(inti=0;i<3;i++)
33
{
34
lcd.backlight();
35
delay(250);
36
lcd.noBacklight();
37
delay(250);
38
}
39
lcd.backlight();// finish with backlight on
40
41
//-------- Write characters on the display ----------------
42
// NOTE: Cursor Position: CHAR, LINE) start at 0
43
lcd.setCursor(3,0);//Start at character 4 on line 0
44
lcd.print("Hello, world!");
45
delay(1000);
46
lcd.setCursor(2,1);
47
lcd.print("From YourDuino");
48
delay(1000);
49
lcd.setCursor(0,2);
50
lcd.print("20 by 4 Line Display");
51
lcd.setCursor(0,3);
52
delay(2000);
53
lcd.print("http://YourDuino.com");
54
delay(8000);
55
// Wait and then tell user they can start the Serial Monitor and type in characters to
56
// Display. (Set Serial Monitor option to "No Line Ending")
57
lcd.setCursor(0,0);//Start at character 0 on line 0
58
lcd.print("Start Serial Monitor");
59
lcd.setCursor(0,1);
60
lcd.print("Type chars 2 display");
61
62
63
}/*--(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 ) */
>> Denn hier> http://www.aliexpress.com/snapshot/6049640235.html>
Das ist kein Sketch, sondern das Display, was ich erworben habe. Auch
wenn dort etwas von 0x20 steht, so habe ich es nur mit der 0x27 zum
laufen bekommen. Habe es eben noch einmal verifiziert mit das Arduino
Nano.
Sarah S. schrieb:>> die LCD Adresse kann nicht 0x27 sein.>>>> Doch, leider.
Ich hab mich schlecht ausgedrückt.
> In der Arduino-IDE, wo ich das bisher ausprobiert hatte,> wollte er mit 0x20 nicht, sondern erst als ich auf 0x27 umgestellt> hatte.
Ist ok.
In der Arduino LIb gibst du die Adresse so an.
Auf dem I2C Bus wird die Adresse aber so kodiert
1
Bit 7 6 5 4 3 2 1 0
2
+--+--+--+--+--+--+--+--+
3
| | | | | | | | |
4
+--+--+--+--+--+--+--+--+
5
6
| | |
7
+-----------------+ +-- Richtungsbit
8
Adresse
die Adresse ist also eine 7 Bit Adresse, die in den Bits 7 bis 1 steht.
In deiner Arduino Lib gibst du die Adresse OHNE die Verschiebung an, die
Lib schiebt sie selber um 1 Bit hoch und ergänzt das Richtungsbit.
In der benutzten Fleury Lib gibst du aber beim i2c_start bereits das
komplette Byte inklusive Richtungsbit an.
Daher kann an dieser Stelle 0x27 nicht richtig sein. Die 0x27 müssen um
1 Bit nach links verschoben werden, damit der Platz für das Richtungsbit
entsteht, das dann ebenfalls noch korrekt gesetzt werden muss.
Bei
1
i2c_start(Adresse+I2C_WRITE);
bzw.
1
i2c_start(Adresse+I2C_READ);
muss daher 'Adresse' schon diese Verschiebung enthalten.
> Auch ausprobiert, wie immer ohne Erfolg.
ok. dann gibt es mindestens noch einen Fehler.
> wenn dort etwas von 0x20 steht, so habe ich es nur mit der 0x27 zum> laufen bekommen.
Gut, dann ist in der Version, die die FLeury Lib benutzt 0x4E [bzw.
(0x27<<1)] korrekt.
// Set the pins on the I2C chip used for LCD connections:
2
// addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
3
LiquidCrystal_I2Clcd(0x27,2,1,0,4,5,6,7,3,POSITIVE);// Set the LCD I2C address
mit dem hier
1
#define LCD_D4_PIN 0
2
#define LCD_D5_PIN 1
3
#define LCD_D6_PIN 2
4
#define LCD_D7_PIN 3
5
#define LCD_RS_PIN 4
6
#define LCD_RW_PIN 5
7
#define LCD_EMPTY_PIN 6
8
#define LCD_E_PIN 7
vergleiche, dann stimmen die Pinnummern aber nicht zusammen.
Im Arduino Code steht, dass zb. der Enable Pin auf Pin2 vom Port
Expander liegt, in deinem Code steht, er wäre am Pin 7.
Ja, was denn nun? Was stimmt denn jetzt?
Wahrscheinlich der Arudino Code, denn von dem sagst du ja, das der
funktioniert. Du musst schon auch noch in i2clcd.h die Anschlussbelegung
korrekt eintragen. Die kann dein µC nicht riechen.
Karl Heinz schrieb:>> vergleiche, dann stimmen die Pinnummern aber nicht zusammen.>> Im Arduino Code steht, dass zb. der Enable Pin auf Pin2 vom Port> Expander liegt, in deinem Code steht, er wäre am Pin 7.> Ja, was denn nun? Was stimmt denn jetzt?> Wahrscheinlich der Arudino Code, denn von dem sagst du ja, das der> funktioniert. Du musst schon auch noch in i2clcd.h die Anschlussbelegung> korrekt eintragen. Die kann dein µC nicht riechen.>
Da gebe ich dir natürlich recht. Es war mein Fehler, das ich dies nicht
gesehen habe. Aber ich bin auch Anfängerin, was natürlich keine
Entschuldigung sein darf. Habe das entsprechend korrigiert:
1
#define LCD_D4_PIN 4
2
//#define LCD_D4_PIN 0
3
#define LCD_D5_PIN 5
4
//#define LCD_D5_PIN 1
5
#define LCD_D6_PIN 6
6
//#define LCD_D6_PIN 2
7
#define LCD_D7_PIN 7
8
//#define LCD_D7_PIN 3
9
#define LCD_RS_PIN 0
10
//#define LCD_RS_PIN 4
11
#define LCD_RW_PIN 1
12
//#define LCD_RW_PIN 5
13
#define LCD_EMPTY_PIN 3
14
//#define LCD_EMPTY_PIN 6
15
#define LCD_E_PIN 2
16
//#define LCD_E_PIN 7
Habe die alten Einstellungen noch mal drin gelassen, damit ich weis,
woher es kam.
>> Gut, dann ist in der Version, die die FLeury Lib benutzt 0x4E [bzw.> (0x27<<1)] korrekt.>
Habe das jetzt auch so drin stehen. Ich habe es schon nachvollziehen
können mit der Verschiebung.
1
#define LCD_I2C_DEVICE (0x27 << 1)
>> ok. dann gibt es mindestens noch einen Fehler.>
Das sehe ich auch so. Ich stelle mir die ganze Zeit die Frage, ob der
Nano einen knacks hat. Andererseits habe ich mit dem Atmel Studio ein
kleines Blinkprogramm übertragen, was er ohne murren macht
(LED-Wechselblinker).
Eine anderer Gedanke, den ich nicht vorenthalten möchte. Also, ich habe
zwei Nano's, von dem der Nano #1 der ist, wo wir gerade dran arbeiten.
Der Nano #2 ist der, welchen ich mit der Arduino-IDE verbinde und wo
alles läuft. Der Nano #1 kann seid dem Flashen via Atmel Studio nicht
mehr mit der Arduino-IDE kommunizieren. Bekomme jedesmal ein Fehler:
avrdude: stk500_getsync(): not in sync: resp=0x00
Kann es doch sein, das der Nano #1 einen knacks hat?
Servus Helmut;
Helmut -dc3yc schrieb:> Sarah,> kann es sein, dass du den Bootloader überschrieben hast?>> Servus,> Helmut.
Nun, wenn ich mir das so überlege, könnte das für den Nano #1 vielleicht
zutreffen.
Da ich aber eh vor habe, mit dem Atmel Studio zu arbeiten und nicht mit
der Arduino-IDE sollte das eigentlich egal sein. Denn letztlich ist es
ein Atmega328P - ob nun mit oder ohne Bootloader.
Oder sehe ich das falsch?
Sarah S. schrieb:> Denn letztlich ist es ein Atmega328P - ob nun mit oder ohne Bootloader.
Und es ist auch nicht verboten, den Bootloader wieder per ISP
draufzuspielen ...
Mike schrieb:>> Und es ist auch nicht verboten, den Bootloader wieder per ISP> draufzuspielen ...
Das stellen sich mir zwei Fragen:
1. Warum sollte ich den Bootloader wieder aufspielen? Da ich in meinen
Projekten in C, bzw. letztlich in C++ und mit dem Atmel Studio arbeiten
will, sehe ich keinen Sinn darin. Denn so wird auch wieder Speicher
frei, der ja kostbar ist.
2. Sollte es doch einen plausiblen Grund geben, dann wüsste ich gerne,
wie ich den Bootloader wieder aufspielen kann, wenn ich keine Verbindung
über die Arduino-IDE bekomme. Zustäzlich bräuchte ich auch das File zum
aufspielen.
Sarah S. schrieb:> 1. Warum sollte ich den Bootloader wieder aufspielen? Da ich in meinen> Projekten in C, bzw. letztlich in C++ und mit dem Atmel Studio arbeiten> will, sehe ich keinen Sinn darin. Denn so wird auch wieder Speicher> frei, der ja kostbar ist.
Zum Beispiel um die Frage zu beantworten, ob der Nano eine Macke hat.
Stell den Ausgangszustand wieder her, spiel die Arduino Version deines
LCD Programmes ein und sieh nach ob es funktioniert. Dann weißt du, ob
der Arduino eine Macke hat oder nicht.
> 2. Sollte es doch einen plausiblen Grund geben, dann wüsste ich gerne,> wie ich den Bootloader wieder aufspielen kann, wenn ich keine Verbindung> über die Arduino-IDE bekomme. Zustäzlich bräuchte ich auch das File zum> aufspielen.
Du hast doch einen zweiten Nano, auf dem der Bootloader noch drauf ist.
Lies ihn aus und brenne ihn in den ersten.
PS: Als du den Bootloader gelöscht hast, hast du dann auch die
Bootloader Fuses wieder gelöscht?
Karl Heinz schrieb:>> Zum Beispiel um die Frage zu beantworten, ob der Nano eine Macke hat.> Stell den Ausgangszustand wieder her, spiel die Arduino Version deines> LCD Programmes ein und sieh nach ob es funktioniert. Dann weißt du, ob> der Arduino eine Macke hat oder nicht.>
Stimmt, das hätte mir selbst wie Schuppen von den Augen fallen müssen.
>> Du hast doch einen zweiten Nano, auf dem der Bootloader noch drauf ist.> Lies ihn aus und brenne ihn in den ersten.>
Das habe ich noch nie gemacht. Hoffe, das ich bei dieser Aktion nicht
den Nano#2 auch beschädige.
Ich werde das morgen machen, heute habe ich keine Zeit mehr dazu. Habe
die ganze Woche Nachtdienste und zum basteln nicht viel Zeit.
>> PS: Als du den Bootloader gelöscht hast, hast du dann auch die> Bootloader Fuses wieder gelöscht?
Nicht bewusst. Wenn, dann hat es die Atmel-IDE gemacht, als die
Programme auf den Nano#1 übertragen wurde. Damit meine ich sowohl den
Bootloader löschen als auch die Fuses evtl. verändern.
Da ich aber eh vom Nano#2 auslese, kann ich auch gleich die Fuses
anschauen und ggf. verändern.
Hallo Leute,
also ich habe ein Image von dem Nano#2 auf den Nano#1 gezogen und damit
das Arduino-Programm aufgespielt. Es hat funktioniert, was heißt, das
der Nano#1 nicht beschädigt ist.
Einzig, was nicht stimmte, waren die Fuses, bzw. die Lockbits.
Hier die Aufstellung:
Ich habe die Fuses, bzw. Lockbits entsprechend angepasst.
Soweit, sogut. Also wieder zurück zum Programm. Nachdem ich es wieder
aufgespielt hatte, zeigt sich das übliche Ergebnis.
Ich bin ein wenig die i2clcd.c durchgegangen und habe dort in Zeile 49
etwas entdeckt, was mich stutzig macht. Dort steht:
Für mich stellt es sich so dar, dass das Display als zweizeiliges
Display initialisiert wird. Ich habe aber ein vierzeiliges Display. In
der i2clcd.h ist die Variable definiert. Für ein vierzeiliges Display
müsste ich also dort eine entsprechende Definition einbringen.
1
#define LCD_4LINE LCD_CONFIGURATION | 0xXX
Ich bin jetzt nicht sicher, was bei XX stehen müsste. Soll es 0x16 sein?
Oder ein anderer Wert?
@ Verzweifelt (Gast)
>Gibt es schon jemanden der eine Lösung bzw. vielleicht sogar eine>Library für AVR Controller hat ?
Sicher.
Beitrag "Re: I2CLCD Library für HD44780 LCDs"
Für den Arduino muss man das allerdings geringfügig anpassen.
Wie es der Zufall will, hatte ich das sogar schon vor einiger Zeit mal
auf den Arduino angepasst. Man muss nur in i2clcd.h die Adresse des I2C
Portexpanders eintragen, als 8-Bit Adresse mit dem LSB=0!