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!
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.
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?
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?
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.
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("")); |
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 :(
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?
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
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?
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
> 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!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.