Auf dieser Seite findest du die Dokumentation zum Praktikum Prozessprogrammierung mit dem Thema: "Simulation einer Windradanlage".
Im Jahr 2003 habe ich zusammen mit einem Kommilitonen an diesem Projekt gearbeitet und eine Simulation für den Betrieb eines Windrads entwickelt, basierend auf dem Multi-Threading-Echtzeitsystem RTKERNEL (FH-Wedel, SS2003).
2.2 Programminstallation und Programmstart 3
2.3.1 Die grafische Oberfläche. 4
2.3.2 Benutzersteuerung und Ablauf. 4
3.1 Entwicklungskonfiguration. 5
3.2 Problemanalyse und Realisierung. 6
3.3 Übersicht und Beschreibung aller Tasks. 6
3.4 Intertask-Kommunikation und Synchronisation. 7
3.5 Die Verwendeten Datenstrukturen. 7
3.6 Grobe Ablaufbeschreibung. 9
4.1 Original Aufgabenstellung Prozessprogrammierung 1, SS 2003. 11
4.2 Quellcode des Programms. 11
Für den Ablauf des Programms werden folgende Hard- und Softwarekomponenten vorausgesetzt:
Hardware |
|
Software |
|
Um die Simulation starten zu können, muss das Programm zuerst installiert werden.
Zur Installation des Programms muss das komplette Verzeichnis „Windrad“ von der Installations-CD auf die Festplatte kopiert werden. Dort kann dann das Programm durch Aufruf von „RADK.EXE“ gestartet werden. Ggf. muss noch das Schreibschutzattribut der Datei „log.txt“ entfernt werden, falls der Dateimanager dies nicht schon automatisch beim Kopieren erledigt hat.
Durch Löschen des kopierten Verzeichnisses (inkl. aller Unterdateien) kann das Programm einfach wieder deinstalliert werden.
Der Programmstart direkt von CD ist nicht möglich, da auf diesem Medium kein Schreibzugriff (zum Erstellen der Logdatei) gestattet ist.
Bei dieser Simulation einer Windradanlage wird auf dem Bildschirm eine komplette Ansicht aller relevanten Daten sowie die Buttons zur Windrad- und Verbrauchersteuerung bereitgestellt.
Das untenstehende Bild zeigt die grafische Oberfläche des Programms, nach erfolgreichem Start. Das Hauptfenster ist in elf kleinere Fenster mit blauen Rand unterteilt, wobei jedes Fenster die jeweils beschriebenen Informationen darstellt, so dass der Lauf der Simulation zu jedem Zeitpunkt mitverfolgt werden kann.
Nach Aufruf und Start des Programms („RADK.EXE“) wird die Simulation der Windradanlage automatisch gestartet. Durch Drücken der „Escape“-Taste kann sie zu jedem Zeitpunkt wieder beendet werden. Nach vier Simulationstagen bleibt das Programm stehen und zeigt die zuletzt ermittelten Daten bis zum Programmende an.
Mit Hilfe der Maus kann durch Klicken der Buttons sowohl jeder einzelne Verbraucher als auch das Windrad an- und ausgeschaltet werden. Die jeweilige Beschriftung der Buttons zeigt den aktuellen Zustand. Außerdem ist es möglich mit Hilfe der „Print“-Taste das Windrad sofort stillzulegen. Dieser Notaus-Schalter hat höchste Prioriät und wird umgehend nach Druck der Taste wirksam. Ein erneutes Drücken setzt den Notaus-Schalter zurück.
Um das Ergebnis der Simulation zu sehen, genügt ein Blick in das Logfile. Während der gesamten Simulation werden alle wichtigen Zustände protokolliert und sind anschließend im Logfile zu finden. Für jede Minute ist der Status des Windrads zu sehen (ob es an-/ausgeschaltet war bzw. ob es durch den Notaus-Schalter deaktiviert wurde). Anhand der angegebenen Differenz erkennt man zu jedem Zeitpunkt, ob das Windrad Energie in das öffentliche Netz eingespeist oder Energie daraus bezogen hat. Die Gesamtdifferenz zeigt dann den kumulierten Wert und gibt Auskunft darüber, ob der Einsatz des Windrads ökonomisch ist oder nicht. Außerdem enthält das Logfile den jeweiligen Status (eingeschaltet/ausgeschaltet) der drei Verbraucher (V1, V2 und V3) zu jedem Zeitpunkt der Simulation. Das folgende Bild zeigt einen Auszug der Logdatei:
Tag: █ Status: █ Differenz: █ Gesdifferenz: █ V1 █ V2 █ V3 ____________________________________________________________________ 1 0:49 Uhr █ Rad aus █ 0.00 kW █ 37.32 kWh █ Aus █ Aus █ Aus 1 0:50 Uhr █ Rad aus █ 0.00 kW █ 37.32 kWh █ Aus █ Aus █ Aus 1 0:51 Uhr █ Rad aus █ 0.00 kW █ 37.32 kWh █ Aus █ An █ Aus 1 0:52 Uhr █ Rad aus █ 0.00 kW █ 37.32 kWh █ Aus █ An █ Aus 1 0:53 Uhr █ Rad aus █ 0.00 kW █ 37.32 kWh █ Aus █ An █ Aus 1 0:54 Uhr █ Rad aus █ 0.00 kW █ 37.32 kWh █ Aus █ An █ Aus 1 0:55 Uhr █ Rad aus █ 0.00 kW █ 37.32 kWh █ Aus █ An █ Aus 1 0:56 Uhr █ Rad aus █ 0.00 kW █ 37.32 kWh █ Aus █ An █ Aus 1 0:57 Uhr █ Rad aktiv █ 116.48 kW █ 39.26 kWh █ Aus █ An █ Aus 1 0:58 Uhr █ Rad aktiv █ 115.05 kW █ 41.17 kWh █ Aus █ An █ Aus 1 0:59 Uhr █ Rad aktiv █ 125.26 kW █ 43.26 kWh █ Aus █ An █ Aus 1 1: 0 Uhr █ Rad aktiv █ 64.01 kW █ 44.33 kWh █ Aus █ An █ Aus 1 1: 1 Uhr █ Rad aktiv █ 68.07 kW █ 45.46 kWh █ Aus █ An █ Aus 1 1: 2 Uhr █ Rad aktiv █ 70.58 kW █ 46.64 kWh █ Aus █ An █ Aus 1 1: 3 Uhr █ Rad aus █ 0.00 kW █ 46.64 kWh █ Aus █ An █ Aus 1 1: 4 Uhr █ Rad aus █ 0.00 kW █ 46.64 kWh █ Aus █ An █ Aus 1 1: 5 Uhr █ Rad aus █ 0.00 kW █ 46.64 kWh █ Aus █ An █ Aus 1 1: 6 Uhr █ Rad aus █ 0.00 kW █ 46.64 kWh █ Aus █ An █ Aus 1 1: 7 Uhr █ Rad aus █ 0.00 kW █ 46.64 kWh █ Aus █ An █ Aus 1 1: 8 Uhr █ Rad aus █ 0.00 kW █ 46.64 kWh █ Aus █ An █ Aus 1 1: 9 Uhr █ Rad aktiv █ 75.15 kW █ 47.89 kWh █ Aus █ An █ Aus 1 1:10 Uhr █ Rad aktiv █ 133.58 kW █ 50.12 kWh █ Aus █ An █ Aus 1 1:11 Uhr █ Rad aktiv █ 92.99 kW █ 51.67 kWh █ Aus █ An █ Aus 1 1:12 Uhr █ Rad aktiv █ 118.64 kW █ 53.65 kWh █ Aus █ Aus █ Aus
Die Entwicklung von „Fighter“ wurde mit Hilfe folgender Software durchgeführt:
Die Realisierung des Simulators stellt mehrere Anforderungen an die Entwickler. Die wichtigsten Bestandteile des Programms sind:
Die Intertask-Kommunikation wurde im Wesentlichen mit zwei Konzepten realisiert: Mailboxen und Message-passing.
Beim Message-passing müssen Sender- und Empfängertask synchronisiert sein, d.h., beide Tasks müssen zum gleichen Zeitpunkt zum Senden und Empfang bereit sein. Ist dies nicht der Fall, blockiert die schon bereite Task, solange bis die andere auch bereit ist, so dass der Transfer stattfinden kann.
Das Mailboxkonzept ist so aufgebaut, dass die Tasks beim Datentransfer nicht unbedingt synchronisiert sein müssen, da eine (frei definierbare) Menge von ‚Slots’ (im vorliegenden Programm bei jeder Mailbox immer nur ein Slot) zur Verfügung steht – Speicherplatz passend zu dem Datentypen, von dem die zu verschickenden Daten sind. Soll ein Datensatz versendet werden, so wird dieser von der Sendertask in der Mailbox abgelegt. Die Empfängertask liest diesen Datensatz aus der Mailbox aus und löscht ihn anschließend dort wieder. Soll ein Datensatz empfangen werden, obwohl die Mailbox leer ist, blockiert die Empfängertask solange bis die Mailbox mit einem Datensatz gefüllt ist. Genauso verhält es sich mit der Sendertask und voller Mailbox.
Es kann jedoch bei beiden Konzepten die Synchronisation insofern etwas „gelockert“ werden, indem man spezifizieren kann, dass eine Task nicht blockiert, wenn die andere Task nicht zum Transfer bereit ist oder eine Mailbox leer, bzw. voll ist. Es besteht bei dieser Methode die Möglichkeit abzufragen, ob ein Transfer stattgefunden hat oder nicht. Im vorliegenden Programm wurde diese Methode bei der Entnahme aus der Notaus-Mailbox verwendet, da nur beim Aufruf der ISR von Int5 diese Mailbox gefüllt wird.
Typ: |
Beschreibung:
|
TMin = 0..59; TStd = 0..23; TTag = 0..3; TUhrzeit = record Tag : TTag; Std : TStd; Min : TMin; end; |
- Definiert 60 Minuten für eine Stunde - Definiert 24 Stunden für einen Tag - Simulationsdauer: 4 Tage Speichert die aktuelle Simulationszeit, welcher Tag, welche Stunde, welche Minute |
TWind = array[0..4*24-1] of real; |
Array für Konstanten der Windgeschwindigkeit, 4 Tage à 24 Stunden werden direkt angegeben, die Werte dazwischen werden linear interpoliert. |
TWirk = array[5..25] of real; |
Array für Konstanten der Wirkungsgrade |
TVerbraucher = record Pmin, Pmax : longint; Tmin, Tmax : longint; end; TVerbrArr = array[1..3] of TVerbraucher; |
zum Speichern des Zeitintervalls und Leistungs-Intervalls der drei Verbraucher. Pmin/Pmax: Minimal- bzw. Maximalwert der geforderten Leistung des Verbrauchers Tmax/Tmax: Minimal- bzw. Maximalwert der zeitlichen Dauer der Leistungsanforderung (wie lange ein Wert angefordert wird) |
TVerbBox = record Energie : real; Num : byte; end; |
Speichert die aktuell Verbrauchte Energie und die zugehörige Indexnummer des jeweiligen Verbrauchers (dieser „Num“-Wert ist wichtig, um die einzelnen Tasks unterscheiden zu können, da alle die gleiche Task-Funktion besitzten. |
TWPBox = record vWind : real; wirk : real; EWind : real; keinnotaus : boolean; end; |
Speichert alle Daten, die von der Windradtask an die Prozesswarte geschickt werden (Windgeschwindigkeit, Wirkleistung, Windenergie und der Status des Notaus-Schalters). Dieser Typ wird für die Mailbox verwendet. |
TVerbrAnzeige = array[1..4] of real; |
Speichert die Werte, die im Verbraucherfenster angezeigt werden (4 = Gesamtverbrauch) |
TEPBox = record EVerbraucher : TVerbrAnzeige; PVerbraucher : real; PErzeuger : real; Differenz : real; ENetzrein : real; ENetzraus : real; end; |
Speichert alle Daten, die von der Verteilertask an die Prozesswarte geschickt werden. Die Prozesswarte übernimmt die Ausgabefunktion und muss somit über alle berechneten Daten verfügen. |
TBtnState = array [0..3] of integer; |
Speichert die Stati der vier Buttons (ob gedrückt oder nicht gedrückt) |
Tbuffer = array [1..3] of real; |
Speichert die letzten drei Windgeschwindigkeiten für die Hysterese-Berechnung (erst bei dreimaliger Überschreitung der Grenze soll sich das Windrad ein- bzw. ausschalten) |
CWind : TWind = ( {Tag1} 6,6.5,6.7,6.7,6.8,7,8,9,9.5,10,10.2, 10.5,10.7,11,12,13,14,17,18,18,16,15.5, 15,15, {Tag2} 15,14,13.5,13,12,12.2,12.5,12,12.3,12, 11, 10,9,9,8,7.5,7,6,5.8,5.4,5,3,2,2, {Tag3} 2,2.5,3,3.5,4,4.2,4.5,5,5.3,6,7,8,7.7, 7,6,5,5.4,6,7,8,9,9,7,6, {Tag4} 7,8,9,9.5,10,10.2,10.5,10.7,11,12,13, 14,17,18,20,23,26,25.5,25,23,22,20, 19,17 ); |
Konstantwerte der Wirkungsgrade bei verschiedenen Windgeschwindigkeiten aus dem Wetterlabor für vier Simulationstage. Es gibt jeweils 24 Mittelwerte, je ein Wert für eine Stunde des Tages. Die Werte für die Minuten werden daraus linear interpoliert. |
CWirk : TWirk = ( 26.2,37.2,41.9,43.7,44,43.3,40.9, 37,32.5,27.2,22.3,18.5,15.4,12.9, 11,9.3,8,7,6.1,5.2,4.5 ); |
Dieses konstante Array enthält die Wirkungsgrade für entsprechende Windgeschwindigkeiten. Es beginnt bei der Windgeschwindigkeit 5 m/s und geht in ganzen Schritten bis zu dem Wert für die Windgeschwindigkeit von 25 m/s. Dies hat den Vorteil, dass der Wirkungsgrad direkt mit der Windgeschwindigkeit indiziert werden kann. |
CVerbraucher : TVerbrArr = ( (Pmin:20000; Pmax:200000; Tmin:2; Tmax:10), (Pmin:40000; Pmax:100000; Tmin:10; Tmax:30), (Pmin:100000; Pmax:250000; Tmin:5; Tmax:20) ); |
Konstantwerte für die Zeit- und Leistungsintervallangaben aller drei Verbraucher |
CTickDelay = 10; CWindrad = 0.8495; CWindflaeche = 1452; CFensterAnzahl = 11; CLogFile = '.\log.txt'; |
Setzt die Geschwindigkeit der Simulation (Zeit-Delay) Proportionalitätsfaktor zur Berechnung der Windenergie Fläche des Windrades Anzahl der Grafikfenster bei der Bildschirmausgabe Dateiname der Logdatei |
Legende der Objekte:
Im Folgenden wird grob der Ablauf einer Simulationsminute beschrieben:
Im vorliegenden Programm geht die Synchronisation von der Zeittask aus, die ja die Simulationsgeschwindigkeit vorgibt. Von ihr aus werden Messages mit den aktuellen Zeitinformationen zur Windfeldtask, zu allen Verbrauchern und zur Prozesswarte gesendet. Von der Windfeldtask wird eine Message mit der Windgeschwindigkeit zur Windradtask gesendet, dies geschieht aber erst nachdem die Zeit von der Windfeldtask empfangen worden ist. Die Windradtask wiederum sendet eine Message mit der erzeugten Energie an die Verteilertask. Die Verbraucher senden jeweils nach dem Zeitempfang und Statusabfrage der Prozesswarte auch eine Message an den Verteiler mit der angeforderten Energie. Nachdem der Verteiler alle Messages empfangen hat, werden in dieser Task aller erforderlichen Daten errechnet und per Mailbox an die Prozesswarte geschickt. Ebenso werden die Informationen der Windradtask per Mailbox an die Warte geschickt. Bei der Intertask-Kommunikation mit der Prozesswarte bieten sich Mailboxen an, da sich die Programmierung bei gleicher Effektivität etwas flexibler gestaltet, da es sonst u.U. evtl. durch Benutzereingaben zu Deadlocks kommen könnte.
Die Windradtask empfängt ggf. eine Mail von der ISR des Notausschalters. Wird eine Mail empfangen, wird der Notausschalter getoggelt.
Um dem Benutzer eine sichere und schnelle Möglichkeit zu bieten, dass Windrad (z.B. im Störfall) auszuschalten, löst das Programm bei Druck auf die „Print“-Taste einen Interrupt aus, der höchste Priorität besitzt.
Damit das Programm auf den Interrupt reagieren kann, besitzt es eine eigene Interrupt Service Routine, die bei Auslösen des Interrupts abgearbeitet wird. Damit DOS diese Routine kennt und auf sie reagieren kann, wird zu Beginn unseres Programms zunächst der alte Interruptvektor 5 gesichert und anschließend auf unsere ISR umgebogen. Um Deadlocks beim Verbiegen des Vektors zu vermeiden geschieht dies in einem durch eine Semaphore abgesicherten Bereich. Wird die Taste gedrückt und dadurch der Interrupt ausgelöst, so kommt unsere ISR zum Aufruf. Die ISR beendet zunächst den kritischen Abschnitt bzw. die Semaphore, anschließend schickt die Routine mit Hilfe einer Mailbox eine Nachricht an die Windradtask, welche daraufhin sofort die Berechnung einstellt bzw. das Windrad stilllegt (es wird der Wert Null für die erzeugte Energie an die Energieverteilung gesendet).
Beim Beenden des Programms wird der alte, gesicherte Interruptvektor 5 wiederhergestellt, da unsere ISR nicht länger existiert.
Das Programm verwendet insgesamt acht Tasks. Damit die Synchronisation untereinander ordnungsgemäß funktioniert, ist es wichtig, dass die einzelnen Tasks unterschiedliche Prioritäten besitzen. Andernfalls würden einige Tasks blockieren und das Programm in einer Endlosschleife anhalten. Die folgende Tabelle zeigt die verschiedenen Prioritäten aller verwendeten Tasks und beschreibt warum diese Vorgabe wichtig ist:
Task |
Priorität |
Beschreibung |
Zeitgeber |
MainPriority+2 |
Um einen sicheren und synchronen Simulationstakt zu gewährleisten muss gewährleistet sein, dass der Zeitgeber-Task immer aufgerufen wird, da er die aktuelle Zeit bereitstellt. |
Prozeß-Warte |
MainPriority+1 |
Die Prozesswarte besitzt eine höhere Priorität, da sie die Steuerfunktion und Ausgabe auf dem Bildschirm übernimmt. Sie muss die Daten vom Windrad und Energieverteiler annehmen können, damit diese nicht zu lange blockieren und die Simulation somit anhalten. |
Wind |
MainPriority |
Diese Tasks haben alle dieselbe Priorität, da aufgrund des implementierten Message-Passing in einer Kette immer gewährleistet ist, dass diese Kette aus Tasks auf die Daten des „Vorgängers“ wartet und anschließend sendet. |
Windrad |
MainPriority |
|
Energie-Verteiler |
MainPriority |
|
Verbraucher 1,2,3 |
MainPriority |
Da es beim Betrieb eines Windrades zu plötzlich auftretenden Störungen kommen kann, ist es für die Sicherheit sehr wichtig, dass es immer eine Möglichkeit gibt, dass Windrad sofort anzuhalten. Diese Funktion übernimmt in unserer Simulation der „interruptgesteuerte“ Notaus-Schalter. Da ein Interrupt immer eine sofortige Unterbrechung des laufenden Programms bedeutet, ist das Abschalten auf diesem Wege eine sichere Option. Der „Notaus-Interrupt“ hat somit eigentlich die höchste Priorität!
Diese Website benutzt Cookies. 🍪 Wenn Sie die Website weiter nutzen, stimmen Sie der Verwendung von Cookies zu. Mehr Infos