Forum: Mikrocontroller und Digitale Elektronik I2C hängt mit ADXL345


von Christoph H. (christoph_b)


Lesenswert?

Hallo

Ich habe folgende Frage.

Ich probiere seit Tagen einen ADXL345 an einem Atmega zum laufen zu 
bekommen. Der ADXL345 ist über I2C mit dem Atmega verbunden. Ich habe 
den I2C Bus mit Pullup Widerständen (4.7k ) auf 3.3V gezogen. (Der 
ADXL345 kann nur max 3.9V ab)

Ich setze beim Start folgende Bits

0x2D auf 0x08 // Measure

Wenn ich die Bits 0x32 und 0x33 auslesen will kommt 0 oder teilweise 
sendet der ADXL345 gar nichts.

In der while Schleife setze ich zuerst 0x2D auf 0x08. Danach eine Pause 
von 100µs. Danach will ich das Bit 0x32 und 0x33 auslesen.

Funktioniert nicht wirklich.

Übersehe ich da etwas im Datenblatt?

Habe auch schon verschiedene  FIFO Modes  probiert.
Standard ist das der FIFO bypassed ist. Habe auch schon den FIFO Buffer 
auf Stream gestellt. Ändert aber nichts an meinem Problem.

Wenn ich die Device ID mit 0x00 auslese bekomme ich 0xE5 was richtig ist 
zurück. Daher weis ich das der I2C Bus funktioniert.

Irgendwie scheint der ADXL345 recht kompliziert oder zickig zu sein.

Im Internet finde ich nur Quellcodes für Arduino. Was extrem helfen 
würde wenn jemand eine Code für einen "normalen" Atmega hätte.

Gruß Christoph

von Thomas F. (tomasf)


Lesenswert?

Das Setzten des Registers 0x2D sollte reichen (ich setze zusätzlich nur 
noch DATA_FORMAT). Das solltest Du aber nur einmalig in der 
Start-up-Sequenz tun, nicht jedes Mal, wenn Du einen Wert abrufen 
willst.

Wenn das nicht funktioniert, solltest Du den Wert des Registers 0x2D 
abrufen und überprüfen, ob da die 0x08 wirklich drinsteht, ansonsten 
hast Du doch noch ein Problem mit dem Bus.

TF

von Christoph H. (christoph_b)


Lesenswert?

So habe nun den ADXL345 zum laufen bekommen. Leider werde ich nicht ganz 
schlau was ich mit xData0 und xData1 auslese. Gibt mir Data0 den Wert 
aus und Data1 das Vorzeichen?? Und wie rechne ich die Werte in g um??

Besten Dank

von Christoph H. (christoph_b)


Lesenswert?

So habe nun den ADXL345 zum laufen bekommen.

Da Problem ist nur das wenn ich ihn auf den Kopf stelle falsche Werte
angezeigt bekommen.

z.B
x =2553.5021
y =2546.0371
z =0.2300

Wenn er richtig liegt zeigt er alles richtig an.
x =0.0104
y =0.0780
z =0.9711

Ich multiplizier die Raw daten einfach mit 0.0039.

Gruß Christoph

von spess53 (Gast)


Lesenswert?

Hi

>Da Problem ist nur das wenn ich ihn auf den Kopf stelle falsche Werte
>angezeigt bekommen.
>...
>Ich multiplizier die Raw daten einfach mit 0.0039.

Und wie behandelst du negative Werte?

MfG Spess

von Matthias N. (nippey)


Lesenswert?

Hey ich habe mir den  Adxl 345 nicht genau angesehen  aber wenn er dich 
geradezu so verhält wie der adxl  312: hast du beachtet, dass die werte 
im zweier Komplement abgelegt werden? Sonst schau  mal bitte in die 
Main.c, die ich hier gepostet habe:
http://embdev.net/topic/239501
Ausschnitt:
1
 int x,y,z;
2
  x = (twiSensor.readData[1]<<8)|twiSensor.readData[0];
So würde man ein 16 Bit zweiter Komplement mit Vorzeichen in einen int 
kriegen

von Christoph H. (christoph_b)


Lesenswert?

