Forum: Mikrocontroller und Digitale Elektronik Beschl-Sensor mit i2C reagiert nicht


von Dshing S. (dshing)


Angehängte Dateien:

Lesenswert?

Hi,
ich hänge bei einem Problem fest und brauche hilfe.

Ich versuche einen MMA8452Q Beschleunigungssensor zum Laufen zu 
bekommen. Ich scheitere bereits daran, das "WHO_AM_I" Byte abzufragen 
(soll immer 0x2A sein)
Ich bin im TWI auch nicht so fit, vielleicht seht ihr ja den Fehler?

Im Code unten ist der TWI ablauf, wie ich denke das er richtig ist.
Das Problem ist, das bereits beim zweiten überprüfen des TWSR ein Fehler 
auftritt. Es kommt nicht zum ACK received sondern zum NACK received. 
Also denke ich mal das der Beschl-Sensor gar nicht reagiert oder? Er 
hängt sich dann auch beim nächsten while auf.
Die Adresse sollte aber die Richtig sein laut Datenblatt (entschiedener 
Auszug siehe Bild). Den SA0 Pin hab ich auf Masse liegen.

Habt ihr einen Tipp?

1
///////////////////////////////STARTBEDINGUNG///////////////////////////////////////////
2
  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);  //TWSTA = TWI START Condition Bit //Sende das START-signal
3
  //////////////////////////////////////////////////////////////////////////
4
  while (!(TWCR & (1<<TWINT)));
5
  //////////////////////////////////////////////////////////////////////////
6
  if ((TWSR & 0xF8) != TW_START && ((TWSR & 0xF8) != TW_REP_START))      //war der start NICHT erfolgreich?
7
  Fehler();//sende das TWSR über UART
8
  TWDR = 0x38;              //wenn alles ok, dann sende das Adressbyte und ob der master lesen oder schreiben will
9
  TWCR = (1<<TWINT) | (1<<TWEN);
10
  //////////////////////////////////////////////////////////////////////////
11
  while (!(TWCR & (1<<TWINT)));
12
  //////////////////////////////////////////////////////////////////////////
13
  if ((TWSR & 0xF8) != TW_MT_SLA_ACK)    //war die Sendung  NICHT erfolgreich?(ACK ok)
14
  Fehler();//sende das TWSR über UART 
15
  TWDR = 0x0D;
16
  TWCR = (1<<TWINT) | (1<<TWEN);
17
  //////////////////////////////////////////////////////////////////////////
18
  while (!(TWCR & (1<<TWINT)));
19
  //////////////////////////////////////////////////////////////////////////
20
  if ((TWSR & 0xF8) != TW_MT_DATA_ACK)    //war die Sendung  NICHT erfolgreich?(ACK ok)
21
  Fehler();//sende das TWSR über UART
22
  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);  //TWSTA = TWI START Condition Bit //Sende das START-signal
23
  TWDR = 0x39;              //wenn alles ok, dann sende das Adressbyte und ob der master lesen oder schreiben will
24
  TWCR = (1<<TWINT) | (1<<TWEN);
25
  //////////////////////////////////////////////////////////////////////////
26
  while(!(TWCR & (1<<TWINT)));
27
  //////////////////////////////////////////////////////////////////////////
28
  if ((TWSR & 0xF8) != TW_MR_SLA_ACK)    //war die Sendung  NICHT erfolgreich?(ACK ok)
29
  Fehler();//sende das TWSR über UART
30
  master_read_data= TWDR;
31
  TWCR = (1<<TWINT) | (1<<TWEN);          //letzte byte empfangen
32
  TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);  // sende das STOP-signal
33
  while(TWCR & (1<<TWSTO));

von PittyJ (Gast)


Lesenswert?

Ich hänge dann immer ein Oszilloskop ran und schaue, ob die Bits auch 
wirklich richtig rein/raus gehen.

von Dshing S. (dshing)


Lesenswert?

