Forum: Mikrocontroller und Digitale Elektronik i²c kein ACK vom SLAVE


von Felix K. (felix133711)


Angehängte Dateien:

Lesenswert?

Hallo,

ich versuche nun seit kurzem folgendes Modul über i²c anzusprechen:

https://www.adafruit.com/products/815

Ich nutze das Modul, um LEDs zu dimmen. Als Master nutze ich ein 
ATMEGA328p.
Im Ahang befindet sich die i²c Bibliothek, die ich nutze, um das Modul 
anzusprechen. Ein Fehler in der Software kann ich allerdings zu 99% 
auschließen, da ich die Bibliothek bereits nun für mehrere i2c fähigen 
Module erfolgreich genutzt habe.

Kommen wir nun zum Aufbau:

20MHZ Quarz (22pF) -> für Atmega328p
SDA und SCL line sind mit 4k7 auf 5V gezogen

Dieser Aufbau funktionierte bereits mit einem Gyroscope, einem Kompass 
und einem weiteren Atmega238p. (Diese Geräte/ Module hingen an der 
SDA/SCL line).


https://www.adafruit.com/products/815

<-- Dieses Modul liefert nun allerdings kein ACK nach dem Senden der 
device-addr. (0x40)... anscheinend wird es also unter dieser addr. nicht 
gefunden.

