MikroKopter-Wiki   •   SHOP   •   Video-Liste   •   MikroKopter-FAQ   •    English translation

Mikrocontroller- & MicroSPS-Forum » Software & Programmierung » Gyro - Daten interpretieren

Gyro - Daten interpretieren

Moderatoren: jamiro, ligi, P_Latzhalter.

Seite: 1 2 >

Autor Neuer Beitrag
Mitglied
Registriert seit: Jul 2008
Beiträge: 59
Hallo,

eine Frage zur Software, ich habe ein Murata Gyro an ein
Explorer 16 Board mit einem PIC32 angeschlossen.
Als PHP Programmierer die ersten Gehversuchen mit Microcontrollern.

Die Software ist soweit schon fertig, (ein fertiges Script zum
Anzeigen eines Potentionmeter (0-3V = Display Anzeige 0-1023)).

Das Gyro zeigt mir die folgenden Werte an
- stehenden ~690
- rechts drehend ~715
- links drehend ~665

Ich hoffe mal mein Aufbau funktioniert.
Schön läßt sich hier auch der Gyro Drift verstehen,
die Mittelposition verändert sich nach und nach.

Meine Frage, wie interpretiert man nun die Daten?
Gibts hierzu, zu den Grundzügen Informationen?

Mein Vermutung.
- Man muß jede Abweichung registrieren und die
Anzahl der Schritte.
- Wäre der Startwert 0 Grad (z.B. 690), könnte man so
immer die Position errechnen.
- Je mehr Messungen desto besser.

Stimmt das soweit, sind die Werte von meinem
Aufbau in etwa richtig. (Zu ungenau?)

Vielen Dank & Viele Grüße
Askan Simon
Mitglied
Registriert seit: Apr 2007
Beiträge: 280
Hi!

Als erstes solltest du den Gyro etwas verstärken. Du hast ja kaum Auflösung! Dann ists prinzipiell ne reine Kalibrierungsfrage. Z.b. am Anfang davon ausgehen, dass dein Gyro nicht bewegt wird, 100 Messwerte sammeln, mittelwert errechnen und immer abziehen. Dann hast du einen Ausschlag um 0 herum. Dann kannste das ganze noch kalibrieren...das ist bei einem Gyro leider nicht ganz so einfach. Folgende Punkte solltest du sicherstellen: a) schnelle Abtastrate (z.b.500Hz-1kHz) b) konstante Zeit (mit Timer triggern!) c) in Ruhe sollte dein Ausgang ca. 0 sein (+ Rauschen). Dann kannst du in jedem Zyklus die Werte aufsummieren (digitales Integral) und z.b. mit nem Taster zurücksetzten. Jetzt brauchste nur noch verlässliche 90° (Tischecke?), drückst auf den Knopf, drehst die Platine um 90° um die Messachse und schreibst dir den Wert auf. Das machst du 10-20mal, dann mittelwert bilden, den durch die Anzahl der Integralzyklen teilen (500 oder 1000) und schon hast du einen Umrechnungswert Messwert für 90°/s Drehgeschwindigkeit. Das ist grob nur für einen Gyro gültig, wobei die auch nicht sooo extrem auseinanderliegen...

mfg
Jast
Mitglied
Registriert seit: Jul 2008
Beiträge: 59
Hallo Jast,

vielen Dank für das Feedback zu diesem doch sehr speziellen Thema.

Gyro verstärken, Auflösung zu gering? Ist hier die Hardware oder
Software gemeint, Sofware via.

 a = 0;
for ( j=0; j<100; j++) {
a += readADC(GYRO);
}
a /= 10; // und nicht durch 100 :-)


Bzgl. der Hardware, hier habe ich den gleichen Aufbau (Verstärkter)
wie vom Mikrokopter. (Ich hoffe mal inständig es ist nicht die Hardware :-)
hier fange ich nämlich so ziemlich bei 0 an).
So sieht mein Aufbau in etwa aus.

Zum meinem Verständnis. Theoretisch

Bzgl. dem Gyro:

Skalierungsfaktor:
0,67 mV/(°/s)

