Forum: Mikrocontroller und Digitale Elektronik Probleme mit Code für Gyro ADIS16250


von reflection (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen

Irgendwie druckt wieder mal der Schuh :o) Versuche schon den ganzen Tag 
mein Gyro zum laufen zu bewegen, aber es will nicht so recht.

Hier mal der Code. Es handelt sich um einen ADIS16250 von Analog Device. 
Programmieren tue ich auf einem MSP430 mit mspgcc und Eclipse. Dachte 
mir ich lese zuerst mal die Spannung aus, die kann ich gut überprüfen. 
Die Adresse für die Spannung ist 0x03

float ADIS16250_Read_spannung12bit(unsigned short address)
{
  unsigned int result = 0;           // Variable für Messwert
  float result_temp = 0;             // Variable für Resultat definieren

  P6OUT &= 0xF7;      // setze Chip select P6.3 low

  TXBUF0 = address;                 // Sende Adresse
  while ((IFG1 & UTXIFG0) == 0);    // USART0 TX buffer ready?
  while ((IFG1 & URXIFG0) == 0);    // USART0 RX buffer ready?

  char dummy = RXBUF0;              // RXBUF0 auslesen (somit: löschen
  TXBUF0 = 0x00;                    // Sende Dummy Byte um SCLK zu 
generieren
  while ((IFG1 & UTXIFG0) == 0);        // USART0 TX buffer ready?
  while ((IFG1 & URXIFG0) == 0);        // USART0 RX buffer ready?

  dummy = RXBUF0;

  P6OUT |= 0x08;      // setze chip select high
  delay(100);
  P6OUT &= 0xF7;      // setze chip select low

  TXBUF0 = 0x00;                     // Sende Dummy Byte um SCLK zu 
generieren
  while ((IFG1 & UTXIFG0) == 0);     // USART0 TX buffer ready?
  while ((IFG1 & URXIFG0) == 0);     // USART0 RX buffer ready?

  result = RXBUF0;                   // erhalte MSB des Sensors
  result = result << 8;              // Shifte MSB um 8 nach links

  TXBUF0 = 0x00;                     // Sende Dummy Byte um SCLK zu 
generieren
  while ((IFG1 & UTXIFG0) == 0);     // USART0 TX buffer ready?
  while ((IFG1 & URXIFG0) == 0);     // USART0 RX buffer ready?
  result |= RXBUF0;                  // erhalte LSB des Sensors


  P6OUT |= 0x08;                     // Setze P6.3 high (Chip Select 
ADIS16250 löschen)

  result &= 0x0FFF;    // maskiere oberste 4 bit mit 0

  result_temp = result;              // resultat als float abspeichern
  result_temp = (result_temp * 0.001832);   // Counts in Volt umrechnen

  return result_temp;
}


Hier dann noch wie ich den SPI initialisiert habe:

void init_spi_0(void)
{
  U0CTL |= SWRST;
  P3SEL = 0x0E;                          // Port 3 fur SPI verwenden
  U0CTL = CHAR + SYNC + MM;              // SPI-Modus (8-bit, Master)
  U0TCTL = CKPL + SSEL0 + STC;           // (polarity, ACLK, 3-wire)
  U0BR0 = 0x02;                          // SPICLK = ACLK/2 entspricht 
500kHz
  U0BR1 = 0x00;
  U0MCTL = 0x00;
  ME1 |= USPIE0;                         // Modul aktivieren
  U0CTL &= ~SWRST;                       // SPI aktivieren
}

Ich bekomme ganz komische Werte Werte, meist 7.5….Volt. Das würde 
heissen es sind alles „1er“. Manchmal bekomme auch auch genau die 
Hälfte, 3.75….. und dann wieder 0. Schön immer in der selben 
Reihenfolge.
Habe echt keinen Plan mehr wo ich noch suchen soll. Irgendwas verstehe 
ich an dem Datenblatt falsch. Wäre toll wenn ihr mir helfen könntet.

Gruss reflection

von reflection (Gast)


Lesenswert?

Hat keiner eine Ahnung, habe gester noch den ganzen Abend 
weiterversucht, aber leider ohne Erfolg. Wäre echt toll wenn mir jemand 
weiterhelfen könnte

Gruss reflection

von Ralph (Gast)


Lesenswert?

nimm den folgenden Block raus

  P6OUT |= 0x08;      // setze chip select high
  delay(100);
  P6OUT &= 0xF7;      // setze chip select low


Hat dein µC eine FPU ? Falls nicht lass die FLOAT weg und rechne mit 
Integer.

von reflection (Gast)


Lesenswert?

Das ist nur mal so für einen Test, also das mit dem Floating Point.

