PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zeiten zwischen Flanken von Interrupts messen



LeeTheMaster
02.04.2009, 20:11
Hallo mal wieder,

Ich denke gerade drüber nach, wie man die Zeiten zwischen Flanken von Interrupts möglichst genau messen kann.

Und zwar ist das ganze für folgendes:
Ich möchte an meinem RP6 den Beschleunigungssensor MEMSIC D2125E anschließen. In der Doku des Sensors befindet sich ein Aufbau die Digitalen Signale aus dem Sensor in Analoge umzuwandeln. Das habe ich jetzt aufgebaut und die analogen Signale auf die A/D-Wandler gelegt. Das Problem ist nur das das ganze ziemlich schwankt und von den Messergebnissen eigentlich gar nicht sein kann.

Also die zweite Version:
Und zwar gibt der Sensor die Signale mithilfe von steigenden und fallenden Flanken aus. Die steigende flanke symbolisiert den Start der Messreihe und der erste Wert wird bei der fallenden Flanke genommen. Der komplette Zyklus geht dann bis zur nächsten steigenden Flanke. Dann berechnet man noch den Anteil des ersten Wertes am kompletten Zyklus und man erhält den Wert, den man haben will. Da der Sensor zweiachsig ist, müsste man die fallende Flanke des zweiten Sensors auch noch mit aufnehmen und diese auch ins Verhältnis zum gesamten Zyklus setzen.

Jetzt ist nur die Frage:
Wie kann die die 1. Achse so ansteuern, dass sie bei steigender und fallender Flanke aufgerufen wird und wie kann ich die 2. Achse so anschließen, dass sie nur bei einer fallenden Flanke das Interrupt aufruft.

Und dann wäre halt noch die Sache wie ich die Zeiten zwischen steigend/fallend und steigend/steigend aufnehmen kann.

Wäre echt klasse wenn mich jemand mal aufklären könnte. Am besten vielleicht mit einem kleinen Beispiel, wie ich überhaupt die Interrupts ansteuer, da ich noch nie damit gearbeitet hab.

Anbei findet ihr die Dokumentation zum Sensor.

Gruß Lee

Besserwessi
02.04.2009, 22:51
Die meistens beste methode zur Zeitmessung ist die Input Capture Funktion von Timer1. Allerdings weiss ich nicht, ob Timer 1 eventuell schon blockiert ist (nicht jede nutzung blockiert den Timer auch) und ober der ISP Pin (= PD6 beim Mega32) noch frei ist. Statt des ICP Pins kann man notfalls auch einen ADC Eingang nutzen, ist dann aber komplizierter.
Ein Beispielprogramm dazu findet sich im Wiki Bereich:
https://www.roboternetz.de/wissen/index.php/Timer/Counter_(Avr)

Da sind auch ein paar Beispiele zu Interrupts dabei.
Die anderen Pins die einen Interrupt auslösen können sind Int0,Int1,Int2.

LeeTheMaster
04.04.2009, 14:06
Hi,

Ich habe mir das in der Wiki mal durchgelesen. In einem anderen Forum unter http://opensourcesegway.forumprofi.de/thema-anzeigen-drehratengeber-und-beschleunigungssensor-t24.html hat jemand schonmal den selben Sensor angeschlossen. Er nutzt für Xout INT0 und für Yout INT1. Desweiteren nutzt er den Timer1 mit einem Prescaler von 64. Allerdings bin ich aus dem Wikibeitrag nicht so wirklich schlau geworden. Dort wird zwar das Überlauf Interrupt genuzt aber bei einem 16-bit Timer wird der glaub ich gar nicht benötigt, da der komplette Zeitraum in etwa bei 10ms liegt. Oder lieg ich mit dem Gedanken jetzt völlig falsch?

Wodurch würde denn der Timer1 schon genutzt?
Die Stopwatches des RP6 nutzen Timer0 und wenn TCCR2 Timer2 ist, wird der auch bereits genutzt.

Sonst werden eigentliche keine Timer-Funktionen genutzt.

Der PD6 jedenfalls ist frei. Aber eine Frage noch zu ISP und ICP. Du erwähnst oben beides und meinst das selbe oder? Wo ist denn da der Unterschied?

Wäre klasse wenn du mir das ganze nochmal erklären könntest.

Gruß Lee