(Ich denke mit der Angabe kann man nix anfangen, da ja das
Signal noch verstärkt wurde)

Bei meinem Script entsprechen 3.3V genau dem digitalen Wert 1023
(gemäß dem Potentiometer) 0V ist 0.

Gemessener Output vom Gyro 2.18V. (gemessen mit dem Multimeter)
Der digitale Wert ist demnach
((1023/3.3) * 2.18) = 675.8.
Passt :-)

Ok, soweit so gut. :-)

Bei 100 Messungen dauern (Fpb=36MHz) jeweils um die 0,0174 sek.
Ich hab hier einen einfachen Timer um die Abfrage gestellt.

OpenTimer45( T4_ON | T4_SOURCE_INT, 0);
WriteTimer45( 0);

for ( j=0; j<100; j++) { // 0.17 sek.
a += readADC(POT);
}

t = ReadTimer45();
f = t/mhz;


Jetzt habe ich den Mittelwert aus 100 Messungen und die
genaue Zeit für 100 Messungen.

Beispiel:

Start:
Mittelwert 690 * Zeit 0,0174 sek = 12,006
(Winkelgeschwindigkeit?)

Nächster Wert:
Mittelwert 682 * Zeit 0,0171 sek = 11,6622
(Winkelgeschwindigkeit?)

Die Differenz aus den beiden Werten +0,3438 gibt dann
die Bewegung in den letzten 0,0171 sek an. Hoffentlich

Oder besser wäre ebenfalls die Zeit zu mitteln,
+0,3438 in (0,0174 sek / 2) + (0,0171 sek / 2) = 0.01725 sek.

(Ob die Zeit überhaupt eine Rolle spielt wohl nicht... da ja jeweils nur die
Ist Position errechnet werden soll, Zeit gleich Jetzt :) .)

Ok, demnach müsste ich einfach nur die Differenz aufaddieren
(hier erster Wert +0,3438 ) um zu einem Wert für die aktuelle
Position zu kommen.

Den Wert dann zu "eichen", +neunzig Grad entsprechen dem Wert
z.B. 44,332. 1 Grad ist dann 44,332/90 - Dreisatz... usw.

Kann mir jemand folgen, bin ich voll auf dem Holzweg?

:-)

Sehr spannendes Thema.

Viele Viele Grüße aus Neuss

Askan Simon
Mitglied
Registriert seit: Jul 2008
Beiträge: 59
Hallo Yast,

so jetzt bin ich soweit (nach obigem Muster) das der Auschlag recht
zuverlässig bei Null bleibt, sofern das Board nicht bewegt wird.
(Plus ein etwas rauschen.)

Abgesehen von Auflösung (Hardware, Software) versteht ich leider
den letzten Schritt nicht.

Zitat
Dann kannst du in jedem Zyklus die Werte aufsummieren (digitales Integral)
um mit einem Schalter zurücksetzen.


Könntest Du mir das vielleicht noch kurz erklären?
Wär super.

Vielen Dank
Askan
MK-Betatester
Registriert seit: Jan 2008
Beiträge: 607
Der Gyro misst nur Winkelgeschwindigkeit omega, also die zeitabhängige Winkeländerung.
Um zu einem Winkel zu gelangen muss man integrieren:

angle(T) = integral(omega(t)*dt, t=0..T) + angle(T=0)

im code dann

omega = gyro - gyro_offset;

Angle = Angle + omega; // digitales integral

Mit zurücksetzten ist Angle = 0 gemeint.

Das Problem bei der Bestimmung des Lagewinkels ist das Rauschen und die Drift des Gyrooffsets. Die gaukelt einem dann über die Zeit eine gewisse Drehrate vor. Daher wird im MK zusätzlich nich ein Beschleunigungssensor verwendet, der die
die absolute Lage durch das Gravitationsfeld bestimmt. Damit wird das Gyrointegral bzw der Gyro_Offset korregiert.

