Hallo, Ich benutze das RD4247Mag3110-Evaluationskit von Freescale zum Aufbau eines eKompasses. Auf diesem Board befindet sich zum einen der MMA8451Q-Beschleunigungssensor(3-Achsen) und der bereits erwähnte Magnetfeldsensor MAG3110(3-Achsen). Die beiden hängen an einem I2C-Bus. Nun hab ich aber dass Problem, dass sich der Beschleunigungssensor ohne Probleme auslesen lässt, aber der Magnetfeldsensor leider Probleme macht. Dieser liefert mir beim ACK-Bit bei richtiger Addressierung ein Bit mit halber VCC, was der Master aber leider (natürlich) als NACK erkennt. Adressiere ich den Magnetfeldsensor absichtlich falsch, liefert er mir ein NACK mit normalem Pegel von VCC, wie es auch normalerweise sein sollte. An den Routinen kanns nicht legen, da der Beschleunigungssensor das gleiche Kommunikationsprotokoll hat wie der Magnetfeldsensor, und dieser ja funktioniert. Ich habe bereits mehrere Pullups von 4,7k bis 1k versucht, leider ändert sich hierbei nichts. Bin momentan Ratlos, und wär für jeden Tip dankbar. Gruß Andy
Kannst du mal das Steuerprogramm für den Magnetfeldsensor posten? Ich hab das Ding auch (funktioniert gut), erinnere mich aber, dass es ein bisschen knifflig in Betrieb zu nehmen war. Wenn ich daheim bin, poste ich mein Steuerprogramm mal.
Wär super von dir. Hier mal der i2c-code, is momentan eh nur ganz simpel gehalten. Wollte damit nur am anfang das auslesen der Register probieren.
1 | #include <stdio.h> |
2 | |
3 | #include "derivative.h" /* include peripheral declarations */ |
4 | |
5 | #define GPIO_PIN_MASK 0x1Fu
|
6 | #define GPIO_PIN(x) (((1)<<(x & GPIO_PIN_MASK)))
|
7 | |
8 | void transfer_complete(void); |
9 | |
10 | int acceleration_x; |
11 | int acceleration_y; |
12 | int debug = 0; |
13 | |
14 | |
15 | int counter; |
16 | int i; |
17 | int test; |
18 | |
19 | int main(void) |
20 | {
|
21 | |
22 | // Turn on I2C0 clock
|
23 | SIM_SCGC4 |= 0xC0; |
24 | |
25 | // Turn on all port clocks
|
26 | SIM_SCGC5 = SIM_SCGC5_PORTA_MASK | SIM_SCGC5_PORTB_MASK | SIM_SCGC5_PORTC_MASK | SIM_SCGC5_PORTD_MASK | SIM_SCGC5_PORTE_MASK | SIM_SCGC5_PORTF_MASK; |
27 | |
28 | // Einstellen des Taktes MCGOUTCLK = 50 MHz
|
29 | MCG_C1 |= MCG_C1_CLKS(2); // Externer Takt als Quelle |
30 | |
31 | PORTE_PCR19 = PORT_PCR_MUX(4); // SCL |
32 | PORTE_PCR18 = PORT_PCR_MUX(4); // SDA |
33 | |
34 | // I2C1 clock configuration
|
35 | I2C0_F = 0x23; // I2C bus clock 100 kHz |
36 | |
37 | for(;;) { |
38 | // read out MMA7660FC tilt register to enable next interrupt
|
39 | I2C0_C1 |= I2C_C1_IICEN_MASK; // enable I2C0 |
40 | I2C0_C1 |= I2C_C1_MST_MASK; // I2C0 is master, start condition |
41 | for (i = 0; i < 100; i++); // wait |
42 | I2C0_C1 |= I2C_C1_TX_MASK; // transmit mode |
43 | I2C0_D = 0x1C; // MMA7660FC write address 1C/38 |
44 | transfer_complete(); // wait until transfer is complete |
45 | if (I2C0_S & I2C_S_RXAK_MASK) |
46 | printf("Fehler, kein ACK bekommen"); |
47 | I2C0_D = 0x07; // address MMA7660FC tilt register 07/0D |
48 | transfer_complete(); // wait until transfer is complete |
49 | if (I2C0_S & I2C_S_RXAK_MASK) |
50 | printf("Fehler, kein ACK bekommen"); |
51 | I2C0_C1 |= I2C_C1_RSTA_MASK; // repeat start condition |
52 | for (i = 0; i < 100; i++); // wait |
53 | I2C0_D = 0x1D; // MMA7660FC read address 1D/39 |
54 | transfer_complete(); // wait until transfer is complete |
55 | if (I2C0_S & I2C_S_RXAK_MASK) |
56 | printf("Fehler, kein ACK bekommen"); |
57 | I2C0_C1 &= ~I2C_C1_TX_MASK; // receive mode |
58 | I2C0_C1 |= I2C_C1_TXAK_MASK; // no acknowledge needed |
59 | acceleration_x = I2C0_D; // dummy read to start receiving |
60 | transfer_complete(); // wait until transfer is complete |
61 | I2C0_C1 &= ~I2C_C1_MST_MASK; // send stop condition |
62 | acceleration_x = I2C0_D; // read out data |
63 | I2C0_C1 &= ~I2C_C1_IICEN_MASK; // disable I2C0 |
64 | |
65 | printf("%d\n\r", acceleration_x); |
66 | |
67 | for (i = 0; i < 100000; i++); // wait |
68 | |
69 | }
|
70 | |
71 | return 0; |
72 | }
|
73 | |
74 | |
75 | |
76 | |
77 | // function to test transfer complete flag
|
78 | void transfer_complete(void) |
79 | {
|
80 | test = 1; |
81 | while (test) |
82 | {
|
83 | if (I2C0_S & I2C_S_TCF_MASK) |
84 | {
|
85 | test = 0; |
86 | }
|
87 | }
|
88 | }
|
Sven B. schrieb: > Ich > hab das Ding auch (funktioniert gut), erinnere mich aber, dass es ein > bisschen knifflig in Betrieb zu nehmen war. Wenn du denn schon mal in Gebrauch hattest, würd mich interresieren welche Genauigkeit du mit dem MAG3110 erreicht hast. z.B wenn ich mich um 90°drehe, wie weit liegt man dann von den wirklichen 90° weg?
Andy S. schrieb: > Sven B. schrieb: >> Ich >> hab das Ding auch (funktioniert gut), erinnere mich aber, dass es ein >> bisschen knifflig in Betrieb zu nehmen war. > > Wenn du denn schon mal in Gebrauch hattest, würd mich interresieren > welche Genauigkeit du mit dem MAG3110 erreicht hast. z.B wenn ich mich > um 90°drehe, wie weit liegt man dann von den wirklichen 90° weg? Kann ich Dir nicht sagen, weil ich bisher nicht in der Lage (bzw. eher zu faul) war, die Werte in Neigungswinkel umzurechnen. Das ist nicht ganz trivial, weil du ja sowas bekommst wie "Projektion des Magnetfeldvektors auf x, y, und z-Achse des Geräts", und der Magnetfeldvektor zeigt irgendwie schräg nach unten und nach Norden. Du bekommst also nichtmal Winkel raus, sondern eben die Projektionen dieses Vektors auf das Koordinatensystem, und daraus müsste man die Winkel erstmal errechnen, und dann noch richtig hindrehen (bzw. andersrum). * Wenn man ein paar Werte mittelt, ist der Jitter aber ~1 Grad. Ich hab mal ein paar Objekte in Blender damit gedreht, das geht recht flüssig (bis darauf, dass die Winkel halt alle total komisch und falsch sind). Zum eigentlichen Problem: Sendest Du denn keine Konfiguration an das Ding? Ich weiß nicht, was das tut, wenn Du alle Steuer-Register nicht initialisierst. Hier ist jedenfalls mal das, was ich mache (auf dem Raspberry Pi, deshalb ein bisschen mehr High-Level):
1 | #include <errno.h> |
2 | #include <string.h> |
3 | #include <stdio.h> |
4 | #include <stdlib.h> |
5 | #include <unistd.h> |
6 | #include <i2c-dev.h> |
7 | #include <i2cbusses.h> |
8 | #include <util.h> |
9 | |
10 | int main() |
11 | {
|
12 | int res, file; |
13 | char filename[20] = "/dev/i2c-0"; |
14 | int axis = 0, byte = 0, count = 0; |
15 | |
16 | file = open_i2c_dev(0, filename, 0); |
17 | set_slave_addr(file, 0x0e, 0); |
18 | |
19 | // DR(3) OS(2) FR(1)
|
20 | unsigned char reg0 = (0b000 << 5) + (0b00 << 3) + (0 << 2) |
21 | // TRIG(1) ACT(1)
|
22 | + (0 << 1) + (1 << 0); |
23 | // ARST(1) Res(1) RAW(1) RST(1) Res(4)
|
24 | unsigned char reg1 = (0b1 << 7) + (0b0 << 5) + (0b0 << 4); |
25 | i2c_smbus_write_byte_data(file, 0x10, reg0); |
26 | i2c_smbus_write_byte_data(file, 0x11, reg1); |
27 | |
28 | // x, y, z offset
|
29 | i2c_smbus_write_byte_data(file, 0x09, 0); |
30 | i2c_smbus_write_byte_data(file, 0x0A, 0); |
31 | i2c_smbus_write_byte_data(file, 0x0B, 0); |
32 | i2c_smbus_write_byte_data(file, 0x0C, 0); |
33 | i2c_smbus_write_byte_data(file, 0x0D, 0b11110110); |
34 | i2c_smbus_write_byte_data(file, 0x0E, 0b11111111); |
35 | |
36 | float fullScale = 925.0; |
37 | |
38 | while ( 1 ) { |
39 | count++; |
40 | res = i2c_smbus_read_byte_data(file, 0x00); |
41 | if ( res != 0xff ) |
42 | continue; |
43 | for ( axis = 0; axis < 3; axis++ ) { |
44 | int value = 0; |
45 | for ( byte = 0; byte <= 1; byte++ ) { |
46 | value += i2c_smbus_read_byte_data(file, axis*2 + 1 + byte) << (1-byte)*8; |
47 | }
|
48 | if ( value >= (1 << 15) ) { |
49 | value -= 1 << 16; |
50 | }
|
51 | printf("%i ", (int) ( value / fullScale )); |
52 | }
|
53 | printf("\n"); |
54 | fflush(stdout); |
55 | }
|
56 | exit(0); |
57 | }
|
Als Slave Address habe ich irgendwie 0x0e, das ist anders als bei Dir, oder? Grüße, Sven _______ * P.S.: Wenn jemand Code dafür hat, den nehme ich gern! :D
Hab auch schon probiert, vorher die register zu konfigurieren, leider kann ich ja ned mit dem Baustein sprechen, was die sache erschwert;:). Die Adresse ist 0x0E, hab ich auch. Du betreibst den baustein alleine am bus oder? Ich werds morgen auch mal mitn raspberry pi ausprobieren, vielleicht gehts so. Aber weshalb mein ACK bei halb Vcc liegt weiss keiner oder? Deshalb funzt die kommunikation leider nicht.
Ah, du hast ein Raspberry Pi? Das ist ja günstig, dann kannst du ja einfach mal meinen Code probieren. Wenn's damit funktioniert, wissen wir immerhin, ob es an der Software oder an der Hardware liegt. Der Baustein ist bei mir allein am Bus, ja. Wegen des ACK habe ich leider überhaupt keine Ahnung. Im Anhang der Code mit Makefile und so.
Jep, werd ich morgen dann mal ausprobieren. Sobald ich mehr weiss, werd ich meine Erkenntnise morgen dann posten.
Also ich hab das Problem gelöst, wobei die Lösung schon sehr komisch ist. Hab jetzt 14,7k Pullups drin, jetzt liegt der Pegel des ACK endlich bei <0,3VCC. Entweder ist auf dem Board ein riesen Serienwiederstand drin, oder der Open-Kollektor Transister des MAG3110 kann den Transistor nicht komplett durchschalten, wobei ich nicht weiss warum und weshalb er das nicht machen sollte. Mit FAST-I2C wirds dann wahrscheinlich nichts mehr bei den Pullups:).
Ich hab das Ding genau so aufgebaut wie im Datenblatt beschrieben [1] und bei mir funktioniert es anstandslos. Weiß ich dann auch nicht. ;) ___ [1] Foto: http://2.bp.blogspot.com/-ymnNCx3JuYI/ULF1COlw4kI/AAAAAAAAAPw/BSSYQvIiNZ4/s1600/magnetometer_front.jpg
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.