Forum: Mikrocontroller und Digitale Elektronik Beschleunigungssensor ADXL345 Probleme bei der SPI Kommunikation


von Stefan (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich versuche seit Tagen, die Kommunikation mit einem ADXL345 
Beschleunigungssensor herzustellen. Leider ohne Erfolg.

Mitlerweile beschränke ich mich auf den Versuch, einfach nur die Device 
ID auszulesen. Aber selbst das gelingt nicht.

Zuerst habe ich versucht, die AVR interne USI Schnittstelle zu 
verwenden, als ich nach zwei Tagen immer noch keine Daten vom ADXL345 
erhielt, habe ich die Kommunikation vollständig in Software umgesetzt, 
um auszuschließen, dass ich bei der Verwendung der USI einen Fehler 
mache.

Leider bietet sich mir exakt das gleiche Bild wie mit der USI.


Habe Euch im Anhang mal die Timing Diagramme angehängt:
1. Timing Diagramm aus dem Datenblatt
2. Timing Diagramm meines Programms 1
3. Timing Diagramm meines Programms 2

Die Zustände in Diagramm 2 und 3 wechseln sich in regelmäßigen Abständen 
ab.

Der Sensor ist per 4 Wire SPI angeschlossen.

Die Zeiten(s. Datenblatt S. 17):
insbesondere:
-tDELAY (CS falling edge to SCLK falling edge)
-tQUIET (SCLK rising edge to CS rising edge)
-tSETUP (SDI valid before SCLK rising edge)

werden eingehalten(delays im Programm).

Link zum Datenblatt des ADXL345:
http://www.analog.com/static/imported-files/data_sheets/ADXL345.pdf
Ab Seite 15 geht die Beschreibung der SPI Kommunikation los.


Viele Grüße und für jeden hilfreichen Beitrag Danke im Vorraus!
Stefan

von Stefan (Gast)


Lesenswert?

Sehe gerade, dass in den Diagrammen teilweise die Beschriftung fehlt 
bzw. durcheinander sind.
Die Signale von oben nach unten:
-  ~CS(active low)
-  SCL
-  SDI
-  SDO

Gruß
Stefan

von Gartenzwergleiche (Gast)


Lesenswert?

Stimmt der SPI mode?

Muesste nach den Bildchen "steigende CLK aktiv" sein.

ist das auch in Deiner Software so eingestellt?

von Gartenzwergleiche (Gast)


Lesenswert?

>Leider ohne Erfolg.

Geht's auch genauer?

>als ich nach zwei Tagen immer noch keine Daten vom ADXL345
>erhielt,

Deine Oszillogramme zeigen das Gegenteil...

Was steht nach der Übertragung eines Bytes im
SPI RX Datenregister?

von Stefan (Gast)


Lesenswert?

Gartenzwergleiche schrieb:
> Was steht nach der Übertragung eines Bytes im
> SPI RX Datenregister?

Lese ich mitlerweile gar nicht mehr aus, da die Oszillogramme ja schon 
Murks zeigen!?

Ich sende ja immer nur: Befehl lesen (R = 1, Bit 7), einfache 
Übertragung(MB = 0, Bit 6) und Adresse 0x00 (Bits 5:0), so dass ja 
eigentlich nur die Device ID ausgegeben werden muss.

Diese lautet 11100101

Danke unf Gruß
Stefan

von Stefan (Gast)


Lesenswert?

Gartenzwergleiche schrieb:
>>Leider ohne Erfolg.
>
> Geht's auch genauer?

Ich erhalte keine gültgen Daten, da ich nur die Device ID auslese und 
diese nicht stimmt(siehe Beitrag oben).

Gruß
Stefan

von Dieter F. (Gast)


Lesenswert?

Schaltung (Pullups?), Code?

von Stefan (Gast)


Lesenswert?

Nabend,

im Bildanhang mal die Zeichenfolge die ich erhalte. Der wechsel zwischen 
0x00 und 0xE6 ist mir nicht ganz klar, wie dieser Zustande kommt. Genau 
so wenig aber auch, warum 0xE6 und nicht 0xE5 (Device ID)


Hier der Code
1
#include <avr/io.h>
2
 
3
//#define F_CPU 8000000UL
4
#define F_CPU 3686400UL
5
6
#include <util/delay.h>
7
#include "usi_isp.c"
8
9
void uart_init(void)   
10
{
11
   #define BAUD 9600
12
   #include <util/setbaud.h>
13
  /* Set baud rate */
14
  UBRRH = UBRRH_VALUE;
15
  UBRRL = UBRRL_VALUE;
16
     #if USE_2X
17
   UCSRA |= (1 << U2X);
18
   #else
19
   UCSRA &= ~(1 << U2X);
20
   #endif
21
  //  Enable receiver and transmitter 
22
  UCSRB = (1<<RXEN)|(1<<TXEN);
23
  // Set frame format: 8data, 
24
  UCSRC = (3<<UCSZ0);
25
26
}  
27
28
 
29
int main (void)
30
{
31
32
  uart_init();
33
  spi_init();
34
   
35
  while (1)
36
  {                         
37
    UDR = spi_read_byte(0x00);
38
    _delay_ms(100);
39
  }
40
41
return 0;
42
}

Datei usi_isp.c
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
//#define SPI_CLK 12500   // spi clock 
5
6
#define CS_PIN PB4    // chip select pin
7
#define CS_REG PORTB  // chip select register
8
#define SPI_DEVICE_T_DELAY 1
9
10
// SPI port and pin definitions.
11
12
#define SPI_PORT  PORTB  //!< SPI port output register.
13
#define SPI_PIN_REG  PINB  //!< SPI port input register.
14
#define SPI_DIR_REG  DDRB  //!< SPI port direction register.
15
#define SPI_CLOCK_PIN  PB7  //!< SPI clock I/O pin.
16
#define SPI_DATAIN_PIN  PB5  //!< SPI data input pin.
17
#define SPI_DATAOUT_PIN  PB6  //!< SPI data output pin.
18
#define SPI_CS_PIN  PB4    //!< SPI Cock Select pin.
19
20
21
void spi_init(){
22
  // outputs
23
  SPI_DIR_REG |= ( 1<< SPI_CLOCK_PIN | 1<< SPI_CS_PIN );
24
  // inputs
25
  // when 4  wire mode is choosen, define DI- and DO- pin mode here
26
}
27
28
29
void spi_chip_enable()
30
{
31
  CS_REG &= ~(1<<CS_PIN); // ~CS = 0 -> enable slave device;
32
  _delay_us(10);  //später durch _delay_cycles ersetzen
33
}
34
35
void spi_chip_disable()
36
{
37
   // _delay_us(SPI_DEVICE_T_DELAY);  // see ADXL345 Data Sheet Figure 37 to 39
38
  _delay_us(10);  //später durch _delay_cycles ersetzen!
39
  CS_REG |= (1<<CS_PIN); // ~CS = 1 -> disable slave device;
40
}
41
42
43
//**************************************************************
44
//***********[ READ BYTE FROM SPI without USI ]*****************
45
//**************************************************************
46
47
unsigned char spi_read_byte( unsigned char address ){
48
49
  unsigned char cnt, data; 
50
51
 //******************** transmitt byte *********************************
52
53
  // configure IO pin functions (not nessesary for 4-wire spi but for 3 wire mode)
54
  SPI_DIR_REG |= ( 1<< SPI_DATAOUT_PIN);  //!< USI port direction register
55
 
56
  // 0x80: read(single byte) mode
57
  data = ( 0x80 | (address & 0x3F) );
58
  cnt = 0;
59
60
  spi_chip_enable();
61
62
  if( ( (data << cnt) & 0x80 ) )    
63
    SPI_PORT |= (1<< SPI_DATAOUT_PIN);  //  
64
  else
65
    SPI_PORT &= ~(1<< SPI_DATAOUT_PIN);  // 
66
67
  _delay_ms(1); // t_delay (ADXL345)
68
69
  //  generate SLK
70
  SPI_PORT &= ~(1<< SPI_CLOCK_PIN);  //  
71
  _delay_ms(20); //  _delay_us(1000000/(2*SPI_CLK));
72
  SPI_PORT |= (1<< SPI_CLOCK_PIN);  //
73
  _delay_ms(20); //  _delay_us(1000000/(2*SPI_CLK));
74
  cnt++;
75
76
  do{
77
    // transmitt data
78
    if( ( (data << cnt) & 0x80 ) )    
79
      SPI_PORT |= (1<< SPI_DATAOUT_PIN);  //  
80
    else
81
      SPI_PORT &= ~(1<< SPI_DATAOUT_PIN);  // 
82
    
83
    //  generate SLK
84
    SPI_PORT &= ~(1<< SPI_CLOCK_PIN);  //  
85
    _delay_ms(20); //  _delay_us(1000000/(2*SPI_CLK));
86
    SPI_PORT |= (1<< SPI_CLOCK_PIN);  //
87
    _delay_ms(20); //  _delay_us(1000000/(2*SPI_CLK));
88
89
    cnt++;
90
91
  }while ( cnt < 8 ); // stop when 8bits are transmitted
92
93
  //******************** receive byte *******************************
94
95
  // configure IO pin functions (not nessesary for 4-wire spi but for 3 wire mode)
96
  SPI_DIR_REG &= ~( 1<< SPI_DATAIN_PIN);  // 
97
  SPI_PORT |= ( 1<< SPI_DATAIN_PIN);
98
  cnt = 0;
99
  data = 0;
100
101
  do{   
102
    //  generate SLK
103
    SPI_PORT &= ~(1<< SPI_CLOCK_PIN);
104
    _delay_ms(20); //  _delay_us(1000000/(2*SPI_CLK));
105
    SPI_PORT |= (1<< SPI_CLOCK_PIN);  //
106
    
107
     // read data from pin DI (sample on rising edge)
108
    if( SPI_PIN_REG & ( 1<< SPI_DATAIN_PIN) ) 
109
     data |= ( 1 << cnt );
110
111
    _delay_ms(20); //  _delay_us(1000000/(2*SPI_CLK));
112
113
     cnt++;
114
   }while ( cnt < 8 ); // stop when 8 bits are transmitted
115
 
116
117
  spi_chip_disable();
118
119
return data;
120
}


Einen Schaltplan müsste ich noch erstellen, ist ein fertiges Modul aus 
dem Netz 
http://hobbycomponents.com/other/431-gy-291-adxl345-triple-axis-accelerometer

SDI, SDA, SCL, CS liegen jedenfalls über Pullups an Vcc

Grüße
Stefan

von Stefan (Gast)


Angehängte Dateien:

Lesenswert?

Bildanhang zu letztem Beitrag

von Stefan (Gast)


Lesenswert?

Stefan schrieb:
> nicht ganz klar, wie dieser Zustande kommt. Genau
> so wenig aber auch, warum 0xE6 und nicht 0xE5 (Device ID)

ausgeben wird.

von Stefan (Gast)


Lesenswert?

Guten Abend,

durch Zufall habe ich die Schaltung zum Laufen bekommen. Der Zufall 
sieht so aus, dass ich dem ADXL345 die GND leitung durchtrennt habe. Er 
verfügt jetzt also nicht mehr über GND, sondern nur SDA,SDO, SLC, und 
CS.

Habe gerade nochmal alle Spannungspegel überprüft und die Qualität mit 
dem Oszilloskop untersucht. Ergebnis, alles einwandfrei.

Da breche ich mir seit jetzt bald einer Woche einen ab und verstehe die 
Welt nicht mehr und jetzt entferne ich durch zufall GND und alles 
geht???

Kann sich das jemand logisch erklären oder hat schonmal ein Ähnliches 
Problem gehabt?

Viele Grüße
Stefan

von Detlef K. (adenin)


Lesenswert?

Stefan schrieb:
> durch Zufall habe ich die Schaltung zum Laufen bekommen. Der Zufall
> sieht so aus, dass ich dem ADXL345 die GND leitung durchtrennt habe. Er
> verfügt jetzt also nicht mehr über GND, sondern nur SDA,SDO, SLC, und
> CS.

Klingt nicht gut.
Das Ding hat ja 3 GND-Pins.
Schaltplan (original!) wäre interessant. Besonders die Verschaltung von 
Pin 3 und 11.

von Stefan (Gast)


Lesenswert?

Wie gesagt, ist ein fertiges Modul gewesen.
http://hobbycomponents.com/other/431-gy-291-adxl345-triple-axis-accelerometer

Werde mich morgen in Ruhe mal dran setzen und das Modul untersuchen und 
einen Schaltplan erstellen. Wobei die Dinger ja in Tausenden verkauft 
werden. Würde daher einen schwerwiegenden Fehler im Schaltplan 
ausschließen.

Es kann ja eigentlich nur ein Bauteil- oder Lötstellendefekt sein.

Gruß
Stefan

von Detlef K. (adenin)


Lesenswert?

Wie erzeugst Du die Beriebsspannung für den AVR und wie hoch ist die?
Abblockkondensatoren drin? Der Schaltplan wäre auch sehr 
aufschlussreich.

von Stefan (Gast)


Lesenswert?

Detlef Kunz schrieb:
> Wie erzeugst Du die Beriebsspannung für den AVR und wie hoch ist die?
> Abblockkondensatoren drin? Der Schaltplan wäre auch sehr
> aufschlussreich.

Der Avr steckt in einem STK500 und die Bertriebsspannung erzeuge ich 
über den boardeigenen VTarget Generator. Habs zwischendrin aber auch 
über externe Spannung versucht, hat auch nicht geholfen.

Gru0
Stefan

von adenin (Gast)


Lesenswert?

Stefan schrieb:
> Detlef Kunz schrieb:
>> Wie erzeugst Du die Beriebsspannung für den AVR und wie hoch ist die?
>> Abblockkondensatoren drin? Der Schaltplan wäre auch sehr
>> aufschlussreich.
>
> Der Avr steckt in einem STK500 und die Bertriebsspannung erzeuge ich
> über den boardeigenen VTarget Generator. Habs zwischendrin aber auch
> über externe Spannung versucht, hat auch nicht geholfen.
>
> Gru0
> Stefan

Nagut, aber wie hoch ist die Betriebsspannung, weil mit 5V wäre das ganz 
schlecht.
Du musst den AVR mit 3.3v betreiben, weil der ADXL auch mit 3.3v 
arbeitet (die kleine Platine hat einen eigenen Spannungsregler).

von Stefan (Gast)


Lesenswert?

adenin schrieb:
> Du musst den AVR mit 3.3v betreiben, weil der ADXL auch mit 3.3v
> arbeitet (die kleine Platine hat einen eigenen Spannungsregler).

Betreibe den AVR mit 3.6V

Gruß
Stefan

von adenin (Gast)


Lesenswert?

Es ist auf alle Fälle keine gute Idee, wenn die Spannung an den AVR-Pins 
größer als die Versorgungsspannung des ADXL ist.

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.