Dirk
04.04.2009, 14:42
Wodurch würde denn der Timer1 schon genutzt?
Beim RP6 wird Timer1 für die Motor-PWM benutzt.
Sieh dir mal die RP6RobotBaseLib.c an. Am Ende der Lib findest du die Initialisierung der Timer. Es werden alle genutzt.

Gruß Dirk

LeeTheMaster
04.04.2009, 15:06
Hallo Dirk,

Ich nutze den RP6 mit der M32-Erweiterung. In der lib des M32 konnte ich nur den Timer0 und Timer2 finden. Sprich Timer1 müsste frei sein.

Gruß Lee

Besserwessi
04.04.2009, 17:55
Das oben mit ISP waw ein Tipfehler, das sollte ICP heißen. Wenn der Timer1 für PWM benutzt wird könnte er immer noch für die ICP funktion geeigent sein. Hängt dann aber von den Einstellungen ab. Wenn der frei durchläuft und die Frequenz reicht, sollte es gehen. Wenn man nur kurze Zeiten braucht kann man den Überlaufinterrupt natürlich auch weglassen. m Prinzip stellt der ICP Pin einen weiteren externen Interrupt zur Verfügung bei dem man zusätzlich den Timerstand vom Timer 1 gespeichert kriegt.

SlyD
04.04.2009, 18:53
> Sprich Timer1 müsste frei sein.

Ist er. Steht sogar in nem Kommentar in der Initialisierung vom RP6 M32 Modul drin ;)

LeeTheMaster
04.04.2009, 20:49
TCCR1B = (1<< ICNC1) + (1<<CS10) // start Timer mit Systemtakt
+ (1 << ICES1); // steigende Flanke auswählen

Da wird ja der Interrupt auf steigende Flanke gesetzt. Wie kann ich die jetzt auf fallend oder auf beides einstellen?

Und wofür steht folgendes im Beispielcode:


DDRB = 0; // Alles Eingänge, PB0 ist ICP
PORTB = 0xFF - (1<<PB0); // Pullups an Eingängen außer ICP
DDRC = 0; // Eingänge
PORTC = 0xFF; // Pullups an Eingängen
DDRD = (1<<PD1); // Eingänge, außer PD1 = Tx (UART)
PORTC = 0xFF- (1<<PD1); // Pullups an alle Eingängen (außer TX)


Gruß Lee

Besserwessi
04.04.2009, 20:57
Der 2 te Teil des beispielcodes ist das definieren welche Ports Eingänge/Ausgänge sind. Das sollte im wesenlichen schon bein RO6 code da sein. Fehlt eventuell nur ein oder 2 Pins.

Der ICP Interrupt kann man nur entweder auf steigende oder fallende Flanke setzen. Wenn man wie hier beide Flanken braucht, dann muß man jedesmal die Falanke umschalten.
Die Falnke steuert das BIT ICES1. Wenn man den teil (1<<ICES1) durch (0 << ICES1) ersetzt, dann gibts die fallende Flanke.

(0 << ICES1) ist auch nur eine andere Schreibweise für 0, aber das sieht man welches Bit man gerade nicht setzen wollte.

LeeTheMaster
04.04.2009, 21:30
Ok das mit den Flanken hab ich jetz kapiert, aber wozu werden die ganzen Ein-/Ausgänge denn benötigt? Ich meine im Grunde gehts ja nur um den Timer und die dazugehörigen Interrupts. Oder sind die Ein-/Ausgänge für die UART?

Besserwessi
05.04.2009, 15:59
Die einstellungen der Ein/Ausgänge sind u.A. für die UART. Für die Messung der Flanken braucht man nur die Eingangspins auch wirklich als Eingänge definieren.

SlyD
05.04.2009, 16:07
Die Pins in obigem Code passen allerdings nicht zur RP6 Hardware.
Das ist für nen MEGA8 o.ä.

Schau Dir die Schaltpläne und das MEGA32 Datenblatt an!
PD6 ist beim RP6 M32 Erweiterungsmodul ICP...

MfG,
SlyD

Dirk
05.04.2009, 17:45
Hallo Lee,

Ich nutze den RP6 mit der M32-Erweiterung.
Davon konnte ich nach deinem 1. Post ...

Ich möchte an meinem RP6 den Beschleunigungssensor MEMSIC D2125E anschließen.
... nicht ausgehen.
Klar: Bei der RP6Control M32 ist Timer1 frei.
ICP ist PD6 und auf der M32 auch noch frei (Name: IO_PD6).