Da neben der statischen Erdbeschleunigung noch die dynamische Beschleuning des Fluges hinzukommt, kann die Lagebestimmung über den Beschleunigungssensor schon mal heftig daneben liegen. Daher wird die Korrektur nur über den zeitlichen Mittelwert des Beschleunigugssensors berechnet.
Mitglied
Registriert seit: Jul 2008
Beiträge: 59
ui, ich seh jetzt nicht direkt einen unterschied zu meinem Mini-Script... (?)
Mein Quellcode.

// Mittelwert errechen
for (i = 0; i < 100; i++) {
gyro += ADC
}
gyro /= 100;

// Winkel berechnen
omega = gyro - gyro_offset;
Angle = Angle + omega;
gyro_offset = gyro


Die Variablennamen habe ich angepasst, nur das bei mir wieder nur
die/eine Winkelgeschwindigkeit ausgegeben wird.

Steht das Board ruhig = 0
Langsam Aufwärt = 5
Schnell Abwärts = -50
Steht wieder still = 0

usw.

Positive und Negative Omega (Abbremsen?) gleichen sich aus.
Das Addieren klappt wohl noch nicht ganz, (kopfschüttelnd..)
ist jetzt zu spät und ich sitz zu lange dran.

vielleicht sehe ich das morgen. naja

Nochmals vielen Dank
und Viele Grüße aus Neuss
Askan
Mitglied
Registriert seit: Apr 2007
Beiträge: 2241
Dieser Fred mausert sich zum 1*1 der Ufo-Theorie... :P
Macht mal step-by-step weiter. Das ist richtig spannend. Wenn das so detailliert abgehandelt wird, hat keiner mehr Horror vor Schiefständen oder anderen Effekten.
_______________
;-)
Mitglied
Registriert seit: Jul 2008
Beiträge: 59
So einen kleinen Schritt weiter,

ich hab mich heute hingesetzt und versucht etwas zum addieren zu finden was in der Summe
nicht nicht wieder 0 ergibt. Nach einigen Stunden :-) :

User image

Der Quellcode sieht dann so aus.

 // Mittelwert errechen
for (i = 0; i < 100; i++) {
gyro += ADC
}
gyro /= 100;

offset = gyro - gyro_alt;
integral = integral_alt + offset;

gyro_alt = gyro;
integral_alt = integral;


Integral ist hier dann einen Winkel (noch nicht auf Grad geeicht).

Auf meinem Explorer Board gibt das dann Werte von 50 (0 Grad)
bis 2500 (90 Grad).

Nur, ist meine Auflösung mit 680 bis 720 (siehe oben) ganz schlecht
und die Anzeige driftet schnell nach oben (nach fünf Minuten sind
bei 0 Grad nicht mehr 50 in der Anzeige sonder ca. 8000 ! :-))

So ganz fertig ist es wohl noch nicht. ;)

Jetzt kommt wohl noch

- ADC Setting PIC32 - Genauere Messwerte
- Auslösen der ADC Messung über Interrupts (Wie beim Mikrokopter - vermutlich besser
als eine Schleife)

Ob's dann besser ist? mal schaun

Sofern jemand noch einen Fehler sieht oder noch was einfällt,
würde ich mich über Feedback sehr freuen.

Fortschritte werde ich hier posten.

Soweit Viele Grüße
Askan Simon
MK-Betatester
Registriert seit: May 2007
Beiträge: 574
Ort: Otterbach bei Kaiserslautern
Hi,

klar das dein Gyrowert nach oben wegläuft.
for (i = 0; i < 100; i++) { 
gyro += ADC
}
gyro /= 100;


Du setzt nirgendwo (wenigsten nicht im Codeschnippsel zu sehn) gyro = 0

Da du immer gyro += ADC MUSS gyro immer größer werden.
Du hast nämlich 101 Werte, teilst aber nur durch 100.
Vor der Mittelwertschleife gyro = 0 setzen, sonst hast du immer noch den Rest von vorher drin.

Bye
Mikeljo
Mitglied
Registriert seit: Jul 2008
Beiträge: 59
Hallo Mikeljo,

danke für die Info. Leider hab ich das schon so, ich hatte das nur vereinfacht,
hier der komplette Quellcode (main function)

 // initializations
initADC( AINPUTS);
initLCD();

