Timingprobleme

Status
Für weitere Antworten geschlossen.

oldmax

Mitglied
Premium Benutzer
03. Nov. 2008
595
15
18
Landkreis Göttingen
Sprachen
  1. Assembler
Hi
Mit diesem kleinen Beitrag soll ein wenig Zeitbewußtsein in die Programmerstellung einfließen.
Ein Vorteil der µC ist sicherlich die vielfältige Einsatzmöglichkeit. Jedoch gilt es immer wieder zu prüfen, ob die Anwendung mit der Rechengeschwindigkeit des ausgesuchten Controllers zurecht kommt. Dem Anfänger ist oft nicht klar, was Laufzeiten sind. Kann man in einem Assemblerprogramm noch nachvollziehen, wie viele Taktzyklen ein Programmdurchlauf benötigt, ist es mit C oder Bascom wesentlich schwieriger. Na ja, für die ersten Gehversuche ist es sowieso unerheblich, ob 30 oder 50 mS, ach was schreib ich, Nanosekunden Zykluszeit benötigt werden. Bei den ersten Schritten werden wohl kaum mehr als 100 bis 500 Anweisungen zustande kommen, so das selbst der interne Takt keine Geschwindigkeitsunterschiede spüren lässt. Es sei den, es werden Bibliotheken mit Fließkomma Arithmetik eingebunden und aufgerufen. Da könnten schon Probleme mit der Zykluszeit auftauchen. Auch die allseits beliebten Warteschleifen sind äußerst schädlich für die Zykluszeit.
Nun, ich spreche von der Zykluszeit so selbstverständlich, vielleicht sollte ich diesen Begriff erst einmal erklären. Die Ausführungen beziehen sich auf Maschinenbefehle, also grob gesagt Assemblercode. Bei anderen Programmiersprachen gelten andere Regeln, denn eine Bascom-Anweisung ist oft ein kompletter Block von einigen Maschinenbefehlen, im Prinzip ein Unterprogramm. Auch in C sieht es nicht viel anders aus. Daher ist hier die Laufzeit viel schwerer zu berechnen und selbst geübte Programmierer haben sich schon gewundert, warum ein Programm gelegentlich falsche Ergebnisse lieferte.
Ein Controller oder Computer bearbeitet sein Programm Befehl für Befehl ab und beginnt dann wieder von vorn. Damit dies funktioniert, hat er einen Takt, der die Zugriffe auf die Speicher steuert.
Ob das, was ich jetzt sage, absolut richtig ist, weiß ich nicht, aber das Prinzip sollte stimmen.
Werft mal einen Blick auf die Skizze im Anhang. Dort möchte ich den Zusammenhang Befehl und Ausführungszeit einmal deutlich machen.

Im Datenblatt Stichwort „Instruction Set Summary“ wird im Befehlssatz angegeben, wie viele Takte ein Controller zur Ausführung benötigt und da ein Takt eine feste Zeit hat, ist anhand der Anzahl von Befehlen schnell die Zeit berechnet. Zumindest grob abgeschätzt, denn jedes Programm hat Bedingungen und da werden mal mehr oder weniger Befehle durchgeführt. Wenn es wichtig ist, eine bestimmte Zeit einzuhalten, muss diese Zykluszeit halt gemessen werden. Bei Steuerungen für Maschinen wird diese Zykluszeit auch gemessen und kontrolliert.
http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf
Nun soll ja so ein Controller nicht im eigenen Saft vor sich hin schmoren, sondern auf Information von Außen reagieren. Und da beginnen die Probleme.
Kontakte von Relais oder Tastern sind völlig unkritisch, Die erfasst ein Controller auch, wenn er einmal in seinem Programmzyklus seine Peripherie abfragt. Er ist da sogar so schnell, das ein Signal von einem Kontakt nicht sofort bewertet, sondern das sogenannte „Prellen“ erst abgewartet wird, um eine Fehlinterpretation zu vermeiden. Im Klartext bedeutet es, das ein Taster oder Kontakt nicht gleich schließt und ein stabiles Signal liefert, sondern ein paar Mal öffnen und schließen, eben prellen. Ein Controller ist so schnell, das er die unterschiedlichen Signalwerte erfasst und bearbeitet. Möchte man bspw. Kontaktsignale zählen, ist der Zählerwert zufällig. Aus diesem Grund werden Kontakte „entprellt“.
Nun sind aber nicht nur Kontakte Informationsquellen, sondern auch Signale, die elektronisch aufbereitet werden. RxD ist ein solcher Eingang, der Impulse in schneller Folge empfängt und keinen „verlieren“ darf. Die Information wäre sonst nicht vollständig und würde zu falschen Werten führen. Aber betrachten wir erst einmal einen ganz normalen Eingang, der mit einem Optokoppler beschaltet ist. Kontakte hatte ich ja bereits als „langsam“ eingestuft, daher mal ein Signal, welches durchaus sehr kurz ansteht. Zum Beispiel fragen wir bei einer Slotcarbahn die Führung im Slot mit einer Lichtschranke ab. Nun kann ein solches Fahrzeug durchaus eine Geschwindigkeit von bis zu 80 km/h erreichen. Die Führung ist ca. 15 mm. Wie lang ist nun das erzeugte Signal und ist die Erfassung im Polling zuverlässig? Polling nennt man die zyklische Abfrage in einer Programmschleife.

