Embedded Systems Engineering LU WS2010 Angaben zu Beispiel 2

Werbung
Embedded Systems Engineering LU WS2010
Angaben zu Beispiel 2
Allgemeines
Die zweite Aufgabenstellung setzt sich aus zwei Teilproblemstellungen zusammen. Jede
Gruppe bekommt von Ihrem Tutor eine Variante der unten aufgelisteten
Kommunikationsprotokolle zugeteilt sowie eine damit zu realisierende Applikation. Das zu
implementierende Kommunikationsprotokoll dient somit als Grundlage für die Lösung des
Applikationsbeispiels. Für die Lösung des Applikationsbeispiels sind (so weit als möglich)
die von Ihnen in Beispiel 1 implementierten Treiberfunktionen zu verwenden.
Achten Sie darauf, dass die am Board vorhandene I/O, insbesondere der Ventilatormotor und
die Glühbirne ausgeschaltet sind, wenn Sie diese nicht benötigen. Dies trägt der Lebensdauer
der Glühbirne und einem niedrigen Lärmpegel im Labor zu.
Testen Sie Ihre Protokollimplementierung bevor Sie die eigentliche Applikation darüber
setzen. Ermitteln Sie die für Parameter Ihrer Implementierung (z.B. time outs,
Übertragungsgeschwindigkeit, etc) sinnvolle, d.h. sichere aber dennoch performante Werte.
Dokumentieren Sie im Protokoll durch eine geeignete Darstellung (z.B. Diagramme) die
Ermittlung Ihrer Protokollparameter.
Allgemeine Protokollvorgaben
Für alle zu implementierenden Kommunikationsprotokolle sollen folgende Daten ermittelt
werden:

UART-Baudraten (nur die vom ATMega 128 unterstützten): 2400 – 115.2k

Für jede Baudrate die minimale/maximale Latenz für den Versand einer Nachricht
ohne Störungen der Kommunikation durch andere Knoten. Geben Sie sowohl einen
theoretischen (errechneten) Wert als auch eine Messung (z.b. mittels Oszilloskop) an
und vergleichen Sie diese. Das Szenario bei dem eine Nachricht am längsten/kürzesten
benötigt kann protokollabhängig sein und ist von Ihnen zu ermitteln. Eine Begründung
muss im Protokoll angeführt werden.

Ist es bei Ihrem Protokoll/Ihrer Implementierung möglich, dass ein Knoten, der als
Störknoten funktioniert, den Bus monopolisieren kann?
Kommunikationsprotokolle
Protokoll A:
Implementieren Sie ein Warteraum (waiting-room) Kommunikationsprotokoll entsprechend
der folgenden Beschreibung. Achten Sie darauf, dass das Protokoll in einem separaten C-File
mit Header-File implementiert wird, sodass auf jedem Knoten derselbe Code dazugelinkt
werden kann.
Der Zugriff auf das Medium wird bei Warteraumprotokollen durch 3 Zeitgrenzen (timeouts)
arbitriert:
 SG (Synchronization Gap): Mit diesem Parameter wird die Zeitspanne beschrieben,
die Knoten warten müssen, bevor sie den Warteraum betreten dürfen. Diese
Zeitspanne ist für alle Knoten gleich.
 TG (Terminal Gap):. Diese Zeitspanne gibt an, wie lange ein Knoten im Warteraum
warten muss, bevor er – Stille am Bus vorrausgesetzt – mit der Datenübertragung
beginnen darf. Dieser Paramter ist für alle Knoten unterschiedlich und entspricht der
Priorität des Knoten, wobei in kurzer TG-Wert einer hohen Priorität entspricht. Sollte
nach Ablauf des TGs der Bus besetzt sein, bleibt der Knoten im Warteraum, muss aber
wieder so lange warten bis der in TG spezifizierte Wert erreicht ist um einen neuen
Sendeversuch starten zu dürfen.
 TI (Transmit Interval): Dieser Wert verhindert, dass ein einzelner Knoten den Bus