while(1) {

// Abfrage
mittelwert = 0;
for (i = 0; i < 100; i++) {
mittelwert += readADC(POT);
}
mittelwert /= 100;

// Winkelwert bilden
winkelwert = mittelwert; //* zeit;

if (warmlaufen) {
clrLCD();
putsLCD("Loading...");
warmlaufen--;
} else {

current = (winkelwert - winkelwert_alt);
integral = integral_alt + current;
current_sum_plus += integral;

// Debug Anzeige
counter++;
if (counter == 60) {
clrLCD();
sprintf(lesbar, "%4d", current_sum_plus);
putsLCD(lesbar);

counter = 1;
}
}

winkelwert_alt = winkelwert;
integral_alt = integral;
}



Kann mir jemand vielleicht noch die Info geben, was ich als Auflösung normalerweise bei den
Gyros bräuchte. Welche Werte kommen bei einem FlightCtrl Board aus dem AD Wandler?

Ich hab ja nur so 670-720... ganz schlecht. Gibt da vielleicht Debugwerte oder ähnliches.

Bei Microchip hatte man mir - auf meine Anfrage - komischer Weise einen
externen AD Wandler empfohlen. Mit 12bit oder 16bit.

PIC32 hat wohl nur 10bit. Spielraum 0-1023.

Wen dem so ist müßte ich dann doch was an der Hardware machen.
Obwohl das kann ja nicht sein, das das mit dem FlightCtrl Mikrokontroller klappt
und mit dem PIC32 nicht, oder?

Danke, Viele Viele Grüße
Askan
Mitglied
Registriert seit: Jun 2007
Beiträge: 260
Der Atmega hat auch "nur" eine 10-bit-Auflösung. Der Abgleich der Gyro-Nullspannung ist wichtig, damit der digitalisierte Wert ca. bei 500 liegt. Man hat dann für die Links- sowie die Rechtsdrehung die gleiche Auflöäsung von 0-500 bzw. 500-1023.

Eine höhere Auflösung kann man auch durch "oversampling" erreichen.



Gruß.
MK-Betatester
Registriert seit: May 2007
Beiträge: 574
Ort: Otterbach bei Kaiserslautern
Hi,

ABSimon:

hab nochmal gedacht. :D

Die Mittelwertbildung (/100) des Gyrowertes erfolgt nur EINMALIG um den Gyrooffset zu bestimmen.
Mit diesem Wert "normierst" du nachher den Gyrowert auf 0 (null).

Bei der späteren Berechnung wird der Wert direkt genommen. Nix Mittelwert!!

Außerdem darfst du des ADC Wert nicht so schnell abfragen. Die Wandlung braucht Zeit! So wie du den ADC/Mittelwert abfragst/bildest bekommst du 100mal den selben Wert zurück. :roll:

Entweder man startet die Wandlung von Hand und wartet bis sie fertig ist. Flag gesetzt/gelöscht wird.
Oder der ADC Wandler läuft ständig und meldet sich per Interrupt wenn er fertig ist.
In der Interruptroutine holst du dir dann den Wert ab und aktivierts die Wandlung für den nächsten Kanal.
Schau in die "analog.c" der FC rein. Geht auch einfacher z.B. über ein Array.
Interrupt hat auch den Vorteil das du ein definiertes Zeitraster hast.

Was soll die Routine "warmlaufen" in der Mainloop? Das gehört davor.

Wenn du den Code etwas aufräumst, fällt dir auch auf das du ein paar Dinge doppelt tust. :?

Bye
Mikeljo
Mitglied
Registriert seit: Jul 2008
Beiträge: 59
Hallo Nick666,

vielen Dank.

Könntest Du vielleicht beim Atmega noch den Ausschlag abschätzen,
wenn man das Board z.B. langsam um 45 Grad nach rechts und links dreht.

z.B.
Messwerte zwischen 300-700 = 500 "Spielraum"

oder
Messwerte zwischen 480-520 = 40 "Spielraum" (wie bei mir...)

Ich weiß noch nicht genau welche Auflösung ich erzielen muß
um vernünftig rechnen zu können.