Gruß Dirk

LeeTheMaster
05.04.2009, 19:59
OK. Ich glaub das Beispielprogramm hab ich jetz so langsam verstanden. Nun hab ich mir auch schon nen paar Gedanken zu meinem Anwendungsfall gemacht und ich frage mich jetzt, wie ich den ICP am besten nutze. Der Sensor hat ja 2 Ausgänge. Sprich X und Y, die beide angeschlossen werden müssen. Die Frage ist jetzt, was ich an den ICP anschließe, wenn ich X und Y an INT1 und INT2 oder wie auch immer anschließe.

Im Grunde wäre es ja optimal, wenn man zwei ICP´s hätte. Eine andere möglichkeit wäre den ICP immer dann zu schalten, wenn ein Interruptereignis ausgelöst wird, sprich beide Ereignisse vereint auf den ICP zu führen, wenn ihr versteht was ich meine :-k . Aber dann wäre es wahrscheinlich sogar schneller nur die Interrupts zu nehmen und direkt die Zeit aus dem Timer auszulesen. Der ICP ist doch nur so, dass er bei der ausgewählten Flanke automatisch den Zähler ins Register schreibt oder?

Wäre nett wenn mir mal jemand einen gedanklichen Anstoß geben könnte, wie man das am Besten löst.

Gruß Lee

Besserwessi
05.04.2009, 20:58
Man kann die ICP Funktion nicht nur über den ICP Pin nutzen. Man kann auch den analogen Komperator nutzen, um die selbe Funktion auszulösen. Insbesondere der Pin AIN1 = PB3 beim Mega32 ist dazu gut geeigent. Die andere Komperator Seite läßt sich softwaremäßig auf 1.2 V setzen. Damit könnte man im Wesel die beiden Kanäle messen.

Der unterschied zu normalen Interrupteingängen und dem Auslesen des Timer standes ist auch nur gering. Man kreigt mit der ICP funktion etwa mehr Genauigkeit, denn es kann etwas dauern bis der Interrupt tatsächlich ausgelöst wird. Das wird vor allem dann interessant wenn noch andere Interrupts auftreten können, denn die können einen Interrupt schon etwas länger aufhalten. Müßte man sehen wie hoch die nötige Auflösung ist und was sonst noch an Interrupts aktiv ist.

LeeTheMaster
05.04.2009, 21:45
Öhm sorry aber: Versteh ich nicht.

Also laut Datenblatt des Sensors dauert ein Zyklus entweder 2,5ms oder 10ms, hab leider kein Oszilloskop, sonst würd ich mir das mal angucken. Innerhalb dieses Zeitraumes fällt die Flanke dann irgendwann wieder ab, je nach der Position des Sensors. Sprich man muss bei der aufsteigenden Flanke anfangen zu messen, bei der fallenden die Zeitdifferenz aufnehmen, bei der nächsten steigenen die Zeit des kompletten Zyklusses aufnehmen und den Timer wieder zurücksetzen. Wenn man dann jetzt die Werte ins Verhältnis setzt (Fallende Flanke/kompletter Zyklus) bekommt man einen Wert zwischen 0 und 1 der einem Auskunft über die Erdbeschleunigung gibt. Soviel zur Theorie. Jetzt ist nur die Frage, wie genau das mit den Interrupts ist. Und dann wäre noch das Problem das es das ganze noch einmal gibt. Man müsste also praktisch noch die fallende Flanke des zweiten Ausgangs aufnehmen, da die steigenden Flanken von X und Y parallel sind.

Und es wäre echt mal cool, wenn ihr mir ne Antwort gebt die ich auch verstehe :-D . Denn ich hab vor dem RP6 noch nie was in C gemacht und ich hab eigentlich keine Ahnung von den Interrupts. Bin halt nur so weit, dass ich den Beispielcode halbwegs versteh.

Gruß Lee

wkrug
06.04.2009, 08:59
OK versuchen wir es mal ganz von vorne.

Ein Interrupt ist ein Ereignis, das von einer externen oder internen Quelle des Microcontrollers ausgelöst wird und den normalen Programmablauf unterbricht.

Der ATMEGA 32 hat eine ganze Menge von diesen Interruptquellen.
Die für Dich interessanten dürfte der ICP Interrupt sowie der INT0 bzw. der INT1 und der Timer 1 Overflow Interrupt sein.