Ich habe das Modul nun einfach mal an ein Arduino gehangen (nac 
folgendem Tutorial: 
https://learn.adafruit.com/16-channel-pwm-servo-driver) und das Modul 
wurde sofort erkannt und lieferte auch das gewünschte Ergebnis.

Es liegt also definitiv auch nicht am Modul.

Ich bin nun ziemlich ratlos, was die Fehlerursache betrifft. Hat jemand 
noch eine Idee, woran es noch liegen könnte, dass ich das Modul unter 
der Adresse 0x40 mit meinem Atmega nicht finden kann?

Vielen Dank im vorraus!

von R. R. (elec-lisper)


Lesenswert?

Hast du die Leitungen mal durchgemessen?
Hast du den Bus mal mit nem Oszi oder nem LA belauscht?
Kommt überhaupt was von dem Modul zurück? Ohne ACK
scheint der Bus zu dem Modul ja noch garnicht zu stehen,
müsste also an der Hardware liegen.

von Wolfgang (Gast)


Lesenswert?

Felix K. schrieb:
> <-- Dieses Modul liefert nun allerdings kein ACK nach dem Senden der
> device-addr. (0x40)... anscheinend wird es also unter dieser addr. nicht
> gefunden.

Hast du die Adressjumper auch passend zu dieser Adresse gesetzt?
Warum läßt du nicht einfach mal einen I2C Scanner drüber laufen, der dir 
sagt, auf welchen I2C Adressen sich jemand meldet?

von Karl H. (kbuchegg)


Lesenswert?

Felix K. schrieb:

> Ich bin nun ziemlich ratlos, was die Fehlerursache betrifft. Hat jemand
> noch eine Idee, woran es noch liegen könnte, dass ich das Modul unter
> der Adresse 0x40 mit meinem Atmega nicht finden kann?

Wo hast du die 0x40 her?
Hast du auch daran gedacht, dass eien I2C Adresse eine 7 Bit Adresse 
ist, die um 1 Bit nach links verschoben werden muss, weil im Bit 0 die 
Art des Zugriffs (lesen oder schreiben) codiert wird?

von Felix K. (felix133711)


Lesenswert?

Robin R. schrieb:
> Hast du die Leitungen mal durchgemessen?
> Hast du den Bus mal mit nem Oszi oder nem LA belauscht?
> Kommt überhaupt was von dem Modul zurück? Ohne ACK
> scheint der Bus zu dem Modul ja noch garnicht zu stehen,
> müsste also an der Hardware liegen.

Vielen Dank für die zahlreichen Antworten!

Ich habe mal ein Oszi dazwischengehangen. Screenshot ist im Anhang.

Die Device-addr. gibt mit Adafruit mit 0x40 vor, dass ist die 
Default-Addr. (ohne das ich Jumper setzen muss). Mit dieser Adresse kann 
ich das Modul über ein Arduino ja auch erreichen, das ist das 
merkwürdige.

Das mit der 7 Bit Adresse ist mir auch bewusst - und es funktioniert ja 
wunderbar mit der Biobliothek bei jedem anderem Modul.

von Joachim B. (jar)


Lesenswert?

Wolfgang schrieb:
> Warum läßt du nicht einfach mal einen I2C Scanner drüber laufen, der dir
> sagt, auf welchen I2C Adressen sich jemand meldet?

wäre auch mein Tipp, gleich mal ins arduino setup übernehmen nach 
Serial.begin:
1
  Serial.println(F("\nI2C Scanner -> Scanning..."));
2
3
  byte error, address;
4
  int nDevices=0;
5
  for(address = 1; address < 127; address++ ) 
6
  { // The i2c_scanner uses the return value of
7
    // the Write.endTransmisstion to see if
8
    // a device did acknowledge to the address.
9
    Wire.beginTransmission(address);
10
    error = Wire.endTransmission();
11
12
    if (error == 0)
13
    { Serial.print(F("I2C device found at address 0x"));
14
      if (address<16) 
15
        Serial.print(F("0"));
16
      Serial.print(address,HEX);
17
      Serial.print(F("; "));
18
      if (address<64) 
19
        Serial.print(F("0"));
20
      Serial.print(address,BIN);
21
      Serial.print(F("x; << 0x"));
22
      Serial.print((address<<1),HEX);
23
      Serial.print(F("; "));
24
      if ((address<<1)<128) 
25
        Serial.print(F("0"));
26
      Serial.print((address<<1),BIN);
27
      
28
      switch(address<<1)
29
      {
30
        case 0x40:
31
          Serial.println(F(" PCF8574  Tastatur"));
32
          break;
33
        case 0x70:
34
          Serial.println(F(" PCF8574A Tastatur"));
35
          break;
36
        case 0xA0:
37
          Serial.println(F(" I2C EEPROM       "));
38
          break;
39
        case 0xD0:
40
          Serial.println(F(" DS1307/DS3231 RTC"));
41
          break;
42
        default:
43
          Serial.println(F(""));
44
          break;
45
      }
46
/*      
47
      if((address<<1)==0x40) Serial.println(F(" PCF8574  Tastatur"));
48
      if((address<<1)==0x70) Serial.println(F(" PCF8574A Tastatur"));
49
      if((address<<1)==0xA0) Serial.println(F(" I2C EEPROM       "));
50
      if((address<<1)==0xD0) Serial.println(F(" DS1307/DS3231 RTC"));
51
//      Serial.println(F(""));
52
*/
53
      nDevices++;
54
    }
55
    else if (error==4) 
56
    { Serial.print(F("Unknow error at address 0x"));
57
      if (address<16) 
58
        Serial.print(F("0"));
59
      Serial.println(address,HEX);
60
    }    
61
  }
62
  if (nDevices == 0)
63
    Serial.println(F("No I2C devices found\n"));
64
  else
65
    Serial.println(F("done\n"));
66
  Serial.println(F(""));

von Felix K. (felix133711)


Lesenswert?

Joachim B. schrieb:
> Wolfgang schrieb:
>> Warum läßt du nicht einfach mal einen I2C Scanner drüber laufen, der dir
>> sagt, auf welchen I2C Adressen sich jemand meldet?
>
> wäre auch mein Tipp, gleich mal ins arduino setup übernehmen nach
> Serial.begin:


Das habe ich mit dem Arduino nun auch gemacht. Gefunden wird das Device 
auf 0x40, wie es auch im Datasheet zu finden ist. Muss also irgendwie an 
meinem Circuit liegen :(

von Felix K. (felix133711)


Lesenswert?

Ich habe nun endlich eine Verbindung herstellen können. Habe nun einen 
kleinen Scan mit meinem atmega329p chip gemacht.

1. LCD Display drangehangen
2. Schleife von 0..255
3. Innerhalb der Schleife alle WRITE Anfragen  gesendet:
1
for(uint8_t i = 0;i < 255;i++) {
2
    
3
  i2c_start(i*2);
4
  i2c_stop();
5
}

4. Nun checke ich in jedem Durchlauf das TWSR (statusregister vom TWI) 
und TWDR (dataregsiter vom TWI)

Code vom modifizierten i2c_start()
1
  TWCR = (1 << TWEN) | (1 << TWINT) | (1 << TWSTA); // send start condition
2
  i2c_wait_flag_to_be_set(); // wait until transmission completed
3
  
4
  if(i2c_check_status_register(0x08) == 0) i2c_error(); // check for status register: START CONDITION FIRED
5
  else i2c_success(); // check SLA+W transmitted and ACK rcv'd
6
7
  TWDR = address;
8
  
9
  i2c_clear_flag_and_enable();
10
  i2c_wait_flag_to_be_set();
11
  char buf[8];
12
  itoa(TWDR, buf, 10);
13
  lcd_string(buf);
14
  lcd_string(": ");
15
  itoa(TWSR & 0xF8, buf, 10);
16
  lcd_string(buf);
17
  
18
  _delay_ms(500);  
19
  lcd_clear();


Mein LCD zeigt mir nun bei dem TWDR-Inhalt von "0x80" ein "0x18" (aus 
dem TWSR an --> ACK RECEIVED) an. Das Modul lässt sich somit auf 0x80 
(WRITE) und 0x81 (READ) ansprechen.

Auf dem Arduino klappt es problemlos auf 0x40 (so sollte es laut 
hersteller auch defaultmäßig sein).

Wieso ist die Adresse denn jetzt plötzlich genau das doppelte? :D Das 
ist doch bestimmt kein Zufall oder?

Wieso verdoppelte sich jetzt die Adresse vom PWM-Modul?

von spess53 (Gast)


Lesenswert?

Hi

>Wieso verdoppelte sich jetzt die Adresse vom PWM-Modul?

Weil ein Programm die um eins nach links geschobene Adresse erwartet, 
und das andere das selbst macht.

MfG Spess

von Felix K. (felix133711)


Lesenswert?

spess53 schrieb:
> Hi
>
>>Wieso verdoppelte sich jetzt die Adresse vom PWM-Modul?
>
> Weil ein Programm die um eins nach links geschobene Adresse erwartet,
> und das andere das selbst macht.
>
> MfG Spess

Sorry, da bin ich nicht ganz mitgekommen... Wie meinst du das jetzt 
genau?

von Joachim B. (jar)


Lesenswert?

Felix K. schrieb:
> Wieso verdoppelte sich jetzt die Adresse vom PWM-Modul?

spess53 schrieb:
> Weil ein Programm die um eins nach links geschobene Adresse erwartet,
> und das andere das selbst macht.

genau und wenn du "meinen" geborgten Code ansiehst fallen dir bestimmt 
die  << shifts aus weil je nach Quelle der eine von kuchenbacken redet 
und der andere von popobacken redet. Damit ich da einfach eine gewisse 
Eindeutigkeit bekomme shifte ich immer und bleibe bei der verdoppelten 
Adresse und nicht von 1-127

es ist einfach leichter nach den Datenblätter zu gehen:
http://www.nxp.com/documents/data_sheet/PCF8574.pdf

Die Adresse befindet sich in Bit 1-7, Bit 0 ist nur R/W also muss ich 
eine vorgegebene Adresse 0x40 oder 0x70 nach rechts shiften um sie hier 
zwischen 1-127 zu plazieren, gleichwohl aber danach wieder nach links 
shiften um sie mit den Bits 1-7 in einklang zu bringen, siehe 
Datenblatt:
http://www.nxp.com/documents/data_sheet/PCF8574.pdf
Seite 13

von Felix K. (felix133711)


Lesenswert?

> Die Adresse befindet sich in Bit 1-7, Bit 0 ist nur R/W also muss ich
> eine vorgegebene Adresse 0x40 oder 0x70 nach rechts shiften um sie hier
> zwischen 1-127 zu plazieren, gleichwohl aber danach wieder nach links
> shiften um sie mit den Bits 1-7 in einklang zu bringen, siehe
> Datenblatt:
> http://www.nxp.com/documents/data_sheet/PCF8574.pdf
> Seite 13


Ich danke euch!

von Joachim B. (jar)


Lesenswert?

Felix K. schrieb:
> Ich danke euch!

gerne, ich komme ja vom Atmel Studio und bin beim Nutzen der Arduino IDE 
auch reingefallen, wollte aber nicht umdenken, deswegen shifte ich in 
der Arduino IDE weil dort alle nur von 1-127 gucken.

Das ist besonders unlustig wenn man immer zwischen den Welten schaut -> 
rasPI z.B.

Man wundert sich das dort die Adressen nie so sind wie man sie erwartet, 
noch schlimmer wirds bei Subadressen und fertigen Modulen, mal sind sie 
offen also 1 mal geschlossen also 0, ergo muss man das Erkennen auch 
noch in verschiedenen Subadressen erweitern.

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.