Laut Datenblatt wird aber der CS dort kurz high gesetzt. Habe es auch 
schon ohne versucht, aber geht auch nicht.
Ist das mit der Adresse so richtig? Denke da liegt irgendwo mein Fehler. 
(Vielleicht MSB,LSB verdreht oder so) oder setze ich die empfangenen 
Daten falsch zusammen? Habe noch einen Code für einen Pic im Netz 
gefunden. Da schiebt er die Adresse zuerst um 8 nach links. Wieso ist 
mir schleierhaft.

Gruss reflection

von reflection (Gast)


Lesenswert?

Könnte es vielleicht an der Initialisierung des SPI liegen?

Gruss reflection

von J. J. (j_j)


Lesenswert?

Mich irritieren ein paar Sachen in deinem Code.
Wieso betreibst du deinen SPI im 8bit Mode?
Eigentlich solltest du 16 Bit verwenden.

Dann überträgst du ganz zu Anfang die Adresse des gewünschten Registers, 
Ok.
Danach liest du deinen Empfangsbuffer aus der etwas enthält was du nicht 
haben willst.

Danach überträgst du abwechseld 0x00 und liest die Empfangenen Daten 
ein.
0x00 ist aber die Adresse des "Flash Memory Write Counter".

An deiner Stelle würde ich zunächst also erstmal den SPI-Master im 16Bit 
Mode betreibnen.
Und danach lass den Unsinn immer "Dummy"-Daten (die noch nichtmal dummy 
sind) zu übertragen, sondern sende immer deine Zieladresse und lese den 
Empfang ein. Dann  hast du ab dem zweiten Empfangszyklus immer den 
gewünschten Wert.

Gruß

von reflection (Gast)


Lesenswert?

Also ich sende lediglich 0x00 weil das so in einem Timingdiagramm im 
Datenblatt ist. (siehe S. 13/20)

Hm, der TXBuf0 ist beim MSP430 doch nur 8Bit, oder sehe ich das jetzt 
falsch? Ist nicht so schön, ok, aber es sollte doch auch gehen wenn ich 
2x8Bit sende, oder nicht?

"Danach liest du deinen Empfangsbuffer aus der etwas enthält was du 
nicht
haben willst"...

Ja das sieht man auch im DAtenblatt, steht da, das es don't Care Bits 
sind. Denke mal für diese bekomme ich auch eine Antwort vom Gyro. Diesen 
lese ich dann in dummy ein um das Register des SPI wieder frei zu 
bekommen.

Beim zweiten Druchlauf sende ich dann 0x00 um das MSB vom Sensor zu 
erhalten. Danach noch einmal 0x00 um das LSB vom Sensor zu erhalten.
grrrr jetzt sehe ich das 0x00 das Flash Memory ist... Wieso machen die 
das dann im Datenblatt so? (S13/20)

von J. J. (j_j)


Lesenswert?

> "Danach liest du deinen Empfangsbuffer aus der etwas enthält was du
> nicht
> haben willst"...
>
> Ja das sieht man auch im DAtenblatt, steht da, das es don't Care Bits
> sind. Denke mal für diese bekomme ich auch eine Antwort vom Gyro. Diesen
> lese ich dann in dummy ein um das Register des SPI wieder frei zu
> bekommen.
>
Nein, damit meinte ich bloss, dass du erst mit dem zweiten Lesen die 
gewünschten Daten bekommst.

> Beim zweiten Druchlauf sende ich dann 0x00 um das MSB vom Sensor zu
> erhalten. Danach noch einmal 0x00 um das LSB vom Sensor zu erhalten.
> grrrr jetzt sehe ich das 0x00 das Flash Memory ist... Wieso machen die
> das dann im Datenblatt so? (S13/20)
Im Datenblatt gehen sie davon aus, dass deine SPI-Schnittstelle im 
16bit-Mode arbeitet. In dem Fall ist es egal was für einen Wert die 
hinteren 8 bit haben.

Ob man Problemlos den Sensor über 8bit SPI ansprechen kann, das weiss 
ich nicht, in die Verlegenheit bin ich noch nicht gekommen. Da müsste 
sich jemand anderes zu Wort melden.
Evtl. musst du dir sonst ne Softwarelösung basteln.

Gruß

von reflection (Gast)


Lesenswert?

Ich habe glaube ich ein grundsätzliches Verständnisproblem:

Ist das so korrekt?