Der Input Capture Interrupt ( ICP ) wird durch eine Zustandsänderung am ICP Pin ausgelöst. Ob das bei der steigenden oder fallenden Flanke an diesem Pin passiert ist Einstellbar.
Der Vorteil des ICP ist, das der aktuelle Zählerstand des TCNT1 Registers in das Capture Register übernommen wird, sobald ein ICP Ereignis auftritt.
Sprich die Funktion ist optimal zum messen von Zeiten geeignet.

Der INT0 bzw. 1 wird auch durch zustandsänderungen am entsprechenden Input Pin ausgelöst.
Will man ihn aber zur Zeitmessung nutzen muss der Timer TCNT1 per Software ausgelesen werden, wodurch es manchmal zu Problemen kommen kann - Überholeffekte in der Überlaufvariable des Timers 1.

Nun kommt es noch auf die maximal mögliche Periodendauer zwischen 2 Interrupts an. Ist diese Periodendauer so groß, das der maximale Zählerstand des Counters 1 ( 65535 ) überschritten wird, muß in der Timer 1 Overflow Routine eine weitere Variable hochgezählt werden, die dann das höherwertige Wort der Zeitmessung darstellt und in den ICP und INTx Routinen mit verarbeitet werden muß.
Da der Zeitpunkt vom Auftreten des Interrupts bis zum Auslesen durch die Interruptroutine immer gleich ist ( wenn man das ganz an den Anfang der Interruptroutine setzt ) kriegt man auch mit INTx sehr genaue Werte.
Die tatsächlichen Reaktionszeiten kann man wunderbar mit dem Simulator aus dem AVR Studio 4 ermitteln.
Für optimalen Speed kann man die Interruptroutinen auch in Assembler programmieren, wenn man das kann und mag.

Die umstellung des Interrupt sensing macht man sinnvollerweise im entsprechenden Interrupt.
Wurde der Interrupt durch eine steigende Flanke ausgelöst wird in der gestarteten Interuptroutine auf fallende Flanke umgeschaltet.
Die nun folgende Flanke deines Sensors wird also wieder diese Interruptroutine aufrufen, wo dann wieder auf "steigende Flanke" umgeswitched wird.

Die Auswertung der ermittelten Zeiten lass ich immer in der Hauptroutine machen.
Die entsprechede Interruptroutine ermittelt die Meßwerte, speichert diese in einer Variable ab und setzt ein Flag ( Bit Variable ).
Die Hauptroutine fragt dieses Flag ab, wenn es gesetzt ist wird des wieder zurückgesetzt und die Berechnungsroutine / Displayanzeige oder was auch immer ausgeführt.
So kriegt man schlanke Interruptroutinen und ein nachvollziehbares Programm.

LeeTheMaster
06.04.2009, 15:34
Das ist mal eine schöne Antwort \:D/. Ich werde das mal so Umsetzen und gucken wie genau es wird. Da ich die ICP Variante mit zwei Sensor-Ausgängen nicht wirklich nutzen kann, bzw. nicht weiß wie, hoffe ich das das mit den 2 Interrupts auch recht genau ist.

Wie gesagt, schöne Antwort! Danke dir!

Wenn ich das Testprogramm fertig hab werd ich euch mal ein Äuglein drüber werfen lassen.

Gruß Lee

wkrug
06.04.2009, 17:29
Da ich die ICP Variante mit zwei Sensor-Ausgängen nicht wirklich nutzen kann, bzw. nicht weiß wie, hoffe ich das das mit den 2 Interrupts auch recht genau ist.
Du kannst die ICP Variante auf jeden Fall schon mal für einen Ausgang nutzen.
Der Unterschied zu einem normalen INTx ist, das der Wert, den das TCNT1 Register zum Zeitpunkt des Interrupts hatte im ICR1 Register abgespeichert wird.
Du kannst Dir dann in der dazugehörigen Interruptroutine den Wert von dort abholen ( auslesen ).