Also, die Rechenmaschine heraus und die Zeit berechnen.
Bei 80 km/h werden in 1 Sek 80000000/3600 Millimeter zurückgelegt, das sind
22222.222 mm/s. Ich habe aber nur 15 mm, also muss die Zeit für diese Strecke errechnet werden und das ergibt 0,000675 s oder 675 µs. Das Signal steht also im ungünstigsten Fall nur 675 µSekunden an. In dieser Zeit muss das Programm mindestens einmal den Eingang eingelesen haben. Jetzt wird die Laufzeit des Programms betrachtet. Bei einer Taktfrequenz von 16 MHz ist ein Takt 1/16000000 Sekunden lang also 0,0000000625 Sekunden oder 62,5 Nanosekunden. Bei 2 Takten für einen Befehl könnte ich nun ca 5000 Befehle abarbeiten und würde das Signal immer noch sicher erfassen.
Aber aufgepasst! Es geht nicht um programmierte Befehle sondern bearbeitete Befehle. Werden Schleifen abgearbeitet, kann aus einer Liste von 50 Anweisungen mal schell ein paar tausend Befehle werden. Auch EEProm – Zugriffe, AD-Wandlungen oder das Senden von Bytes verzögert schon mal mit Wartezeiten den Programmdurchlauf. Dazu kommen Interrupt-Routinen, deren Aufruf kaum kontrollierbar ist.
An dieser Stelle möchte ich mit einem Beispiel aus dem Alltag die Interrupts erklären.
Angenommen, ihr sitzt zu hause im Sessel und lest ein Buch. Auf dem Herd steht der Teekessel und im Bad läuft die Waschmaschine. Es klingelt das Telefon. Aha, eine Unterbrechung ist angesagt, also ein Lesezeichen in das Buch und den Hörer abgenommen. Nachdem das Gespräch beendet ist, wendet ihr euch wieder dem Buch zu, also Lesezeichen herausnehmen und weiterlesen. Da klingelt es an der Tür und der Teekessel pfeift los. Hier haben wir zwei Unterbrechungen, wobei nun der Teekessel wichtiger ist und sofort bedient werden muß. Also merken wir uns die Person an der Tür und legen wieder das Lesezeichen in das Buch, gehen in die Küche und nehmen den Kessel vom Herd, gießen den Tee auf und gehen zur Tür. Es ist Post, die aber nicht sofort gelesen wird, weil die Stelle im Buch grad so spannend ist. Daher kommt die Post erst mal in die Ablage. Sie hat Zeit und weitere Post kommt auch erst am nächsten Tag. Auch die Waschmaschine zeigt durch einen kurzen Summton den Abschluss des Waschvorganges. Dies ist nicht wichtig, wir nehmen es lediglich nur zur Kenntnis und werden die Wäsche erst nach dem Lesen von Buch und Post aus der Maschine holen.
Ich hoffe, die Aufgabe von Interrupts ist hierdurch etwas klarer geworden. Nicht jede Unterbrechung erfordert eine abschließende Bearbeitung. Der Teekessel, ja, weil das Wasser verdampfen und Schaden entstehen kann, das Wasser kalt wird und die Arbeit umsonst war. Aber ob ich die Post sofort lese oder erst eine Stunde später ist nicht wichtig, aber die Person an der Tür kann ich trotzdem nicht ewig warten lassen.
Es sollte auch klar werden, jede Unterbrechung nimmt Zeit in Anspruch, mal mehr, mal weniger.
Wie sähe das Leben ohne Unterbrechung aus? Es gibt keine Klingel an der Tür, keine Pfeife auf dem Kessel und keinen Summer an der Waschmaschine.
Gleiche Situation: Buch lesen, drei.. vier Zeilen, dann nachsehen, kocht der Kessel. Das muss ich relativ oft machen, da eine Gefahr besteht. Auch der anschließende Gang an die Tür erfordert eine kurze Zeitspanne. Der Besucher wird nicht ewig warten wollen und geht vielleicht wieder. Auch das Telefon muss oft abgenommen werden, um Anrufe nicht zu verpassen, die Waschmaschine hingegen ist nicht so wichtig, da reicht vielleicht jede Stunde aus, um den Zustand zu prüfen. Sie läuft ja nicht weg und der Wäsche ist’s auch egal, ob noch ein paar Minuten in der ungemütlichen Trommel angesagt sind. Auf jeden Fall würde durch unsinniges ständiges Kontrollieren irgendwelcher Umgebungsbedingungen eine Menge Zeit verschwendet. Klar, hast du Besucher die auf jeden Fall warten, bis du mal an der Tür nachschaust, braucht es die Unterbrechung nicht. Vergleich es mit der Bushaltestelle, da fährt auch in festen Abständen ein Bus vorbei. Personen, die mitwollen, warten und laufen nicht wieder weg. Aber das kochende Wasser im Kessel verdampft. Unaufhaltsam, solange Energie zugeführt wird.
Zurück zum Thema. Prüfen wir zuerst einmal alle zeitkritischen Bedingungen und legen fest, welche Zykluszeit akzeptabel ist. Ich denke, eine Zykluszeit von 50 – 70% einer Signalzeit ist ausreichend schnell für das Signal und gibt auch genügend Luft für auftretende Interrupts, aber mehr darf es nicht werden. Dabei gehe ich davon aus, die ISR (Interrupt-Service-Routinen) sind nicht zu umfangreich.
Wie kann ich nun sicherstellen, das die Information im Programm immer bearbeitet wird und nicht Signale „übersehen“ werden?
Im Prinzip rechnen, praktisch wird man eine Abschätzung machen. Zuerst geht man davon aus, das jeder Code auch durchlaufen wird, bei Verzweigungen nimmt man halt den größeren Block von Anweisungen. Schleifen werden entsprechend der Anzahl der Durchläufe berechnet. Nun kann man pingelig sein und aufdröseln, wie viele Takte die einzelnen Befehle verbraten, oder gleich Pi mal dicken Daumen die Anweisungen mit 2 multiplizieren. Damit hat man die Takte. Nun die Frequenz im Kehrwert und mit den Takten multipliziert und schon hat man die Zykluszeit….
Ähhhh und die ISR ? verbraucht die nicht auch Zeit ? Klar, auch hier wird mit jedem Interrupt die Zykluszeit verlängert. Wie kann man überschauen, ob trotz Interrupt die Zykluszeit kalkulierbar bleibt?
Dazu muß man die Signale betrachten, die einen Interrupt auslösen. Bleiben wir einmal bei unserem Beispiel mit der Führung eines Rennwagens in einer Slotcarbahn und nehmen einmal an, das ein detektiertes Signal durch die Lichtschranke kürzer ist, wie die Zykluszeit. Damit ist nicht sichergestellt, das dieses Signal durch pollen erfasst wird und mit einem Interrupt eingelesen werden muss. Allerdings ist danach erst mal wieder eine Zeit lang ruhe, bevor mit einem weiteren Signal zu rechnen ist. Deshalb wird in der ISR lediglich eine Flagge gesetzt, die besagt, hier war ein Signal. In der Programmschleife wird dann diese Flagge abgefragt, die Bearbeitungsschritte durchgeführt und danach die Flagge gelöscht. Dies ist wieder berechenbar.