monopolisiert. Das TI beginnt mit dem Zeitpunkt, ab dem ein Knoten einen
erfolgreichen Nachrichtentransfer startet. Es muss ein entsprechend langer Wert
gewählt werden, dass alle Knoten die Möglichkeit haben eine Nachricht zu senden.
Wurde eine Nachricht erfolgreich gesendet, verläßt der Knoten den Warteraum. Soll eine
neue Nachricht versendet werden, beginnt der Protokollablauf von vorne (d.h. der Knoten
muss zuerst wieder die in SG spezifizierte Zeitspanne warten um erneut in den Warteraum
eintreten zu dürfen).
Das Protokoll funktioniert korrekt, wenn folgende Bedingung erfüllt ist:
Verwenden Sie den Hardware-UART für die Implementierung.
Jede Nachricht besteht aus der Sender/Empfängeradresse (insgesamt 1Byte), der NettoNachrichtenlänge (1Byte), der eigentlichen Nachricht (0-7 Bytes) sowie einer Checksumme
(1 Byte). Die 4 most-significant Bits der Sender/Empfängeradresse enthalten den Sender, die
4 least-significant Bits den Empfänger. Binär „00010010“ entspricht einer Nachricht von
Knoten 1 zu Knoten 2. Die Nachrichtenlänge entspricht der totalen Anzahl der Bytes in der
Nachricht ohne Sender/Empfängeradresse, ohne Nachrichtenlängenangabe und ohne
Checksumme. Die Checksumme berechnet sich byteweise über Sender/Empfängeradresse,
Nachrichtenlänge und den Bytes der Nachricht als Exklusiv-Oder-Verknüpfung.
Das Protokoll soll über die folgenden Funktionen angesprochen werden:
Code:
void protocol_init(uint8_t priority, void (*receive_msg)(uint8_t msg_length,
uint8_t *msg_body));
Initialisiert das Protokoll und definiert einen Pointer auf die receive_msg(…) Funktion.
Mittels priority wird die Priorität des Knotens spezifiziert. Sie entspricht dem Wert TG.
Code:
int8_t send_msg(uint8_t msg_length, uint8_t *msg_body)
Speichert eine Nachricht zum Versand, wobei msg_length die Anzahl der Nutzbytes und der
Pointer msg_body die Nachricht selbst enthält. Die Prüfsumme soll von der Funktion
automatisch berechnet werden. Diese Funktion soll blockierend implementiert werden. Der
Rückgabewert der Funktion enthält die Anzahl der Versuche (d.h. die Anzahl der
abgelaufenen TGs) bis eine Nachricht versendet werden konnte.
Jedes mal wenn eine Nachricht empfangen wird, wird die bei der Initialisierung angegebene
Funktion vom Protokoll aufgerufen, welche folgende Syntax aufweisen soll:
Code:
void receive_msg(uint8_t msg_length, uint8_t *msg_body)
Diese Funktion ist als Teil der Applikation außerhalb der Protokollimplementierung zu
erstellen. Jedes Mal wenn eine Nachricht empfangen wird, wird diese Funktion von Ihrer
Protokollimplementierung aufgerufen und die Anzahl der Nutzbytes der Nachricht sowie der
Zeiger auf den Empfangsbuffer werden als Parameter übergeben. Wenn Nachrichten mit
fehlerhafter Checksumme empfangen werden, so soll Ihre Protokollimplementierung den
Aufruf der receive_msg() Funktion unterdrücken.
Hinweis: Unter diesem link1 steht Ihnen ein Applet zur Simulation des Protokolls zur
Verfügung. Nutzen Sie dieses, um sich ein genaueres Verständnis für den Ablauf des
Protokolls zu erarbeiten und geeignete Parameter für Ihre Implementierung abzuleiten.
1
http://luna.vmars.tuwien.ac.at/~armin/wool/
Protokoll B:
Implementieren Sie ein CSMA/CA Kommunikationsprotokoll entsprechend der folgenden
Beschreibung. Achten Sie darauf, dass das Protokoll in einem separaten C-File mit HeaderFile implementiert wird, sodass auf jedem Knoten derselbe Code dazugelinkt werden kann.
Jeder Knoten besitzt einen unterschiedlichen time out Parameter, z.B. 1ms, 2ms, 3ms, 4ms.
Will nun ein Knoten eine Nachricht Senden, so prüft er zuerst, ob nicht gerade eine
Nachrichtenübertragung im Gang ist. Falls ja wartet er bis zum Ende der Übertragung, falls
nein, beginnt er sofort mit dem Sendevorgang. Diskutieren Sie im Protokoll, wie sich eine
Änderung der time out Parameter auf die Performance des Protokolls auswirkt (z.B. Anzahl
der benötigten Sendeversuche eines Knotens bei gleich bleibender Last am Bus und
Verringerung des time outs auf allen Knoten).
Der Sendevorgang beginnt damit, dass der Knoten den Bus für die Länge seines Time-Outs in
den dominanten Zustand (logisch 0) zwingt. Nach Ablauf des Time-Outs versetzt der Knoten
den Bus in den Zustand logisch 1 und prüft, ob der Bus auch tatsächlich in diesen übergeht.
Wenn nein, so gibt es einen konkurrierenden Knoten mit einem längeren Time-Out der seine
Nachricht senden wird. Wenn ja, so beginnt der Knoten mit dem Senden der eigentlichen
Nachricht.
Implementieren Sie die Busarbitrierung in Software, das Senden der Nachricht soll mittels
Hardware-UART implementiert werden. Verwenden Sie hierfür das Datenformat 8e1.
Jede Nachricht besteht aus der Netto-Nachrichtenlänge (1Byte), der eigentlichen Nachricht
(0-15 Bytes) sowie einer Checksumme. Die Nachrichtenlänge entspricht der totalen Anzahl
der Bytes in der Nachricht ohne Nachrichtenlängenangabe und Checksumme. Die
Checksumme berechnet sich über Nachrichtenlänge und die Bytes der Nachricht als ExklusivOder-Verknüpfung.
Das Protokoll soll über die folgenden Funktionen angesprochen werden:
Code:
void protocol_init(uint8_t timeout, void (*receive_msg)(uint8_t msg_length,
uint8_t *msg_body))
Initialisiert das Protokoll und definiert einen Pointer auf die receive_msg() Funktion.
Code:
int8_t send_msg(uint8_t msg_length, uint8_t *msg_body)
Verschickt eine Nachricht, wobei msg_length die Anzahl der Nutzbytes und der Pointer
msg_body die Nachricht selbst enthält. Die Prüfsumme soll von der Funktion automatisch
berechnet werden. Diese Funktion soll solange blockieren, bis die Nachricht erfolgreich
versandt wurde. Der Rückgabewert der Funktion soll der Anzahl der notwenigen
Sendeversuche entsprechen
Jedes mal wenn eine Nachricht empfangen wird, wird die bei der Initialisierung angegebene
Funktion vom Protokoll aufgerufen, welche folgende Syntax aufweisen soll:
Code:
void receive_msg(uint8_t msg_length, uint8_t *msg_body)
Diese Funktion ist als Teil der Applikation außerhalb der Protokollimplementierung zu
erstellen. Jedes Mal wenn eine Nachricht empfangen wird, wird diese Funktion von Ihrer
Protokollimplementierung aufgerufen und die Anzahl der Nutzbytes der Nachricht sowie der
Zeiger auf den Empfangsbuffer werden als Parameter übergeben. Wenn Nachrichten mit
fehlerhafter Checksumme empfangen werden, so soll Ihre Protokollimplementierung den
Aufruf der receive_msg() Funktion unterdrücken.
Tipp: Das Protokoll selbst beinhaltet keine Information bezüglich Adressierung von Knoten
beim Nachrichtenversand. Das heißt, die Adressinformation ist Teil der Nutzdaten und muss
von der eigentlichen Applikation verwaltet werden. Wie sie die Adressierung lösen (z.B.
Angabe eines Senders als Header in den Nutzdaten anhand einer eindeutigen Knoten-ID,
eindeutige Identifizierung eines Nachrichtentyps anhand eines Headers in den Nutzdaten, etc.)
ist Ihnen überlassen. Diskutieren Sie im Protokoll, welchen Overhead diese zusätzliche
Adressierungsinformation in den Nutzdaten hervorruft.
Protokoll C:
Implementieren Sie ein CSMA/CA Kommunikationsprotokoll entsprechend der folgenden
Beschreibung. Achten Sie darauf, dass das Protokoll in einem separaten C-File mit HeaderFile implementiert wird, sodass auf jedem Knoten derselbe Code dazugelinkt werden kann.
Jeder Nachrichtentyp (z.B. Temperaturwert gesendet von Knoten 3) besitzt eine eindeutige
Nummer msg_id im Bereich von 0 bis 255, die zugleich ihrer Priorität entspricht. Wenn eine
Nachricht zu senden ist, so soll der sendende Knoten zuerst eine gewisse Zeit lang am Bus
horchen, ob bereits eine Kommunikation im Gang ist. (Wählen Sie dieses Sende-Timeout
entsprechend der nachfolgenden Protokollbeschreibung und protokollieren Sie Ihre Wahl.)
Nach dem Horchen sendet der Knoten eine logische Null, gefolgt von der msg_id im
Binärformat. Jedes gesendete Bit soll gleichzeitig vom Bus zurück gelesen werden. Wird
dabei eine gesendete Eins als Null zurück gelesen, so ist gleichzeitig der Sendevorgang eines
anderen Knotens aktiv und der Knoten bricht den Sendevorgang ab und wartet auf das
Freiwerden des Busses, um den Sendevorgang zu wiederholen. Nach 10 erfolglosen
Versuchen wird die Nachricht verworfen.
Gelingt dem Knoten das Senden der vollständigen msg_id, so erfolgt nach einer kurzen
Wartezeit die Sendung der eigentlichen Nachricht im 8N1-Format.
Dabei ist das erste Byte die Nachrichtenlänge und das letzte Byte eine Checksumme. Die
Nachrichtenlänge ist ohne msg_id, Nachrichtenlänge und Checksumme zu berechnen (reine
Nutzdaten). Die Checksumme berechnet sich mittels Exklusiv-Oder-Verknüpfung über
msg_id, Nachrichtenlänge und eigentliche Nachricht.
Implementieren Sie die Busarbitrierung in Software und das Versenden/Empfangen der Daten
mittels Hardware-UART. Die Geschwindigkeit für Arbitrierung und Datenversand darf
unterschiedlich sein. Es soll eine maximale Nachrichtenlänge von 16 Byte unterstützt werden.
Das Protokoll soll über die folgenden Funktionen angesprochen werden:
Code:
void protocol_init(uint8_t receiver_on, void (*receive_msg)(uint8_t msg_id,
uint8_t msg_length,
uint8_t *msg_body))
Initialisiert das Protokoll. Ist receiver_on ungleich Null, so soll der Empfänger "scharf"
gestellt werden, sodass bei jeder hereinkommenden Nachricht die Funktion receive_msg
aufgerufen wird. Achten Sie darauf, dass sich der Knoten nach der Initialisierung im passiven
Zustand (logisch 1) am Bus befindet.
Code:
int8_t send_msg(uint8_t msg_id, uint8_t msg_length, uint8_t *msg_body)
Verschickt eine Nachricht, wobei msg_length die Anzahl der Nutzbytes und der Pointer
msg_body die Nachricht selbst enthält. Die Prüfsumme soll von der Funktion automatisch
berechnet werden. Diese Funktion soll solange blockieren, bis die Nachricht erfolgreich
versandt, oder der Sendevorgang nach 10 erfolglosen Versuchen abgebrochen wurde. Der
Rückgabewert der Funktion soll der Anzahl der notwenigen Sendeversuche entsprechen, bzw.
-1 bei Abbruch des Sendevorgangs.
Jedes Mal wenn eine Nachricht empfangen wird, wird die bei der Initialisierung angegebene
Funktion vom Protokoll aufgerufen, welche folgende Syntax aufweisen soll:
Code:
void receive_msg(uint8_t msg_id, uint8_t msg_length, uint8_t *msg_body)
Die Funktion ist als Teil der Applikation außerhalb der Protokollimplementierung zu
erstellen. Jedes Mal wenn eine Nachricht empfangen wird, wird diese Funktion von Ihrer
Protokollimplementierung aufgerufen und die eindeutige Identifikation der Nachricht
(msg_id), die Anzahl der Nutzbytes der Nachricht und der Zeiger auf den Empfangsbuffer als
Parameter übergeben. Wenn Nachrichten mit fehlerhafter Checksumme empfangen werden,
so soll der Aufruf der receive_msg() Funktion unterdrückt werden.
Tipp: Beachten Sie, dass das Protokoll selbst keine Adressierung der Nachrichten vorsieht.
Sie haben in der Implementierung Ihrer eigentlichen Applikation selbst dafür zu sorgen, dass
jeder Knoten die für Ihn gedachten Nachrichten speichert. Ob Sie dafür die msg_id
verwenden, oder zusätzliche Header-Informationen in die Nutzdaten verpacken, bleibt Ihnen
überlassen. Begründen Sie auf jeden Fall im Protokoll Ihre Lösung.
Applikationsbeispiele
Applikation 1: Lüftersteuerung
Realisieren Sie eine Lüftersteuerung bestehend aus folgenden Komponenten:
Node3:
Node3 liest periodisch Temperatur (Genauigkeit so hoch als möglich bzw. sinnvoll –
z.B. 0.1°C) und Drehzahl des Lüfters ein und schickt bei jeder Änderung eine Temperaturbzw. Drehzahlnachricht an Node1.
Per „#define“-Makros sollen 2 Schaltschwellen eingestellt werden, wobei der Lüfter sich
nicht dreht, wenn sich die Temperatur unterhalb der ersten Schwelle befindet. Liegt die
Temperatur zwischen der ersten und der zweiten Schwelle, soll der Lüfter mit 50% und bei
Überschreiten der zweiten mit 100% laufen.
Wenn der Lüfter stehen bleibt, obwohl er eigentlich laufen sollte, soll periodisch zweimal pro
Sekunde eine Nachricht an Node0 versandt werden, bis dieser Fehlerzustand behoben ist.
Node1:
Node1 soll die empfangenen Temperatur- und Drehzahlnachrichten am LCD-Display
darstellen. Dabei soll in der obersten Zeile die Temperatur in der Form: "Temperatur:
XX.X°C" und in der zweiten Zeile die Drehzahl in der Form: "Lüfter: XXXX U/min"
dargestellt werden.
Implementieren Sie außerdem die Funktion eines 'rolling Bargraphs' in den unteren zwei
Zeilen des Displays, der den Temperaturverlauf der letzen 20 Sekunden visualisiert. Sehen
Sie dafür zwei „#define“-Makros vor, die die Temperaturen von 0 und 100% des Balkens
angeben. Liegt die Temperatur auf oder unter der 0% Marke bleibt der Balken leer, liegt sie
auf oder über der 100% Marke wird der Balken komplett ausgefüllt. Die Balkenhöhe
dazwischen ergibt sich durch lineare Interpolation. Das Balkendiagramm wird im
Sekundentakt nach links geshifted, an die rechteste Stelle kommt der aktuelle Wert. Die dafür
erforderlichen Zeichen müssen selbst definiert werden.
Node1 soll weiters die aktuelle Temperatur und Drehzahl im 100ms Takt an Node0 schicken.
Achten Sie darauf, dass Node0 die Nachrichten von Node1 und Node3 unterscheiden kann.
Node0:
Node0 soll als Gateway fungieren, der bei Erhalt einer Fehlernachricht von Node3 eine
entsprechende Fehlermeldung an den PC schickt. Zusätzlich soll er die Temperatur- und
Drehzahlwerte, die von Node1 gesendet werden an den PC weiterleiten.
Node2:
Implementieren Sie auf Node2 einen 'Belastungstest' für das Protokoll. Senden Sie dafür
periodisch Dummy-Nachrichten (Nachrichten ohne Nutzdaten). Die Zeit zwischen den
Nachrichten soll per „#define“-Makros einstellbar sein.
Machen Sie mehrere Testläufe, wobei Sie die Zeit zwischen den Nachrichten von Testlauf zu
Testlauf verringern und protokollieren Sie die Schranke ab der die Dummypakete die
Übertragung der Nutzdaten stören.
Applikation 2: Lüftersteuerung
Realisieren Sie eine Lüftersteuerung bestehend aus folgenden Komponenten:
Node3:
Node3 liest periodisch Temperatur (Genauigkeit so hoch als möglich bzw. sinnvoll –
z.B. 0.1°C) und Drehzahl des Lüfters ein und schickt bei jeder Änderung eine Temperaturbzw. Drehzahlnachricht an Node2.
Per „#define“-Makros sollen 2 Schaltschwellen eingestellt werden, wobei der Lüfter sich
nicht dreht, wenn sich die Temperatur unterhalb der ersten Schwelle befindet. Liegt die
Temperatur zwischen der ersten und der zweiten Schwelle, soll der Lüfter mit 50% und bei
Überschreiten der zweiten mit 100% laufen.
Wenn der Lüfter stehen bleibt obwohl er eigentlich laufen sollte, soll periodisch zweimal pro
Sekunde eine Nachricht an Node0 versandt werden, bis dieser Fehlerzustand behoben ist.
Node2:
Node2 soll die empfangenen Temperatur- und Drehzahlnachrichten mit Hilfe der 7-Segment
Anzeige darstellen. Durch Betätigung des virtuellen Tasters soll zwischen der Darstellung von
Temperatur und Lüfterdrehzahl umgeschaltet werden können.
Die Temperatur soll in Grad Celsius in der Form: „XX.X" (d.h. der Maximalwert beträgt
99.9°C) dargestellt werden. Die Lüfterdrehzahl soll in U/min in der Form " XXXX" (d.h. der
Maximalwert beträgt 9999 U/min) dargestellt werden.
Node2 soll weiters die aktuelle Temperatur und Drehzahl im 100ms Takt an Node0 schicken.
Achten Sie darauf, dass Node0 die Nachrichten von Node2 und Node3 unterscheiden kann.
Node0:
Node0 soll als Gateway fungieren, der bei Erhalt einer Fehlernachricht von Node3 eine
entsprechende Fehlermeldung an den PC schickt. Zusätzlich soll er die Temperatur- und
Drehzahlwerte, die von Node1 gesendet werden an den PC weiterleiten.
Node1:
Implementieren Sie auf Node1 einen 'Belastungstest' für das Protokoll. Senden Sie dafür
periodisch Dummy-Nachrichten (Nachrichten ohne Nutzdaten). Die Zeit zwischen den
Nachrichten soll per „#define“-Makro einstellbar sein.
Machen Sie mehrere Testläufe wobei Sie die Zeit zwischen den Nachrichten von Testlauf zu
Testlauf verringern und protokollieren Sie die Schranke ab der die Dummypakete die
Übertragung der Nutzdaten stören.
Applikation 3: Wetterstation
Realisieren Sie eine Wetterstation bestehend aus folgenden Komponenten:
Node3:
Node3 liest periodisch Temperatur (Genauigkeit so hoch als möglich bzw. sinnvoll –
z.B. 0.1°C) und Helligkeit ein und schickt bei jeder Änderung eine Temperatur- bzw.
Helligkeitsnachricht an Node1. Kalibrieren Sie den Helligkeitssensor so, dass er bei
ausgeschalteter Glühbirne '0', bei voll eingeschalteter Glühbirne '100' zurückgibt.
Helligkeitswerte zwischen den zwei Grenzen sollen linear interpoliert werden.
Per „#define“-Makro soll man eine Temperaturschwelle einstellen können. Wenn sich die
Temperatur über dieser Schwelle befindet, soll periodisch jede Sekunde eine Fehlernachricht
an Node0 versandt werden, bis die Temperatur wieder unter die Schwelle gesunken ist.
Node0:
Node0 soll als Zeitgeber und Gateway fungieren. Implementieren Sie dazu eine Uhr, die eine
Auflösung von 100ms besitzt und senden Sie bei jeder Zeitänderung eine Nachricht mit der
aktuellen Zeit an Node1. Durch drücken des virtuellen Tasters soll man die Uhr auf null
zurücksetzen können.
Node0 soll bei Erhalt einer Fehlernachricht von Node3 eine entsprechende Fehlermeldung an
den PC schicken. Zusätzlich soll er die Temperatur- und Helligkeitswerte, die von Node1
kommen an den PC in der Form "hh:mm:ss.z - tt.t° - iii%" weiterleiten (die t's entsprechen der
Temperatur, i der Helligkeit).
Kommt eine Primzahlnachricht von Node 2, soll sie in der Form "Primzahl: xxxxx!" den
Benutzer am PC darüber informieren.
Node1:
Node1 soll die empfangenen Uhrzeit-, Temperatur- und Helligkeitswerte am Display
darstellen. Dabei soll in der obersten Zeile die aktuelle Zeit in der Form
"Zeit:_____hh:mm:ss.z" (wobei '_' einem Leerzeichen entspricht) und in der zweiten Zeile die
Temperatur in der Form: "Temperatur: XX.X°C" dargestellt werden.
Implementieren Sie außerdem die Funktion eines 'rolling Bargraphs' in den unteren zwei
Zeilen des Displays, der den Helligkeitsverlauf der letzen 20 Sekunden visualisiert. Ist die
Helligkeit 0% bleibt der Balken leer, ist die Helligkeit 100% wird der Balken komplett
ausgefüllt. Die Balkenhöhe dazwischen ergibt sich durch lineare Interpolation. Das
Balkendiagramm wird im Sekundentakt nach links geshifted, an die rechteste Stelle kommt
der aktuelle Wert. Die dafür erforderlichen Zeichen müssen selbst definiert werden.
Node1 soll weiters die aktuelle Temperatur und Helligkeit im 100ms Takt an Node0 schicken.
Achten Sie darauf, dass Node0 die Nachrichten von Node1 und Node3 unterscheiden kann.
Node2:
Realisieren Sie auf Node2 einen 'Störknoten' für das Protokoll. Implementieren Sie dafür
einen 16-Bit-Counter, der sich periodisch erhöht (Periodendauer soll per „#define“-Makro
einstellbar sein).
Senden Sie jedes Mal, wenn der Wert des Counters eine Primzahl ist, eine Nachricht mit der
Primzahl an Node0. Machen Sie mehrere Testläufe, wobei Sie die Periodendauer jedes Mal
verringern und protokollieren Sie die minimale Periodendauer, bei der noch alle Primzahlen
am PC ankommen (beginnen Sie mit 100ms; das muss Ihr Algorithmus auf jeden Fall
schaffen).
Applikation 4: Wetterstation
Realisieren Sie eine Wetterstation bestehend aus folgenden Komponenten:
Node3:
Node3 liest periodisch Temperatur (Genauigkeit so hoch als möglich bzw. sinnvoll –
z.B. 0.1°C) und Helligkeit ein und schickt bei jeder Änderung eine Temperatur- bzw.
Helligkeitsnachricht an Node2. Kalibrieren Sie den Helligkeitssensor so, dass er bei
ausgeschalteter Glühbirne '0', bei voll eingeschalteter Glühbirne '100' zurückgibt.
Helligkeitswerte zwischen den zwei Grenzen sollen linear interpoliert werden.
Per „#define“-Makro soll man eine Temperaturschwelle einstellen können. Wenn sich die
Temperatur über dieser Schwelle befindet soll periodisch jede Sekunde eine Fehlernachricht
an Node0 versandt werden bis die Temperatur wieder unter die Schwelle gesunken ist.
Node0:
Node0 soll als Zeitgeber und Gateway fungieren. Implementieren Sie dazu eine Uhr, die eine
Auflösung von 100ms besitzt und senden Sie bei jeder Zeitänderung eine Nachricht mit der
aktuellen Zeit an Node2. Durch drücken des virtuellen Tasters soll man die Uhr auf null
zurücksetzen können.
Node0 soll bei Erhalt einer Fehlernachricht von Node3 eine entsprechende Fehlermeldung an
den PC schicken. Zusätzlich soll er die Temperatur- und Helligkeitswerte, die von Node1
kommen an den PC in der Form "hh:mm:ss.z - tt.t° - iii%" weiterleiten (die t's entsprechen der
Temperatur, i der Helligkeit).
Kommt eine Primzahlnachricht von Node 1, soll sie in der Form "Primzahl: xxxxx!" den
Benutzer am PC darüber informieren.
Node2:
Node2 soll die empfangenen Uhrzeit-, Temperatur- und Helligkeitswerte mit Hilfe der 7Segment Anzeige darstellen. Dabei soll mit dem virtuellen Taster zyklisch zwischen der
Anzeige der Temperatur, der Helligkeitswerte und der Uhrzeit umgeschaltet werden können.
Die aktuelle Zeit soll in der Form " hhmmssz" dargestellt werden, die Helligkeit in der Form
„iii“ (in Prozent) und die Temperatur in Grad Celsius in der Form: „XX.X" (d.h. der
Maximalwert beträgt 99,9°C).
Node2 soll weiters die aktuelle Temperatur und Helligkeit im 100ms Takt an Node0 schicken.
Achten Sie darauf, dass Node0 die Nachrichten von Node2 und Node3 unterscheiden kann.
Node1:
Realisieren Sie auf Node1 einen 'Störknoten' für das Protokoll. Implementieren Sie dafür
einen 16-Bit-Counter, der sich periodisch erhöht (Periodendauer soll per „#define“-Makro
einstellbar sein).
Senden Sie jedes Mal, wenn der Wert des Counters eine Primzahl ist, eine Nachricht mit der
Primzahl an Node0. Machen Sie mehrere Testläufe, wobei Sie die Periodendauer jedes Mal
verringern und protokollieren Sie die minimale Periodendauer, bei der noch alle Primzahlen
am PC ankommen (beginnen Sie mit 100ms; das muss Ihr Algorithmus auf jeden Fall
schaffen).
Herunterladen