Besserwessi
06.04.2009, 18:27
Die größte Unsicherheit die man bei der verwendung des externen interrupts erwarten kann, ist wenn ein anderer Interrupt dazwischen kommt. Für einen kurze ISR routine sollten da ein paar µS, sein. Das sollte gegen die 2,5 ms in der Regel zu vernachlässigen sein. Vor allem tritt dieser Fehler nur eher selten auf. Ein bischen aufpassen müßte man nur ob da für andere Programmteile noch Interrupts aktiv sind, die eventuell länger brauchen.
Wenn einem das zu ungenau ist müßte man den analog Comperator als Alternativen ICP-eingang nutzen und die Messungen der beiden Kanäle nacheinander machen. Man kann den analog Comperator auch ähnlich dem externen Interrupt nutzen und legt sich also durch die Wahl des Pins noch nicht auf eine Softwarevariante fest.

Solange die einzelen Zeitdifferenzen nicht größer als 65000 Timer Takte sind, muß man sich um die Überläufe noch nicht extra kümmern. Das vereinfacht das Programm schon um einiges und man braucht den timer Overflow interrupt nicht.

Wenn man den Prescaler für den Timer richtig wählt, sollte man ohne den Überlauf auskommen. Für 2,5 ms Periode dürfte der Timer noch mit 20 MHz laufen, ist also gar kein Problem. Für 10 ms Periode dürfte der Timer mit höchstens 6,5 MHz laufen, man wird da wohl den Timertakt niedriger als den vollen Systemtakt wählen müssen.

LeeTheMaster
06.04.2009, 19:05
So hab mir jetzt folgendes Testprogramm geschrieben, aber es will nicht so recht:


#include "RP6ControlLib.h" // The RP6 Control Library.
// Always needs to be included!
#include <stdlib.h>
#include <avr/interrupt.h>

volatile unsigned long timestamp; // volatile wegen Zugriff im Interrrupt
unsigned long impuls;
unsigned long periode;
unsigned long zeit;
uint8_t flag;
uint8_t position;
unsigned long wert;
char puffer[5];

void int1(void) // Flanke an INT1
{
timestamp = TCNT1;
if (position == 0)
{
MCUCR = (0<<ISC10); //fallende Flanke
TCNT1 = 0; //zurücksetzen (Anti-Überlauf)
position = 0;
}
else
{
MCUCR = (1<<ISC10); //steigende Flanke
position = 1;
}
flag = 1;
}

int main(void)
{
initRP6Control();
initLCD();
INT1_setEventHandler(int1);

MCUCR = (1<<ICS11) + (1<<ICS10); // Flanke von INT1 einstellen
GICR = (1<<INT1); // INT1 aktivieren
sei(); // Interrupts aktivieren
while(true)
{
if (flag == 1)
{
flag = 0;
if (position == 0)
{
periode = timestamp - zeit; // Zeit der kompletten Periode
zeit = timestamp; // neue Zeit
wert = impuls / periode; // werte ins Verhältnis setzen
utoa(wert,puffer,4);
writeStringLCD(puffer); // Ausgeben lassen
}
else
{
impuls = timestamp - zeit; // Zeit zwischen Rising up und Rising down
}
}
}
return 0;
}

Wenn ich das kompilieren will kommt folgende Fehlermeldung:

Beschleunigungssensor.c: In function 'main':
Beschleunigungssensor.c:66: error: 'ICS11' undeclared (first use in this function)
Beschleunigungssensor.c:66: error: (Each undeclared identifier is reported only once
Beschleunigungssensor.c:66: error: for each function it appears in.)
Beschleunigungssensor.c:66: error: 'ICS10' undeclared (first use in this function)
make: *** [Beschleunigungssensor.o] Error 1

Ich hoffe ihr findet meinen dummen Fehler -.-

Gruß Lee

//EDIT: hab vergessen den Prescaler von 64 zu setzen und den Timer zu starten, aber ich weiß grad nicht wie -.-

//EDIT 2.0: mir ist gerade erst aufgefallen das man die 16 bit Register in zwei Schritten lesen muss. Och man ey ich raff det nich #-o

Besserwessi
06.04.2009, 21:02
Die Fehler beim Compilieren kommen daher, das io.h nicht eingebunden ist. Da werden die ganzen Register und Bit namen erst definiert.

Der prescaler sollte eher bei 8 liegen. Die einstellung geht im Register TCCR1B.

Den Zugriff für die 16 Bit Registerpaare macht gcc schon selber, das ist also schon richtig so.

Es müssen noch ein paar mehr Variablem als volatile markiert werden, denn auch auf flag und postion wird in der ISR und main zugriffen. Bei den Variablen kommt man im wesentlichen mit dem Typ unsigned int aus. Man braucht da kein LONG. Das zurücksetzen des Zähler ist auch nicht nötig. Wenn ein Überlauf auftritt, dann wird der bei der Differenzbildung richtig berücksichtigt, wenn man konsequent beim Datentyp unsigned int bleibt.

