Hallo zusammen, ich versuche mit dem angehängten Testprogramm mit einem Mega32 eine Sprungantwort aufzuzeichnen: ich gebe ein PWM-signal auf einen Elektromotor (der als Ventilator eine Klappe hochbläst) und messe eine Reaktion mittels ADC. Ich will möglichst in festen Zeitschritten die AD-Werte mittels UART (ich verwende P.Fleurys Library) auslesen. Ich löse das jetzt, indem ich in einer ISR die Daten sende. Ist das so OK, oder eher schlecht weil ich in der ISR interruptbasierten UART verwende? Ich bin mir auch nicht ganz im klaren darüber wie die UART-Funktionen funktionieren - in der ISR sind ja Interrupts eigentlich disabled (global interrupt enable flag gelöscht), aber die interruptbasierte Kommunikation geht trotzdem - ich vermute das klappt weil in der ISR nur der Buffer beschrieben wird und das eigentliche Senden erst später erfolgt? Der Code in den ISRs soll ja zudem so kurz wie möglich sein, ist meine Lösung in dieser Hinsicht OK? Alternativ könnte ich in der while-Schleife des Hauptprogramms den AD-Wert jeweils mit Timestamp (d. h. Anzahl durchlaufener ISRs) senden, aber die erste Version ist denke ich besser weil die Abtastfrequenz fest ist. (Bei der zweiten wird ab und zu eine ISR nicht übertragen, so dass Lücken entstehen.) (Die LED lasse ich übrigens als Indikator blinken, ob die ISRs gleichmässig durchlaufen oder sich bei Programmänderungen Verzögerungen bemerkbar machen.) Die Abtastfrequenz ist meiner Berechnung jetzt 50 Hz, oder täusche ich mich da? Vielen Dank für Antworten! Uli
Na ja: Wenn Interrupts gesperrt sind, geht ja die Anforderung des Interrupts deswegen ja trotzdem nicht verloren. D.h. du stellst was in den Buffer, die UART Routine sendet ein Zeichen und generiert einen Interrupt sobald das Zeichen draussen ist. Sind zu diesem Zeitpunk die Interrupts noch nicht freigegeben, so wird die ISR Anforderung einfach nur gespeichert und erst dann ausgeführt sobald die Interrupts wieder freigegeben wurden. Im schlimmsten Fall entsteht ein Zeitverzug zwischen senden des ersten Zeichens und senden des zweiten Zeichens, da ja die ISR die das zweite Zeichen senden würde warten muss, bis deine ISR die Interrupts wieder freigegeben hat.
OK, dankeschön für die gute Erklärung! Aber itoa() in der ISR durchzuführen ist auch sehr kritisch, oder? Ich vermute das haut bei mir nur hin aufgrund der recht langsamen ISR-Frequenz, aber wenn ich die Frequenz erhöhe oder mehr itoa()-Wandlungen in der ISR vornehme geht das zeitlich nicht mehr? (zumindest blinkt dann die LED nicht mehr...) Ich will im nächsten Schritt nämlich mehrere Regelparameter per UART auslesen, also pro ISR-Durchlauf einen ganzen Satz an Zahlen. Ist dann der beste Weg (oder der einzige?) in der Schleife der main-Funktion die Daten immer mit Timestamp zu senden (also so wies im Beispielprogramm auskommentiert in der while-Schleife steht)? Nachteil ist halt dass das nicht schnell genug geht so dass immer nur z.B. nur jeder dritte ISR-Parametersatz (je nach ISR-Frequenz)gesendet wird. Gibt es Alternativen oder bessere Möglichkeiten? Vielen Dank Uli
Generell solltest du ISR zeitlich so kurz wie nur irgend möglich halten. Aber das weist du eh. > in der Schleife der main-Funktion die > Daten immer mit Timestamp zu senden So wuerde ich das machen. > Nachteil ist halt dass das > nicht schnell genug geht so dass immer nur z.B. nur jeder dritte > ISR-Parametersatz (je nach ISR-Frequenz)gesendet wird. Das liegt aber wahrscheinlich nicht am Pgm Aufbau an sich, sondern daran, dass die UART Übertragung ja auch Zeit benötigt. Wenn die Daten nun schneller anfallen als sie übertragen werden können, fällt irgendetwas unter den Tisch. Dabei ist es aber unerheblich wo due die Übertragung initiierst. Die UART Übertragung ist einfach zu langsam. Da hilft nur: Baudrate hochdrehen oder weniger Daten generieren oder weniger übertragen.
Danke vielmals, das bestätigt was ich geahnt habe! Dann muss jetzt ein Quarz für höhere Baudraten her...
Wenn ich sowas machen muesste wuerde ich folgendes beachten, 1. PWM Frequenz des Motor's mindestens bei 10 fachen der ADC Abtastrate 2. vor ADC, Tiefpass mit entsprechender Grenzfrequenz Am besten gehen sämtliche Samples erstmal in einen Puffer und erst wenn man fertig aufgezeichnet hat fragt man am PC ab. Sonst interruptgersteuerte UartKomunikation, Samples in Ringpuffer zwischenspeichern. Auf Überlauf prüfen. Du nennst keine Abtastraten, dies ist aber eigentlich das erste worüber man sich Gedanken machen sollte. (Dauer des Vorgangs und nötige zeitliche Auflösung) Ich würde denken, dass ein AVR mit 8 MHz für sowas durchaus ausreicht. Wahrscheinlich auch mit 1MHz
Hi Wolfram, danke für die Hinweise. UART ist ja schon interruptbasiert, aber wie kann ich denn den Buffer auf Überlauf prüfen und was passiert wenn er überläuft (oder wo finde ich Infos dazu, hab gerade ergebnislos gesucht)? Entgegenwirken kann ich am besten durch möglichst grossen Buffer und hohe Baudraten vermute ich? Abtastrate für die Sprungantwort ist 50Hz, das hatte ich am Anfang erwähnt...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.