1. Ich sende die Adresse z.B. 0x03 (8Bit)
2. Ich erhalte dann vom Gyro irgendwelche Daten (8Bit) die ich nicht 
benötige
3. Ich sende 8 Dummy Bits um Clock zu generieren und erhalte wieder 
Daten die ich nicht benötige (vom letzten Zugriff)
4. CS HIGH
5. CS LOW
6. Ich sende irgendetwas und bekomme das MSB des Registers welches ich 
unter Pkt. 1 angesprochen habe
7. Ich sende wieder irgendwas und bekomme das LSB des REgisters welches 
ich unter Pkt. 1 angesprochen habe.

Wenn diese Vorgehensweise stimmen sollte muss es wohl an dem senden der 
0x00 liegen, auch wenn ich das nicht nachvollziehen kann. Wenn ich 0x00 
sende, hat das ja erst für den nächste 16Bit Wert eine Bedeutung oder 
nicht?

Gruss reflection

von reflection (Gast)


Lesenswert?

Hallo zusammen

Habe immer noch grosse Probleme das Ding zum laufen zu kriegen. Im 
Moment bekomme ich zwar Werte aber nur sch...
Was ich nun aber mit erstaunen feststellen musste ist: Ich habe drei 
Gyros montiert, eines auf dem Hauptprint und je eins 90° dazu auf einen 
kleinen steckbaren Printchen. SPI Leitungen sind dennoch rel. kurz 
gehalten. sicher kleiner 5cm. Wenn ich jetzt nur schon eines dieser 
beiden einstecke, bleibt der uP einfach stehen. Also er initialiert 
alles inkl. SPI, gibt mir meinen Startup Screen aus und dann ist 
sense... bleibt einfach stehen das Teil. Stecke ich es aus, und schalte 
mein Gerät erneut ein läuft alles wunderbar (mit dem einen Gyro auf der 
Hauptplatine) Angeschlossen sind die beiden steckbaren genau gleich. 
Gemerkt habe ich es eigentlich wegen der SD Karte, die konnte ich auf 
einmal nicht mehr initialisieren. Als ich dann diesen Teil als Kommentar 
deklarierte passierte eben oben beschriebenes.

Kann es sein, dass ich meinen SPI Bus vom MSP einfach "überlaste"? :o) 
Folgendes läuft an dem Bus:

1x 3-Achsen Beschleunigungsmesser VTI3000
1x SD-Karte
1x LCD (4x20 Zeichen Electronic Assembly blau/weiss)
3x oder besser gesagt halt im Moment 1x Gyro Analog Device ADIS16250

Ist das zu viel? Kann es sein dass die TrieState (oder wie man das 
schreibt) einfach zu niederohmig sind? Ich habe in meinen Leitungen 
übrigens keine Wiederstände drin, weder in Serie, noch Pull-Ups. Tja, 
der Print ist leider komplett SMD und die Gyros waren das einzige was 
ich vorher nicht testen konnte weil die doch einen stolzen Preis haben. 
Der Rest lief absolut problemlos, selbst auf einer mit Kabel 
verdrahteten Lochrasterkarte. Kann also fast keine Wiederstände mehr 
einfügen. Sch.............. :o) Hoffe es liegt vielleicht an was 
anderem, hat von Euch schonmal jemand so ein Prob gehabt?

Gruss reflection

von MD-Gast (Gast)


Lesenswert?

Antwort etwas spät, aber wir haben erst gestern den ADIS16251 in Betrieb 
genommen. Der folgende Codeausschnitt läuft für den ATMEGA128 von ATMEL 
mit WINAVR und eigenen libs, ist ein quick-shot, noch nicht optimiert, 
aber läuft.
Unser Hauptproblem war die Initialisierung der SPI mit CPOL und CPHA, 
also Setup und Sample-Zeitpunkt.

