Hallo,
ich möchte das Gyroscope (L3G4200D - ich besitze das Breakout board von
Pololu) gerne auslesen und die Daten dann auf einem Display ausgeben.
Ich nutze einen ATMEGA16 und programmiere in C / C++.
Verbinden möchte ich den Sensor per SPI.
Leider gelingt es mir nicht geeignete Tutorials oder Einsteigertipps
hierzu zufinden. Auf der Pololu-Seite gibt es nur Arduino-Language
Sample-Code. Arduino-Language möchte ich aber nicht nutzen auch wenn
diese c-ähnlich oder was auch immer ist.
Meine konkrete Frage ist also wie ich programmiertechnisch auf die
verschiedenen Register des Sensors zugreifen kann bzw. diese auslese und
in Variablen abspeicher.
Simpelster Beispielcode in c wäre Klasse oder irgendwelche Hinweise wie
ich mich darüber schlau lesen kann.
EDIT: Die grundsätzliche Kommunikation per SPI ist mir bekannt und hat
auch schon mit einem anderen µC funktioniert, allerdings will ich nun ja
verschiedene Register des Sensors auslesen bzw verändern, nur weiß ich
nicht wie das funtioniert.
Anhang meiner bisherigen SPI-Kommunikation siehe SPI.c
Funktioniert Die Kommunikation mit dem Sensor vielleicht so, dass ich
wenn ich das Ctrl_Reg1 auslesen will, dafür folgendes vom Master senden
muss:
1 0 100000
Read | no incre. | Ctrl_Reg1
Daraufhin sendet mir der Sensor das Register und ich kann es aus dem
SPDR auslesen?
Ich kenne mich mit SPI leider noch so gutt wie garnicht aus und möchte
meinen Sensor nicht gleich mit dem ersten "Befehl" zerstören. Ich wäre
sehr dankbar für eine Reaktion!
Florian K. schrieb:> Ich kenne mich mit SPI leider noch so gutt wie garnicht aus
Also darfst du dich SELBST einarbeiten. Dauer: keine 15 Minuten. Im
Datenblatt des Atmega ist ALLES piekfein beschrieben.
Florian K. schrieb:> möchte> meinen Sensor nicht gleich mit dem ersten "Befehl" zerstören
Also wenn du es schaffst, irrtümlich durch einen "falschen" Befehl den
Sensor zu schrotten, dann kommst du in den "Hall of Flame" und ich kaufe
dir einen neuen Sensor :-)
Jetzt aber im Ernst: nur Mut! Programmieren, testen, debuggen... so wie
es auch die Großen machen.
Das ist recht einfach. Ich habe noch Code für den L3G4200D auf der
Platte liegen (geschrieben für einen Atmega64 mit soft SPI). Den müsst
ich aber erstmal raussuchen.
@Dennis: Danke für deine Motivation, leider schaffe ich es dennoch nicht
alleine aus den Datenblättern heraus schlau zu werden, ich möchte auch
garnicht eine fertige Lösung für eine konkrete Aufgabenstellung, mir
würde schon reichen das WHO_AM_I Register auszulesen und in einer
Variable abzuspeichern.
Mein Versuch sieht so aus und gibt mir leider nur 255 zurück, was dann
wohl für 0b11111111 steht und nicht meinem WHO_AM_I Register entspräche!
:(
Kann mir nicht vielleicht jemand weiterhelfen?
Wie gesagt mir reichen wirklich nur die nötigen Zeilen um das WHO_AM_I
Register auf meinem AVR zu empfangen und abzuspeichern.
Hallo Florian,
ich habe mal hier meine BASCOM-Dateien angehäng.
Was ich allerdings benutzt habe war das MinIMU-9 von Pololu
an ein PollinBoard mit ATmega88 drauf. Anschlüsse waren angelötet
mit 10kOhm Pullup-Widerständen gegen +5V.
Auf dem Board sind 3-Achsen Gyro L3G4200D und 3-Achsen Kompass /
Beschleunigungssensor LSM303DLM.
Sollte mal für ein Mikrokopter sein, habe aber schon länger aus
Zeitmangel
nichts mehr damit gemacht.
Ich hoffe du kannst was damit anfangen auch wenn es nur BASIC ist.
Und für alle anderen MitLeser:
-> Bitte verzeiht mein schlechten Programmierstil!
(Aber es hat funktioniert!!)
Holger
@Holger: Vielen Dank für deinen Beitrag, leider suche ich C-Code und SPI
als Kommunikation. Leider kann ich daher mit deinen Dateien nicht viel
anfangen.
Ich verzweifele bald :/
@ Florian,
sorry habs gestern vergessen. Wenn du dich noch bis heute Abend gedulden
kannst - hab die Daten leider nicht auf meinem Arbeitsrechner.
Werde den Code heute abend posten - versprochen ;)
Florian K. schrieb:> Vielen Dank schon einmal ich werde es mir sofort anschauen! :)> Was genau bedeutet diese Zeile Code?>
1
>if(byte&(1<<(7)))
2
>
Ich schau mir das Bit Nummer 7 in der Variablen Byte an und setze
demgemäß meinen Ausgangspin auf 1 oder 0 je nachdem ob das Bit 1 ist
oder 0 ist. Das Ganze wird 8 mal durchgeführt bis das ganze Byze
rausgesendet wurde. Der Code ist deshalb etwas lang geraten. Prinzipiell
kann man den ganzen Spaß auch in einer For-Schleife machen, dann spart
man sich eine Menge Zeilen.
PS:
Deine Ausgangspins musst du natürlich noch entsprechend an dein Design
anpassen. Das vergaß ich oben zu erwähnen.
Ok ich hab es verstanden, ich nahm naiver weise an, das der AVR am
SPI-BUS zumindest die Chip-Select Leitung selbst steuert und ich direkt
eine 8-BIT Zahl senden kann.
Naja aber vielen vielen dank! Du hast mir damit sehr geholfen, heute
habe ich keinen Kopf mehr das anzupassen aber ich werde morgen versuchen
die Register auszulesen und teile dann nochmal mein Ergebnis mit :)
Genau danach habe ich nun Zwei Tage gesucht :D
> Ok ich hab es verstanden, ich nahm naiver weise an, das der AVR am> SPI-BUS zumindest die Chip-Select Leitung selbst steuert und ich direkt> eine 8-BIT Zahl senden kann.
Zur Harware SPI des AVR kann ich nichts sagen. Der Code von oben ist
Soft-SPI - d.h an allen Portpins verwendbar.
Auf jeden Fall viel Erfolg.
Florian K. schrieb:> SPI-BUS zumindest die Chip-Select Leitung selbst steuert und ich direkt> eine 8-BIT Zahl senden kann.
Wieso sollte er das tun? Wäre doch vollkommen sinnlos.
Florian K. schrieb:> OK das erklärt vermutlich so einiges :/>> Dann bin ich weiterhin auf der Suche nach Hilfe!
Bist du denn auf die Hardware SPI angewiesen? Die brauchst du doch nur,
wenn du zeitkritische Anwendungen machst.
@Eumel:
Ich meine überall zu lesen das folgende Zeilen ausreichen um ein Byte
auzulesen:
1
charReadByteSPI(charaddr)
2
{
3
SPDR=addr;//Load byte to Data register
4
while(!(SPSR&(1<<SPIF)));// Wait for transmission complete
5
addr=SPDR;
6
returnaddr;
7
}
Wobei addr zum Beispiel = 0b10001111 ist um das Register WHO_AM_I
auszulesen.
Und als Rückgabewert dann 0b11010011 ausgeben sollte
Ich erhalte allerdings immer als Rückgabewert 255.
@ Jo:
Ja ich möchte wirklich gerne den SPI-BUS verwenden!
Um es nochmal etwas deutlicher zu sagen. Du hast nocht nicht ganz
verstanden wie SPI funktioniert. Deine Funktion ReadByteSPI sendet ein
Byte an deinen Sensor und wartet, dass der Controller mit Senden fertig
ist. Allerdings musst du danach noch ein Byte nachschieben. Dein Sensor
verhält sich nämlich so wie jeder SPI slave. Die machen NICHTS von
alleine.
Also: du schickst 0b10001111 an den Sensor. Der weiß jetzt: "Aha, er
will mein WHO_AM_I Register auslesen" Der Sensor legt dann das
entsprechende Byte in sein Schieberegister. Allerdings kommt das da von
alleine nicht raus, der Master muss es rausschieben. Also sendest du
noch ein Dummybyte hinter. Der Wert dieses Bytes ist EGAL, es dient nur
dazu die von dir gewollten Daten aus dem Sensor rauszuschieben.
Richtig wäre also:
char ReadByteSPI(char addr)
{
SPDR = addr; //Load byte to Data register
while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
SPDR = addr; //Load byte to Data register, wir jetzt als Dummybyte
benutzt!!!!!
while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
addr=SPDR;
return addr;
}
das sollte funktionieren.
Holger E. schrieb:> Hallo Florian,> ich habe mal hier meine BASCOM-Dateien angehäng.> ....>> Ich hoffe du kannst was damit anfangen auch wenn es nur BASIC ist.>> Und für alle anderen MitLeser:> -> Bitte verzeiht mein schlechten Programmierstil!> (Aber es hat funktioniert!!)>> Holger
Holger, genau dieses Beisp. für den minIMU-9 mit BASCOM hab ich gesucht!
Es funktioniert wunderbar!
DANKE!!!!!
Gruß
Hans
Hi,
ich bin auch grad daran, den L3G4200D auszulesen. Mache das aber über
I2C...
Hab alles korrekt angeschlossen und die Kommunikation gelingt auch. Also
Das WhoAmI bekomm ich korrekt zurück.
Wenn ich aber nun die 3 Achsen auslesen möchte, erhalte ich nicht die
erwarteten Wert zurück.
Hier zunächst mal der Code:
1
//*** IC starten ***
2
L3G4200D_PowerUP(250);
3
4
//*** Achsen auslesen ***
5
L3G4200D_GetAxis();
6
7
//*** Temperatur auslesen ***
8
L3G4200D_GetTemp();
9
10
//Konfig:
11
shortL3G4200D_x,L3G4200D_y,L3G4200D_z;
12
shortL3G4200D_Temp;
13
14
voidL3G4200D_PowerUP(intscale){
15
I2C_WriteToDevice(i2c_fd,L3G4200D_REG_CTRL1,0b00001111);//PowerUP, Enable X, Y, Z
Als Ergenis bekomme ich dann:
X: -5
Y: -104
Z: 31
T: 17
X: -25
Y: -101
Z: 63
T: 17
X: 5
Y: -110
Z: 31
T: 17
X: 5
Y: -78
Z: 31
T: 17
X: -37
Y: -141
Z: 15
T: 17
X: -15
Y: -53
Z: 42
T: 17
X: -20
Y: -77
Z: 43
T: 17
X: -14
Y: -82
Z: 41
T: 17
X: 28
Y: -60
Z: 21
T: 16
X: -20
Y: -83
Z: 50
T: 17
X: 10
Y: -95
Z: 31
T: 17
Wie man sieht schwanken die Achsen ziemlich stark, was nicht sein kann,
da der Sensor nur auf dem Tisch liegt. Die Temperatur ist zwar relativ
stabil, jedoch viel zu niedrig...
Hat hierzu jemand eine Idee, was das Problem sein könnte?
In der Konfig ein Register vergessen oder ähnliches?
Hallo nochmal,
wie ich mittlerweile herausgefunden habe ist der Temperatursensor nicht
für die Umgebungstemperatur, sondern für die IC-Temperatur gedacht.
Die Achsenwerte scheinen doch zu stimmen, da der Gyro die Werte in °/s
ausgibt. Und wenn der Sensor nur liegt, bleiben die Werte natürlich
gleich, bis auf die üblichen Schwankungen.