Ein Oszilloskop hab ich leider nicht, nur meine Soundkarte, aber die 
kommt da nicht mehr hinterher :/

von Dshing S. (dshing)


Lesenswert?

Also ich hab jetzt alle Adressen mal durch probiet, es ist immer das 
gleicht, also wenn ihr keinen fehler im Code seht, dann muss ja der 
Beschl-Sensor kaputt sein.

von Pull-up (Gast)


Lesenswert?

An die Pull-up Widerstände gedacht?

von xeliH v. (xileh)


Lesenswert?

Hallo Dshing!


Bei Deinem Code kann ich Dir leider nicht helfen, aber wie sieht es mit 
der Beschaltung aus?

- Sind Pullup's dran? 4,7k z.B.
- I²C-Bus zu schnell? Mal auf 100kHz oder erheblich weniger stellen.
- Mal einen I²C-Scan auf alle Adressen (0-127) machen.
- Zappelt es überhaupt auf der Leitung?
  Dafür nehme ich eine Piezo-Tröte ohne Elektronik + 3 R's

   --==10k==-----==1k==-----==10k==--
              I          I
              ---Piezo---


Gruss - xileH

von Stefan (Gast)


Lesenswert?

Wie hast Du denn die Übertragungsrate eingestellt (Register TWBR).

Ein Oszilloskop wäre sehr hilfreich.  Ich kann nur dringend raten, eins 
zu kaufen - ein billiges für 300 Euro wäre schon ok.

von Dennis (Gast)


Lesenswert?

Stefan schrieb:
> Ein Oszilloskop wäre sehr hilfreich.  Ich kann nur dringend raten, eins
> zu kaufen - ein billiges für 300 Euro wäre schon ok.


Oder zumindest soetwas hier:

http://www.saleae.com/logic

Es gibt auch (viel günstigere) China-Nachbauten, die mit der - meiner 
Meinung nach - sehr guten Originalsoftware zusammenarbeiten. Aber 
ehrlicher ist es schon, wenn man die Mühe des Entwicklers schätzt...

von Timmo H. (masterfx)


Lesenswert?

Ohne mir jetzt deinen code im Detail angesehen zu haben, ich lese mit 
folgendem code unter Verwendung der Peter Fleury lib aus (hier nur die 
X-Achse)
1
#include <avr/io.h>
2
#include <util/delay.h>
3
 
4
#include "i2cmaster.h"
5
 
6
#define MMA8452_ADDR 0x38
7
 
8
void i2c_write_reg(uint8_t addr, uint8_t reg, uint8_t val){
9
 
10
    i2c_start(addr+I2C_WRITE);
11
    i2c_write(reg);
12
    i2c_write(val); // Low Noise
13
    i2c_stop();
14
 
15
}
16
 
17
uint8_t i2c_read_reg(uint8_t addr, uint8_t reg){
18
    uint8_t val;
19
 
20
    i2c_start(addr+I2C_WRITE);
21
 
22
    i2c_write(reg); //Status register
23
    i2c_start(addr+I2C_READ);   //Register 1
24
 
25
    val = i2c_readNak();
26
 
27
    i2c_stop();
28
    return val;
29
}
30
 
31
void MMA8452_Act_Stby(uint8_t active_bit){
32
    uint8_t val;
33
 
34
    val = i2c_read_reg(MMA8452_ADDR, 0x2A);
35
 
36
    if(active_bit)
37
        val |= 0x01;
38
    else
39
        val &= ~0x01;
40
 
41
    i2c_write_reg(MMA8452_ADDR, 0x2A,val);
42
 
43
}
44
 