Mit dem Multimeter habe ich bei PIN 1 (für GY_N) am IC2 des Flight-Ctrl
bei schnellerem "Rütteln" (sehr präszise ich weiß)
2,0V bis 2,6V. Ist das Min/Max in etwa ok, oder stimmt da was nicht,
müßte die Winkelgeschwindigkeit nicht eigentlich von z.B. 0V bis 3,3V
angezeigt werden?

Denn dann würd etwas an der Hardware nicht stimmen.
(Ich glaub teste mal ein zweites Gyro.)

Viele Grüße aus Neuss
Askan
MK-Betatester
Registriert seit: May 2007
Beiträge: 574
Ort: Otterbach bei Kaiserslautern
Hi,
ABSimon meinte
Mit dem Multimeter habe ich bei PIN 1 (für GY_N) am IC2 des Flight-Ctrl
bei schnellerem "Rütteln" (sehr präszise ich weiß)
2,0V bis 2,6V. Ist das Min/Max in etwa ok, oder stimmt da was nicht,
müßte die Winkelgeschwindigkeit nicht eigentlich von z.B. 0V bis 3,3V
angezeigt werden?


Schnelles Schütteln bringt dir mit einem Multimeter gar nix. :roll:
Dafür ist ein Standart Multimeter viel zu träge. Das geht nur mit einem Scope.
Wenn du nur ein DMM hast, geht nur eine gleichförmige (Dreh)Bewegung in EINE Richtung um was messen zu können.

Schau in das Datenblatt der Gyros. Dort steht drin welche Spannung( delta-V) pro Grad pro Sekunde ausgegeben wird. Damit kannst du "abschätzen" welche Spannungsänderung du messen könntest.

Bye
Mikeljo
Mitglied
Registriert seit: Jul 2008
Beiträge: 59
Hallo mikeljo,

super Vielen Dank.

Zitat
Die Mittelwertbildung (/100) des Gyrowertes erfolgt nur EINMALIG um den Gyrooffset zu bestimmen.
Mit diesem Wert "normierst" du nachher den Gyrowert auf 0 (null).


Probier ich gleich mal aus.

Zitat
Außerdem darfst du des ADC Wert nicht so schnell abfragen.


Die Funktion hat eine Warteschleife.

int readADC( int ch)
{
AD1CHSbits.CH0SA = ch; // select analog input channel
AD1CON1bits.SAMP = 1; // start sampling
while (!AD1CON1bits.DONE); // wait to complete conversion
return ADC1BUF0; // read the conversion result
}


Müßte so eigentlich klappen.

Langsames Drehen (gemessen mit dem Digital Multimeter - mehr hab ich nicht...)
gibt Werte zwischen 2,2V (Rechts) bis 2,4V (Links). Mit den Ausschlägen wird
das wohl nix.

Mit dem Schätzen der Spannungsänderung,
da ist ja noch ein Verstärker dazwischen. (Das Gyro hat 0,67 mV/(°/s). )
An dem Gyro messe ich minimale Ausschläge um 1.49V bis 1,51 V....

Als Alternative könnte man wohl noch die Referenzspannung verändern,

Zitat
If this is a small change in voltage e.g. from 2.1V to 2.5V then you need to either...
1. Amplify and level shift the signal so that is operates near the input range of the PIC (3,3V)
(Could be done with one or two op-amps and a reference voltage)

2. Set AVref+ and AVref- inputs to the limit of you r input signal.
(Note: if ADC operating over low range, it possibly may not give full 10 bit accuracy any more)


oder einen anderen PIC verwenden. PIC24H und dsPIC33F haben 12 Bit ADC.
(soweit die Infos aus dem Netz)

Ist es eigentlich normal, das sobald das GyroSignal abgeklemmt wird
der ADC Wandler vom PIC32 im Explorer Board 16 ein Rauschen von 140-180 anzeigt?
Entspricht ja fast der Auflösung vom Gyro..

Gar nicht mal so einfach... ;)

Soweit Vielen Grüße aus Neuss
Askan Simon
Mitglied
Registriert seit: Jul 2008
Beiträge: 59
Hallo,