Ein anderes Beispiel:
Ein Motor läuft mit einer max. Drehzahl von 1800 U/min und hat einen Incrementalgeber angeflanscht, der pro Umdrehung 4096 Impulse liefert.
Hier ist nach einem Impuls nicht mit einer längeren Pause zu rechnen, daher muss in der ISR dieser Impuls bearbeitet werden.
Also sehen wir uns die Rechnung einmal an:
30 U/sek = 30 *4096 Impulse = 122880 Imp/Sek = ca. 0,000008 sek = 8µSekunde.
50 Befehle benötigen ca. 6 µSekunden, also ist da nix mit pollen. Auch darf die ISR nicht allzu viele Befehle haben denn alle 8µs wird die ISR aufgerufen und abgearbeitet und das verlängert auch den Zyklus. Hab ich in der ISR z.B. nur die Impulszählung und die Abfrage auf Überläufe, so sind schnell 20 oder 30 Befehle verbraten. In den 8µSek., die uns die Impulse Zeit lassen, kann ich grad mal ca. 60 Befehle abarbeiten. Darin sind auch die Befehle der in der ISR. Werden innerhalb einer ISR nun mehr Anweisungen bearbeitet, als die Zeit zwischen den Interrupts hergibt, werden entweder bei abgeschaltetem Interrupt Signale verloren gehen oder lässt man den Interrupt scharf, wird sich das Programm durch einen überlaufenden Stack verabschieden. Sollte dies zu einem Problem werden, dann müssen andere Bedingungen gewählt werden. Da ist die Taktfrequenz. Möglicherweise gibt es Controller, die wesentlich höher getaktet werden können. Auch eine andere Wahl des Impulsgebers mit geringeren Impulsen pro Umdrehung reduziert die Zykluszeit. Oder man prüft, ob ein Eingang auf einen Zähler zu schalten geht und liest dann die Werte über einen zeitgesteuerten Interrupt. Auch externe Zähler können Verwendung finden. Immerhin gibt es vielleicht auch noch andere Bedingungen für einen Interrupt.
Da sind die Timer. Sie lösen ebenfalls Interrupts aus und verlängern das Programm. So sind Interrupts, die jede mS ausgelöst werden, gut geeignet, zeitgesteuerte Aufgaben anzustoßen, ohne das Programm im Ablauf zu stören.
Ein weiterer Interrupt wird durch die Datenkommunikation, den USART ausgelöst. Immer, wenn ein Byte empfangen wurde, meldet sich die ISR. Hier genügt es, einfach das Byte in einen Puffer zu schreiben und den Platz für das nächste Byte freizugeben. Später im Programm kann man dann entscheiden, was mit dieser Information angefangen werden soll. Beispiel „Postbote an der Tür“.