45
int main(void)
46
{
47
    int16_t i=0, last_i, value,abs;
48
    uint8_t last_tsop_state,tsop_state, val;
49
    int16_t x,y,z,x1,y1,z1;
50
    double angle, gk, ak;
51
 
52
    DDRB = (1<<PB2) | (1<<PB1) | (1<<PB0) ;
53
    DDRD = (1<<PD7) | (1<<PD6);
54
    i2c_init();
55
 
56
    MMA8452_Act_Stby(0);
57
 
58
    i2c_write_reg(MMA8452_ADDR, 0x0F, 0x00);
59
 
60
    i2c_write_reg(MMA8452_ADDR, 0x2A, 0x2C);
61
 
62
    i2c_write_reg(MMA8452_ADDR, 0x2B, 0x02);
63
 
64
    MMA8452_Act_Stby(1);
65
 
66
    val = i2c_read_reg(MMA8452_ADDR,0x2A);
67
 
68
    while(1){
69
        i2c_start(MMA8452_ADDR+I2C_WRITE);
70
        i2c_write( 0x01);   //Register 1
71
        i2c_start(MMA8452_ADDR+I2C_READ);   //Register 1
72
 
73
        x = (i2c_readAck()<<8);
74
        x |= i2c_readNak();
75
        x >>= 6;
76
 
77
        i2c_stop();
78
 
79
        _delay_ms(5);
80
81
        UART_putint (x);         
82
 
83
    }
84
}

von Tim (Gast)


Lesenswert?

@xeliH v2: Coole Idee mit dem Piezo.

@Dshing Sung:
Wenn du mehr als ein Projekt mit I2C machen willst besorge dir einen
I2C-Sniffer. Gibt hier auch sehr brauchbare im Forum.
Und ein digitales Oszi.

In deinem Code fehlt nach dem Restart-Befehl an das TWI noch
eine Warteschleife.
Ausserdem fehlt vor
1
master_read_data= TWDR;
noch ein Zwischenschritt in dem du dem TWI sagst das es jetzt
Daten empfangen und mit NAK antworten soll (+ Warteschleife):
1
// Slave hat auf SLA+R ACK gesagt, also TWI 1 Byte hohlen
2
// lassen und mit NAK antworten (0<<TWEA)
3
TWCR = (1<<TWINT) | (1<<TWEN) | (0<<TWEA);  
4
while (!(TWCR & (1<<TWINT))); // Warten bis Daten da.

und das
1
 TWCR = (1<<TWINT) | (1<<TWEN);          //letzte byte empfangen
am ende muss raus.
Apropos warum fragst du da in der Schleife das Stopbit ab?

Du hat die da eine Fehler(); Funktion gebaut...
Woher weißt du von welcher Stelle die Aufgerufen wurde?

von xeliH v. (xileh)


Lesenswert?

@Tim
Das Piezo-Teil läuft in der Firma unter der Bezeichnung "Schnarcher".
Egal ob RS485, RS232, oder TTL, das Teilchen macht diverses Pin-Gezappel 
hörbar. Man kann zwar nicht die Antwort direkt dekodieren, aber man hört 
Veränderung (LED-Geflacker ist schwerer zu interpretieren). Das hilft 
schon mal einen großen Schritt weiter.

@all
Um Daten wirklich sichtbar zu machen wäre die Anschaffung des Bus-Pirat 
sicher nicht die dümmste Idee.

Damit ist SPI-Master, SPI-Sniff, I²C-Master, I²C-Sniff möglich. Also 
quasi das elektronische Schweizer-Taschenmesser.


http://www.watterott.com/de/Bus-Pirate
25€
+ Kabelset
http://www.watterott.com/de/Bus-Pirate-Kabelset-mit-Klemmen
4,95€

macht also ca. 30€ + Versandt

Sowas sollte auf keiner (Hobby-)Werkbank fehlen.


Gruss - xileH

von Dshing S. (dshing)


Lesenswert?

Hi,
also ich hab jetzt getestet den Bus mit langsameren Frequenzen zu fahren 
(normal ist TWBR=32).
Bei 200Hz hab ich mal meine Soundkarte mit hören lassen(siehe Anhang), 
da sah alles soweit i.O. aus. Mit dem Piezo höre ich bei 100kHz ein 
klicken.

