Hallo,
ich programmiere schon seit einigen Jahren mit C/C++, bin aber auf dem
Gebiet der Mikrocontroller totaler Anfänger. Vor allem von Schaltungen
habe ich kaum Ahnung.
Ich versuche nun schon seit Tagen verzweifelt mit dem Atmega32(=Master)
über TWI/I2C eine Kommunikation mit einem Sharp Infrarotsensor(Slave)
aufzunehmen. Das Problem tritt allerdings bereits beim Start auf. Der
Master bleibt beim Initialisieren der Verbindung in der Endlosschleife
hängen. Hier ein Ausschnitt aus meinem Programm:
1
//das Start Signal geben:
2
TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
3
4
//warten bis das TWINT Flag gesetzt ist:
5
while(!(TWCR&(1<<TWINT)));//<--an dieser Stelle bleibt das Programm hängen
-Den Code habe ich teils mit dem hervorragenden Tutorial von dieser
Seite, teils mit dem Atmega32 Datenblatt, erarbeitet
-Alternativ habe ich das Beispiel von Peter Fleury probiert, ohne
Erfolg(zumal die Erste Zeile in der der Fehler auftritt, in meinem Code
identisch mit dem von Peter Fleury ist...)
-Pull Ups ca. 4.7k Ohm sind von SDA->VCC und SCL->VCC
-Alternativ: Vorwiederstände 470 Ohm + Dioden(an GND)->hat auch nicht
zum Erfolg geführt
-JTAG Fuse ist deaktiviert
-Das Forum habe ich nach Antworten durchforstet, bisher leider ohne
Erfolg (vielleicht habe ich einen Antworten liefernden Beitrag
übersehen...)
-Auch wenn kein Slave am Bus hängt, bleibt der Master während der
Initialisierung hängen
Was mir aufgefallen ist, als ich die Dioden angeschlossen habe, dass nur
die Diode an SCL high war, die an SDA blieb dunkel.
Beim Starten des Atmega32 ist die Diode an SCL high und die Diode an SDA
low. Erst auf Tastendruck hin beginnt der Start des TWI. Der Zustand der
LEDs ändert sich jedoch nicht...
Vielleicht habe ich nur irgendwas ganz banales Übersehen, oder mache nur
einen ganz blöden (Anfänger)fehler, aber ich weiß einfach nicht mehr
weiter.
Danke im Voraus für die Hilfe!
>-Pull Ups ca. 4.7k Ohm sind von SDA->VCC und SCL->VCC
Brauchst du auf jeden Fall.
>-Alternativ: Vorwiederstände 470 Ohm + Dioden(an GND)->hat auch nicht>zum Erfolg geführt
Sowas ist bei I2C verboten.
@holger
danke für die rasche Antwort, aber dass ich die 4.7K Ohm brauche, wusste
ich ja bereits...
Das mit den LEFs ist mir neu und dafür bin ich dir dankbar!
Aber eine Lösung für mein Problem hab ich leider noch immer nicht... :(
Ich gehe mal davon aus, dass es nicht am/n (den) Slave(s) leigen kann,
wenn der Master nicht mal über die START Bedingung hinauskommt...
>Ich gehe mal davon aus, dass es nicht am/n (den) Slave(s) leigen kann,>wenn der Master nicht mal über die START Bedingung hinauskommt...
Ich gehe mal davon aus, das es sehr wohl an den Slave(s) liegen kann,
wenn der Master nicht mal die START Bedingung hinauskommt...
Schau dir das Kommunikationsprotokoll doch mal an. Zum Start zieht der
Master SDA auf GND, und wartet, bis ein Slave reagiert.
Ob der Master überhaupt was macht, lässt sich am einfachsten per Oszi
überprüfen. Zur Not tut es auch ein PC mit Soundkarte. Spannungspegel
überprüft man am sichersten mir einem Multimeter, nicht per LED.
Oliver
P.S. Der Slave ist aber richtig angeschlossen (SDA an SDA, SCL an SCL)?
mit der Led würdest du Daten auf der SDA Leitung warscheinlich gar nicht
erkennen, da sie mit 100kHz daherkommen. und wenn er nach nur 8 Bits
(Startbyte) abbricht, dann würdest du das denke ich nicht sehen.
Wie sind denn die Leds angeschlossen ?
Dir ist schon klar, daß bei diesem Bus die beteiligten Partner die
Leitungen nur nach Low ziehen ? Nach High wird's von den Widerständen
erledigt.
Sollten also die Leds nach Masse angeschlossen sein, so würde das den
Bus auf einen unerwünschten Level bringen, und wie es schon Oliver
geschrieben hat, kann eine Blockade sehr wohl vom Bus, respektive von
den beteiligten Slaves ausgehen.
Deswegen meine Frage auch nach TWBR gesetzt, denn wenn Du Dich darum
nicht gekümmert hast, dann läuft der Bus möglicherweise mit zu hohem
Takt.
TWPS0/1 in TWSR hat da übrigens auch noch Einfluss drauf.
Also, ich bin jetzt in aller Ruhe das Ganze nochmals durchgegangen und
habe mir eure Ratschläge zu Herzen genommen:
Dass die Sache mit den LEDs wohl ziemlicher Schwachsinn war, darauf hab
ihr mich ja glücklicherweise hingewiesen!
@ MWS: ich gehe davon aus, dass TWBR richtig gesetzt ist, da ich dies
dem Beispiel von Peter Fleury entnommen habe:
1
#define F_CPU 8000000UL
2
#define SCL_CLOCK 100000L
3
4
//...
5
6
TWSR=0;
7
TWBR=((F_CPU/SCL_CLOCK)-16)/2;
@Oliver
Da der Sensor(genaue Bezeichnung: High Precision Medium Range Infrared
distance sensor for NXT) für den Lego Mindstorms ausgerichtet ist, hat
er auch so eine sechs polige spezial Buchse. Um damit dennoch in meiner
Schaltung arbeiten zu können habe ich einfach bei einem Lego-
Verbindungskabel auf der einen Seite den Stecker entfernt.
SCL ist zu SCL und SDA zu SDA angeschlossen, da bin ich mir ganz sicher,
da ich das dem Lego Datenblatt entnommen habe!
Du hast recht es liegt am Slave, denn wenn kein Slave am Bus hängt,
klappt der Start, aber logischerweise der Verbindungsaufbau nicht...^^
Bis hier her mal Danke für alle Antworten!
Auch wenn ich bisher nicht in der Lage war(an wem das wohl liegen
mag...^^) das Problem zu beheben...
Ja, TWSR & TWBR stimmen.
Ich hab' mich mal nach Sharp IR Sensoren umgekuckt.
Handelt es sich um einen Distanzsensor ? Welcher Typ ?
Sollten es die GP2... Typen sein, dann ist Dir schon klar daß es da zwar
welche mit digitalem Ausgang gibt, das dann aber kein I2C ist ?
Es gibt hier: http://www.hvwtech.com/products_view.asp?ProductID=665
etwas, daß dem Ding I2C Fähigkeit verpasst. Ist es das was Du hast ?
Das TWINT flag im TWCR manuell löschen.
Somit sendet der Master danach weiter.
Falls du die I2C im IRQ verwendest wird das TWINT flag automatisch
gelöscht.
Fazit: Der Slave muss nach dem Empfang das TWINT-Bit im TWCR
löschen,damit der
Master das nächte Zeichen senden kann. (Handschake-Funktion ).
Holger,
>> Falls du die I2C im IRQ verwendest wird das TWINT flag automatisch>> gelöscht.
Das ist schon mal Käse, siehe Datenblatt Meag32A,S.202, oder Mega32
S.177:
"The TWINT Flag must be cleared by software by writing a logic one to
it. Note that this flag is not automatically cleared by hardware when
executing the interrupt routine."
Und der Rest ist auch nicht besser.
Warum soll denn das Löschen des TWINT Flags irgendetwas bewirken wenn es
noch nicht mal gesetzt ist ? Im Beispielcode von Atmel wird extra auf
ein gesetztes TWINT Flag gewartet, um den erfolgreichen Start des Buses
zu erkennen.
Und genau dort hängt's ja auch, das TWINT-Flag wird nicht gesetzt, da
offenbar kein erfolgreicher Busstart zustande kommt.
>> Fazit: Der Slave muss nach dem Empfang das TWINT-Bit im TWCR>> löschen,damit der Master das nächte Zeichen senden kann.
Wie soll denn ein Slave, also ein Busteilnehmer, auf ein INTERNES
Register des Mega32 zugreifen und es löschen können ?
Der Slave kann gar nix löschen, der kann höchstens Pegelzustände
annehmen, die das I2C Interface des µC erwartet. Das ist ein richtiger
Schmarrn was Du da schreibst.
@MWS
der Sensor wird von mindsensors.com vertreiben und ist speziell für den
Lego Mindstroms NXT Bausatz. Was da für ein Chip drin steckt weißt ich
leider nicht, das Datenblatt und die Seite sind nicht sonderlich
freizügig mit technischen Infos.
Der NXT jedefalls beherrscht das I2C und kommuniziert mit digitalen
Sensoren(der Infrarot Sensor ist ein solcher) ausschließlich über dieses
Protokoll.
Ich habe diesen Sensor, und auch andere Digitale, über das I2C schon mal
in Verbindung mit dem NXT benutzt. Allerdings ist beim NXT die Schaltung
funktionstüchtig, an der kann man auch nichts verändern, und für die I2C
Kommunikation gibt es Funktionen bei denen man eben nur noch angeben
muss, welches Byte man zurückgesendet bekommen möchte. Da hat wie gesagt
alles funktioniert.
Was man, wie du bereits erwähnt hast, nicht garantieren kann, dass Lego
sich an die Vorgaben des "originalen" I2C hält. Im Datenblatt wird aber
versprochen: "... are used for digital communication implemented as I2C
compliant communication..."
@Holger
Ich sehe keinen Grund warum ich ein Flag nachdem ich es manuell gesetzt
habe, wieder manuell löschen sollte, bevor etwas passiert ist...
Auf das Programm des Slaves habe ich keinen Zugriff, aber es muss
korrekt sein da es ja in Verbindung mit dem NXT sehr wohl funktioniert
hat.
Soweit mal
Danke an alle!
Hab gar nicht gewusst, dass man sich um die Ein und Ausgänge beim TWI
kümmern muss. Ich dachte immer dass erledigt mein Atmega32 von selbst...
Zur Sicherheit habe ich aber probiert die Register zu setzen, hat aber
nichts gebracht. Auch im Datenblatt steht nichts davon dass ich dies
manuell erledigen müsste...
Das kann es wohl auch nicht gewesen sein...
Chris,
bist Du sicher bezüglich des Anschlusses SCL & SDA ?
Ich hab' mir die Userguides der NXT Adapter angesehen, leider wenig
Inhalt. Gar keiner zur Steckerbelegung. Hast Du mehr Info vorliegen ?
Dir ist bekannt, daß I2C Bausteine auch einen Reseteingang haben können,
der auf dem richtigen Pegel liegen sollte ?
>> Hab gar nicht gewusst, dass man sich um die Ein und Ausgänge beim TWI>> kümmern muss.
Musst Du auch nicht :D
************************************************************************
****
Note that the internal pullups in the AVR pads can be enabled by setting
the PORT bits corresponding to the SCL and SDA pins, as explained in the
I/O Port section.
************************************************************************
****
• Bit 2 – TWEN: TWI Enable Bit
The TWEN bit enables TWI operation and activates the TWI interface. When
TWEN is written to one, the TWI takes control over the I/O pins
connected to the SCL and SDA pins, enabling the slew-rate limiters and
spike filters.
************************************************************************
****
Ja wegen SCL und SDA bin ich mir ganz sicher.
Ich habe das "Lego Mindstroms Hardware Developer
Kit"(http://mindstorms.lego.com/Overview/NXTreme.aspx), dieses umfasst
einige PDF Dateien. Unter anderem sind da die Schaltpläne der
Standartsensoren usw. enthalten.
Da steht ausdrücklich dass der Pin 5 der Leitung der SCL und der Pin 6
der SDA ist, und so habe ich es auch angeschlossen(-> LEGO MINDSTORMS
NXT Hardware Developer Kit.pdf Seite 9)
Vom Reset Eingang wusste ich nichts, aber auf den kann ich im Sensor gar
nicht zugreifen. Habe ich vorher vergessen, da ist die
"ausführliche"(^^) Beschreibung des Herstellers:
http://www.mindsensors.com/index.php?module=pagemaster&PAGE_user_op=view_page&PAGE_id=72
*was da im Datenblatt von Lego zu lesen ist, dass die Pull-ups intern in
Serie geschaltet sind, habe ich sicherheitshalber probiert, hat aber
auch nichts gebracht.
Ich werden morgen, versuchen den Spieß um zudrehen und meinen Atmega32
zum Slave gegenüber dem NXT(den ich ja eigentlich aus dem Spiel lassen
wollte^^) machen. Vielleicht bringt mich das auf irgendwelche
Ergebnisse.
So viel weiß ich mittlerweile über TWI, auch wenns bei mir nicht
funktioniert, dass ich die Ein und Ausgänge nicht setzen muss. Ich hab
nur keinen Weg gefunden Sarkasmus in schriftlicher Form anzuzeigen :D
Die "ausführliche" Beschreibung hatte ich schon gefunden, mittlerweile
auch das HDK und die Steckerbelegung. Reset gibt's da keinen.
Ein interessantes Detail ist vielleicht der Hinweis, daß der I2C Bus mit
9600bit/s läuft. Bedeutet natürlich nicht automatisch, daß der Sensor
nicht schneller kann.
Aber der 100000er Clock könnte dann ein bisserl viel sein, falls die
Zusatzhardware auf dieser Vorgabe aufbaut.
Ich würd' auch an Deiner Stelle die HW I2C, HW I2C sein lassen und mal
versuchen, ob die Softvariante von Peter Fleury drauf läuft.
Die ist recht unkompliziert, beim I2C Start Befehl wir z.B. nur SCL &
SDA in passender Form auf 0 gezogen und wieder freigegeben, da wird
nicht auf einen gesetzten Pin oder auf ein Flag gewartet.
Damit wär' sie möglicherweise toleranter zu Deiner Hardware, und so wie
ich das sehe kannst Du die HW I2C von der Geschwindigkeit sowieso nicht
nutzen.
Hab letzthin so etwas Ähnliches geschrieben um ein paar TCL59116
parallel anzusteuern (außerhalb Specs, wäre mit der HW I2C nicht zu
machen gewesen), das klappt einwandfrei. Durch die Parallelisierung ist
die SW Variante mehr als doppelt so schnell wie die HW I2C :D
MWS,
Tatsächlich! Ein Lichtblick, mit der Software Umsetzung von Peter Fleury
bleibt der Mikrocontroller nicht mehr in der Endlosschleife hängen. Aber
er liefert mir eine Fehlermeldung, dass der Start missglückt sei. Also
funktionieren tut es noch immer nicht.
Ich denke aber, dass es daran liegt, dass die Sensoren auf ein besonders
langsames Tempo abgestimmt sind. Ich werde einfach versuchen die
Geschwindigkeit des Masters zu reduzieren. Ich kann nur kein Assembler
und werde mich da ein wenig einarbeiten müssen, aber ich denke das
schaffe ich schon.
Herzlichen Dank für deine Mühe und Hilfe!
Gern geschehen :D
Du kannst mit nachfolgendem Code die i2c_delay_T2 Routine ersetzen.
Ich habe einen 16 Bit Zähler vorgesehen, obwohl man hier mit 8 Bit
möglicherweise auch auskäme. Der Zähler wird aus R26/R27 gebildet und
geladen bei "***total 400 Zyklen***". Hex 0x64 bedeutet dabei Dezimal
100, mal jeweils 4 Zyklen = 400. Plus der Rest der Routine ergibt 417
Zyklen.
Da ich in Bascom in Kombination mit Inline Assembler schreibe, hoffe ich
die Syntax getroffen zu haben. Aber eigentlich sollt's passen.
Hi,
ich lese immer wieder die folgende Formel für TWBR:
TWBR = ((F_CPU/SCL_CLOCK)-16)/2;
Dabei stört mich der Faktor 2, da laut Datenblatt gilt:
SCL_CLOCK = F_CPU/(16+2*TWBR*(4^TWPS)); // TWPS >= 1
Da muss also mindestens eine 8 stehn.
Gruss Potter68
Es wird für TWPS ein Prescalerwert von 1 genommen, und die Datenrate nur
über das TWBR eingestellt.
Da für Prescaler = 1 das TWPS den Wert 0 erhält, ergibt sich: 4^0 = 1,
kann damit ignoriert werden.
MWS, danke für deine Assembler Warteroutine, aber es hat damit auch
nicht funktioniert... :'(
Ich habe auch noch eine eigene C Software Lösung geschrieben. Zusätzlich
habe ich den Quelltext der NXT Firmware, die ja Opensource ist,
durchgesehen und einfach nichts auffälliges gefunden. Es sieht aus wie
eine ganz normale I2C Umsetzung.
Daher habe ich überprüft ob die Pins meines Controllers in Ordnung sind.
Dabei ist mir aufgefallen, dass sich der SCL Pin nicht mehr auf LOW
ziehen lässt sobald einer der Sensoren dran hängt! Ich vermute dass hier
der Fehler liegt. I2C funktioniert sicherlich nicht ordnungsgemäß wenn
SCL ständig auf High ist, und ich kann es nicht durch den Master
beeinflussen...
SDA funktioniert soweit wie es sollte und lässt sich high und low
schalten.
Wie könnte ich das lösen, ich bin einfach nur mehr ratlos...
Hi Chris,
wenn sich der Scl-Anschluss am µC auf Low ziehen lässt, ohne daß ein
Sensor dran ist, spräche das für ein korrektes Funktionieren des Pins.
Der µC kann nicht allzuviel Strom auf den Port liefern, um die 20-30mA.
Mit der Soft I2C hättest Du die Möglichkeit andere Pins für Scl & Sda
auszuwählen, das ist Dir klar ?
Aber Prinzip des I2C Busses ist daß jeder Teilnehmer sowohl Scl, als
auch Sda problemlos nach Low ziehen kann, nach High geht's mit Hilfe der
Widerstände.
So können sich niemals Signale kurzschließen, im schlimmsten Fall
funktioniert's einfach nicht.
Dein Sensor sollte aus beschriebenem Grund nicht in der Lage sein, das
Signal auf High zu halten. Geh doch mal mit dem Messgerät im mA Bereich
von Sensor Scl auf Masse und schau' wieviel Strom da fließt. Das könnte
helfen.
Alternativ versuch' den Sensor an einer NXT Steuereinheit anzuschließen,
damit Du siehst, ob er noch lebt.
MWS,
Manchmal sollte man über Dinge eine Nacht schlafen... Mit der Software
TWI Lösung von Peter Fleury und deiner Assembler Warteroutine hat es
geklappt.
Ich vermute ich weiß auch wo mein Fehler lag. Ich bin es gewohnt aus
Visual Studio, dass beim Compilieren automatisch alle Projekt Dateien
gespeichert werden und die aktuellen Dateien verwendet werden.
Das AVR Studio speichert anscheinend nicht automatisch. Und nach dem
Einfügen deines Codes habe ich offensichtlich die Datei nicht
gespeichert, sofort kompiliert und da ich schon ganz verzweifelt war,
habe ich nach einem Versuch aufgegeben^^
Wäre für mich die einzig logische Erklärung warum es plötzlich klappt.
Die Schaltung habe ich ja nicht verändert.
Nochmals herzlichen Dank für die Hilfe und für die Assembler
Warteroutine!!!
Hi Chris,
genau, es werden die Dateien nur in dem Zustand kompiliert, in dem sie
auf der Festplatte sind, nicht gespeichert kompiliert eben nicht das was
am Bildschirm steht, sonder was auf der Platte liegt.
Außerdem ist's glaube ich sinnvoll ein Make clean zu machen, nicht daß
alte Objektdateien mit dazugelinkt werden. Aber muss aufpassen, keinen
Schmarrn zu erzählen, denn wie gesagt, C bin ich nicht sooo fit.
Freut mich, daß es geht, jetzt kannst Du noch versuchen das Delay zu
verkleinernn, um eine schnellere Übertragung zu bekommen. 9600 ist schon
seeeehr langsam. Da wärst Du mit dem nackichen Sensor besser bedient /
schneller.
Ja ich bin vom Visual Studio verwöhnt :D
Ich hoffe hier ist ein wenig Platz für private Geschichten^^
Das ganze geht von meiner Schule aus. Da haben wir vor ca. zwei Jahren
mit dem RoboCup begonnen, falls dir das was sagt. Wir haben damals von
unserem Lehrer die Lego Mindstorms Bausätze erhalten. Er hat sie für uns
ausgesucht weil sie einerseits recht kostengünstig waren, da unser
Budget stark eingeschränkt ist, und andererseits einfach handhaben sind.
Ursprünglich war geplant unserer Roboter mit der mitgelieferten
graphischen Entwicklungsumgebung zu programmieren.
Die Schule in die ich gehe, ist ein naturwissenschaftliches
Realgymnasium und hat mit Informatik nicht viel am Hut. Ich bin der
einzige aus der Roboter Gruppe, der Programmieren kann, wahrscheinlich
auch der einzige aus ganzen Schule. Alles was ich also über C/C++ und
Mikrocontroller weiß habe ich mir selbst beigebracht, auch teils
mithilfe dieser tollen Seite :D
Wir waren heuer beim Robocup, im Bewerb RoboRescue Junior, der in Graz
meiner Heimatstadt statt gefunden hat, recht erfolgreich. Da haben mein
Teamkollege und ich festgestellt, dass wir bei einem internationalen
Bewerb mit einem Lego Mindstorms wenig Chancen haben... Außerdem ist die
NXT Steuereinheit viel zu groß und sperrig, da es Limitierungen bei der
Größe(Durchmesser des Roboters max. 22cm) gibt.
Daher wollen wir jetzt selbst einen Roboter bauen. Die Sensoren sind
aber schon gekauft und wie gesagt das Budget ist klein. Wir müssen also
mehr oder weniger bei den Lego Sensoren bleiben.
Ok, verstehe.
Robocup, hab' ich ansatzweise was davon gehört.
Und dann sind ja alle sozusagen von Dir abhängig, wenn Ihr auf C
umsteigt :D
Was ich bei dem NXT Zeugs gesehen habe, sind die angebotenen Sensoren
durchaus brauchbar, das ist sicher kein Schaden die jetzt zu haben. Ich
denk' auch am Anfang ist man froh so etwas zu haben, wo einfach ein paar
Sachen bereits laufen. Jetzt heißt's halt improvisieren. Und wenn Erfolg
da ist, kommen auch weitere Mittel.
Der Sharp Distanzsensor ist von Haus aus mit ~40ms eh' nicht der
Schnellste, aber für einen sinnvollen Einsatz wär's gut mit der I2C
Frequenz insgesamt höher gehen zu können, denn da gelten bereits 100kHz
als eher gemächlich.
Ist auch blöd einen schnellen µC zu haben und der muss auf den Sensor
warten, weil der die Daten zu schnarchig überträgt.
Na, dann wünsch' ich Dir/Euch mal viel Erfolg !