Als Assembler-Programmierer bin ich mir der Laufzeiten bewusst, aber in Bascom oder „C“ denkt man darüber gar nicht so nach. Und plötzlich hat man keine oder nur holpernde Anzeigen, Tastendrücke werden nicht mehr sicher erfasst oder Lampen flackern und noch schlimmer, Relais „rasseln“.

Dieser Beitrag soll aus euch keine Assembler-Experten machen, sondern nur den ein oder anderen Fehler erklären, der aus Unwissen über Zykluszeiten entsteht. Controller sind schnell und für viele Anwendungen geeignet. Trotzdem ist manchmal ein Nachrechnen erforderlich. Und wenn’s denn in die Grenzwerte geht, das eine Reaktion von einem Controller im Millisekunden- oder sogar im Mikrosekundenbereich verlangt wird, muss schon einmal darüber nachgedacht werden, welcher Programmumfang dann noch abgearbeitet werden kann.
 

Anhänge

  • ControllerTakt.JPG
    ControllerTakt.JPG
    21,6 KB · Aufrufe: 29
Hi oldmax

super Beitrag!

mfg

Hero_123
 
Hi,

schließe mich an.
Das Bildchen ist allerdings fehlerhaft.

62,5pS wären 62,5 piko-Siemens.
Richtig wären 62,5ns (nano-Sekunden)

Schönen Gruss
Markus
 
Status
Für weitere Antworten geschlossen.

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)