so nun der letze Stand

 // Mittelwert errechen
offset = 0;
for (i = 0; i < 100; i++) {
offset += readADC(GYRO);
}
offset /= 100;

integral = 0;
gyro = 0;
i = 1;
while(1) {

// Integral Rechnung
gyro = readADC(GYRO);
integral += gyro - offset;

}


Kann ich mir jetzt garnicht vorstellen wie das so schwierig war :)

Läuft aber leider immer noch aus dem Ruder, recht konstant ca. 1000 Schritte pro Sekunde
nach oben. Ansonsten würde ich sagen, es funktioniert.

Hat hier jemand eine Idee?

Danke nochmals für die Hilfe & Viele Grüße
Askan
MK-Betatester
Registriert seit: May 2007
Beiträge: 574
Ort: Otterbach bei Kaiserslautern
Hi,

integral += gyro - offset;


mach das mal Spaßeshalber in 2 Zeilen.

gyro -= offset;
integral += gyro;


Hab schon die leidige :evil: Erfahrung gemacht das die Compiler nicht immer das machen was man will.

Hast du dir mal den Gyrowert ausgeben lassen?
Also ohne Offset.
Dann müßte der Schnippsel so ausshen:

temp = gyro - offset;
integral += temp;

print(offset, gyro, integral); // Die genaue Syntax weißt du ja ;)

Um mal zu sehn was die Werte so machen.

Bye
Mikeljo
Mitglied
Registriert seit: Jul 2008
Beiträge: 59
Hallo Mikeljo,

die Gyro werte sehen eigentlich ganz gut aus,

integral = gyro - offset
28211 = 667 - 667


Das Gyro zeigt hier eine Tendenz, 667 bis 671 (0 bis +3)
Es scheint so als sei der offset nicht ganz korrekt.
Ein Test mit offset += 1 ergibt

integral = gyro - offset + 1
-8911 = 668 - 668


Das Gyro zeigt hier eine Tendenz, 666 bis 669 (-1 bis +2)
und das Integral galoppiert nach unten.

Sprich die Auflösung des Offsets ist zu gering.
Spielt sich alles im Bereich von 0-1 ab.

Ich mach das mal mit float zahlen.

Viele Grüße
Askan
MK-Betatester
Registriert seit: May 2007
Beiträge: 574
Ort: Otterbach bei Kaiserslautern
Hi,

float is böse. :evil:

Bilde mal deinen Mittelwert anders.
Addier 2 Werte teil dies durch 2 und das ganze 100 mal.
In etwa so:
offset = readADC(GYRO);
for (i = 0; i < 100; i++) {
offset += readADC(GYRO);
offset /=2;
}


Und denk nicht, das ist viel langsamer. Im gegenteil, da die division durch 2 (LSR) extrem schnell ist dürfte die Schleife so schneller sein. Die meiste Zeit verbummelt sie eh beim Warten auf die ADC Wandlung.

Wie ist eigentlich deine definition der Variablen?

Bye
Mikeljo
Mitglied
Registriert seit: Aug 2007
Beiträge: 17
Ort: Obertshausen
@mikeljo:
Du berechnest aber nicht den Mittelwert, sondern einen exponentiellen Zerfall:
offset(T_ende) = Summe{ 2^-(T_ende - t) * gyrowert(t)} wobei t von T_0 bis T_ende laeuft.
Mitglied
Registriert seit: Jul 2008
Beiträge: 100
Ort: Mühldorf a. Inn
Float würde ich auch eher vermeiden. Wenn die Auflösung nicht reicht, besser größere Integer verwenden (wenn sein muss 32bit).
[Edit] Anscheinend verwendest Du sowieso schon 32bit Integer; sonst hättest Du bei 100*offset += readADC(GYRO); schon einen Overflov (667*100=66700 also größer 65536)
[End Edit]
Die Div durch Shift zu ersetzen ist eigentlich üblich, aber eher im Sinne von höheren Zweierpotenzen. Wenn es nicht zu zeitkritisch ist, könntest Du ja auch die aktuellen Messungen ein wenig 'häufiger' durchführen.
Pseudocode (ich bin nicht sicher ob der Compiler das so versteht - bin kein C-Programmierer...):