Erfahrungsbericht bisher:
Momentan sind wir von der Genauigkeit des Gyros etwas enttäuscht, da er 
mit 14 Bit bei Einstellung 20°/s zu viel rauscht (ca. +/- 60°/min). 
Zusätzliche Mittelungen helfen natürlich, machen den Gyro aber zu 
langsam. Wir probieren gerade noch ein paar Sachen. Bei Interesse halte 
ich Euch gerne auf dem Laufenden.
1
//----------------------------------------------------------
2
//----------------------------------------------------------
3
#define ADIS_GYRO_OUT    0x04
4
#define ADIS_TEMP_OUT    0x0C
5
#define ADIS_ANGL_OUT           0x0E
6
#define ADIS_GYRO_SENS_AVG  0x38
7
//-----------------------------------------------
8
9
10
//-----------------------------------------------
11
//general SPI-interface to ADIS-device
12
//sends  16Bit OutData to MOSI
13
//returs 16Bit data  from MISO
14
u16 ADIS_getsetData(u16 OutData) {
15
  u16 Result=0;
16
  u08 Count =0;
17
  //
18
  CPUSYS_stopInt();
19
  cbi(PORTB,0);      //Gyro CS
20
  cbi(PORTB,0);
21
  cbi(PORTB,0);
22
  //
23
  OutData&=0xBFFF;     //with !Bit6-Mask
24
  //MSB
25
  SPDR  =(OutData>>8);
26
  Count =255; while((!(SPSR & (1<<SPIF)))&&(Count--));
27
  Result=(u16)SPDR<<8;
28
  //LSB
29
  SPDR  =OutData&0xFF;
30
  Count =255; while((!(SPSR & (1<<SPIF)))&&(Count--));
31
  Result|= SPDR;
32
  //
33
  sbi(PORTB,0);      //Gyro CS
34
  CPUSYS_enabInt();
35
  waituS(5);
36
  //
37
  return Result;
38
}
39
40
u08 ADIS_OldAdr=0xFF;
41
//-----------------------------------------------
42
//reads 16-Bit expression from ADIS-device
43
//Param    Address 6Bit-Address
44
//returns  Data at Address
45
u16 ADIS_readWord(u08 Address) {
46
  //
47
  u08 Adr=Address&0x3F;       //filters read Address and LSB
48
  if (ADIS_OldAdr!=Adr) {
49
    //set Address before reading
50
    ADIS_getsetData((u16)Adr<<8);
51
    ADIS_OldAdr=Adr;
52
  }
53
  return ADIS_getsetData((u16)Adr<<8);
54
}
55
56
//-----------------------------------------------
57
//writes 16-Bit Data to Address of ADIS-device
58
void ADIS_writeWord(u08 Address, u16 Data) {
59
  u08 Adr    =Address&0x3E;   //filters read Address and LSB
60
  ADIS_OldAdr=Adr;
61
  Adr       |=0x80;           //write
62
  //
63
  ADIS_getsetData(((u16)Adr<<8)|(Data&0xFF));
64
  Adr++;
65
  ADIS_getsetData(((u16)Adr<<8)|(Data>>8  ));
66
  //
67
}
68
69
//-----------------------------------------------
70
//writes 16-Bit Data to Address of ADIS-device
71
//with Readback before writing
72
void ADIS_writeWordRB(u08 Address, u16 Data) {
73
  if (ADIS_readWord(Address)!=Data) {
74
    //only write if not already set (non volatile mem-parts)
75
    ADIS_writeWord(Address,Data);
76
  }
77
}
78
79
//-----------------------------------------------
80
//returns 1, if new value was polled
81
//returns Turnrate (0.1 °/min) in &Value
82
u08 ADIS_readTurnrate(s16 *Value) {
83
  u16 Test  =ADIS_readWord(ADIS_GYRO_OUT);
84
  s16 Result=(Test&0x3FFF);
85
  Result    =(Result<<2);  //shift to Minus-Bit
86
  //math-divide
87
  s32 Res=Result;
88
  Res   *=  2748;
89
  Res   /=  4000;
90
  *Value =   Res;
91
  if (Test&0x8000)
92
    return 1;
93
  else
94
    return 0;
95
}
96
97
//-----------------------------------------------
98
s16 ADIS_readTemperature(void) {
99
  s16 Result=(ADIS_readWord(ADIS_TEMP_OUT)&0x3FFF);
100
  //shift to Minus-Bit
101
  Result =(Result<<4);
102
  //math-divide
103
  s32 Res=Result;
104
  Res   *=  1453;
105
  Res   /= 16000;
106
  Res   +=   250;
107
  return Res;
108
}
109
110
//-----------------------------------------------
111
s16 ADIS_readCourse(void) {
112
  s16 Result=(ADIS_readWord(ADIS_ANGL_OUT)&0x3FFF);
113
  //shift to Minus-Bit
114
  //math-divide
115
  s32 Res=Result;
116
  Res*=  3663;
117
  Res/= 10000;
118
  //
119
  return Res;
120
}
121
122
//----------------------------------------------------------
123
//----------------------------------------------------------
124
void ADIS_init(void)
125
{
126
  DDRB =0x07;
127
  PORTB=0xFF;    // Configure SPI-PINs
128
  //
129
  DDRF =0xFF;    //all output for LS245-TestBoard
130
  PORTF=0x20;    //only Dir high for LS245-TestBoard
131
  //PORTF=0x60;    //Dir/CS high
132
  //
133
  waitMS(10);    //reset Gyro
134
  sbi(PORTF,3);  //Gyro-Reset up
135
  waitMS(30);    //reset Gyro
136
  //
137
  //div 16
138
  SPSR= 0;
139
  SPCR=_BV(SPE)|_BV(MSTR)|_BV(SPR0)|_BV(CPOL)|_BV(CPHA);  
140
}

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.