| 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... 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 :-) :  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. 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. 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. 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  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. 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.jpgAlternativ 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!! 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 |
© Holger Buss & Ingo Busker • Mikrocontroller- & MicroSPS-Forum is powered by UseBB Forum Software