Die i2cmaster.h von Fleury bekomme ich nicht richtig eingebunden, da 
kommt dann fehler:
" undefined reference to `i2c_start' "
Weiß nicht stelle mich wohl nur zu blöd an, hab die in der Projektmappe 
drin und sie liegt im gleichen Verzeichnis wie die main.c

Meinen Code hab ich jetzt nach Tim geändert in:
1
///////////////////////////////STARTBEDINGUNG///////////////////////////////////////////
2
  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);  //TWSTA = TWI START Condition Bit //Sende das START-signal
3
  //////////////////////////////////////////////////////////////////////////
4
  while (!(TWCR & (1<<TWINT)));
5
  //////////////////////////////////////////////////////////////////////////
6
  if ((TWSR & 0xF8) != TW_START && ((TWSR & 0xF8) != TW_REP_START))      //war der start NICHT erfolgreich?
7
  Fehler();//sende das TWSR über UART
8
  //UARTAusgang(TWSR);
9
  TWDR = 0x38;              //wenn alles ok, dann sende das Adressbyte und ob der master lesen oder schreiben will
10
  TWCR = (1<<TWINT) | (1<<TWEN);
11
  //////////////////////////////////////////////////////////////////////////
12
  while (!(TWCR & (1<<TWINT)));
13
  //////////////////////////////////////////////////////////////////////////
14
  if ((TWSR & 0xF8) != TW_MT_SLA_ACK)    //war die Sendung  NICHT erfolgreich?(ACK ok)
15
  Fehler();//sende das TWSR über UART 
16
  //UARTAusgang(TWSR);
17
  TWDR = 0x0D;
18
  TWCR = (1<<TWINT) | (1<<TWEN);
19
  //////////////////////////////////////////////////////////////////////////
20
  while (!(TWCR & (1<<TWINT)));
21
  //////////////////////////////////////////////////////////////////////////
22
  if ((TWSR & 0xF8) != TW_MT_DATA_ACK)    //war die Sendung  NICHT erfolgreich?(ACK ok)
23
  Fehler();//sende das TWSR über UART
24
  //UARTAusgang(TWSR);
25
  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);  //TWSTA = TWI START Condition Bit //Sende das START-signal
26
  //////////////////////////////////////////////////////////////////////////
27
  while (!(TWCR & (1<<TWINT)));
28
  //////////////////////////////////////////////////////////////////////////
29
  TWDR = 0x39;              //wenn alles ok, dann sende das Adressbyte und ob der master lesen oder schreiben will
30
  TWCR = (1<<TWINT) | (1<<TWEN);
31
  //////////////////////////////////////////////////////////////////////////
32
  while(!(TWCR & (1<<TWINT)));
33
  //////////////////////////////////////////////////////////////////////////
34
  if ((TWSR & 0xF8) != TW_MR_SLA_ACK)    //war die Sendung  NICHT erfolgreich?(ACK ok)
35
  Fehler();//sende das TWSR über UART
36
  //UARTAusgang(TWSR);
37
  TWCR = (1<<TWINT) | (1<<TWEN) | (0<<TWEA);
38
  //////////////////////////////////////////////////////////////////////////
39
  while (!(TWCR & (1<<TWINT))); // Warten bis Daten da.
40
  //////////////////////////////////////////////////////////////////////////
41
  master_read_data= TWDR;          //letzte byte empfangen
42
  TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);  // sende das STOP-signal
Jetzt sieht man auch woher ich weiß an welcherstelle er mir in Fehler(); 
geht. Ich hab einfach mal an gedem Schritt mir den Status code ausgeben 
lassen. Es ist immer NACK anstatt ACK.
Mit dem While vor dem "master_read_data= TWDR;"  hängt er ich jetzt dort 
natürlich auf, da er nichts bekommt. Wenn ich nicht warte, dann bekommt 
er das 0x39 Byte was ich erst rein geschrieben habe zurück.

