Forum: Mikrocontroller und Digitale Elektronik I2C am ATMega88


von plexus c. (plexucra)


Lesenswert?

Hallo Zusammen,

ich schreibe diesen neuen Beitrag nicht leichtfertig und habe bereits 
ausgiebig hier im Forum und via Google nach ähnlichem gesucht und 
einiges probiert:

Ich versuche (vergeblich) über einen "nackten" ATMega88PA (1 Mhz 
getaktet) einen Feuchtigkeitssensor via TWI/I2C auszulesen.

Vorweg: jegliche Probleme mit dem Sensor/Spannung oder den Leitungen 
kann ich ausschließen da ich probeweise mit einem Arduino UNO die 
Ansteuerung über dieselben Kabel erfolgreich hinbekomme (Ebenfalls mit 
5V versorgt).

Er bleibt bei folgendem Code immer in der letzten Zeile (wohl in einer 
Endlosschleife stecken:
...

#define F_CPU 1000000UL
#include <avr/io.h>
#include "util/delay.h"
#include "i2cmaster.h"

...
  PORTC |= (1 << 4);  //pullups
  PORTC |= (1 << 5);
 while(1)
    {
_delay_ms(500);
i2c_init();
_delay_ms(50);
i2c_stop();
_delay_ms(50);
i2c_init();
_delay_ms(50);
i2c_start_wait(0x51+I2C_WRITE);

// <-- hier kommt er nicht mehr hin....

anstatt "0x51+I2C_WRITE" habe ich auch nur "0x51" oder dezimal 
ausprobiert.
Ebenfalls habe ich etliche andere Code-Beispiele und Bibliotheken 
ausprobiert sogar eine simple eigene geschrieben. Immer ohne Erfolg.
Die Delays und das 2malige i2c_init() habe ich zuletzt hinzugefügt weil 
hier im Forum jemand meinte, dass man auf diese Weise I2C Probleme 
umgehen könnte. Auch eine andere Adresse und einen Arduino als Slave 
habe ich probiert.

Hier der Code der mit dem Arduino funktioniert bzw. den Sensor 
erfolgreich auslesen kann:

...
  delay(10);
  Wire.beginTransmission(0x51);
  Wire.write(0x0A);
  Wire.endTransmission();

  Wire.requestFrom(0x51, 4);

  Serial.println("Lese Daten - sens:");
  byte bytes[4];
  for(byte i = 0; i <= sizeof(bytes); i++)
    if(Wire.available())
      bytes[i]=Wire.read();
  unsigned int Sensitivity = bytes[1] + (bytes[0] << 8);
  unsigned int Offset      = bytes[3] + (bytes[2] << 8);
...

Ich habe auch schon probiert den Code der von Arduino produziert wird 
möglichst 1:1 zu adaptieren und auf dem ATmega8 auszuführen (nat. ohne 
Erfolg)
Hier mal der Assembler-Code in dem wohl bei der grade verwendeten 
Bibliothek die Endlosschleife steckt. (Wenn ich eine C-Bibliothek 
verwende steckt er dann nat. in der jew. anderen C-Bibliothek fest);



  .global i2c_start_wait
  .func   i2c_start_wait
i2c_start_wait:
  mov  _tmp_reg_,r24
i2c_start_wait1:
  sbi   SDA_DDR,SDA  ;force SDA low
  rcall   i2c_delay_T2  ;delay T/2
  mov  r24,__tmp_reg__
  rcall   i2c_write  ;write address
  tst  r24    ;if device not busy -> done
  breq  i2c_start_wait_done
  rcall  i2c_stop  ;terminate write operation
  rjmp  i2c_start_wait1  ;device busy, poll ack again
i2c_start_wait_done:
  ret
  .endfunc

...

Wenn ich das richtig verstehe (Vermutung), ist der Bus wohl andauernd 
Busy weshalb diese ewige Warterei passiert. Am Bus hängt sonst nichts. 
Also der Sensor ist mit 2 kurzen Drähten direkt verbunden. Bei anderen 
Bibliotheken habe ich zudem mit der Datenrate herum gespielt. Diese hier 
ist von Peter Fleury und scheint die Datenrate in Abhängigkeit der 
eingestellten Prozessortaktung selbst einzustellen (F_CPU steht bei mir 
auf 1 Mhz was überprüfterweise korrekt ist).

Generell handelt es sich also nicht um ein sporadisches Problem (wie bei 
Anderen hier im Forum) sondern um etwas ganz grundsätzliches / immer 
auftretendes. Über Anregungen / Hinweise was ich noch machen könnte wäre 
ich seeehr Dankbar.

Danke auch für das Durchlesen bis hierher ;-)

von Stefan F. (Gast)


Lesenswert?

Vermuten kannst Du gerne was du willst, aber das bringt Dich nicht 
wweiter.

Messe nach, ob der Bus in Ruhelage High Pegel auf beiden Leitungen 
führt. Das wäre mal der erste Schritt, um das Problem einzukreisen.

Ich bezweifle, dass die internen Pull-Ups im I2C Betrieb wirksam sind. 
Denn im Datenblatt des mC steht: "The only external hard-ware needed to 
implement the bus is a single pull-up resistor for each of the TWI bus 
lines."

Hast Du externe Pull-Up Widerstände in der Schaltung?

von spess53 (Gast)


Lesenswert?

Hi

>Ich bezweifle, dass die internen Pull-Ups im I2C Betrieb wirksam sind.
>Denn im Datenblatt des mC steht: "The only external hard-ware needed to
>implement the bus is a single pull-up resistor for each of the TWI bus
>lines."

Sind sie schon. Aber um einen Faktor >10 zu hochohmig.

MfG Spess

von plexus c. (plexucra)


Lesenswert?

Vielen Dank für die Anregung.
Der SCL liegt bei 3,9V
Der SDA liegt ebenfalls bei 3,9V

Dies wird in Bezug zur Referenzspannung von 4,5V als HIGH gewertet.

Dies gilt sowohl im Ruhezustand als auch wenn der obige Code abläuft in 
seiner Endlosschleife.

Die Pullup-Setzung habe ich mir nicht ausgedacht sondern von anderen als 
funktionierend titulierten Beispielen abgekupfert. Zudem hatte der 
Arduino auch ohne extra Pullups keine Probleme.
Dennoch werde ich das gleich noch ausprobieren (verspreche mir aber nix 
davon)

Ist evtl. noch eine andere Idee vorhanden?

von WS (Gast)


Lesenswert?

Hallo,

hier die Beschreibung der Arduino Wire-Bibliothek:

Es gibt sowohl 7-Bit als auch 8-Bit Versionen der I2C-Adressen. 7 Bit 
bezeichen die Geräteadresseund 8 Bit bestimmen, ob gelesen geschrieben 
wird. Die Wire-Library benutzt durchweg 7-Bit-Adressen. Wenn in einem 
Datenblatt oder einem Beispielcode 8-Bit-Adressen verwendet werden, kann 
man das niederwertigste Bit einfach löschen (z.B. durch Verschieben um 
ein Bit nach rechts), mit dem Ziel eine Adresse zwischen 0 und 127 zu 
erhalten.

Die I2C-Bibliothek verlangt 8-bit Adressen d.h. 0x51 wird zu 0xA2 (1 Bit 
nach links geschoben).
Diese muss verwendet werden.

von plexus c. (plexucra)


Lesenswert?

Das mit der Adresse probier ich gleich noch aus vielen Dank.
Ich hatte nun zudem die beiden I2C pins anlässlich des obigen Hinweises 
nochmal jeweils am Sensor und am ATMega8 mal separat vermessen (ohne 
angeschlossenen Kabel) dabei habe ich gesehen, dass der Sensor lediglich 
1,2V liefert und der ATMega 4,8V. Kann/darf das überhaupt sein? Der 
Arduino läuft ja mit 5V und hatte damit ja scheinbar auch kein Problem. 
Der Sensort läuft generell mit 3,2 V Versorgung. Ist hier noch eine 
Verstärkerschaltung nötig? (Auch wenn ich mir nicht erklären kann wieso 
es dann am Arduino geklappt hat)

von spess53 (Gast)


Lesenswert?

Hi

>Die Pullup-Setzung habe ich mir nicht ausgedacht sondern von anderen als
>funktionierend titulierten Beispielen abgekupfert. Zudem hatte der
>Arduino auch ohne extra Pullups keine Probleme.

Man sollte nicht jeden Dünnschiss aus dem Web glauben. Such mal nach 
UM10204. Das ist die I2C Spezifikation.

MfG Dpess

von ATMega88PA (Gast)


Lesenswert?

Kannst du in deinen I2C Dateien mal nach deinem "ATMega88PA" suchen ?
Glaube das der dort nirgendwo auftauchen wird.

von plexus c. (plexucra)


Lesenswert?

ATMega88PA schrieb:
> Kannst du in deinen I2C Dateien mal nach deinem "ATMega88PA" suchen ?
> Glaube das der dort nirgendwo auftauchen wird.

Ich verwende die neueste Version des Atmel Studios und konnte den 
korrekten Typ beim Anlegen des Projektes auswählen. Welche Dateien soll 
ich da nun konkret durchsuchen? Den Programm-Ordner des Atmel Studios?

von ATMega88PA (Gast)


Lesenswert?

Entschuldige, ich war aus irgendeinem Grund gerade bei Uart, nicht bei 
I2C.

von plexus c. (plexucra)


Lesenswert?

Hab jetzt die Vorgeschlagenen Pullup-Widerstände dran.
Hatte leider nur noch 18k Ohm (anstatt 4,7k) aber das sollte ja eig. 
dennoch ausreichen.

...immer noch ohne Veränderung / in Endlosschleife weil Leitung 
angeblich "Busy" (so war ja meine ursprüngliche Vermutung).

von Stefanus (Gast)


Lesenswert?

> dabei habe ich gesehen, dass der Sensor lediglich
> 1,2V liefert und der ATMega 4,8V. Kann/darf das überhaupt sein?

Ja das kann richtig sein. Es wäre auch richtig, wenn der Sensor gar 
keine Spannung liefert, denn das sollten eigentlich Open-Drain Ausgänge 
sein. Der High pegel ergibt sich durch die Pull-Up Widerstände, dier 
laut Deiner Meissung (3,9V statt 4,5V) eindeutig zu hochohmig sind. Wenn 
die Spannung schon in Ruhelage nicht ideal ist, dann wird sie es bei 
einigen hundert khz erst recht nicht sein.

> immer noch ohne Veränderung / in Endlosschleife weil Leitung
> angeblich "Busy"

Welchen Pegel (bitte in Volt) haben die beiden Bus-Leitungen in diesem 
"Busy" Zustand?

von Stefanus (Gast)


Lesenswert?

> Der Sensor läuft generell mit 3,2 V Versorgung

Hat er denn 5V tolerante I/O Leitungen am Bus? Wenn nicht, dann kann es 
so nicht funktionieren, dann brauchst Du Pegelweandler. Dazu gibt's in 
diesem Forum einen eigenen Artikel).

