ich beschäftige mich seit ein paar Wochen mit einem Projekt für den Arduino Mega2560, bei welchem ich mehrere Sensorwerte gleichzeitig auslesen muss. Dabei soll die Lage im Raum gemessen werden (5D-Koordinaten eines Roboterarmes, also 5 Sensorwerte) .Mein Problem liegt dabei noch am Erstellen eines Konzeptes, wie die Daten ausgelesen werden.
Die erste Idee wäre die Verwendung von 5 Interrupts, da die drei verwendeten Encoder kein Signal verpassen dürfen. Problematisch dabei ist aber meine Fehlende Kenntnis über die ISR bzw. das Interrupt-handling. Dabei stellen sich mir folgende Fragen?
Kann man einen Interrupt in einem Interrupt ausführen?
(nach einigen Versuchen ist mir aufgefallen, dass die Interrupts einzeln nacheinander ausgeführt werden, wenn alle
gleichzeitig ein Signal erfassen, lag das nun daran, dass das Signal lang genug vorhanden war, dass der Arduino alle Interrupts
ausführen kann, oder wurden die auszuführenden Interrupts auf eine Liste gesetzt)
Wie Funktioniert genau der Interrupt bei Arduino? Anscheinend werden der momentane Ablaufort auf einem Stack
gespeichert, aber was passiert, wenn dieser durch zuviele Interrupts überflutet wird? Kann man die Implementierung des
Arduinos bezüglich diesem Handling einsehen?)
Welche Zeit benötigt die ISR?
Stimmt es, dass die Zeit während einem Interrupt nicht richtig mitgezählt wird?
Alternativ zu den Interrupts habe ich mir ein normales Polling vorgestellt, da ich hier jeden Wert erfassen muss, würde kein besonderes Scheduling in Frage kommen, sondern nur eine Simple Abfrage in fester Reihenfolge. Dabei müsste man über eine Abschätzung die Laufzeiten berücksichtigen, da schließlich kurze Impulse gezählt werden müssen. Diese Lösung würde sicherlich fehlerhafte Messungen ergeben.
Zuletzt hatte ich die Idee für jeden Sensor einen eigenen Arduino zu verwenden, damit die Daten richtig aufgenommen werden. Ein Sechster Arduino würde die Werte getaktet aus den anderen abfragen und zusammenfügen. Leider wäre das zu teuer.
Ich würde mich über eine kleine Hilfe bzw. Nachhilfe in Sachen Interrupts bedanken.
Kann man einen Interrupt in einem Interrupt ausführen?
Nein. Beim Eintritt ein die ISR wird das globale Interrupt Enable Flag deaktiviert und am Ende wieder gesetzt. Man kann die Interrupts auch wieder per Hand aktivieren, aber das kann auch schnell Probleme verursachen wenn die Interrupts zu schnell kommen
Wie Funktioniert genau der Interrupt bei Arduino? Anscheinend werden der momentane Ablaufort auf einem Stack gespeichert, aber was passiert, wenn dieser durch zuviele Interrupts überflutet wird? Kann man die Implementierung des Arduinos bezüglich diesem Handling einsehen?)
Das ist im Prinzip ein automatischer Funktionsaufruf. Also mit call/return
Auf dem AVR gibt es allerdings keine Interrupt Warteschlange. Für jeden Interrupt-Vektor gibt es ein Flag Bit, dass vom Controller automatisch überprüft wird. Wenn also während des Interrupts ein Interrupt auf einem anderen Vektor (oder glaube ich auch auf dem gleichen Vektor) kommen, wird dieser danach bearbeitet. Aber wenn mehrere Interrupts auf dem gleichen Vektor eintreffen geht der erste verloren.
Welche Zeit benötigt die ISR?
Da gehen schon ein paar Takte drauf, wie bei einem normalen Funktionsaufruf, da Register auf dem Stack gesichert werden und danach wieder geladen werden müssen.
Stimmt es, dass die Zeit während einem Interrupt nicht richtig mitgezählt wird?
Der Zähler läuft in einem Overflow Interrupt auf Timer0. Es wird also während einer ISR nicht aktualisiert. Deshalb geht delay() nicht (was sowieso in einer ISR Unsinn ist) und millis() kann man nur einmal am Anfang machen
Alternativ zu den Interrupts habe ich mir ein normales Polling vorgestellt, da ich hier jeden Wert erfassen muss, würde kein besonderes Scheduling in Frage kommen, sondern nur eine Simple Abfrage in fester Reihenfolge.
Wenn du für jeden Sensor nur ein Bit auslesen musst, kannst du auch 8 Bits auf einmal einlesen, wenn du die Pins so auswählst, dass sie auf einem Port liegen: http://www.arduino.cc/en/Reference/PortManipulation
EDIT:
Der Mega hat natürlich 5 HW Interrupts. Da Stand ich auf dem Schlauch.
Digitale Signale kannst du gleichzeitig einlesen.
Wie Serenifly schon angedeutet hat: ohne digitalRead kommst du in ganz andere Geschwindigkeitsbereiche.
( Für jeden PORT = bis zu 8 Signale ) brauchst du einen Takt, was bei einem 16 MHz Mega2560 62,5 ns sind )
Ein Gefühl für "kurze Impulse" zu bekommen, ist nicht so leicht. Da ist erstmal Rechnen angesagt.
Da du die Daten über Encoder-Pulse ermitteln willst, gehe ich mal davon aus, dass es nicht mal auf Gleichzeitigkeit im Bereich unter 1 Mikrosekunde ankommt. Was ist denn die zu erwartende Pulsfrequenz ?
Wie schnell du dann daraus 6 ( oder mehr ?) Gleitkomma-Raumkoordinaten errechnest und was du damit wie schnell machen kannst, ist eine andere Frage ...
Ich würde fast schätzen dass es ausreicht relativ schnell zu pollen. So schnell wird sich das Ding vielleicht nicht bewegen können.
Aber wie du sagst, wenn man dann aufwendige Berechnungen macht kann das u.U. problematisch werden. Alle Gleitkomma-Berechnungen sind in Wirklichkeit Funktionsaufrufe die etwas dauern. Wenn dann noch Trigonometrie o.ä. hinzukommt kann da schon Zeit draufgehen.
Ich denke, wie so oft ist die Frage der Anforderungen zu erst zu klären:
Was ist "gleichzeitig"?
Hier muß eine Zeit her! Zeit die zwischen 2 Sensorauswertung vergehen darf:
tsd max = 2ms (zum Beispiel)
Und, ausserdem: Welche Sensorschnittstelle? Analog? Digital? Ein Bus?
Ein Arduino kann nichts gleichzeitig, er kann immer nur einen Befehl nach dem anderen abarbeiten.
Da dies sehr schnell passiert, ist oft der Eindruck der gleichzeitigkeit gegeben.
Das oben angegebene Beispiel mit 2ms z.B. wäre für den Arduino kein Problem.
Wenns 50µs sein sollen, gehts nicht mehr. Da muß dann externe Hardware dran.
Stimmt, 50 µs ist nicht viel.
Aber einen "gleichzeitig" zusammengehörenden Satz von mehreren Encoder-Impuls-Zählern erfassen, hangt von der Impuls-Frequenz ab, und sollte bei solcher Größenordnung ( ~ 50 µs ) möglich sein.
Alles weitere, z.B. Geschwindigkeiten, würde ich lieber in mm / ms ermitteln, statt mit µs zu hantieren.