Ich hab jetzt auch mal einen anderen MMA8452Q von Hand angelötet, aber 
das bringt auch nichts :(

von Timmo H. (masterfx)


Lesenswert?

Dshing Sung schrieb:
> Die i2cmaster.h von Fleury bekomme ich nicht richtig eingebunden, da
> kommt dann fehler:
> " undefined reference to `i2c_start' "
> Weiß nicht stelle mich wohl nur zu blöd an, hab die in der Projektmappe
> drin und sie liegt im gleichen Verzeichnis wie die main.c
twimaster.c auch angepasst und im Project drin?

von Tim (Gast)


Lesenswert?

>Bei 200Hz hab ich mal meine Soundkarte mit hören lassen(siehe Anhang),
>da sah alles soweit i.O. aus.

Anhang?

>Jetzt sieht man auch woher ich weiß an welcherstelle er mir in Fehler();
>geht. Ich hab einfach mal an gedem Schritt mir den Status code ausgeben
>lassen. Es ist immer NACK anstatt ACK.

Wenn der MMA8452Q gar nicht reagiert sollte bereits beim 1.
if ((TWSR & 0xF8) != TW_MT_SLA_ACK) rausfliegen.
Dann musst da auch abbrechen und ein Stop senden.
Sonst bleibt der logischerweise irgendwo weiter unten hängen.
Wenn der MMA8452Q wirklich auf das SLA+W mit NACK antwortet
hast du ein Hardware Problem. Clock/Data Vertauscht?
Überall 3,3V und gnd dran?

von Dshing S. (dshing)


Angehängte Dateien:

Lesenswert?

Anhang ist jetzt da ;)

Also mit Timos code passiert auch nichts.Ich hab noch mal alle Drähte 
überprüft, aber es ist so wie im Datenblatt angeschlossen.

Vertragen die vielleicht keine Hitze, das ich die zu heiß gelötet habe?
ich meine die können ja nicht alle kaputt sein.

von Dshing S. (dshing)


Angehängte Dateien:

Lesenswert?

Und der SCL!

von Timmo H. (masterfx)


Angehängte Dateien:

Lesenswert?

Zeig mal deinen Aufbau.
Viel falsch kann man bei dem Ding eigentlich nicht mache. Mein letzter
fliegender Aufbau sah so aus wie im Bild, klappt wunderbar :D

von Tim (Gast)


Lesenswert?

Kauf dir mal ein brauchbares digital oszi.
Mit viel Liebe kann man erkennen das da kein ACK nach SLA+W kommt.
Das deckt sich ja auch mit den Angaben vom TWSR.
Also (noch) mal Hardware überprüfen.
Schaltplan? Bild vom Aufbau?

>Vertragen die vielleicht keine Hitze, das ich die zu heiß gelötet habe?
Was ist bei dir zu heiß?

von Dshing S. (dshing)


Angehängte Dateien:

Lesenswert?

Also hier erst mal der Aufbau an sich. Die ersten beiden ersten Bilder 
sind die Sensoren, einmal mit board und einmal abgetötet und per Hand 
verdrahtet.
Dann der mit bord an der Testplatine. Rechts die Spannungsversorgung und 
ein BT-Modul um die Daten am PC zu lesen. Links der µC und in der Mitte 
der a-Sensor. Die beiden nicht angeschlossenen Kabel sind die Interrupt 
Signale. Beim verlöten bin ich dvon ausgegangen, das unter dem Punkt auf 
dem Gehäuse der Pin1 ist.

Gelötet ab ich die Boards mit einem Dampffrasenlotofen und ich glaube 
der war bei 350°C Abschalttemperatur, muss aber nicht stimmen, da werde 
ich nächste Woche versuch noch mal genaueres in Erfahrung zu bringen.
Das per Hand verkabelte hab ich mit einem Heißluft Lötkolben angelötet 
und dann mit einem Normalen Lötkolben gelötet, wie hoch da die 
Temperaturen genau waren lässt sich schwer sagen, aber die waren auch so 
auf ca. 350°C eingestellt.