Hier mein Code
1
/*
2
 * I2C_01.c
3
 *
4
 * Created: 01.12.2011 20:37:21
5
 *  Author: Christoph
6
 */ 
7
#define F_CPU 16000000UL 
8
9
10
typedef enum {
11
  false = 0,
12
  true
13
}bool;
14
15
#include <avr/io.h>
16
#include <mk3/MK3_2560_TWI.h>
17
#include <avr/delay.h>
18
#include <mk3/MK3_2560_LCD.h>
19
20
typedef union{
21
  unsigned char wert_SPI[5];
22
  unsigned short int wert_int[2];
23
}t_union ;
24
t_union u;
25
26
27
28
29
30
31
int main(void)
32
{
33
34
  MK3_INIT_TWI();
35
  MK3_INIT_LCD();
36
  MK3_LCD_CLEAR();
37
38
            
39
  
40
  
41
    while(1)
42
    {
43
44
    
45
  
46
    MK3_TWI_START();
47
      MK3_TWI_SEND(0xA6,false);
48
     MK3_TWI_SEND(0x2D,false);
49
    MK3_TWI_SEND(0x08,false);
50
    MK3_TWI_STOP();
51
    
52
    MK3_TWI_START();
53
      MK3_TWI_SEND(0xA6,false);
54
     MK3_TWI_SEND(0x32,false);
55
    MK3_TWI_SEND(0x03,false);
56
    MK3_TWI_STOP();
57
    
58
    
59
          MK3_TWI_START();
60
    MK3_TWI_SEND(0xA6,false);
61
    MK3_TWI_SEND(0x32,false);
62
    MK3_TWI_START();
63
    MK3_TWI_SEND(0xA6+1,false);
64
    u.wert_SPI[0]=MK3_TWI_READ(false);
65
     MK3_TWI_STOP();
66
     
67
      
68
    MK3_TWI_START();
69
    MK3_TWI_SEND(0xA6,false);
70
    MK3_TWI_SEND(0x34,false);
71
    MK3_TWI_START();
72
    MK3_TWI_SEND(0xA6+1,false);
73
    u.wert_SPI[2]=MK3_TWI_READ(false);
74
     MK3_TWI_STOP();
75
     
76
     
77
         MK3_TWI_START();
78
    MK3_TWI_SEND(0xA6,false);
79
    MK3_TWI_SEND(0x35,false);
80
    MK3_TWI_START();
81
    MK3_TWI_SEND(0xA6+1,false);
82
    u.wert_SPI[3]=MK3_TWI_READ(false);
83
     MK3_TWI_STOP();
84
     
85
      
86
    MK3_TWI_START();
87
    MK3_TWI_SEND(0xA6,false);
88
    MK3_TWI_SEND(0x37,false);
89
    MK3_TWI_START();
90
    MK3_TWI_SEND(0xA6+1,false);
91
    u.wert_SPI[3]=MK3_TWI_READ(false);
92
     MK3_TWI_STOP();
93
    
94
    MK3_TWI_START();
95
    MK3_TWI_SEND(0xA6,false);
96
    MK3_TWI_SEND(0x36,false);
97
    MK3_TWI_START();
98
    MK3_TWI_SEND(0xA6+1,false);
99
    u.wert_SPI[4]=MK3_TWI_READ(false);
100
     MK3_TWI_STOP();
101
     
102
      
103
    MK3_TWI_START();
104
    MK3_TWI_SEND(0xA6,false);
105
    MK3_TWI_SEND(0x37,false);
106
    MK3_TWI_START();
107
    MK3_TWI_SEND(0xA6+1,false);
108
    u.wert_SPI[1]=MK3_TWI_READ(false);
109
     MK3_TWI_STOP();
110
     MK3_LCD_SETCURSOR(0,0);
111
     MK3_LCD_PRINT_FLOAT(u.wert_int[0]*0.0039);
112
     MK3_LCD_SETCURSOR(0,30);
113
     MK3_LCD_PRINT_FLOAT(u.wert_int[1]*0.0039);
114
     MK3_LCD_SETCURSOR(0,50);
115
     MK3_LCD_PRINT_FLOAT(u.wert_int[2]*0.0039);
116
     
117
     _delay_ms(1000);
118
    
119
     
120
     
121
     
122
    
123
124
    }
125
}