1. Offset messen/berechnen

// Mittelwert errechen
offset = 0;
for (i = 0; i < 128; i++) {
offset += readADC(GYRO);
}
offset = offset >> 4; // entspricht /16; offset ist also 8* 'Normalwert'

2. Aktuellen Wert messen und integrieren

integral = 0;
gyro = 0;
i = 1; //warum??
while(1) {

// Integral Rechnung
gyro = 0;
for (i = 0; i < 8; i++) {
gyro += readADC(GYRO);
}
gyro = gyro - offset;
gyro = gyro >> 3 // wieder durch 8 teilen - sollte daher eher 0 bleiben :)
integral += gyro
« Bearbeitet von borax am 01.08.2008. »
Mitglied
Registriert seit: Jul 2008
Beiträge: 59
Hallo Zusammen,

vielen Dank. Sehr gute Ideen. Leider alles ohne Erfolg.
Selbst diese Berechnung vom Offset und vom aktuellen Wert
mit identischer Methode ergab keinen konstanten Wert.

// configuration bit settings, Fcy=72MHz, Fpb=36MHz
#pragma config POSCMOD=XT, FNOSC=PRIPLL
#pragma config FPLLIDIV=DIV_2, FPLLMUL=MUL_18, FPLLODIV=DIV_1
#pragma config FPBDIV=DIV_2, FWDTEN=OFF, CP=OFF, BWP=OFF

#include <p32xxxx.h>
#include <plib.h>
#include <explore.h>
#include <LCD.h>

#define GYRO 9 // on AN9 input
#define AINPUTS 0xffcf // Analog inputs for POT and TSENS

void initADC( int amask) {
AD1PCFG = amask; // select analog input pins
AD1CON1 = 0x00E0; // auto convert after end of sampling
AD1CSSL = 0; // no scanning required
AD1CON2 = 0; // use MUXA, AVss/AVdd used as Vref+/-
AD1CON3 = 0x1F3F; // max sample time = 31Tad
AD1CON1SET = 0x8000;// turn on the ADC
} //initADC


int readADC( int ch) {
AD1CHSbits.CH0SA = ch; // select analog input channel
AD1CON1bits.SAMP = 1; // start sampling
while (!AD1CON1bits.DONE); // wait to complete conversion
return ADC1BUF0; // read the conversion result
} // readADC


main () {

char my_string[12];
int i, j, gyro, offset, integral;

// initializations
initADC(AINPUTS);
initLCD();

Delayms(2000);

integral = 0;
gyro = 0;
j = 1;
while(1) {

gyro = 0;
for (i = 0; i < 50; i++) {
gyro += readADC(GYRO);
}
gyro /= 50;

gyro -= offset;
integral += gyro;

j++;
if (j == 150) {
j = 1;

clrLCD();
sprintf(my_string, "%4d", integral);
putsLCD(my_string);
//sprintf(my_string, "\t %4d", offset);
//putsLCD(my_string);
sprintf(my_string, "\n %4d", gyro);
putsLCD(my_string);
}
}
}


Ich hab mal test weise in 100 Zyklen im Stand den minimalen und maximalen Wert vom Gyro
abgefangen. 671 und 676. (!)

Gerade bei meiner kleinen Auflösung, hätte ich die größten Chancen das
der Wert konstant bleibt (z.B. nur 674).

Ich denke mein Explorer Board ist einfach zu noisy (rauschen). Oder?
Hier ist ja ganz viel verbaut, siehe http://www.segger.com/jpg/EvalBoards/Explorer_16_Microchip_600x468.jpg

Alternativ hätte ich hier noch einen dsPIC33 mit 12 bit ADC.

Brauch ich demnach einen externen ADC?

Vielen Dank & Viele Grüße
Askan
MK-Betatester
Registriert seit: May 2007
Beiträge: 574
Ort: Otterbach bei Kaiserslautern
Hi,
Sleipnir meinte
Du berechnest aber nicht den Mittelwert, sondern einen exponentiellen Zerfall:


Du hast ja Recht. Aber da hier das Rauschen rausgerechnet werden soll kann man damit ja auch arbeiten.
Mir gings auch erstmal darum einen evtl. auftretenden Überlauf bei 100 Additionen zu vermeiden.

@ABSimon
Du hast die Mittelwertbildung ja schon wieder in der Mainloop drin.
DAS GEHÖRT DEFINITIV VOR die Whileschleife!! :roll:

Bei der Berechnung der Lage wird der Gyrowert direkt benutzt!
Wenn du erst 100 mal die ADC Wandlung durchführst, etc. stimmt dein Timing ÜBERHAUPT nicht mehr.

Und wo wird eigentlich der offset berechnet??

Frag mal mit sizeof() die Länge Variablen ab.
Gyro sollte 16bit signed
offset sollte 16bit unsigned
integral sollte 32bit signed
sein.

Bye
Mikeljo
Mitglied
Registriert seit: Jul 2008
Beiträge: 59
nein, das war ja nur zu kontrolle - um mal zu schauen ob
diese Abfrage mehrfach

gyro = 0;
for (i = 0; i < 50; i++) {
gyro += readADC(GYRO);
}
gyro /= 50;


den gleichen Wert ergibt. Aber auch hier gibt es Differenzen,
die dazu führen das ein gleicher Wert nicht gehalten wird.

sizeof() kommt gleich.
Mitglied
Registriert seit: Jul 2008
Beiträge: 59
Hallo,

wenn ich jetzt nix falsch gemacht habe sind das 4 bit zahlen?
Jedenfalls bei dem Quelltext

// configuration bit settings, Fcy=72MHz, Fpb=36MHz
#pragma config POSCMOD=XT, FNOSC=PRIPLL
#pragma config FPLLIDIV=DIV_2, FPLLMUL=MUL_18, FPLLODIV=DIV_1
#pragma config FPBDIV=DIV_2, FWDTEN=OFF, CP=OFF, BWP=OFF

#include <p32xxxx.h>
#include <plib.h>
#include <explore.h>
#include <LCD.h>

#define GYRO 9 // on AN9 input
#define AINPUTS 0xffcf // Analog inputs for POT and TSENS

void initADC( int amask) {
AD1PCFG = amask; // select analog input pins
AD1CON1 = 0x00E0; // auto convert after end of sampling
AD1CSSL = 0; // no scanning required
AD1CON2 = 0; // use MUXA, AVss/AVdd used as Vref+/-
AD1CON3 = 0x1F3F; // max sample time = 31Tad
AD1CON1SET = 0x8000;// turn on the ADC
} //initADC


int readADC( int ch) {
AD1CHSbits.CH0SA = ch; // select analog input channel
AD1CON1bits.SAMP = 1; // start sampling
while (!AD1CON1bits.DONE); // wait to complete conversion
return ADC1BUF0; // read the conversion result
} // readADC


main () {

char my_string[12];
int i, j, gyro, offset, integral;
int q,w,e;

// initializations
initADC(AINPUTS);
initLCD();

Delayms(2000);

offset = 0;
for (i = 0; i < 100; i++) {
offset += readADC(GYRO);
}
offset /= 100;

integral = 0;
gyro = 0;
j = 1;
while(1) {

gyro = readADC(GYRO);

// DEBUG
q = sizeof(gyro);
w = sizeof(offset);

gyro -= offset;
integral += gyro;

// DEBUG
e = sizeof(integral);

j++;
if (j == 150) {
j = 1;

clrLCD();
sprintf(my_string, "%d bit", q);
putsLCD(my_string);
sprintf(my_string, "\t %d bit", w);
putsLCD(my_string);
sprintf(my_string, "\n %d bit", e);
putsLCD(my_string);
}
}
}


versteh ich nicht.

Viele Grüße
Askan

Seite: 1 2 >

Mikrocontroller- & MicroSPS-Forum » Software & Programmierung » Gyro - Daten interpretieren

© Holger Buss & Ingo Busker   •  Mikrocontroller- & MicroSPS-Forum is powered by UseBB Forum Software