Ich hab jetzt mal geschaut, was passiert wenn ich den Sensor komplett 
ablasse, dann macht er genau das selbe.
Also ich bekomme: 0x08 0x20 0x30 0x48 (ohne auf Daten warten noch 0x39)
Ich hab den kompletten Code mal in den Anhang gelegt, vielleicht ist ja 
da irgendwo ein Fehler.

von Timmo H. (masterfx)


Lesenswert?

Also ich vermute mal, dass du meintest, dass beim ersten Bild der PIN 1 
unten links ist. Wenn dem so ist hast du SDA (Pin6) vergessen 
anzuschließen und stattdessen SA0 (Pin7) und N/C (Pin8)

Dshing Sung schrieb:
> Beim verlöten bin ich dvon ausgegangen, das unter dem Punkt auf
> dem Gehäuse der Pin1 ist.
Man geht von sowas nicht aus, sondern man schaut ins Datenblatt.

von Ingolf G. (harpax)


Angehängte Dateien:

Lesenswert?

Hallo Dsching!


Wenn ich mir das Bild so ansehe, dann bist Du wohl durcheinander 
gekommen.
Falls unten links wirklich die 1 ist, dann:

Pin6 - SDA
Pin8 - NC

(Timmo ist ja der gleichen Meinung, dafür habe ich Dein Foto 
verunstaltet ;-)

Wenn Du den Lötkolben sowie anwirfst, dann klebe doch noch einige C's 
mit dran. Bitte - dann geht's den kleinen bestimmt wieder besser. :-)
(Siehe anhängliches Datenblatt S.4)

Deine Lötmethode... ähm... 350°C Uiii

Bitte nicht machen!!



Gruss - xileH

von Timmo H. (masterfx)


Lesenswert?

Ingolf Geißler schrieb:
> Deine Lötmethode... ähm... 350°C Uiii
Ist kein Problem, so hab ich mein ding auch gelötet. Man sollte nur die 
Lötzeit so kurz wie möglich halten.
Wenn ich solche ICs mit Heißluft löte, steht die Heißluftlötstation auch 
auf 300-350°C. Was dann unten beim Bauteil ankommt weiß ich nicht, aber 
man kann ja sehr genau beobachten wann das Lötzinn flüssig wird und das 
IC "einrastet", dann geht man langsam wieder weg. Bisher ist mir noch 
nichts kaputt gegangen und ich habe schon einige Dutzend so gelötet 
(Gyros, Beschleunigungssensoren, Magnetsensoren, µC...)
Nur in einen Ofen it 350°C würde ich das ganze nicht stellen, denn da 
wird ja auf jeden Fall das ding auf 350°C aufgeheizt, weil man wohl 
nicht direkt sieht wann die Schmelztemperatur nun erreicht ist.

von Ingolf G. (harpax)


Lesenswert?

@Timmo

OK, wenn man das Schmelzen des Lotes betrachtet und dann abbricht - gut. 
:-)
Bin selber gerade am Pizza-Ofen-Umbau und die ersten Test-LP's sind auch 
unter Schmelzbeobachtung entstanden.



@Dshing

Deine Leiterplatte sieht prima aus!
Aber bei den folgenden Platinen bitte die Stützkondensatoren gleich mit 
vorsehen. Je näher am IC, desto gut! :-)

von Dshing S. (dshing)


Lesenswert?

Ahh Scheibenkleister, mit dem räumlichen Denken hapert es wohl noch bei 
mir.
Also der verdrahtete funktioniert jetzt ^^
Das heißt, dass bei den Anderen irgendwas mit der Verlötung nicht 
stimmt.
Dann schaue ich mal ob ich erstmal aus dem Einen eine Beschleunigung 
raus bekomme.

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.