von spess53 (Gast)


Lesenswert?

Hi

Das solltest du dringend überarbeiten.

Was sendest du hier

>    MK3_TWI_SEND(0x32,false);
>    MK3_TWI_SEND(0x03,false);

an DATAX0?

In u.wert_SPI[3] liest du 0x35 und 0x37 ein.

Die sechs Register kannst du in einem Rutsch, ohne jedes Register 
einzeln zu adressieren, einlesen.

Also:
0x32 adressieren
0x32...0x36 mit ACK lesen
0x37 mit NACK lesen.

Und wie nippey schon geschrieben hat: Deine Raw-Werte sind signed.

fertig.



MfG Spess

von Alex (Gast)


Lesenswert?

Hi,

ich habe auch ein Problem mit dem ADXL345 und dem I2C-Bus. Ich bekomme 
keine Kommunikation hin.
Ich habe als Controller das FoxBoard G20 
(http://www.acmesystems.it/FOXG20).

Der Bus ist korrekt angeschlossen (Pullup-R usw...)

Hier mein Code:

#include <stdio.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <errno.h>

#define I2C_ADDR 0x53
int POWER_CTL = 0x2D;    //Power Control Register
int DATA_FORMAT = 0x31;
int DATAX0 = 0x32;   //X-Axis Data 0
int DATAX1 = 0x33;   //X-Axis Data 1
int DATAY0 = 0x34;   //Y-Axis Data 0
int DATAY1 = 0x35;   //Y-Axis Data 1
int DATAZ0 = 0x36;   //Z-Axis Data 0
int DATAZ1 = 0x37;   //Z-Axis Data 1

int main (void) {

  int fd;

  fd = open("/dev/i2c-0", O_RDWR);

  if (fd < 0) {
    printf("Error opening file: %s\n", strerror(errno));
    return 1;
  }
  if (ioctl(fd, I2C_SLAVE, I2C_ADDR) < 0) {
    printf("ioctl error: %s\n", strerror(errno));
    return 1;
  }

    //*** Initialisieren ***

    //DATA_FORMAT
  if ((write(fd, &DATA_FORMAT, 0x08)) != 8) {
        printf("Fehler Dataformat: %s\n", strerror(errno));
  }

  //POWER_CONTROL
  if ((write(fd, &POWER_CTL, 0x00)) != 0) {
        printf("Fehler powerctl0: %s\n", strerror(errno));
  }
  if ((write(fd, &POWER_CTL, 0x10)) != 16) {
        printf("Fehler powerctl10: %s\n", strerror(errno));
  }
  if ((write(fd, &POWER_CTL, 0x08)) != 8) {
        printf("Fehler powerctl8: %s\n", strerror(errno));
  }

    char buffer[1];

    if ((read(fd, buffer, sizeof(buffer))) != 1){
        printf( "Error send the read command\n" );
    }

    printf("Value: %d\n\n", buffer);


/*while(1) {

    //This buffer will hold values read from the ADXL345 registers.
    char values[10];
    //These variables will be used to hold the x,y and z axis 
accelerometer values.
    int x, y, z;


  //Value 0x00 to the DATAX0 register.
  write(fd, &DATAX0, 0x00);

    //Lese letztes Register
    read(fd, &values, 6);

    printf("Val0: %d\nVal1: %d\nVal2: %d\nVal3: %d\nVal4: %d\nVal5: 
%d\n\n", values[0], values[1], values[2], values[3], values[4], 
values[5]);

  //The X value is stored in values[0] and values[1].
    x = ((int)values[1]<<8)|(int)values[0];
    //The Y value is stored in values[2] and values[3].
    y = ((int)values[3]<<8)|(int)values[2];
    //The Z value is stored in values[4] and values[5].
    z = ((int)values[5]<<8)|(int)values[4];

    printf("X: %d\nY: %d\nZ: %d\n\n", x, y, z);

    usleep(500000);
}*/
  //printf("Wert: %d\n\n", value);
  return 0;
}

Der Rückgabewert von PowerControl-Register ist immer -1092948896 oder 
ähnliches...

Ich hoffe es kann jemand helfen.

Danke

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.