wkrug
07.04.2009, 08:53
timestamp = TCNT1;
if (position == 0)
{
MCUCR = (0<<ISC10); //fallende Flanke
TCNT1 = 0; //zurücksetzen (Anti-Überlauf)
position = 0;
}
else
{
MCUCR = (1<<ISC10); //steigende Flanke
position = 1;
}

Sollte da in der Zuweisung bei position = 0; nicht position = 1 stehen und umgekehrt ?
Sonst wird ja beim nächsten Interrupt wieder die "if (position == 0)" durchlaufen.

LeeTheMaster
07.04.2009, 16:47
Mh, habe jetzt die von euch genannten Punkte geändert und es sieht jetzt so aus:


#include "RP6ControlLib.h" // The RP6 Control Library.
// Always needs to be included!
#include "stdlib.h"
#include "avr/io.h"
#include "avr/interrupt.h"

volatile unsigned long timestamp; // volatile wegen Zugriff im Interrrupt
unsigned int impuls;
unsigned int periode;
unsigned int zeit;
volatile uint8_t flag;
volatile uint8_t position;
unsigned int wert;
char puffer[5];

void int1(void) // Flanke an INT1
{
timestamp = TCNT1;
if (position == 1)
{
MCUCR = (0<<ISC10); //fallende Flanke
position = 0;
}
else
{
MCUCR = (1<<ISC10); //steigende Flanke
position = 1;
}
flag = 1;
}

int main(void)
{
initRP6Control();
initLCD();
INT1_setEventHandler(int1);

MCUCR = (1<<ICS11) + (1<<ICS10); // Flanke von INT1 einstellen
GICR = (1<<INT1); // INT1 aktivieren
TCCR1B = (1<<CS11); // Prescaler von 8
sei();
while(true)
{
if (flag == 1)
{
flag = 0;
if (position == 0)
{
periode = timestamp - zeit;
zeit = timestamp;
wert = impuls / periode;
utoa(wert,puffer,4);
writeStringLCD(puffer);
}
else
{
impuls = timestamp - zeit;
}
}
}
return 0;
}


Nach wie vor erhalte ich:


Beschleunigungssensor.c: In function 'main':
Beschleunigungssensor.c:66: error: 'ICS11' undeclared (first use in this function)
Beschleunigungssensor.c:66: error: (Each undeclared identifier is reported only once
Beschleunigungssensor.c:66: error: for each function it appears in.)
Beschleunigungssensor.c:66: error: 'ICS10' undeclared (first use in this function)
make: *** [Beschleunigungssensor.o] Error 1

> Process Exit Code: 2
> Time Taken: 00:00

Weiß echt nicht warum -.-

Gruß Lee

Besserwessi
07.04.2009, 17:09
Es muss ISC11 stat ICS11 heißen. Ein einfacher Buchstabendreher.

LeeTheMaster
08.04.2009, 20:47
Oh, ich Depp. OK jetzt compiliert er das ganze und ich bekomme Messwerte auf 0,1° genau. Allerdings muss ich wohl noch etwas mit dem Verhältnis spielen, da bei 90° die Abweichung schon ca. 1° beträgt. Ich denke mal das ist Temperaturabhängig, da die Messwerte des Herstellers bei 25°C aufgenommen wurden. Ich werde da mal ein wenig mit Faktoren rumspielen und evtl. den Analogen Temperatur output noch mit einbinden, um das möglichst genau zu bekommen.

Danke für Eure Hilfe!

Gruß Lee

wkrug
08.04.2009, 21:10
OK jetzt compiliert er das ganze und ich bekomme Messwerte auf 0,1° genau. Allerdings muss ich wohl noch etwas mit dem Verhältnis spielen, da bei 90° die Abweichung schon ca. 1° beträgt.
Wie genau ist denn dein Referenzgerät ?

Wir haben auch mal fast eine Woche nach einem Fehler in der Software gesucht, bis wir festgestellt haben, das unser Referenz Voltmeter uns falsche Werte angezeigt hat.
Unser Gerät war im Nachhinein genauer als unser Referenz Gerät !?

Im übrigen sollten Referenzen von der Meßtoleranz her um den Faktor 10 besser sein, als die Schaltung die man abgleichen will.