von plexus c. (plexucra)


Lesenswert?

Ich habe die Spannungsversorgung nun generell auf 3,3 V geändert. Also 
sowohl Sensor als auch ATMega8. Bei verbundenen I2C Leitungen Messe ich 
saubere 3,3 V. Pullupwiederstand ist auch vorhanden an jeder der beiden 
Leitungen.
Ich messe zudem keinen Unterschied ob mein Programm im Ruhe-Modus läuft 
(am Anfang _delay_ms(500000);) oder ob er in seiner Endlosschleife 
hängt.

Zudem konnte der Sensor mit einem Arduino ja sauber ausgelesen werden 
was ein Hardwareproblem unwahrscheinlich macht. Wie oben vorgeschlagen 
habe ich es auch mal mit einer "verschobenen" Adresse probiert. Ich 
komme jedoch nie über diese Zeile hinaus:

i2c_start_wait( 0xA2 );

oder

i2c_start_wait( 0x51 );

von plexus c. (plexucra)


Lesenswert?

Habe das Problem gefunden!

In dem Assembler-Code der I2C Bibliothek von Peter Fleury "i2cmaster.S" 
werden die Werte für SDA_PORT und SCL_PORT ohne check mittels "#ifndef" 
einfach mit falschen Werten überschrieben:

#define SDA_PORT        PORTD           // SDA Port D
#define SCL_PORT        PORTD           // SCL Port D

Für einen ATMega liegen diese jedoch bekannterweise am Port C.
Richtig ist also diese Datei direkt anzupassen wie folgt:

#define SDA_PORT        PORTC           // SDA Port D
#define SCL_PORT        PORTC           // SCL Port D

Vielen Dank an Alle die mich hier unterstützt haben.
Ich hoffe diese Lösung hilft jemanden Anderen der auch mal Tomaten auf 
den Augen hat ebenso weiter.

Viele Grüße

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.