Day by Day
(EN google-translate)
(PL google-translate)
Nachfolgend wird chronologisch verzeichnet, welche Inhalte in den Einzellehrveranstaltungen bei Eingebettete Systeme für BMT7 im Wintersemester 2021/22 behandelt wurden.
#1 Mittwoch 29.09.2021 (endet bereits 14Uhr wg. Professor*Innen-Vollversammlung)
Einführung 1: Ubiquitous Computing nach Marc Weiser
Ubiquitous Computing - Wikipedia-EintragMark Weiser: The Computer for the 21st Century
Einführung 2: Welche Eigenschaften sollte ein engebettetes Echtzeitsystem haben?
|
Echtzeit im Sinne von "zeitlich korrekt": 67_Echtzeitsysteme/01_Einfuehrung/02_Korrektheit #aeint 67_Echtzeitsysteme/01_Einfuehrung/03_Hardware 67_Echtzeitsysteme/01_Einfuehrung/03_Hardware Hardware-Plattformen: 67_Echtzeitsysteme/01_Einfuehrung/03_Hardware
State-machine / Zustandsmmaschine: 67_Echtzeitsysteme/12_Zustandsmaschine
Einführung: Was sind Voraussetzungen für die effiziente Entwicklung engebetteter Echtzeitsysteme?
|
Beispiele eingebetteter Echtzeitsysteme (Prototypen / Funktionsstudien aus vergangenen Lehrveranstaltungen)
15_Einachser -- Einachser auf kramann.infoElektrokutsche, Personenkutschfahrt auf kramann.info
Physikalische Echtzeitsimulation einer mechanischen Rassel mit einem Smartphone
Vernetztes Smartphone zur Steuerung einer Elektromechanischen melodischen Trommel
KIBA (Kamerasystem segmentiert Spielchips auf Leuchttisch, absolute Positionen werden als Tonereignis in einer zyklischen Phrase interpretiert)
Lichtharfe: Handpositionen der Benutzer erzeugen Klangereignisse
Masken: elektronische Skulpturen
mechatronical_mantra.mp4
Beispiele eingebetteter Echtzeitsysteme (Professionelle Produkte)
|
"Rocket Lab"
Teil 1: Überblick zum Ablauf des Kurses
|
Teil 2: Einblick in die drei Bereiche: Begriff der Lebenswelt, C/C++ - Java-Programmierung
Teil 3: Entwicklung einer Wasserwaage auf der Grundlage eines Android-Devices
processing.org -- Bitte laden Sie sich die Java-Entwicklungsumgebung Processing herunter und installieren se
|
Teil 4: Übertragung des Entwurfsmodells von Processing auf einen Arduino Nano 33 IoT
Nun sollen Sie selbstständig in Zweiergruppen ein Projekt gleichen Inhalts wie in Teil 3 umsetzen, jedoch auf der Grundlage des Arduino Nano 33 IoT.
Wasserwaage mit Android-App
/** * <p>Ketai Sensor Library for Android: http://Ketai.org</p> * * <p>KetaiSensor Features: * <ul> * <li>handles incoming Sensor Events</li> * <li>Includes Accelerometer, Magnetometer, Gyroscope, GPS, Light, Proximity</li> * <li>Use KetaiNFC for Near Field Communication</li> * </ul> * <p>Updated: 2017-08-29 Daniel Sauter/j.duran</p> */ import ketai.sensors.*; KetaiSensor sensor; float accelerometerX, accelerometerY, accelerometerZ; void setup() { fullScreen(); sensor = new KetaiSensor(this); sensor.start(); orientation(LANDSCAPE); textAlign(CENTER, CENTER); textSize(displayDensity * 36); } void draw() { background(255); float siebtel = width/7.0f; float haelfte = siebtel/2.0f; float schwelle = 1.0f; int anzahl = 7; float diff = abs(9.81 - accelerometerX); int schritte = (int)(diff / schwelle); int index = anzahl / 2; if(accelerometerY>0) index -= schritte; else index += schritte; if(index<0) index=0; if(index>anzahl-1) index = anzahl-1; for(int i=0;i<anzahl;i++) { float xpos = (float)i*siebtel + haelfte; if(index==i) fill(255,0,0); else fill(0); ellipse(xpos,height/2.0f,siebtel*0.8f,siebtel*0.8f); } /* background(78, 93, 75); text("Accelerometer: " + "x: " + nfp(accelerometerX, 1, 3) + " " + "y: " + nfp(accelerometerY, 1, 3) + " " + "z: " + nfp(accelerometerZ, 1, 3), 0, 0, width, height); */ } void onAccelerometerEvent(float x, float y, float z) { accelerometerX = x; accelerometerY = y; accelerometerZ = z; } /* available sensors/methods * void onSensorEvent(SensorEvent e) - raw android sensor event <br /> * void onAccelerometerEvent(float x, float y, float z, long a, int b): x,y,z force in m/s^2, a=timestamp(nanos), b=accuracy * void onAccelerometerEvent(float x, float y, float z): x,y,z force in m/s2 * void onOrientationEvent(float x, float y, flaot z, long a, int b): x,y,z rotation in degrees, a=timestamp(nanos), b=accuracy * void onOrientationEvent(float x, float y, float z) : x,y,z rotation in degrees * void onMagneticFieldEvent(float x, float y, float z, long a, int b) : x,y,z geomag field in uT, a=timestamp(nanos), b=accuracy * void onMagneticFieldEvent(float x, float y, float z): x,y,z geomagnetic field in uT * void onGyroscopeEvent(float x, float y, float z, long a, int b):x,y,z rotation in rads/sec, a=timestamp(nanos), b=accuracy * void onGyroscopeEvent(float x, float y, float z): x,y,z rotation in rads/sec * void onGravityEvent(float x, float y, float z, long a, int b): x,y,z force of gravity in m/s^2, a=timestamp(nanos), b=accuracy * void onGravityEvent(float x, float y, float z): x,y,z rotation in m/s^s * void onProximityEvent(float d, long a, int b): d distance from sensor (typically 0,1), a=timestamp(nanos), b=accuracy * void onProximityEvent(float d): d distance from sensor (typically 0,1) * void onLightEvent(float d, long a, int b): d illumination from sensor in lx * void onLightEvent(float d): d illumination from sensor in lx * void onPressureEvent(float p, long a, int b): p ambient pressure in hPa or mbar, a=timestamp(nanos), b=accuracy * void onPressureEvent(float p): p ambient pressure in hPa or mbar * void onTemperatureEvent(float t, long a, int b): t temperature in degrees in degrees Celsius, a=timestamp(nanos), a=timestamp(nanos), b=accuracy * void onTemperatureEvent(float t): t temperature in degrees in degrees Celsius * void onLinearAccelerationEvent(float x, float y, float z, long a, int b): x,y,z acceleration force in m/s^2, minus gravity, a=timestamp(nanos), b=accuracy * void onLinearAccelerationEvent(float x, float y, float z): x,y,z acceleration force in m/s^2, minus gravity * void onRotationVectorEvent(float x, float y, float z, long a, int b): x,y,z rotation vector values, a=timestamp(nanos), b=accuracy * void onRotationVectorEvent(float x, float y, float z):x,y,z rotation vector values * void onAmibentTemperatureEvent(float t): same as temp above (newer API) * void onRelativeHumidityEvent(float h): h ambient humidity in percentage * void onSignificantMotionEvent(): trigger for when significant motion has occurred * void onStepDetectorEvent(): called on every step detected * void onStepCounterEvent(float s): s is the step count since device reboot, is called on new step * void onGeomagneticRotationVectorEvent(float x, float y, float z): * void onGameRotationEvent(float x, float y, float z): * void onHeartRateEvent(float r): returns current heart rate in bpm */
Code 0-1: Wasserwaage mit Android-App -- Sketch benötigt KETAI-Library im Android-Mode, Ausgangspunkt: Beispiel Accelerometer
#2 Mittwoch 06.10.2021
FRAGEN
|
Internet-Protokolle auf Wikipedia: TCP/IP, UDP, Websocket, MQTT
TCP IP auf Wikipedia.UDP auf Wikipedia
Websocket auf Wikipedia
Websocket auf mozilla.org
MQTT auf Wikipedia
https://de.wikipedia.org/wiki/Liste_der_standardisierten_Ports
Exemplarische Modularisierung von UDP und Sensordatenerfassung
In der letzten Woche wurde u.a. ein Beispiel für den Arduino nano 33 IoT präsentiert, das die Daten des dreiachsigen Beschleunigungssensors über den seriellen Monitor am PC anzeigt.
TEIL 1: Heute soll ein Beispiel aktiviert werden, bei dem Daten zwischen dem Arduino und einem anderen Gerät über WiFi ausgetauscht werden. Als Protokoll wird UDP verwendet.
TEIL 2: Nach Anpassung und erfolgreichem Test der Beispiel-Sketche, werden wir uns Gedanken darüber machen, wie das aktuelle Beispiel mit dem von letzter Woche verknüpft werden kann, also Sensordaten über WiFi übertragen werden können.
TEIL 3: Danach sollen beide Komponenten der entstandenen Software modularisiert werden, um sie leichter auch in weiteren Projekten verwenden, bzw. mit anderen Projektteilen kombinieren zu können.
TEIL 1: Funktionstest von UDP
Bild 0-1: Hier verwendete Geräte: WiFi-Router, Laptop (per LAN-Kabel verbunden und eingewählt), Arduino nano 33 IoT (per WiFi eingewählt).
Grundlage bildet der Beispiel-Sketch "WiFiUdpSendReceiveString". Nachfolgend wurde lediglich der Login ins WiFi-Netz angepasst und dieses Beispiel ansonsten unverändert beibehalten:
/* WiFi UDP Send and Receive String This sketch waits for a UDP packet on localPort using the WiFi module. When a packet is received an Acknowledge packet is sent to the client on port remotePort created 30 December 2012 by dlf (Metodo2 srl) */ #include <SPI.h> #include <WiFiNINA.h> #include <WiFiUdp.h> int status = WL_IDLE_STATUS; #include "arduino_secrets.h" ///////please enter your sensitive data in the Secret tab/arduino_secrets.h char ssid[] = "kramann3"; // your network SSID (name) char pass[] = "23571113"; // your network password (use for WPA, or use as key for WEP) int keyIndex = 0; // your network key index number (needed only for WEP) unsigned int localPort = 2390; // local port to listen on char packetBuffer[256]; //buffer to hold incoming packet char ReplyBuffer[] = "acknowledged"; // a string to send back WiFiUDP Udp; void setup() { //Initialize serial and wait for port to open: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } // check for the WiFi module: if (WiFi.status() == WL_NO_MODULE) { Serial.println("Communication with WiFi module failed!"); // don't continue while (true); } String fv = WiFi.firmwareVersion(); if (fv < WIFI_FIRMWARE_LATEST_VERSION) { Serial.println("Please upgrade the firmware"); } // attempt to connect to WiFi network: while (status != WL_CONNECTED) { Serial.print("Attempting to connect to SSID: "); Serial.println(ssid); // Connect to WPA/WPA2 network. Change this line if using open or WEP network: status = WiFi.begin(ssid, pass); // wait 10 seconds for connection: delay(10000); } Serial.println("Connected to WiFi"); printWifiStatus(); Serial.println(" Starting connection to server..."); // if you get a connection, report back via serial: Udp.begin(localPort); } void loop() { // if there's data available, read a packet int packetSize = Udp.parsePacket(); if (packetSize) { Serial.print("Received packet of size "); Serial.println(packetSize); Serial.print("From "); IPAddress remoteIp = Udp.remoteIP(); Serial.print(remoteIp); Serial.print(", port "); Serial.println(Udp.remotePort()); // read the packet into packetBufffer int len = Udp.read(packetBuffer, 255); if (len > 0) { packetBuffer[len] = 0; } Serial.println("Contents:"); Serial.println(packetBuffer); // send a reply, to the IP address and port that sent us the packet we received Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); Udp.write(ReplyBuffer); Udp.endPacket(); } } void printWifiStatus() { // print the SSID of the network you're attached to: Serial.print("SSID: "); Serial.println(WiFi.SSID()); // print your board's IP address: IPAddress ip = WiFi.localIP(); Serial.print("IP Address: "); Serial.println(ip); // print the received signal strength: long rssi = WiFi.RSSI(); Serial.print("signal strength (RSSI):"); Serial.print(rssi); Serial.println(" dBm"); }
Code 0-2: Leicht modifizierter Sketch WiFiUdpSendReceiveString2.
Nach Übertragen des kompilierten Programms auf den Arduino, verbindet sich dieser erst mit dem WiFi-Netz und erwartet dann irgendein String, das an ihn per UDP gesendet wird. Geschieht dies, so sendet der Arduino "acknowledged" an diesen Sender zurück.
Das WiFi-Netz wurde hier mit einem einfachen W-LAN Router erzeugt:
Bild 0-2: W-LAN-Router.
Nachdem sich der Arduino in das WiFi-Netz eingewählt hat, wird ihm per DHCP eine IP-Adresse zugewiesen, hier 192.168.0.102:
Bild 0-3: Liste der in das WiFi-Netz eingewählten Geräte.
Hinweise:
|
Nachdem über den seriellen Monitor überprüft wurde, ob sich das Android-Device auch wirklich im WiFi-Netz anmeldet, bedarf es nun noch einer Instanz, die über UDP Daten an den Arduino sendet. Hierzu wird ein Processing-Sketch verwendet, der auf dem Laptop gestartet wird und welcher bei jedem Drücken einer Taste auf der Tastatur, das gedrückte Zeichen als String per UDP an die eingetragene IP über den angegebenen Port sendet.
Somit müssen IP-Adresse des Empfängers und der Port über den gesendet wird noch im Processing-Sketch an den Arduino angepasst werden. Als Port wurde der Default-Eintrag des Arduino benutzt: 2390. Die IP des Arduino wurde bereits identifiziert: 192.168.0.102
/** * (./) udp.pde - how to use UDP library as unicast connection * (cc) 2006, Cousot stephane for The Atelier Hypermedia * (->) http://hypermedia.loeil.org/processing/ * * Create a communication between Processing<->Pure Data @ http://puredata.info/ * This program also requires to run a small program on Pd to exchange data * (hum!!! for a complete experimentation), you can find the related Pd patch * at http://hypermedia.loeil.org/processing/udp.pd * * -- note that all Pd input/output messages are completed with the characters * "; ". Don't refer to this notation for a normal use. -- */ // import UDP library import hypermedia.net.*; UDP udp; // define the UDP object /** * init */ void setup() { // create a new datagram connection on port 6000 // and wait for incomming message udp = new UDP( this, 6000 ); //udp.log( true ); // <-- printout the connection activity udp.listen( true ); } //process events void draw() {;} /** * on key pressed event: * send the current key value over the network */ void keyPressed() { String message = str( key ); // the message to send String ip = "192.168.0.102"; // the remote IP address int port = 2390; // the destination port // formats the message for Pd message = message+"; "; // send the message udp.send( message, ip, port ); } /** * To perform any action on datagram reception, you need to implement this * handler in your code. This method will be automatically called by the UDP * object each time he receive a nonnull message. * By default, this method have just one argument (the received message as * byte[] array), but in addition, two arguments (representing in order the * sender IP address and his port) can be set like below. */ // void receive( byte[] data ) { // <-- default handler void receive( byte[] data, String ip, int port ) { // <-- extended handler // get the "real" message = // forget the "; " at the end <-- !!! only for a communication with Pd !!! data = subset(data, 0, data.length-2); String message = new String( data ); // print the result println( "receive: \""+message+"\" from "+ip+" on port "+port ); }
Code 0-3: Processing-Sketch udp aus der Library UDP mit Anpassung von Ziel-IP und Sendeport.
Experiment: Die Buchstaben "b" und dann "p" werden nacheinander auf der Tastatur gedrückt:
Bild 0-4: Oben (weisser Hintergrund): Serial-Monitor, das die Rückmeldung vom Arduino anzeigt. Unten (schwarzer Hintergrund): Rückmeldung des Processing-Sketches. Ganz unten: über USB mit dem Laptop verbundener Arduino nano 33 IoT.
Hinweis: Die USB-Verbindung des Arduino mit dem Laptop dient nur dazu, den inneren Zustand des Arduino zu sehen und ist für die WiFi-Verbindung nicht notwendig.
TEIL 2: Beschleunigungsdaten über UDP an den Leptop senden
Dieser Teil soll als Übung umgesetzt werden. Damit die einzelnen Übungsgruppen in gleicher Weise das lokale WiFi nutzen können, müßten diese ihre normale Verbindung stoppen und sich dort einwählen, oder alternativ den Laptop per LAN-Kabel mit dem WiFi-Router verbinden.
TEIL 3: Modularisieren der beiden Programmteile Sensorerfassung und UDP
Dieser Teil wird gemeinsam diskutiert und umgesetzt.
Im Verlauf der LV entstandener Quelltext:
WiFiUdpSendReceiveString001_kombi.zipWiFiUdpSendReceiveString002_senden.zip
WiFiUdpSendReceiveString003_SensorDatenInReplyBuffer.zip
WiFiUdpSendReceiveString004_SeparationDerInitialisierungen.zip
WiFiUdpSendReceiveString005_OOPaccelerometer.zip
WiFiUdpSendReceiveString005b_OOPaccelerometer.zip
#3 Mittwoch 13.10.2021
TEIL 1: Gemeinsame Weiterentwicklung der Module zu Accelerometer und UDP
|
im Unterricht dabei entstanden:
WiFiUdpSendReceiveString006b_OOPudpKlasse.zip
WiFiUdpSendReceiveString006c_OOPudpKlasse.zip
WiFiUdpSendReceiveString006d_OOPudpKlasse.zip
Lezte Version (Kombi Java-Seite und Arduino-Seite):
WiFiUdpSendReceiveString008_OOPudpKlasse.zip
TEIL 2: Objektorientierte Programmierung (zunächst in Java)
|
aus dem Unterricht, Vererbung mit Java:
Vektor2.zip
30_Informatik3/06_Vererbung/01_MesswerteUML -- Vererbung in UML dargestellt
30_Informatik3/06_Vererbung/03_VererbungsProgramm -- Vererbung in C++
45_Mikro17/05_OOP/02_OOP_ATmega32/05_RS232/04_Vererbung -- Vererbung in C++ beim Mikrocontroller
30_Informatik3/15_Rasterlayout/02_interfaces -- Beispiel zu Interface-Programmierung
30_Informatik3/06_Vererbung/01_MesswerteUML
TEIL 3: Übung -- Klasse entwickeln
studentische Lösungen:
Potentiometer_ansteuern2.zip -- überarbeitet
testNano33.zip
Potentiometer an einem Analog-Digital-Wandler-Eingang einzusetzen ist eine preiswerte und einfache Möglichkeit, zwischen einer Vielzahl an Werte umzuschalten.
Ein einfacher Anwendungsfall ist das Einstellen der Helligkeit über die PWM-Breite bei einer LED, wobei dann die PWM-Breite wiederum über das Potentiometer eingestellt wird.
Erstellen Sie genau solch eine Anwendung und testen sie.
Entwickeln Sie dann eine geeignete Klasse, die alles Notwendige zum Betreiben einer oder mehrerer Potentionemter kapselt und auf einfache Weise bereitstellt.
TEIL 4: Übung -- Autark werden: UDP-Empfänger auf Smartphone übertragen
|
Nachtrag: Erster Teil zu "Briefkastenkonzept"
Nachfolgende Quelltexte realisieren schon den ersten Teil des im Unterricht entwickelten "Briefkastenkonzepts":
Über eine set-Methode, sendet der Arduino eine Float-Variable mit dem Namen x, die dann beim PC in der Variable x abgelegt werden würde.
Briefkasten_UDP001.zip
void loop() { zeigeLokaleSensordaten(); briefkasten.set('x',sensordaten.getAX(),"192.168.0.100",6000); delay(1000); }
Code 0-4: loop() im Arduino-Teil
receive: "+0087x" from 192.168.0.101 on port 2390 Rückumwandlung in float-wert mit Java: Empfangener Wert: x=0.087000005
Code 0-5: Was beim PC ankommt.
#4 Mittwoch 20.10.2021
Teil 1: Vollständige Umsetzung des Briefkastenkonzepts für Arduino und auch Android
92_Soundinstallation/03_material/11_Snippets/11_UDPÜbung zum Briefkastenkonzept
|
Teil 2: Brainstorming zu möglichen Projektthemen
Teil 3: Snippets zur möglichst erschöpfenden Ausnutzung aller Fähigkeiten des Arduino nano 33 IoT.
Demonstration des Heizregelkreises für RST im 3. Semester Maschinenbau.
Bereits getestet, oder so trivial, dass keine Überprüfung nötig ist:
|
Test erforderlich:
|
Im Zusammenhang mit Breakoutboards und externen Modulen nutzbar:
|
Erweiterte Library für LSM6DS3 mit Temperaturabfrage
Hier hat jemand naheliegenderweise eine Methode in der Library ergänzt, die es erlauben neben Beschleunigung und Winkelgeschwindigkeit auch die Daten des integrierten Temperatursensors auszulesen:
Vorgehen zum Erstzen der Library: Original in .../Arduino/libraries/Arduino_LSM6DS3 löschen und Ordner Arduino_LSM6DS3-master umbenannt in Arduino_LSM6DS3 dort ersetzen.
Hinweise zur Verwendung von Hardware-Interrups, eines Schedulers und der internen Clock:
https://itp.nyu.edu/physcomp/introduction-to-the-nano-33-iot/Analog-Ausgang nutzen
Bild 0-5: Anschluß eines 50Ohm-Lautsprechers an DAC0 beim Arduino nano 33 IoT
int x=0; int y=0; int grenze=100; void setup() { // 10-bit Auflösung des DAC: analogWriteResolution(10); } void loop() { if(x<grenze) y=x; else y=grenze+grenze-x; analogWrite(A0, y); x++; if(x>=grenze) { grenze++; x=0; if(grenze>2000) grenze=200; } x%=grenze+grenze; }
Code 0-6: Beispielcode: Sweep einer Dreiecks-Wellenform.
#include<math.h> #define MAX 256 #define DMAX 256.0 int data[MAX]; uint8_t ii=0; void setup() { //Vorberechnung für ein Sinussignal for(int i=0;i<MAX;i++) { data[i] = (int)(500.0+500.0*sin(2.0*PI*(float)i/DMAX)); } analogWriteResolution(10); } void loop() { analogWrite(A0, data[ii++]); }
Code 0-7: Sinussignal am Analog-Ausgang
Brainwave-Hack mit Mattel
http://www.frontiernerds.com/brain-hackStromversorgung
https://www.amazon.de/Phoneboost-Wiederaufladbare-Powerbank-integriertem-Connector-Micro-USB/dp/B07XTHGVLS?th=1#5 Mittwoch 27.10.2021
START DER PROJEKTARBEITEN
|
Projekt #1: CO2-Überwachung und -Reduktion
Projekt #2: Pflanzliche Luftreinigung über Pflanzengitter-Module
https://www.daw.de/fileadmin/data_daw/images/presse/AeroCare_-_Moos/Brosch%C3%BCre_AeroCare.pdfProjekt #3: Brütanlage für den privaten Haushalt
#6 Mittwoch 10.11.2021
Kernzeit: 10-14Uhr. Weiteres nach Absprache. Starten Sie gerne früher. Herr Bräunlich kann die Schränke öffnen.
Übersicht
Am Ende knirscht es immer ein wenig. Doch gerade weil der Termin für Ihre Präsentation bereits kommende Woche ist, möchte ich an Sie appellieren da dran zu bleiben. Gerne können wir morgen noch einen Zusatztermin vereinbaren, wenn sich zeigen sollte, dass es notwendig ist. Jedenfalls werden da kommende Woche Erstsemester im Maschinenbau vor Ihnen sitzen, die ganz gespannt auf das sind, was Sie präsentieren werden. Und es ist besser eine vielleicht nicht ganz perfekte Präsentation zu machen, die auf Interessierte trifft, als eine perfekte, die dann niemanden mehr interessiert. Es bleibt also dabei:
Die von mir benotete Präsentation Ihrer Projekte findet am Mittwoch, den 17.11. ab 12:30Uhr im Hörsaal IWZ101 statt.
Wichtig:
|
Stellen Sie sich also insgesamt darauf ein, die wesentlichen Schritte für Ihr Projekt morgen in Ihrer Gruppe fertig zu bekommen und sich für eventuell noch fehlende Schritte untereinander abzusprechen.
Ich werde hier auf Moodle noch eine Abgabe erzeugen, auf der ich Sie bitte, folgendes hochzuladen:
|
Ich lasse dafür eine Woche Nachlauf. Bitte bauen Sie in die Dateinamen Ihre Namen ein. Verwenden Sie keine Leerzeichen, sondern Unterstriche. Fragen Sie bitte bei Unklarheiten umgehend nach.
Ich wünsche Ihnen nun "in der Zielgeraden" gutes Gelingen.