LeeTheMaster
11.04.2009, 20:14
Mh, ich konnte den Sensor nicht ohne den Roboter auslesen, sprich ich habe kein Referenzgerät. Ein Voltmeter hätte es ohnehin nicht getan, viel eher wäre ein Oszilloskop hilfreich.

Naja ich erreiche jetzt bei voller Fahrt (20cm/s) eine Genauigkeit von +- 0,3°. Ich finde dies schon recht gut, da der Hersteller diese 0,3° schon als statische Toleranz angibt.

Falls jemand das nachbauen möchte hier mein Ansatz:

Ich messe sowohl X als auch Y, wobei ich den Sensor im Winkel von 45° montiert habe. So hebt sich die Beschleunigung des Roboters wieder auf, da dann X steigt, während Y sinkt und umgekehrt. Auf einem Meter Strecke nehme ich jetzt 10 Messwerte auf und verarbeite dann den Mittelwert weiter. Dies wirkt eventuellen Unebenheiten oder Vibrationen während der Fahrt entgegen.

Wie gesagt, alles in allem ist die Toleranz für meinen Zweck völlig annehmbar.

Gruß Lee

Besserwessi
11.04.2009, 22:29
Egal wie man den Sensor montiert sollte es unmöglich sein zwischen einer Neigung des Sensors und einer Beschleunigung zu unterscheiden. Den einzigen Ansatzpunkt den man hat, ist es das die Erdbeschleunigung einen konstanten bekannten Wert hat. Bei eine zusätzlichen Beschleunigung senkrecht dazu ändert sich der Betrag der Beschleuningung, was man theoretisch auswerten kann. Allerdings kriegt man so nicht das Vorzeichen einer Beschleunigung in der horizontalen und kann daher auch nichts korrigieren. Bestenfalls kann man einige Fälle erkennen in denen Beschleunigt wird, sodass man weiss dass diese Werte nicht zur Neigungsmessung taugen.

LeeTheMaster
11.04.2009, 22:51
Es geht ja nicht darum die Beschleunigung des Fahrzeuges zu erkennen, sondern diese eben nicht aufzunehmen. Durch die Montage in 45°, misst bei 0° nach einiger Rechnerei die X-Achse 45° und die Y-Achse sogesehen -45°. Wenn jetzt das Fahrzeug beschleunigt, würd die messbare Erdbeschleunigung an der X-Achse ein wenig steigen und an der Y-Achse dementsprechend sinken. Durch die Differenzbildung bliebe der Winkel bei 0°. So hebt sich die Beschleunigung des Fahrzeugs auf, sodass man wirklich nur die Neigung misst. Eine senkrechte Beschleunigung gibt es theoretisch gar nicht, da das Fahrzeug ja nur Fahren kann. Durch unebenheiten in der Straße könnten solche Beschleunigungen zwar auftreten, diese werden aber durch die Mittelwertsbildung weitestgehend kompensiert.

Gruß Lee

Besserwessi
12.04.2009, 21:04
Eine kleine Neigung kann man nicht von eine Beschleunigung unterscheiden. Das geht einfach von der Physik nicht. Ein beiden Fällen dreht sich die Richtung der Gesamtbeschleunigung ein wenig. Wie man dazu die Sensoren dreht ist völlig egal. Eine Drehung läßt sich schließlich einefach als lineare transfornation rechenerrisch ohne Informations-verlust durchführen oder zurückrechnen.

Am einfachsten sieht man es wenn man den einen Sensor nominal waagerecht hat, den andernen Senkrecht. Der senkrechte mißt bei kleinen Winkeln die Erdbeschleunigung, der waagerechte die Fahrzeugbeschleunigung plus den Effekt der Neigung.

sechsrad
12.04.2009, 21:23
Die entsprechede Interruptroutine ermittelt die Meßwerte, speichert diese in einer Variable ab und setzt ein Flag ( Bit Variable ). ...

Das ist das Grundprinzip für Interrupts, anders gibt es im Programm Fehlinterpretationen, die ein zum Wahnsinn treiben können...

LeeTheMaster
12.04.2009, 21:29
@Besswessi, les dir mal die Doku im Anhang durch, vielleicht verstehst du dann was ich meine. Im Endeffekt ist es auch völlig egal, da es jetzt wunderbar funktioniert.

Gruß Lee