Entwicklung einer bewegungsaktivierten Wortuhr: Unterschied zwischen den Versionen

Aus HSHL Mechatronik
Zur Navigation springen Zur Suche springen
Keine Bearbeitungszusammenfassung
 
(98 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 3: Zeile 3:
[[Kategorie:ProjekteET MTR BSE WS2021]]
[[Kategorie:ProjekteET MTR BSE WS2021]]
[[Kategorie:ProjekteET MTR BSE WS2022]]
[[Kategorie:ProjekteET MTR BSE WS2022]]
<!-- Kopieren Sie diesen Header in Ihren Artikel, damit er aufgelistet wird.  -->
<!-- Kopieren Sie diesen Header in Ihren Artikel, damit er aufgelistet wird.  -->
'''Autoren: Nico Kasprik & Jonas Loddenkemper''' <br/>
'''Autoren: Nico Kasprik & Jonas Loddenkemper''' <br/>
'''Betreuer: ''' <br/>
'''Betreuer: Prof. Schneider''' <br/>
[[Datei:Mittel (IMG 2646).png|rechts|mittel]]




== Einleitung ==
== Einleitung ==
Bei dem vorliegenden Artikel handelt es sich um ein Projekt aus dem Praktikum angewandte Elektrotechnik des Studiengangs Business and Systems Engineering (BSE). Ziel dieses Projekts ist es eine Wortuhr nach dem Vorbild des Designklassikers [https://qlocktwo.com/ QLOCKTWO] zu bauen. Aus Gründen der Energieeffizienz soll die Uhrzeit nur während der Anwesenheit von Personen angezeigt werden. Die Hintergrundbeleuchtung soll mit LEDs realisiert werden. Ob ein LED-Matrix-Panel oder LED-Stripes genutzt werden, muss im Laufe des Projekts geklärt werden. Als Anwesenheitssensor ist derzeit ein Ultraschallsensor geplant.
 
Bei dem vorliegenden Projekt aus dem Praktikum "Angewandte Elektrotechnik" des Studiengangs Business and Systems Engineering (BSE). Ziel dieses Projekts war es eine Wortuhr nach dem Vorbild des Designklassikers [https://qlocktwo.com/ QLOCKTWO] zu bauen. Aus Gründen der Energieeffizienz wird die Uhrzeit nur während der Anwesenheit von Personen angezeigt. Die Hintergrundbeleuchtung ist mit LEDs realisiert worden. Es wurden LED-Strips, ein RTC sowie als Anwesenheitssensor ein Ultraschallsensor genutzt.
[[Datei:Entwurf der Wortuhr.png|mini|zentriert|Erster Entwurf der Wortuhr - Frontansicht]]
[[Datei:Rückansicht des Frontrahmens.png|mini|zentriert|Erster Entwurf der Wortuhr - Rückansicht]]


== Anforderungen==
== Anforderungen==
Zeile 25: Zeile 30:
| Jonas Loddenkemper
| Jonas Loddenkemper
| 04.10.2022
| 04.10.2022
|  
| Nico Kasprik
|  
| 04.10.2022
|-
|-
| 1.1
| 1.1
| Die Regelung muss in Echtzeit erfolgen.
| Die Steuerung muss in Echtzeit erfolgen.
| Jonas Loddenkemper
| Jonas Loddenkemper
| 04.10.2022
| 04.10.2022
|  
| Nico Kasprik
|  
| 04.10.2022
|-
|-
| 2.0
| 2.0
| Die Uhr wird mit einer externen Stromquelle betrieben.
| Die Uhr wird mittels USB-Kabel mit Strom versorgt.
| Jonas Loddenkemper
| Jonas Loddenkemper
| 04.10.2022
| 04.10.2022
|  
| Nico Kasprik
|  
| 04.10.2022
|-
|-
| 3.0
| 3.0
| Die Anwesenheit wird über einen geeigneten Sensor geprüft. (Bspw. Ultraschall)
| Die Anwesenheit einer Person wird über einen Ultraschallsensor geprüft (Schaltabstand ca. 30 cm).
| Jonas Loddenkemper
| Jonas Loddenkemper
| 04.10.2022
| 04.10.2022
|  
| Nico Kasprik
|  
| 04.10.2022
|-
|-
| 4.0
| 4.0
| Die Technik (abgesehen vom Netzteil) soll im Gehäuse unterkommen.
| Der Arduino-Controller, die LED-Strips und der Sensor ist im Gehäuse.
| Jonas Loddenkemper
| Jonas Loddenkemper
| 04.10.2022
| 04.10.2022
|  
| Nico Kasprik
|  
| 04.10.2022
|-
|-
| 5.0
| 5.0
| Die Regelung muss auf einem Arduino Mikrocontroller ausgeführt werden.
| Die Steuerung wird auf einem Arduino Mikrocontroller ausgeführt.
| Jonas Loddenkemper
| Jonas Loddenkemper
| 04.10.2022
| 04.10.2022
|  
| Nico Kasprik
|
| 04.10.2022
|-
|-
| 6.0
| 6.0
| Die Frontblende soll aus einem Bauteil bestehen, in welchem die Wörter ausgespart sind. (Bspw. 3D-gedruckt)
| Die Frontblende ist 3D-gedruckt, die notwendigen Wörter sind direkt ausgespart.
| Jonas Loddenkemper
| 04.10.2022
| Nico Kasprik
| 04.10.2022
|-
| 7.0
| Uhrzeit soll nur angezeigt werden, wenn beabsichtigt (kleine Bewegungen sollen kein Auslösen hervorrufen).
| Jonas Loddenkemper
| 04.10.2022
| Nico Kasprik
| 04.10.2022
|-
| 8.0
| Zu besonderen Uhrzeit, soll ein Farbwechsel eingestellt werden.
| Jonas Loddenkemper
| 04.10.2022
| Nico Kasprik
| 04.10.2022
|-
| 9.0
| Komponenten sollen austauschbar sein.
| Jonas Loddenkemper
| Jonas Loddenkemper
| 04.10.2022
| 04.10.2022
|  
| Nico Kasprik
|  
| 04.10.2022
|-
|-
| O.1.0
| O.1.0
Zeile 74: Zeile 100:
| Jonas Loddenkemper
| Jonas Loddenkemper
| 04.10.2022
| 04.10.2022
|  
| Nico Kasprik
|
| 04.10.2022
|-
|-


Zeile 82: Zeile 108:
== Funktionaler Systementwurf ==
== Funktionaler Systementwurf ==


[[Datei:Funktionaler Systementwurf Wortuhr.png|mini|zentriert]]
[[Datei:Funktionaler Systementwurf Wortuhr neu.png|mini|zentriert|Funktionaler Systementwurf]]


Der funktionale Systementwurf bildet die wesentliche Funktion des zu erstellenden Systems ab. Dabei lässt sich dieser nach dem EVA-Prinzip in die drei Stufen „Eingabe“, „Verarbeitung“ und „Ausgabe“ aufteilen. 
Der funktionale Systementwurf bildet die wesentliche Funktion des zu erstellenden Systems ab. Dabei lässt sich dieser nach dem EVA-Prinzip in die drei Stufen „Eingabe“, „Verarbeitung“ und „Ausgabe“ aufteilen. 
Sensoren lassen sich der ersten Stufe zuweisen, da diese Informationen liefern, auf die der Mikrocontroller reagiert und diese weiterverarbeitet. Die weiterverarbeiteten Informationen werden für das System, so angepasst, dass über ein Ausgabegerät die Daten in gewünschter Form ausgegeben werden.
Sensoren lassen sich der ersten Stufe zuweisen, da diese Informationen liefern, auf die der Mikrocontroller reagiert und diese weiterverarbeitet. Die aktuelle Uhrzeit soll dabei ständig abgefragt werden. Wenn sich eine Person vor der Wortuhr befindet, wird diese angeschaltet. Verlässt die Person einen Bereich zwischen der Uhr von 0 cm bis 30 cm, schaltet sich die Uhr eigenständig ab. Die weiterverarbeiteten Informationen werden für das System, so angepasst, dass über ein Ausgabegerät die Daten in gewünschter Form ausgegeben werden.


== Technischer Systementwurf ==
== Technischer Systementwurf ==


[[Datei:Technischer Systementwurf Wortuhr.png|mini|zentriert]]
[[Datei:Technischer Systementwurf Wortuhr.png|mini|zentriert|Technischer Systementwurf]]




Der technische Entwurf orientiert sich auch nach dem EVA-Prinzip. Dabei wird der Schwerpunkt aber nur auf die technische Zusammenstellung des Systems gelegt. 
Der technische Entwurf orientiert sich auch nach dem EVA-Prinzip. Dabei wird der Schwerpunkt aber nur auf die technische Zusammenstellung des Systems gelegt. 
 
 
Für die Umsetzung des Projektes wird ein Real-Time-Clock-Modul verwendet.  Dadurch erhält das System Informationen über die korrekte Uhrzeit. Durch den Ultraschallsensor soll das System auf Bewegung reagieren und angeschaltet werden können. Der Mikrocontroller verarbeitet die Informationen, sodass sie im Folgenden über einen RGB-Strip ausgegeben werden. 
Für die Umsetzung des Projektes wird ein Real-Time-Clock-Modul verwendet.  Dadurch erhält das System Informationen über die korrekte Uhrzeit. Dies geschieht über einen I2C Bus. Ein Ultraschallsensor soll die Informationen liefern, ob sich eine Person vor der Wortuhr befindet. Der Erfassungsbereich des Ultraschallsensors liegt bei 2 cm bis ca. 400 cm. Wenn sich eine Person in einem Bereich bis 30 cm an die Wortuhr nähert, soll diese angeschaltet werden. Verlässt die Person diesen Distanzbereich, schaltet sich die Uhr nach wenigen Sekunden wieder aus. Dafür wird der Ultraschallsensor über ein HIGH-Signal getriggert. Daraufhin sendet er ein Echo-Signal und wartet bis der Schall zurückkommt. Dabei wird der Echo-Pin solange auf HIGH gesetzt, bis das Signal wieder ankommt. Ist dies der Fall, so wird das Eingangssignal LOW. Über die Zeit lässt sich nun die Distanz zum zu messenden Objekt bestimmen. Der Mikrocontroller verarbeitet die Informationen, sodass sie im Folgenden über einen RGB-Strip ausgegeben werden. Der Arduino kommuniziert mit dem RGB-Strip über ein spezifisches Protokoll. (s. Tabelle 2)
 
{| class="wikitable"
|+ style = "text-align: left"|Tabelle 2: Kommunikationsweg
! style="font-weight: bold;" | ID
! style="font-weight: bold;" | Komponente
! style="font-weight: bold;" | Kommunikationsweg mit Mikrocontroller
|-
| 1.0
| HC-SR 04
| digital über TTL-Pegel
|-
| 2.0
| DS3231
| I2C
|-
| 3.0
| WS2812
| Hersteller eigenes Protokoll
|-
 
|}




Zeile 100: Zeile 147:


== Komponentenspezifikation ==
== Komponentenspezifikation ==
In Abbildung "Steckplatine Layout" ist eine erste Steckbrettansicht zu sehen. Das Real-Time-Clock Modul kommuniziert über I2C mit dem Mikrocontroller. Der Ultraschallsensor über eine digitale Kommunikation mithilfe eines TTL-Pegels. Der LED-Strip wird über ein speziell für ihn ausgelegtes Protokoll angesteuert.
[[Datei:Wortuhr Steckplatine.png|mini|zentriert|Steckplatine Layout]]
== Theoretische Grundlagen und ihre Bewertung in Bezug auf die Aufgabenstellung ==
===3D-Druck===
Der 3D-Druck ist ein Verfahren der generativen Fertigungsverfahren und wird heutzutage insbesondere im Rapid Prototyping genutzt. In diesem Projekt wurde das FLM-Verfahren  <ref name="3D-Druck Verfahren">Hagemann, Florian, Zäh, Michael, 1963-: Wirtschaftliche Fertigung mit Rapid-Technologien : Anwender-Leitfaden zur Auswahl geeigneter Verfahren. Hanser, München 2006, ISBN 3-446-22854-3</ref> (Fused Layer Modelling). Beim FLM wird das genutzte Material, so genanntes Filament, ein schmelzfähiger Kunststoff, erhitzt und durch eine Düse Schicht für Schicht abgelegt. Dadurch entsteht sukzessive ein dreidimensionaler Körper. Genutzt wurde schwarzes PLA <ref name="3D-Druck Material PLA">https://www.3dnatives.com/de/feature-story-3d-druck-material-pla-nachhaltig-230720191/#!</ref> (Polyactic Acid). Das Material besteht aus chemisch aneinander gebundenen Milchsäuremolekülen. Es wird aus nachwachsenden und natürlichen Rohstoffen, wie Mais, gewonnen und gehört als synthetisches Polymer zu den Polyestern. Es wird anders als z.B. beim Gießen keine Grundform oder spezielles Werkzeug benötigt, womit sich nahezu alle Formen realisieren lassen. Ein am Rechner erstelltes 3D-Modell wird dazu in einem so genannten Slicer-Programm in unzählige Schichten zerschnitten. Nach dem Slicen errechnet das Programm den Idealen Fahrweg der Düse unter Berücksichtigung aller voreingestellten Parameter wie Wandstärke, Innenstruktur etc. Diese Daten werden an den 3D-Drucker übermittelt und dieser führt das Programm autark aus. Eine Nacharbeit ist nur minimal für Details mit Schleifpapier oder Ähnlichem notwendig. Weitere Arbeitsschritte wie zum Beispiel Drehen oder Fräsen entfallen komplett, da direkt auf das Fertigmaß gefertigt werden kann. Für das Projekt der bewegungsaktivierten Wortuhr eignet sich dieses Verfahren sehr gut, da zum einen nur ein Einzelteil gefertigt wird und die Herstellung eines Werkzeuges entfällt. Zum anderen lassen sich im 3D-Druck die einzelnen, filigranen Buchstaben sehr gut realisieren, anders als beispielsweise beim Fräsen oder Gießen. Zusätzlich ist es durch die mittlerweile weite Verbreitung von 3D-Druckern möglich gewesen, den Druck im privaten Raum durchzuführen.
===LED-Strips===
LED-Leuchtmittel sind elektrische Lichtquellen, die zum Erzeugen des Lichts Leuchtdioden (LED, light-emitting diodes) einsetzen. Eine LED hat im Allgemeinen eine Lebensdauer von ca. 50.000h. Das entspricht fast 6 Jahre durchgängiger Leuchtdauer. In der Wortuhr werden LED-Streifen eingesetzt. Die Streifen sind zwischen den einzelnen LEDs teilbar und lassen somit eine völlig variable Verteilung hinter den jeweiligen Wörtern zu. Bei den in diesem Projekt eingesetzten LED-Strips ist es möglich, dass jede LED einzeln angesteuert werden kann. Dadurch entfällt großer Verkabelungsaufwand.
===Ultraschallsensor===
Das Ultraschallsensormodul kann Distanzen zwischen 2 cm und 4 m erfassen. Die Genauigkeit beträgt dabei bis zu 3 mm. Der Erfassungswinkel beträgt 15°. Nach einem Triggersignal sendet das Modul acht kurze 40 kHz Signale aus und erwartet das Echo. Wenn ein Echo zurückkommt, so wird im Programm daraus die Distanz berechnet. Bei der Wortuhr wurde die Einschaltdistanz auf 30 cm gesetzt. Der Hauptgrund dafür ist, um während der Präsentation das Wirkprinzip darstellen zu können. Für den alltäglichen Betrieb kann diese Distanz in der Software an die jeweilig gewünscht Distanz, zum Beispiel die Raumgröße, angepasst werden.
===Echzeit-Uhr===
Der RTC bildet einen Counter ab, der über eine Batterie extern betrieben werden kann. Dies ermöglicht es, dass die Uhrzeit weiterhin der Echtzeit entspricht, auch wenn ein Mikrocontroller nicht mehr mit Strom versorgt wird. Dafür muss der RTC mit einer Uhrzeit beschrieben werden. Die Startzeit zählt der RTC, dann wie ein Counter, hoch. Über eine durch Quarz erzeugte Taktfrequenz wird dann der Sekundentakt generiert <ref>https://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC </ref> .


== Umsetzung (HW/SW) ==
== Umsetzung (HW/SW) ==
===Wie funktioniert der Aufbau technisch?===
Die Wortuhr besteht, wie beschrieben, aus elektronischen Komponenten und einem im 3D-Druck angefertigtem Gehäuse.  Der Arduino Nano (Mikrocontroller), der HC-SR04 (Ultraschallsensor), die DS3231 (Echtzeit-Uhr) und die WS2812 (RGB-Strip) bilden den elektronischen Teil der Wortuhr. Dabei dient der Arduino Nano als verarbeitende Einheit. Dieser erhält die aktuelle Uhrzeit der Echtzeit-Uhr. Dieser Vorgang passiert dauerhaft. Ebenso berechnet der Ultraschallsensor dauerhaft den Abstand zum nächstliegenden Objekt. Wenn der Ultraschallsensor ein Objekt in einem Abstand von unter 30 cm detektiert, steuert der Mikrocontroller den RGB-Strip an. Dabei werden nur die RGBs angeschaltet, die die aktuelle Uhrzeit in Verbindung mit dem gedruckten Gehäuse widerspiegeln.
Im Folgenden werden die Funktionsweisen der elektrischen Komponenten und des Gehäuses aus technischer Sicht beschrieben, sodass Bezug auf die Anforderungen der kompletten Wortuhr genommen werden kann.
Die Echtzeit-Uhr wird zum Start des Systems von dem Mikrocontroller mit der aktuellen Uhrzeit beschrieben. Dazu muss eine 8-Bit Adresse mit den Informationen der aktuellen Uhrzeit gesendet werden. Dies geschieht über einen I2C-Bus.<ref> Datenblatt DS321: https://www.analog.com/media/en/technical-documentation/data-sheets/DS3231.pdf </ref> Dann agiert die Echtzeit-Uhr wie ein Counter, welcher ohne weitere Informationen die Uhrzeit hochzählt. Die Uhrzeit wird dann wieder über eine 8-Bit Adresse an den Arduino Nano gesendet, welcher diese Daten dann interpretieren kann.
Der Ultraschallsensor funktioniert technisch gesehen wie eine Fledermaus. Er sendet ein Ultraschallsignal und wartet auf das zurückkommende Echo. Über die Zeit kann dann die Distanz berechnet werden. Dafür muss der Ultraschallsensor getriggert werden. Dies geschieht über den Trigger-Pin. Nach Abschluss des triggern sendet der Ultraschallsensor eine Signalfolge. Der Echo-Ausgang des Sensors wartet nun so lange, bis das gesendete Signal wieder erhalten wird. Über diesen Vorgang kann dann anschließend der Abstand zu einem Objekt gemessen werden.<ref> Datenblatt HC-SR 04: https://cdn.sparkfun.com/datasheets/Sensors/Proximity/HCSR04.pdf </ref> 
Der RGB-Strip kommuniziert mit dem Arduino über einen eignenden seriellen Kommunikationsweg. Dort enthalten ist, welcher RGB angeschaltet werden soll und mit welcher Helligkeit die drei Farbspektren rot, grün und blau leuchten sollen.<ref> Datenblatt WS2812: https://cdn-shop.adafruit.com/datasheets/WS2812B.pdf </ref>
Der Arduino Nano verarbeitet die gesammelten Daten der Sensoren und kommuniziert wieder mit ihnen, sodass dieser als Herzstück des Projektes dient.
Das Gehäuse wurde 3D gedruckt und so designt, dass es durch die richtige Anordnung der RGBs möglich ist, die Uhrzeit im Wortlaut abzulesen (s. Bild: RGBs im Gehäuse). Zusätzlich wurden neben dem Oberflächendesign auch kleine Wände im Inneren des Gehäuses gedruckt, sodass das Licht der RGBs nur jeweils die Zelle mit dem passenden Wort beleuchten(s. Bild: innen Seite der Oberfläche des Gehäuses). Im Gesamten besteht das Gehäuse aus drei Teilen, der Oberfläche mit dem jeweiligen Buchstaben, der Unterseite und ein Case für die Elektronik, welche gleichzeitig, als Fußstütze dient.
[[Datei:Mittel (IMG 2628).png|mini|zentriert|RGBs im Gehäuse]]
[[Datei:Mittel (IMG 2630).png|mini|zentriert|Innen Seite des Gehäuse]]
In Kombination der einzelnen Komponenten ergibt sich die Wortuhr. Durch die technische Umsetzung ist es möglich, alle Anforderungen, die zuvor an das Projekt gestellt wurden zu erfüllen. Die Elektronik wird über eine externe Stromquelle betrieben und findet mit auf das Netzteil Platz im Gehäuse. Das Gehäuse wurde so designt, dass es möglich ist, die Zeit in Fünferschritten abzulesen. Außerdem wurde ein Arduino für das Projekt verwendet, welcher die RGBs anschaltet, wenn sich ein Objekt im Erkennungsbereich des Ultraschallsensors befindet.
===Programmcode===
Der Arduino Nano wurde in der Arduino IDE programmiert. Neben der Library für die Ansteuerung der RGBs wurde eine Library für die Ansteuerung des RTCs verwendet. In der Setup Funktion werden die RGBs initialisiert und überprüft, ob der Kontakt zu dem RTC besteht. Ebenso werden die Pins für den Ultraschallsensor als Output und Input definiert. In der Loop Funktion werden die Funktionen zur Bestimmung der Uhrzeit, sowie zur Ansteuerung der RGBs aufgerufen. Zudem wird die Funktion aufgerufen, die zur Abstandsmessung verwendet wird. Wenn sich kein Objekt in einem Bereich von kleiner 30 cm befindet, werden alle RGBs ausgeschaltet. Ist ein Objekt im Schwellenbereich, werden die RGBs angesteuert. Die eben kurz angesprochenen Funktionen werden im Folgende ausführlich erklärt.
'''Programmablaufplan''' <br/>
[[Datei:Hauptprogramm Wortuhr.png|rahmenlos|Hauptprogramm Wortuhr]]
[[Datei:Erfassung der Distanz.png|rahmenlos|Erfassung der Distanz]]
[[Datei:Anpassung der Zeit.png|rahmenlos|Anpassung der Uhrzeit]]
[[Datei:RGB-Strip ansteuern.png|rahmenlos|RGB-Strip ansteuern]]
'''Code für das Programm:''' <br/>
<div style="width:850px; height:400px; overflow:scroll; border: hidden">
<syntaxhighlight lang="cpp" style="border: none; background-color: #EFF1C1; font-size:larger">
//****************************************************************************//
//                              HSHL - BSE                                  *
//*****************************************************************************
//                                                                            *
// Modul          :  Angewandte Elektrotechnik                              *
//                                                                            *
// Hardware        : Arduino Nano                                            *
//                                                                            *
// Prüfer          : Prof. Schneider                                          *
//                                                                            *
//*****************************************************************************
#include <Adafruit_NeoPixel.h>
#include <avr/power.h>
#include "RTClib.h"
// Definieren der Pins
#define PIN            6
#define NUMPIXELS      58
#define PIN_TRIGGER 11
#define PIN_ECHO    12
// Alpha für Filterung
#define ALPHA 0.75
RTC_DS3231 rtc;
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
const int SENSOR_MAX_RANGE = 3000; // in cm
unsigned long duration;
unsigned int distance;
void setup () {
  Serial.begin(9600);
  pixels.begin();
#ifndef ESP8266
  while (!Serial);
#endif
  if (! rtc.begin()) { //ueberprufen der Verbindung zum RTC
    Serial.println("Couldn't find RTC");
    Serial.flush();
    abort();
  }
  Serial.println("Setting the time...");
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  pinMode(PIN_TRIGGER, OUTPUT);
  pinMode(PIN_ECHO, INPUT);
}
void loop () {
  DateTime now = rtc.now(); // Echtzeit auslesen
  if (expoFilter(distanceMes()) <= 30)
  {
    stripStart();
    timeOnStripHour(conversionTimeHour(now.minute(), now.second()));
    timeOnStripMin (conversionTimeMinute());
    pixels.show();
    delay(10000); // 10 Sekunden werden die RGBs angeschaltet
  }
    for (int i = 0; i < NUMPIXELS; i++) { //Strip ausschalten
      pixels.setPixelColor(i, pixels.Color(0, 0, 0)); // Helligkeit auf 0%
      pixels.show();
    }
  }
</syntaxhighlight>
</div>
Bei der Funktion ''distanceMes()'' wird die Distanz als Rückgabewert ausgegeben. Dabei wird ein Pin erst getiggert. Daraufhin wird ein Impuls gesendet. Wird das Ultraschallsignal wieder zurückerhalten, lässt sich die Distanz zu einem Objekt messen. Anschließend wartet der Sensor eine Sekunde. Der Rückgabewert bzw. die Distanz wird in der Funktion ''expoFilter()'' exponentiell gefiltert. Dafür wird über eine mathematische Funktion ein gefilterter Wert berechnet.
'''Distanzmessung''' <br/>
<div style="width:850px; height:400px; overflow:scroll; border: hidden">
<syntaxhighlight lang="cpp" style="border: none; background-color: #EFF1C1; font-size:larger">
/////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                            Distanzmessung                                  //
//        Distanz wird berrechnet und als Rueckgabewert herausgegeben        //
//                                                                            //
/////////////////////////////////////////////////////////////////////////////////
int distanceMes ()
  {
    unsigned int distance;
    digitalWrite(PIN_TRIGGER, LOW); // triggern
    delayMicroseconds(2);
    digitalWrite(PIN_TRIGGER, HIGH); // Impuls senden
    delayMicroseconds(10);
    duration = pulseIn(PIN_ECHO, HIGH); // Impuls empfangen
    distance = duration / 58; // Distanz berrechnen
    Serial.println(expoFilter(distance));
    delay(1000);
    return distance;
  }
/////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                              Filter                                        //
// Rohdaten werden expontentiell gefiltert und als Rueckgabewert herausgegeben //
//                                                                            //
/////////////////////////////////////////////////////////////////////////////////
  float expoFilter(int rawData)
  {
    float newValueFiltered;
    static float lastValueFiltered;
    newValueFiltered = ALPHA * rawData + (1 - ALPHA) * lastValueFiltered; // Formel zu Filterung
    lastValueFiltered = newValueFiltered;
    return newValueFiltered;
  }
</syntaxhighlight>
</div>
In der Funktion ''stripStart()'' werden die ersten drei RGBs in der Farbe Weiß angesteuert und angeschaltet. Durch das Schalten der RGBs und deren Anordnung im Gehäuse erscheinen die Wörter ''Es ist''. Diese Wörter sollen immer angeschaltet werden, wenn der Ultraschallsensor ein Objekt im Bereich von 30 cm detektiert.
'''Ansteuerung der ersten drei RGBs''' <br/>
<div style="width:850px; height:400px; overflow:scroll; border: hidden">
<syntaxhighlight lang="cpp" style="border: none; background-color: #EFF1C1; font-size:larger">
/////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                    RGBs ansteuern für ES IST                              //
//              die ersten drei RGBs werden angesteuert                      //
//                                                                            //
/////////////////////////////////////////////////////////////////////////////////
void stripStart ()
{
  pixels.setPixelColor(0, pixels.Color(25, 25, 25)); // einstellen der Pixel (Pixel, RGB)
  pixels.setPixelColor(1, pixels.Color(25, 25, 25));
  pixels.setPixelColor(2, pixels.Color(25, 25, 25));
  }
</syntaxhighlight>
</div>
Die folgenden Funktionen wandeln die Echtzeit um, damit die richtigen RGBs für die Funktionsweise der Wortuhr angesteuert werden. In der Funktion ''conversionTimeSecond()'' werden die Sekunden ab 30 Sekunden zu einer vollen Minute aufgerundet. Dadurch ist des möglich, dass in der Funktion ''conversionTimeMinute()'' die Minuten auf-oder abgerundet werden. Dies geschieht immer in Fünfer schritten, da das Gehäuse so konstruiert wurde, dass die Uhr die Minuten in einem Fünf-Minuten-Takt anzeigt. Mithilfe der Funktion ''conversionTimeHour()'' werden die Stunden verändert. Zum einen werden die Stunden so verändert, dass die Uhrzeit von einem 24 Stunden Modus in einen 12 Stunden Modus geändert wird. Zugleich hat die Funktion die Aufgabe, dass wenn die Minuten auf der Wortuhr größer 25 sind, die Stunden um eine Stunde erhöht werden (Bsp. 12:30 Uhr -> Es ist halb '''Drei''').
'''Zeitanpassung''' <br/>
<div style="width:850px; height:400px; overflow:scroll; border: hidden">
<syntaxhighlight lang="cpp" style="border: none; background-color: #EFF1C1; font-size:larger">
/////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                        Sekunden anpassen                                    //
//      Sekunden werden aus vollen Minuten gerundet mit Rueckgabewert          //
//                                                                            //
/////////////////////////////////////////////////////////////////////////////////
  float conversionTimeSecond() {
    int second;
    int secondRound;
    DateTime now = rtc.now(); // Echtzeit auslesen
    second = now.second(); // Echzeit (Sek werden ausgelesen)
    if (second <= 29) { // Runden der Sekunden auf volle Minuten
      secondRound = 0;
    }
    else {
      secondRound = 1;
    }
    return secondRound;
  }
/////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                      Minuten anpassen                                      //
//              Minuten werden gerundet mit Rueckgabewert                      //
//                                                                            //
/////////////////////////////////////////////////////////////////////////////////
  int conversionTimeMinute () { //Anpassen der Minuten in 5er Schritte
    int minute;
    int minuteRound;
    DateTime now = rtc.now(); // Echzeit auslesen
    minute = now.minute(); // Echzeit (Min werden ausgelesen)
    minuteRound = round((minute + conversionTimeSecond()) / 5) * 5; //Runden der Minuten in 5er Schritte
    if (minuteRound == 60) { //wenn Minuten 60 dann 0
      minuteRound = 0;
    }
    return minuteRound;
  }
/////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                          Stunden anpassen                                  //
//            Stunden werden für die Steuerung des RGB-Strip angepasst        //
//                          mit Rueckgabewert                                  //
//                                                                            //
/////////////////////////////////////////////////////////////////////////////////
  int conversionTimeHour (int min, int sec) {
    int hour;
    int hourSmall;
    bool marker = false;
    DateTime now = rtc.now(); // Echzeit auslesen
    hour = now.hour(); // Echzeit (Stunden werden ausgelesen)
    hourSmall = now.hour();
    if (hour >= 13) { // Umrechnung der Stunden in 12-Stuendige-Zaehlung
      hourSmall = hour - 12;
    }
    if (hour == 0) { // bei 0 Uhr = 12 Uhr
      hourSmall = 12;
    }
    /*
    * Stunden werden +1 gerechnet, wenn Min größer 00:22:30
    * damit Pixel passend angesteuert werden
    * Bsp. 14:40 Uhr
    * Es ist zwanzig vor DREI
    */
    if (min >= 22 && sec >= 30 || min >= 23)
    {
      marker = true;
    }
    if (min == 0)
    {
      marker = false;
    }
    if (marker == true)
    {
      hourSmall = hourSmall + 1;
    }
    return hourSmall;
  }
</syntaxhighlight>
</div>
Die Funktionen ''timeOnStripHour()'' und ''timeOnStripMinute()'' sind dafür die zuständig in Abhängigkeit der manipulierten Minuten und Stunden die RGBs anzuschalten, die hinter der Oberfläche des Gehäuses geklebt wurden. Dadurch ist es möglich das die richtigen Wörter in Abhängigkeit der Zeit beleuchtet werden.
'''Code zum Ansteuern der RGBs:''' <br/>
<div style="width:850px; height:400px; overflow:scroll; border: hidden">
<syntaxhighlight lang="cpp" style="border: none; background-color: #EFF1C1; font-size:larger">
/////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                      RGBs ansteuern für Stunden                            //
//      je nach angegebender Stunde werden passende RGBs angesteuert          //
//                                                                            //
/////////////////////////////////////////////////////////////////////////////////
  void timeOnStripHour (int hour) {
    if (hour == 0 || hour == 12) { // wenn Stunde x dann Pixel anschalten
      pixels.setPixelColor(48, pixels.Color(25, 25, 25)); // einstellen der Pixel (Pixel, RGB)
      pixels.setPixelColor(49, pixels.Color(25, 25, 25));
      pixels.setPixelColor(50, pixels.Color(25, 25, 25));
      pixels.setPixelColor(51, pixels.Color(25, 25, 25));
    }
    if (hour == 1) {
      pixels.setPixelColor(33, pixels.Color(25, 25, 25));
      pixels.setPixelColor(34, pixels.Color(25, 25, 25));
    }
    if (hour == 2) {
      pixels.setPixelColor(31, pixels.Color(25, 25, 25));
      pixels.setPixelColor(32, pixels.Color(25, 25, 25));
    }
    if (hour == 3) {
      pixels.setPixelColor(35, pixels.Color(25, 25, 25));
      pixels.setPixelColor(36, pixels.Color(25, 25, 25));
    }
    if (hour == 4) {
      pixels.setPixelColor(37, pixels.Color(25, 25, 25));
      pixels.setPixelColor(38, pixels.Color(25, 25, 25));
    }
    if (hour == 5) {
      pixels.setPixelColor(29, pixels.Color(25, 25, 25));
      pixels.setPixelColor(30, pixels.Color(25, 25, 25));
    }
    if (hour == 6) {
      pixels.setPixelColor(41, pixels.Color(25, 25, 25));
      pixels.setPixelColor(42, pixels.Color(25, 25, 25));
      pixels.setPixelColor(43, pixels.Color(25, 25, 25));
    }
    if (hour == 7) {
      pixels.setPixelColor(44, pixels.Color(25, 25, 25));
      pixels.setPixelColor(45, pixels.Color(25, 25, 25));
      pixels.setPixelColor(46, pixels.Color(25, 25, 25));
      pixels.setPixelColor(47, pixels.Color(25, 25, 25));
    }
    if (hour == 8) {
      pixels.setPixelColor(39, pixels.Color(25, 25, 25));
      pixels.setPixelColor(40, pixels.Color(25, 25, 25));
    }
    if (hour == 9) {
      pixels.setPixelColor(54, pixels.Color(25, 25, 25));
      pixels.setPixelColor(55, pixels.Color(25, 25, 25));
    }
    if (hour == 10) {
      pixels.setPixelColor(56, pixels.Color(25, 25, 25));
      pixels.setPixelColor(57, pixels.Color(25, 25, 25));
    }
    if (hour == 11) {
      pixels.setPixelColor(28, pixels.Color(25, 25, 25));
    }
  }
/////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                    RGBs ansteuern für Minuten                              //
//      je nach angegebender Minuten werden passende RGBs angesteuert          //
//                                                                            //
/////////////////////////////////////////////////////////////////////////////////
  void timeOnStripMin (int Min) {
    if (Min == 0) { //Uhr
      pixels.setPixelColor(52, pixels.Color(25, 25, 25)); // einstellen der Pixel (Pixel, RGB)
      pixels.setPixelColor(53, pixels.Color(25, 25, 25));
    }
    if (Min == 5) { // fünf nach
      pixels.setPixelColor(3, pixels.Color(25, 25, 25));
      pixels.setPixelColor(4, pixels.Color(25, 25, 25));
      pixels.setPixelColor(20, pixels.Color(25, 25, 25));
      pixels.setPixelColor(21, pixels.Color(25, 25, 25));
    }
    if (Min == 10) {
      pixels.setPixelColor(11, pixels.Color(25, 25, 25));
      pixels.setPixelColor(12, pixels.Color(25, 25, 25));
      pixels.setPixelColor(13, pixels.Color(25, 25, 25));
      pixels.setPixelColor(20, pixels.Color(25, 25, 25));
      pixels.setPixelColor(21, pixels.Color(25, 25, 25));
    }
    if (Min == 15) {
      pixels.setPixelColor(14, pixels.Color(0, 25, 0));
      pixels.setPixelColor(15, pixels.Color(0, 25, 0));
      pixels.setPixelColor(16, pixels.Color(0, 25, 0));
      pixels.setPixelColor(17, pixels.Color(0, 25, 0));
      pixels.setPixelColor(18, pixels.Color(0, 25, 0));
      pixels.setPixelColor(19, pixels.Color(0, 25, 0));
      pixels.setPixelColor(20, pixels.Color(0, 25, 0));
      pixels.setPixelColor(21, pixels.Color(0, 25, 0));
    }
    if (Min == 20) {
      pixels.setPixelColor(5, pixels.Color(25, 25, 25));
      pixels.setPixelColor(6, pixels.Color(25, 25, 25));
      pixels.setPixelColor(7, pixels.Color(25, 25, 25));
      pixels.setPixelColor(8, pixels.Color(25, 25, 25));
      pixels.setPixelColor(9, pixels.Color(25, 25, 25));
      pixels.setPixelColor(10, pixels.Color(25, 25, 25));
      pixels.setPixelColor(20, pixels.Color(25, 25, 25));
      pixels.setPixelColor(21, pixels.Color(25, 25, 25));
    }
    if (Min == 25) {
      pixels.setPixelColor(3, pixels.Color(25, 25, 25));
      pixels.setPixelColor(4, pixels.Color(25, 25, 25));
      pixels.setPixelColor(24, pixels.Color(25, 25, 25));
      pixels.setPixelColor(25, pixels.Color(25, 25, 25));
      pixels.setPixelColor(26, pixels.Color(25, 25, 25));
      pixels.setPixelColor(27, pixels.Color(25, 25, 25));
    }
    if (Min == 30) {
      pixels.setPixelColor(26, pixels.Color(0, 25, 0));
      pixels.setPixelColor(27, pixels.Color(0, 25, 0));
    }
    if (Min == 35) {
      pixels.setPixelColor(3, pixels.Color(25, 25, 25));
      pixels.setPixelColor(4, pixels.Color(25, 25, 25));
      pixels.setPixelColor(20, pixels.Color(25, 25, 25));
      pixels.setPixelColor(21, pixels.Color(25, 25, 25));
      pixels.setPixelColor(26, pixels.Color(25, 25, 25));
      pixels.setPixelColor(27, pixels.Color(25, 25, 25));
    }
    if (Min == 40) {
      pixels.setPixelColor(5, pixels.Color(25, 25, 25));
      pixels.setPixelColor(6, pixels.Color(25, 25, 25));
      pixels.setPixelColor(7, pixels.Color(25, 25, 25));
      pixels.setPixelColor(8, pixels.Color(25, 25, 25));
      pixels.setPixelColor(9, pixels.Color(25, 25, 25));
      pixels.setPixelColor(10, pixels.Color(25, 25, 25));
      pixels.setPixelColor(24, pixels.Color(25, 25, 25));
      pixels.setPixelColor(25, pixels.Color(25, 25, 25));
    }
    if (Min == 45) {
      pixels.setPixelColor(14, pixels.Color(0, 25, 0));
      pixels.setPixelColor(15, pixels.Color(0, 25, 0));
      pixels.setPixelColor(16, pixels.Color(0, 25, 0));
      pixels.setPixelColor(17, pixels.Color(0, 25, 0));
      pixels.setPixelColor(18, pixels.Color(0, 25, 0));
      pixels.setPixelColor(19, pixels.Color(0, 25, 0));
      pixels.setPixelColor(24, pixels.Color(0, 25, 0));
      pixels.setPixelColor(25, pixels.Color(0, 25, 0));
    }
    if (Min == 50) {
      pixels.setPixelColor(11, pixels.Color(25, 25, 25));
      pixels.setPixelColor(12, pixels.Color(25, 25, 25));
      pixels.setPixelColor(12, pixels.Color(25, 25, 25));
      pixels.setPixelColor(24, pixels.Color(25, 25, 25));
      pixels.setPixelColor(25, pixels.Color(25, 25, 25));
    }
    if (Min == 55) {
      pixels.setPixelColor(3, pixels.Color(25, 25, 25));
      pixels.setPixelColor(4, pixels.Color(25, 25, 25));
      pixels.setPixelColor(24, pixels.Color(25, 25, 25));
      pixels.setPixelColor(25, pixels.Color(25, 25, 25));
    }
  }
</syntaxhighlight>
</div>


== Komponententest ==
== Komponententest ==


== Ergebnis ==
Bevor die Wortuhr mit den gesamten Komponenten getestet wurde, wurden die Sensoren zuvor erst einzelne getestet, sodass mögliche Komplikationen am Anfang des Projektes, probiert wurden zu vermeiden.
Zu Beginn wurde der Ultraschallsensor in seiner Funktionsweise getestet. Dafür wurde der Arduino programmiert und ein Programm geschrieben, welches es möglich macht, den Abstand zwischen dem Ultraschallsensor und einem Objekt zu messen. Dafür wurden die Messdaten jede 100 ms in dem Serial Monitor der Arduino IDE ausgegeben. Nach einer ersten Testung fiel auf, dass es unregelmäßig zu Ausreißern in den Messungen kam (s. Bild: Sensordaten). Zu erkennen ist, dass der Ultraschallsensor unregelmäßig eine zuvor eingestellte maximal Range erreicht. Daraufhin wurden die Messwerte über einen Exponentialfilter mit einem Alpha von 0,75 gefiltert. Eine erneute Testung ergab, dass die Ausreißer eliminiert wurden.
[[Datei:Sensordaten HC-SR 04.png|mini|zentriert|Sensordaten]]
In der zweiten Teiltestung wurde die Echzeit-Uhr getestet. Dafür wurde wieder ein Programm geschrieben, welches die Uhrzeit über den seriellen Monitor der Arduino IDE ausgibt. Dieser Test verlief ohne Probleme.  Für die dritte Teiltestung wurde der RGB-Strip über den Arduino angesteuert. Hierbei wurden verschiedene RGBs in unterschiedlichen Farben angesteuert.
Für den finalen Test wurden alle Komponenten an einem Arduino Uno angeschlossen (drei Spannungspins und drei Groundpins). Der Code wurde jeweils so angepasst, dass die Wortuhr die zuvor beschrieben Funktionen ausübt. Die Uhrzeit für den Versuch wurde manuell eingegeben, um die Testung zu beschleunigen. Das Ergebnis ergab, dass nachdem die Hand einen geringen Abstand, als 30 cm zum Ultraschallsensor hatte, die vorgesehenen RGBs angeschaltet wurden (s. Bild: Versuch der Komponenten). Zuvor wurde eine Tabelle erstellt, zu welchen Zeiten, welche RGBs leuchten sollte.
Der letzte Versuch zeigt, dass die Anforderungen an das System erfolgreich getestet und erfüllt wurden. In Tabelle 3 ist zu sehen, mit welchem Versuch, die jeweilige Anforderung getestet wurde. Durch die Implementierung der Echtzeit-Uhr kann zu jedem gewünschten Zeitpunkt die Uhrzeit ermittelt werden. Dadurch ist es möglich, dass die RGBs in Echtzeit angesteuert werden können. Durch den Test mit dem Ultraschallsensor, ist es möglich sagen zu können, dass dieser sicher Distanzen zu anderen Objekten messen kann. Die Anforderung an die gesamte Wortuhr, dass die erst die Uhrzeit anzeigen soll, wenn ein Abstand durch ein Objekt von 30 cm unterschritten wird, ist hierdurch erfüllt. Zudem wurde durch die Testung des Ultraschallsensors es möglich gemacht, dass Ausreißer eliminiert wurden. Dies hat zudem den positiven Effekt, dass unerwünschte Schwellen Unterschreitungen die RGBs nicht ansteuern (Wasser vom Nachttisch kurz an der Wortuhr vorbeibewegen). Durch die Auswahl von RGBs ist es zudem möglich diese in den Farben zu ändern, wodurch die es möglich ist wichtige Uhrzeiten farblich hervorzuheben.
[[Datei:Mittel (IMG 2624).png|mini|zentriert|Versuch der Komponenten]]
 
=== Ergebnis ===
{| class="wikitable"
|+ style = "text-align: left"|Tabelle 3: Anforderungstests technischer Komponenten
! style="font-weight: bold;" | ID
! style="font-weight: bold;" | Anforderung
! style="font-weight: bold;" | Getestet durch Komponententest
! style="font-weight: bold;" | Anforderung erfüllt?
! style="font-weight: bold;" | Ersteller
! style="font-weight: bold;" | Datum
! style="font-weight: bold;" | Geprüft von
! style="font-weight: bold;" | Datum
 
|-
| 1.0
| Die Steuerung muss in Echtzeit erfolgen.
| DS3231
| Ja
| Nico Kasprik
| 12.11.2022
| Jonas Loddenkemper
| 12.11.2022
|-
| 2.0
| Die Anwesenheit einer Person wird über einen Ultraschallsensor geprüft (Schaltabstand ca. 30 cm).
| HC-SR 04
| Ja
| Nico Kasprik
| 02.12.2022
| Jonas Loddenkemper
| 02.12.2022
|-
| 3.0
| Uhrzeit soll nur angezeigt werden, wenn beabsichtigt (kleine Bewegungen sollen kein Auslösen hervorrufen).
| HC-SR 04
| Ja
| Nico Kasprik
| 12.12.2022
| Jonas Loddenkemper
| 12.12.2022
|-
| 4.0
| Zu besonderen Uhrzeit, soll ein Farbwechsel eingestellt werden.
| WS2812
| Ja
| Nico Kasprik
| 16.12.2022
| Jonas Loddenkemper
| 16.12.2022
|-
 
|}


== Zusammenfassung ==
== Zusammenfassung ==
=== Lessons Learned ===
=== Zusammenfassung & Lessons Learned ===
Ein Prototyp der bewegungsaktivierten Wortuhr konnte erfolgreich gefertigt werden. Von Anfang an stellte sich heraus, dass die Teammitglieder gut zusammenarbeiten konnten und alle Absprachen funktionierten Reibungslos. Aufgrund verschiedener Erfahrungen im Bereich der Konstruktion bzw. Programmierung von Arduinos konnten die unterschiedlichen Aufgaben fair und effizient aufgeteilt werden. Bereits nach kurzer Zeit stand das Grundgerüst hinsichtlich Design und zu nutzenden Komponenten.
Kleinere Komplikationen gab es zunächst bei der Konnektivität des Arduinos, welche allerdings in Rücksprache mit Herrn Professor Schneider und mithilfe von Herrn Ebmeyer gelöst werden konnten. Die für die LEDs benötigte Library war in Simulink leider nicht nutzbar, weshalb in Rücksprache mit Herrn Schneider auf die Arduino IDE zurückgegriffen wurde. Sowohl die RTC als auch der Ultraschallsensor inklusive Filterung ließen sich ebenfalls in der Arduino IDE programmieren, wodurch letztlich alle softwareseitigen Anforderungen erfüllt wurden.
Der Aufbau des Prototyps hat sich als sehr zeitaufwendig herausgestellt, konnte aber ebenfalls problemlos ausgeführt werden. Während der ersten Inbetriebnahme fielen kleinere und größere Optimierungspotenziale auf. Kleinigkeiten, wie zum Beispiel die Nutzung zusätzlicher Diffusoren um das Licht besser zu streuen oder die Umpositionierung einzelner LEDs wurden direkt umgesetzt. Größere Optimierungspotenziale umfassen zum Beispiel die Anpassung der Konstruktion. Bei dem Bau einer weiteren Wortuhr wäre es zum Beispiel sinnvoll, die Materialstärke der Frontblende zu reduzieren. Dadurch kann eine noch bessere Lesbarkeit der Uhr erreicht werden.
 
Zusammenfassend wird auf ein erfolgreiches Projekt zurückgeblickt, welches mit einem voll funktionsfähigen Prototyp abgeschlossen wurde.


== Projektunterlagen ==
== Projektunterlagen ==
=== Projektplan ===
=== Projektplan ===
[[Datei:Projektplan Wortuhr.png|rahmenlos|Der Projektplan]]
=== Projektdurchführung ===
=== Projektdurchführung ===
{| class="wikitable"
|+ style = "text-align: left"|Tabelle 4: Darstellung des Lösungswegs
! style="font-weight: bold;" | Schritt
! style="font-weight: bold;" | Aufgabe
! style="font-weight: bold;" | Lösung
|-
| 1
| Mögliche Projekte finden
| Brainstorming, verschiedene Ideen wurden gesammelt und auf Umsetzbarkeit/Interesse für Modul „Angewandte Elektrotechnik“ geprüft
• Automatisch schwenkbare Fernsehhalterung
• Bewegungsaktivierte Wortuhr
• Selbstfahrender Legoroboter
• Laserhockey
|-
| 2
| Festlegung auf ein Projekt
| Projekt „Bewegungsaktivierte Wortuhr“ wurde aufgrund Komplexität, Anwendung verschiedener elektrotechnischer Komponenten, kompakter Abmaße und weiterer Nutzbarkeit im Privaten ausgewählt
|-
| 3
| Projektplan erstellen
| Projektplan wurde zuerst in Excel erstellt, aufgrund der geforderten Programme in Gantt finalisiert
|-
| 4
| Erster Entwurf
| Erstellung eines 3D-Modells zur Visualisierung/besseren Vorstellung
|-
| 5
| Auflisten der notwendigen Anforderungen/Bauteile
| Entscheidungen für LED-Strip, 3D-Druck, Ultraschallsensor, RTC (Real Time Clock) und deren Aufgaben wurden gefällt
|-
| 6
| Auswahl sinnvoller Komponenten
| Nach Recherche für ausreichend leistungsstarke, kompakte und gut zu modifizierende Komponenten und Materialen wurden LED-Strip „WS2812“, Ultraschallsensor „HC-SR04“, PLA (3D-Druck-Material), RTC „DS3231“, Arduino-Nano ausgewählt
|-
| 7
| Softwareplanung
| Programmablaufplan wurde erstellt
|-
| 8
| Programmierung
| Auswahl der passenden Library für den LED-Strip, Filterung des Ultraschallsensors, Programmierung der Zeitanzeige
|-
| 9
| 3D-Druck
| 3D-Modell als .stl-Datei für 3D-Druck optimiert und vorbereitet, anschließend gedruckt
|-
| 10
| Zusammenbau
| • LED-Strip auf passende Länge zugeschnitten & verlötet
• Platine, Ultraschallsensor, RTC verlötet
• Diffusor zugeschnitten und in Gehäuse geklebt
• LED-Strip verklebt
|-
| 11
| Testlauf
| • Verschiedene Uhrzeiten angesteuert, überprüft ob die korrekten LEDs leuchten
• Funktion des Ultraschallsensors geprüft
• Lesbarkeit der Uhrzeit überprüft
|-
| 12
| Optimierung nach Testlauf
| • Weitere Diffusoren eingeklebt
• Position einzelner LEDs angepasst
|-
| 13
| Videodreh
| Video zur Veranschaulichung der Funktionsweise gedreht
|-
| 14
| Vorbereitung Messestand
| Infos gesammelt, Plakat gestaltet und in Druck gegeben
|-
|}


== YouTube Video ==
== YouTube Video ==
 
[https://youtu.be/j8s0Sq6OLxY Video der bewegungsaktivierten Wortuhr]
== Weblinks ==


== Literatur ==
== Literatur ==
Zeile 124: Zeile 787:
<!-- Fügen Sie diesen Footer hinzu.  -->
<!-- Fügen Sie diesen Footer hinzu.  -->
----
----
→ zurück zur Übersicht: [[:Kategorie:ProjekteET_MTR_BSE_WS2021|WS 21/22: Angewandte Elektrotechnik (BSE)]]
→ zurück zur Übersicht: [[:Kategorie:ProjekteET MTR BSE WS2022]]

Aktuelle Version vom 10. Januar 2023, 16:34 Uhr


Autoren: Nico Kasprik & Jonas Loddenkemper
Betreuer: Prof. Schneider

mittel
mittel


Einleitung

Bei dem vorliegenden Projekt aus dem Praktikum "Angewandte Elektrotechnik" des Studiengangs Business and Systems Engineering (BSE). Ziel dieses Projekts war es eine Wortuhr nach dem Vorbild des Designklassikers QLOCKTWO zu bauen. Aus Gründen der Energieeffizienz wird die Uhrzeit nur während der Anwesenheit von Personen angezeigt. Die Hintergrundbeleuchtung ist mit LEDs realisiert worden. Es wurden LED-Strips, ein RTC sowie als Anwesenheitssensor ein Ultraschallsensor genutzt.

Erster Entwurf der Wortuhr - Frontansicht
Erster Entwurf der Wortuhr - Rückansicht

Anforderungen

Tabelle 1: Testbare, atomare Anforderungen
ID Inhalt Ersteller Datum Geprüft von Datum
1.0 Die Uhr soll die Uhrzeit in 5-Minuten-Schritten in Worten anzeigen. Jonas Loddenkemper 04.10.2022 Nico Kasprik 04.10.2022
1.1 Die Steuerung muss in Echtzeit erfolgen. Jonas Loddenkemper 04.10.2022 Nico Kasprik 04.10.2022
2.0 Die Uhr wird mittels USB-Kabel mit Strom versorgt. Jonas Loddenkemper 04.10.2022 Nico Kasprik 04.10.2022
3.0 Die Anwesenheit einer Person wird über einen Ultraschallsensor geprüft (Schaltabstand ca. 30 cm). Jonas Loddenkemper 04.10.2022 Nico Kasprik 04.10.2022
4.0 Der Arduino-Controller, die LED-Strips und der Sensor ist im Gehäuse. Jonas Loddenkemper 04.10.2022 Nico Kasprik 04.10.2022
5.0 Die Steuerung wird auf einem Arduino Mikrocontroller ausgeführt. Jonas Loddenkemper 04.10.2022 Nico Kasprik 04.10.2022
6.0 Die Frontblende ist 3D-gedruckt, die notwendigen Wörter sind direkt ausgespart. Jonas Loddenkemper 04.10.2022 Nico Kasprik 04.10.2022
7.0 Uhrzeit soll nur angezeigt werden, wenn beabsichtigt (kleine Bewegungen sollen kein Auslösen hervorrufen). Jonas Loddenkemper 04.10.2022 Nico Kasprik 04.10.2022
8.0 Zu besonderen Uhrzeit, soll ein Farbwechsel eingestellt werden. Jonas Loddenkemper 04.10.2022 Nico Kasprik 04.10.2022
9.0 Komponenten sollen austauschbar sein. Jonas Loddenkemper 04.10.2022 Nico Kasprik 04.10.2022
O.1.0 Optionale Erweiterung: Eine zusätzliche Anzeige einzelner Minuten im 5-Minuten-Fenster. Jonas Loddenkemper 04.10.2022 Nico Kasprik 04.10.2022

Funktionaler Systementwurf

Funktionaler Systementwurf

Der funktionale Systementwurf bildet die wesentliche Funktion des zu erstellenden Systems ab. Dabei lässt sich dieser nach dem EVA-Prinzip in die drei Stufen „Eingabe“, „Verarbeitung“ und „Ausgabe“ aufteilen.  Sensoren lassen sich der ersten Stufe zuweisen, da diese Informationen liefern, auf die der Mikrocontroller reagiert und diese weiterverarbeitet. Die aktuelle Uhrzeit soll dabei ständig abgefragt werden. Wenn sich eine Person vor der Wortuhr befindet, wird diese angeschaltet. Verlässt die Person einen Bereich zwischen der Uhr von 0 cm bis 30 cm, schaltet sich die Uhr eigenständig ab. Die weiterverarbeiteten Informationen werden für das System, so angepasst, dass über ein Ausgabegerät die Daten in gewünschter Form ausgegeben werden.

Technischer Systementwurf

Technischer Systementwurf


Der technische Entwurf orientiert sich auch nach dem EVA-Prinzip. Dabei wird der Schwerpunkt aber nur auf die technische Zusammenstellung des Systems gelegt.    Für die Umsetzung des Projektes wird ein Real-Time-Clock-Modul verwendet.  Dadurch erhält das System Informationen über die korrekte Uhrzeit. Dies geschieht über einen I2C Bus. Ein Ultraschallsensor soll die Informationen liefern, ob sich eine Person vor der Wortuhr befindet. Der Erfassungsbereich des Ultraschallsensors liegt bei 2 cm bis ca. 400 cm. Wenn sich eine Person in einem Bereich bis 30 cm an die Wortuhr nähert, soll diese angeschaltet werden. Verlässt die Person diesen Distanzbereich, schaltet sich die Uhr nach wenigen Sekunden wieder aus. Dafür wird der Ultraschallsensor über ein HIGH-Signal getriggert. Daraufhin sendet er ein Echo-Signal und wartet bis der Schall zurückkommt. Dabei wird der Echo-Pin solange auf HIGH gesetzt, bis das Signal wieder ankommt. Ist dies der Fall, so wird das Eingangssignal LOW. Über die Zeit lässt sich nun die Distanz zum zu messenden Objekt bestimmen. Der Mikrocontroller verarbeitet die Informationen, sodass sie im Folgenden über einen RGB-Strip ausgegeben werden. Der Arduino kommuniziert mit dem RGB-Strip über ein spezifisches Protokoll. (s. Tabelle 2)

Tabelle 2: Kommunikationsweg
ID Komponente Kommunikationsweg mit Mikrocontroller
1.0 HC-SR 04 digital über TTL-Pegel
2.0 DS3231 I2C
3.0 WS2812 Hersteller eigenes Protokoll


Komponentenspezifikation

In Abbildung "Steckplatine Layout" ist eine erste Steckbrettansicht zu sehen. Das Real-Time-Clock Modul kommuniziert über I2C mit dem Mikrocontroller. Der Ultraschallsensor über eine digitale Kommunikation mithilfe eines TTL-Pegels. Der LED-Strip wird über ein speziell für ihn ausgelegtes Protokoll angesteuert.

Steckplatine Layout

Theoretische Grundlagen und ihre Bewertung in Bezug auf die Aufgabenstellung

3D-Druck

Der 3D-Druck ist ein Verfahren der generativen Fertigungsverfahren und wird heutzutage insbesondere im Rapid Prototyping genutzt. In diesem Projekt wurde das FLM-Verfahren [1] (Fused Layer Modelling). Beim FLM wird das genutzte Material, so genanntes Filament, ein schmelzfähiger Kunststoff, erhitzt und durch eine Düse Schicht für Schicht abgelegt. Dadurch entsteht sukzessive ein dreidimensionaler Körper. Genutzt wurde schwarzes PLA [2] (Polyactic Acid). Das Material besteht aus chemisch aneinander gebundenen Milchsäuremolekülen. Es wird aus nachwachsenden und natürlichen Rohstoffen, wie Mais, gewonnen und gehört als synthetisches Polymer zu den Polyestern. Es wird anders als z.B. beim Gießen keine Grundform oder spezielles Werkzeug benötigt, womit sich nahezu alle Formen realisieren lassen. Ein am Rechner erstelltes 3D-Modell wird dazu in einem so genannten Slicer-Programm in unzählige Schichten zerschnitten. Nach dem Slicen errechnet das Programm den Idealen Fahrweg der Düse unter Berücksichtigung aller voreingestellten Parameter wie Wandstärke, Innenstruktur etc. Diese Daten werden an den 3D-Drucker übermittelt und dieser führt das Programm autark aus. Eine Nacharbeit ist nur minimal für Details mit Schleifpapier oder Ähnlichem notwendig. Weitere Arbeitsschritte wie zum Beispiel Drehen oder Fräsen entfallen komplett, da direkt auf das Fertigmaß gefertigt werden kann. Für das Projekt der bewegungsaktivierten Wortuhr eignet sich dieses Verfahren sehr gut, da zum einen nur ein Einzelteil gefertigt wird und die Herstellung eines Werkzeuges entfällt. Zum anderen lassen sich im 3D-Druck die einzelnen, filigranen Buchstaben sehr gut realisieren, anders als beispielsweise beim Fräsen oder Gießen. Zusätzlich ist es durch die mittlerweile weite Verbreitung von 3D-Druckern möglich gewesen, den Druck im privaten Raum durchzuführen.

LED-Strips

LED-Leuchtmittel sind elektrische Lichtquellen, die zum Erzeugen des Lichts Leuchtdioden (LED, light-emitting diodes) einsetzen. Eine LED hat im Allgemeinen eine Lebensdauer von ca. 50.000h. Das entspricht fast 6 Jahre durchgängiger Leuchtdauer. In der Wortuhr werden LED-Streifen eingesetzt. Die Streifen sind zwischen den einzelnen LEDs teilbar und lassen somit eine völlig variable Verteilung hinter den jeweiligen Wörtern zu. Bei den in diesem Projekt eingesetzten LED-Strips ist es möglich, dass jede LED einzeln angesteuert werden kann. Dadurch entfällt großer Verkabelungsaufwand.

Ultraschallsensor

Das Ultraschallsensormodul kann Distanzen zwischen 2 cm und 4 m erfassen. Die Genauigkeit beträgt dabei bis zu 3 mm. Der Erfassungswinkel beträgt 15°. Nach einem Triggersignal sendet das Modul acht kurze 40 kHz Signale aus und erwartet das Echo. Wenn ein Echo zurückkommt, so wird im Programm daraus die Distanz berechnet. Bei der Wortuhr wurde die Einschaltdistanz auf 30 cm gesetzt. Der Hauptgrund dafür ist, um während der Präsentation das Wirkprinzip darstellen zu können. Für den alltäglichen Betrieb kann diese Distanz in der Software an die jeweilig gewünscht Distanz, zum Beispiel die Raumgröße, angepasst werden.

Echzeit-Uhr

Der RTC bildet einen Counter ab, der über eine Batterie extern betrieben werden kann. Dies ermöglicht es, dass die Uhrzeit weiterhin der Echtzeit entspricht, auch wenn ein Mikrocontroller nicht mehr mit Strom versorgt wird. Dafür muss der RTC mit einer Uhrzeit beschrieben werden. Die Startzeit zählt der RTC, dann wie ein Counter, hoch. Über eine durch Quarz erzeugte Taktfrequenz wird dann der Sekundentakt generiert [3] .

Umsetzung (HW/SW)

Wie funktioniert der Aufbau technisch?

Die Wortuhr besteht, wie beschrieben, aus elektronischen Komponenten und einem im 3D-Druck angefertigtem Gehäuse. Der Arduino Nano (Mikrocontroller), der HC-SR04 (Ultraschallsensor), die DS3231 (Echtzeit-Uhr) und die WS2812 (RGB-Strip) bilden den elektronischen Teil der Wortuhr. Dabei dient der Arduino Nano als verarbeitende Einheit. Dieser erhält die aktuelle Uhrzeit der Echtzeit-Uhr. Dieser Vorgang passiert dauerhaft. Ebenso berechnet der Ultraschallsensor dauerhaft den Abstand zum nächstliegenden Objekt. Wenn der Ultraschallsensor ein Objekt in einem Abstand von unter 30 cm detektiert, steuert der Mikrocontroller den RGB-Strip an. Dabei werden nur die RGBs angeschaltet, die die aktuelle Uhrzeit in Verbindung mit dem gedruckten Gehäuse widerspiegeln. Im Folgenden werden die Funktionsweisen der elektrischen Komponenten und des Gehäuses aus technischer Sicht beschrieben, sodass Bezug auf die Anforderungen der kompletten Wortuhr genommen werden kann. Die Echtzeit-Uhr wird zum Start des Systems von dem Mikrocontroller mit der aktuellen Uhrzeit beschrieben. Dazu muss eine 8-Bit Adresse mit den Informationen der aktuellen Uhrzeit gesendet werden. Dies geschieht über einen I2C-Bus.[4] Dann agiert die Echtzeit-Uhr wie ein Counter, welcher ohne weitere Informationen die Uhrzeit hochzählt. Die Uhrzeit wird dann wieder über eine 8-Bit Adresse an den Arduino Nano gesendet, welcher diese Daten dann interpretieren kann. Der Ultraschallsensor funktioniert technisch gesehen wie eine Fledermaus. Er sendet ein Ultraschallsignal und wartet auf das zurückkommende Echo. Über die Zeit kann dann die Distanz berechnet werden. Dafür muss der Ultraschallsensor getriggert werden. Dies geschieht über den Trigger-Pin. Nach Abschluss des triggern sendet der Ultraschallsensor eine Signalfolge. Der Echo-Ausgang des Sensors wartet nun so lange, bis das gesendete Signal wieder erhalten wird. Über diesen Vorgang kann dann anschließend der Abstand zu einem Objekt gemessen werden.[5] Der RGB-Strip kommuniziert mit dem Arduino über einen eignenden seriellen Kommunikationsweg. Dort enthalten ist, welcher RGB angeschaltet werden soll und mit welcher Helligkeit die drei Farbspektren rot, grün und blau leuchten sollen.[6] Der Arduino Nano verarbeitet die gesammelten Daten der Sensoren und kommuniziert wieder mit ihnen, sodass dieser als Herzstück des Projektes dient. Das Gehäuse wurde 3D gedruckt und so designt, dass es durch die richtige Anordnung der RGBs möglich ist, die Uhrzeit im Wortlaut abzulesen (s. Bild: RGBs im Gehäuse). Zusätzlich wurden neben dem Oberflächendesign auch kleine Wände im Inneren des Gehäuses gedruckt, sodass das Licht der RGBs nur jeweils die Zelle mit dem passenden Wort beleuchten(s. Bild: innen Seite der Oberfläche des Gehäuses). Im Gesamten besteht das Gehäuse aus drei Teilen, der Oberfläche mit dem jeweiligen Buchstaben, der Unterseite und ein Case für die Elektronik, welche gleichzeitig, als Fußstütze dient.

RGBs im Gehäuse
Innen Seite des Gehäuse

In Kombination der einzelnen Komponenten ergibt sich die Wortuhr. Durch die technische Umsetzung ist es möglich, alle Anforderungen, die zuvor an das Projekt gestellt wurden zu erfüllen. Die Elektronik wird über eine externe Stromquelle betrieben und findet mit auf das Netzteil Platz im Gehäuse. Das Gehäuse wurde so designt, dass es möglich ist, die Zeit in Fünferschritten abzulesen. Außerdem wurde ein Arduino für das Projekt verwendet, welcher die RGBs anschaltet, wenn sich ein Objekt im Erkennungsbereich des Ultraschallsensors befindet.

Programmcode

Der Arduino Nano wurde in der Arduino IDE programmiert. Neben der Library für die Ansteuerung der RGBs wurde eine Library für die Ansteuerung des RTCs verwendet. In der Setup Funktion werden die RGBs initialisiert und überprüft, ob der Kontakt zu dem RTC besteht. Ebenso werden die Pins für den Ultraschallsensor als Output und Input definiert. In der Loop Funktion werden die Funktionen zur Bestimmung der Uhrzeit, sowie zur Ansteuerung der RGBs aufgerufen. Zudem wird die Funktion aufgerufen, die zur Abstandsmessung verwendet wird. Wenn sich kein Objekt in einem Bereich von kleiner 30 cm befindet, werden alle RGBs ausgeschaltet. Ist ein Objekt im Schwellenbereich, werden die RGBs angesteuert. Die eben kurz angesprochenen Funktionen werden im Folgende ausführlich erklärt.

Programmablaufplan
Hauptprogramm Wortuhr Erfassung der Distanz Anpassung der Uhrzeit RGB-Strip ansteuern

Code für das Programm:

//****************************************************************************//
 
//                               HSHL - BSE                                  *

//*****************************************************************************

//                                                                            *

// Modul           :  Angewandte Elektrotechnik                               *

//                                                                            *

// Hardware        : Arduino Nano                                             *

//                                                                            *

// Prüfer          : Prof. Schneider                                          *

//                                                                            *

//*****************************************************************************

 
#include <Adafruit_NeoPixel.h>
#include <avr/power.h>
#include "RTClib.h"

// Definieren der Pins
#define PIN            6
#define NUMPIXELS      58
#define PIN_TRIGGER 11
#define PIN_ECHO    12
// Alpha für Filterung
#define ALPHA 0.75

RTC_DS3231 rtc;
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

const int SENSOR_MAX_RANGE = 3000; // in cm
unsigned long duration;
unsigned int distance;


void setup () {
  Serial.begin(9600);
  pixels.begin();
#ifndef ESP8266
  while (!Serial);
#endif
  if (! rtc.begin()) { //ueberprufen der Verbindung zum RTC
    Serial.println("Couldn't find RTC");
    Serial.flush();
    abort();
  }
  Serial.println("Setting the time...");

  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  pinMode(PIN_TRIGGER, OUTPUT);
  pinMode(PIN_ECHO, INPUT);

}
void loop () {
  DateTime now = rtc.now(); // Echtzeit auslesen
  if (expoFilter(distanceMes()) <= 30)
  {
    stripStart();
    timeOnStripHour(conversionTimeHour(now.minute(), now.second()));
    timeOnStripMin (conversionTimeMinute());
    pixels.show();
    delay(10000); // 10 Sekunden werden die RGBs angeschaltet
  }
    for (int i = 0; i < NUMPIXELS; i++) { //Strip ausschalten
      pixels.setPixelColor(i, pixels.Color(0, 0, 0)); // Helligkeit auf 0%
      pixels.show();
    }
  }

Bei der Funktion distanceMes() wird die Distanz als Rückgabewert ausgegeben. Dabei wird ein Pin erst getiggert. Daraufhin wird ein Impuls gesendet. Wird das Ultraschallsignal wieder zurückerhalten, lässt sich die Distanz zu einem Objekt messen. Anschließend wartet der Sensor eine Sekunde. Der Rückgabewert bzw. die Distanz wird in der Funktion expoFilter() exponentiell gefiltert. Dafür wird über eine mathematische Funktion ein gefilterter Wert berechnet.

Distanzmessung

/////////////////////////////////////////////////////////////////////////////////
//                                                                             //
//                            Distanzmessung                                   //
//         Distanz wird berrechnet und als Rueckgabewert herausgegeben         //
//                                                                             //
/////////////////////////////////////////////////////////////////////////////////
 
 int distanceMes ()
  {
    unsigned int distance;

    digitalWrite(PIN_TRIGGER, LOW); // triggern
    delayMicroseconds(2);

    digitalWrite(PIN_TRIGGER, HIGH); // Impuls senden
    delayMicroseconds(10);

    duration = pulseIn(PIN_ECHO, HIGH); // Impuls empfangen
    distance = duration / 58; // Distanz berrechnen
    Serial.println(expoFilter(distance));

    delay(1000);
    return distance;
  }

/////////////////////////////////////////////////////////////////////////////////
//                                                                             //
//                               Filter                                        //
// Rohdaten werden expontentiell gefiltert und als Rueckgabewert herausgegeben //
//                                                                             //
/////////////////////////////////////////////////////////////////////////////////

  float expoFilter(int rawData)
  {
    float newValueFiltered;
    static float lastValueFiltered;

    newValueFiltered = ALPHA * rawData + (1 - ALPHA) * lastValueFiltered; // Formel zu Filterung
    lastValueFiltered = newValueFiltered;
    return newValueFiltered;
  }

In der Funktion stripStart() werden die ersten drei RGBs in der Farbe Weiß angesteuert und angeschaltet. Durch das Schalten der RGBs und deren Anordnung im Gehäuse erscheinen die Wörter Es ist. Diese Wörter sollen immer angeschaltet werden, wenn der Ultraschallsensor ein Objekt im Bereich von 30 cm detektiert.

Ansteuerung der ersten drei RGBs

/////////////////////////////////////////////////////////////////////////////////
//                                                                             //
//                     RGBs ansteuern für ES IST                               //
//               die ersten drei RGBs werden angesteuert                       //
//                                                                             //
/////////////////////////////////////////////////////////////////////////////////
 
 void stripStart () 
 {
   pixels.setPixelColor(0, pixels.Color(25, 25, 25)); // einstellen der Pixel (Pixel, RGB)
   pixels.setPixelColor(1, pixels.Color(25, 25, 25));
   pixels.setPixelColor(2, pixels.Color(25, 25, 25));
  }

Die folgenden Funktionen wandeln die Echtzeit um, damit die richtigen RGBs für die Funktionsweise der Wortuhr angesteuert werden. In der Funktion conversionTimeSecond() werden die Sekunden ab 30 Sekunden zu einer vollen Minute aufgerundet. Dadurch ist des möglich, dass in der Funktion conversionTimeMinute() die Minuten auf-oder abgerundet werden. Dies geschieht immer in Fünfer schritten, da das Gehäuse so konstruiert wurde, dass die Uhr die Minuten in einem Fünf-Minuten-Takt anzeigt. Mithilfe der Funktion conversionTimeHour() werden die Stunden verändert. Zum einen werden die Stunden so verändert, dass die Uhrzeit von einem 24 Stunden Modus in einen 12 Stunden Modus geändert wird. Zugleich hat die Funktion die Aufgabe, dass wenn die Minuten auf der Wortuhr größer 25 sind, die Stunden um eine Stunde erhöht werden (Bsp. 12:30 Uhr -> Es ist halb Drei).

Zeitanpassung

/////////////////////////////////////////////////////////////////////////////////
//                                                                             //
//                        Sekunden anpassen                                    //
//      Sekunden werden aus vollen Minuten gerundet mit Rueckgabewert          //
//                                                                             //
/////////////////////////////////////////////////////////////////////////////////

  float conversionTimeSecond() {

    int second;
    int secondRound;

    DateTime now = rtc.now(); // Echtzeit auslesen
    second = now.second(); // Echzeit (Sek werden ausgelesen)

    if (second <= 29) { // Runden der Sekunden auf volle Minuten
      secondRound = 0;
    }
    else {
      secondRound = 1;
    }

    return secondRound;
  }

/////////////////////////////////////////////////////////////////////////////////
//                                                                             //
//                       Minuten anpassen                                      //
//               Minuten werden gerundet mit Rueckgabewert                      //
//                                                                             //
/////////////////////////////////////////////////////////////////////////////////

  int conversionTimeMinute () { //Anpassen der Minuten in 5er Schritte


    int minute;
    int minuteRound;

    DateTime now = rtc.now(); // Echzeit auslesen
    minute = now.minute(); // Echzeit (Min werden ausgelesen)

    minuteRound = round((minute + conversionTimeSecond()) / 5) * 5; //Runden der Minuten in 5er Schritte

    if (minuteRound == 60) { //wenn Minuten 60 dann 0
      minuteRound = 0;

    }

    return minuteRound;
  }

/////////////////////////////////////////////////////////////////////////////////
//                                                                             //
//                          Stunden anpassen                                   //
//             Stunden werden für die Steuerung des RGB-Strip angepasst        //
//                          mit Rueckgabewert                                   //
//                                                                             //
/////////////////////////////////////////////////////////////////////////////////

  int conversionTimeHour (int min, int sec) { 

    int hour;
    int hourSmall;
    bool marker = false;

    DateTime now = rtc.now(); // Echzeit auslesen
    hour = now.hour(); // Echzeit (Stunden werden ausgelesen)
    hourSmall = now.hour();
    if (hour >= 13) { // Umrechnung der Stunden in 12-Stuendige-Zaehlung 
      hourSmall = hour - 12;
    }
    if (hour == 0) { // bei 0 Uhr = 12 Uhr
      hourSmall = 12;
    }
    /*
     * Stunden werden +1 gerechnet, wenn Min größer 00:22:30
     * damit Pixel passend angesteuert werden
     * Bsp. 14:40 Uhr
     * Es ist zwanzig vor DREI
     */
    if (min >= 22 && sec >= 30 || min >= 23)
    {
      marker = true;
    }
    if (min == 0)
    {
      marker = false;
    }
    if (marker == true)
    {
      hourSmall = hourSmall + 1;
    }
    return hourSmall;
  }

Die Funktionen timeOnStripHour() und timeOnStripMinute() sind dafür die zuständig in Abhängigkeit der manipulierten Minuten und Stunden die RGBs anzuschalten, die hinter der Oberfläche des Gehäuses geklebt wurden. Dadurch ist es möglich das die richtigen Wörter in Abhängigkeit der Zeit beleuchtet werden. Code zum Ansteuern der RGBs:

/////////////////////////////////////////////////////////////////////////////////
//                                                                             //
//                      RGBs ansteuern für Stunden                             //
//      je nach angegebender Stunde werden passende RGBs angesteuert           //
//                                                                             //
/////////////////////////////////////////////////////////////////////////////////

  void timeOnStripHour (int hour) {
    if (hour == 0 || hour == 12) { // wenn Stunde x dann Pixel anschalten
      pixels.setPixelColor(48, pixels.Color(25, 25, 25)); // einstellen der Pixel (Pixel, RGB)
      pixels.setPixelColor(49, pixels.Color(25, 25, 25));
      pixels.setPixelColor(50, pixels.Color(25, 25, 25));
      pixels.setPixelColor(51, pixels.Color(25, 25, 25));
    }
    if (hour == 1) {
      pixels.setPixelColor(33, pixels.Color(25, 25, 25));
      pixels.setPixelColor(34, pixels.Color(25, 25, 25));
    }
    if (hour == 2) {
      pixels.setPixelColor(31, pixels.Color(25, 25, 25));
      pixels.setPixelColor(32, pixels.Color(25, 25, 25));
    }
    if (hour == 3) {
      pixels.setPixelColor(35, pixels.Color(25, 25, 25));
      pixels.setPixelColor(36, pixels.Color(25, 25, 25));
    }
    if (hour == 4) {
      pixels.setPixelColor(37, pixels.Color(25, 25, 25));
      pixels.setPixelColor(38, pixels.Color(25, 25, 25));
    }
    if (hour == 5) {
      pixels.setPixelColor(29, pixels.Color(25, 25, 25));
      pixels.setPixelColor(30, pixels.Color(25, 25, 25));
    }
    if (hour == 6) {
      pixels.setPixelColor(41, pixels.Color(25, 25, 25));
      pixels.setPixelColor(42, pixels.Color(25, 25, 25));
      pixels.setPixelColor(43, pixels.Color(25, 25, 25));
    }
    if (hour == 7) {
      pixels.setPixelColor(44, pixels.Color(25, 25, 25));
      pixels.setPixelColor(45, pixels.Color(25, 25, 25));
      pixels.setPixelColor(46, pixels.Color(25, 25, 25));
      pixels.setPixelColor(47, pixels.Color(25, 25, 25));
    }
    if (hour == 8) {
      pixels.setPixelColor(39, pixels.Color(25, 25, 25));
      pixels.setPixelColor(40, pixels.Color(25, 25, 25));
    }
    if (hour == 9) {
      pixels.setPixelColor(54, pixels.Color(25, 25, 25));
      pixels.setPixelColor(55, pixels.Color(25, 25, 25));
    }
    if (hour == 10) {
      pixels.setPixelColor(56, pixels.Color(25, 25, 25));
      pixels.setPixelColor(57, pixels.Color(25, 25, 25));
    }
    if (hour == 11) {
      pixels.setPixelColor(28, pixels.Color(25, 25, 25));
    }
  }

/////////////////////////////////////////////////////////////////////////////////
//                                                                             //
//                     RGBs ansteuern für Minuten                              //
//      je nach angegebender Minuten werden passende RGBs angesteuert          //
//                                                                             //
/////////////////////////////////////////////////////////////////////////////////

  void timeOnStripMin (int Min) {
    if (Min == 0) { //Uhr
      pixels.setPixelColor(52, pixels.Color(25, 25, 25)); // einstellen der Pixel (Pixel, RGB)
      pixels.setPixelColor(53, pixels.Color(25, 25, 25));
    }
    if (Min == 5) { // fünf nach
      pixels.setPixelColor(3, pixels.Color(25, 25, 25));
      pixels.setPixelColor(4, pixels.Color(25, 25, 25));

      pixels.setPixelColor(20, pixels.Color(25, 25, 25));
      pixels.setPixelColor(21, pixels.Color(25, 25, 25));
    }
    if (Min == 10) {
      pixels.setPixelColor(11, pixels.Color(25, 25, 25));
      pixels.setPixelColor(12, pixels.Color(25, 25, 25));
      pixels.setPixelColor(13, pixels.Color(25, 25, 25));

      pixels.setPixelColor(20, pixels.Color(25, 25, 25));
      pixels.setPixelColor(21, pixels.Color(25, 25, 25));
    }
    if (Min == 15) {
      pixels.setPixelColor(14, pixels.Color(0, 25, 0));
      pixels.setPixelColor(15, pixels.Color(0, 25, 0));
      pixels.setPixelColor(16, pixels.Color(0, 25, 0));
      pixels.setPixelColor(17, pixels.Color(0, 25, 0));
      pixels.setPixelColor(18, pixels.Color(0, 25, 0));
      pixels.setPixelColor(19, pixels.Color(0, 25, 0));

      pixels.setPixelColor(20, pixels.Color(0, 25, 0));
      pixels.setPixelColor(21, pixels.Color(0, 25, 0));
    }
    if (Min == 20) {
      pixels.setPixelColor(5, pixels.Color(25, 25, 25));
      pixels.setPixelColor(6, pixels.Color(25, 25, 25));
      pixels.setPixelColor(7, pixels.Color(25, 25, 25));
      pixels.setPixelColor(8, pixels.Color(25, 25, 25));
      pixels.setPixelColor(9, pixels.Color(25, 25, 25));
      pixels.setPixelColor(10, pixels.Color(25, 25, 25));

      pixels.setPixelColor(20, pixels.Color(25, 25, 25));
      pixels.setPixelColor(21, pixels.Color(25, 25, 25));
    }
    if (Min == 25) {
      pixels.setPixelColor(3, pixels.Color(25, 25, 25));
      pixels.setPixelColor(4, pixels.Color(25, 25, 25));

      pixels.setPixelColor(24, pixels.Color(25, 25, 25));
      pixels.setPixelColor(25, pixels.Color(25, 25, 25));

      pixels.setPixelColor(26, pixels.Color(25, 25, 25));
      pixels.setPixelColor(27, pixels.Color(25, 25, 25));
    }
    if (Min == 30) {
      pixels.setPixelColor(26, pixels.Color(0, 25, 0));
      pixels.setPixelColor(27, pixels.Color(0, 25, 0));
    }
    if (Min == 35) {
      pixels.setPixelColor(3, pixels.Color(25, 25, 25));
      pixels.setPixelColor(4, pixels.Color(25, 25, 25));

      pixels.setPixelColor(20, pixels.Color(25, 25, 25));
      pixels.setPixelColor(21, pixels.Color(25, 25, 25));

      pixels.setPixelColor(26, pixels.Color(25, 25, 25));
      pixels.setPixelColor(27, pixels.Color(25, 25, 25));
    }
    if (Min == 40) {
      pixels.setPixelColor(5, pixels.Color(25, 25, 25));
      pixels.setPixelColor(6, pixels.Color(25, 25, 25));
      pixels.setPixelColor(7, pixels.Color(25, 25, 25));
      pixels.setPixelColor(8, pixels.Color(25, 25, 25));
      pixels.setPixelColor(9, pixels.Color(25, 25, 25));
      pixels.setPixelColor(10, pixels.Color(25, 25, 25));

      pixels.setPixelColor(24, pixels.Color(25, 25, 25));
      pixels.setPixelColor(25, pixels.Color(25, 25, 25));
    }
    if (Min == 45) {
      pixels.setPixelColor(14, pixels.Color(0, 25, 0));
      pixels.setPixelColor(15, pixels.Color(0, 25, 0));
      pixels.setPixelColor(16, pixels.Color(0, 25, 0));
      pixels.setPixelColor(17, pixels.Color(0, 25, 0));
      pixels.setPixelColor(18, pixels.Color(0, 25, 0));
      pixels.setPixelColor(19, pixels.Color(0, 25, 0));

      pixels.setPixelColor(24, pixels.Color(0, 25, 0));
      pixels.setPixelColor(25, pixels.Color(0, 25, 0));
    }
    if (Min == 50) {
      pixels.setPixelColor(11, pixels.Color(25, 25, 25));
      pixels.setPixelColor(12, pixels.Color(25, 25, 25));
      pixels.setPixelColor(12, pixels.Color(25, 25, 25));

      pixels.setPixelColor(24, pixels.Color(25, 25, 25));
      pixels.setPixelColor(25, pixels.Color(25, 25, 25));
    }
    if (Min == 55) {
      pixels.setPixelColor(3, pixels.Color(25, 25, 25));
      pixels.setPixelColor(4, pixels.Color(25, 25, 25));

      pixels.setPixelColor(24, pixels.Color(25, 25, 25));
      pixels.setPixelColor(25, pixels.Color(25, 25, 25));
    }
  }

Komponententest

Bevor die Wortuhr mit den gesamten Komponenten getestet wurde, wurden die Sensoren zuvor erst einzelne getestet, sodass mögliche Komplikationen am Anfang des Projektes, probiert wurden zu vermeiden. Zu Beginn wurde der Ultraschallsensor in seiner Funktionsweise getestet. Dafür wurde der Arduino programmiert und ein Programm geschrieben, welches es möglich macht, den Abstand zwischen dem Ultraschallsensor und einem Objekt zu messen. Dafür wurden die Messdaten jede 100 ms in dem Serial Monitor der Arduino IDE ausgegeben. Nach einer ersten Testung fiel auf, dass es unregelmäßig zu Ausreißern in den Messungen kam (s. Bild: Sensordaten). Zu erkennen ist, dass der Ultraschallsensor unregelmäßig eine zuvor eingestellte maximal Range erreicht. Daraufhin wurden die Messwerte über einen Exponentialfilter mit einem Alpha von 0,75 gefiltert. Eine erneute Testung ergab, dass die Ausreißer eliminiert wurden.

Sensordaten

In der zweiten Teiltestung wurde die Echzeit-Uhr getestet. Dafür wurde wieder ein Programm geschrieben, welches die Uhrzeit über den seriellen Monitor der Arduino IDE ausgibt. Dieser Test verlief ohne Probleme. Für die dritte Teiltestung wurde der RGB-Strip über den Arduino angesteuert. Hierbei wurden verschiedene RGBs in unterschiedlichen Farben angesteuert. Für den finalen Test wurden alle Komponenten an einem Arduino Uno angeschlossen (drei Spannungspins und drei Groundpins). Der Code wurde jeweils so angepasst, dass die Wortuhr die zuvor beschrieben Funktionen ausübt. Die Uhrzeit für den Versuch wurde manuell eingegeben, um die Testung zu beschleunigen. Das Ergebnis ergab, dass nachdem die Hand einen geringen Abstand, als 30 cm zum Ultraschallsensor hatte, die vorgesehenen RGBs angeschaltet wurden (s. Bild: Versuch der Komponenten). Zuvor wurde eine Tabelle erstellt, zu welchen Zeiten, welche RGBs leuchten sollte. Der letzte Versuch zeigt, dass die Anforderungen an das System erfolgreich getestet und erfüllt wurden. In Tabelle 3 ist zu sehen, mit welchem Versuch, die jeweilige Anforderung getestet wurde. Durch die Implementierung der Echtzeit-Uhr kann zu jedem gewünschten Zeitpunkt die Uhrzeit ermittelt werden. Dadurch ist es möglich, dass die RGBs in Echtzeit angesteuert werden können. Durch den Test mit dem Ultraschallsensor, ist es möglich sagen zu können, dass dieser sicher Distanzen zu anderen Objekten messen kann. Die Anforderung an die gesamte Wortuhr, dass die erst die Uhrzeit anzeigen soll, wenn ein Abstand durch ein Objekt von 30 cm unterschritten wird, ist hierdurch erfüllt. Zudem wurde durch die Testung des Ultraschallsensors es möglich gemacht, dass Ausreißer eliminiert wurden. Dies hat zudem den positiven Effekt, dass unerwünschte Schwellen Unterschreitungen die RGBs nicht ansteuern (Wasser vom Nachttisch kurz an der Wortuhr vorbeibewegen). Durch die Auswahl von RGBs ist es zudem möglich diese in den Farben zu ändern, wodurch die es möglich ist wichtige Uhrzeiten farblich hervorzuheben.

Versuch der Komponenten

Ergebnis

Tabelle 3: Anforderungstests technischer Komponenten
ID Anforderung Getestet durch Komponententest Anforderung erfüllt? Ersteller Datum Geprüft von Datum
1.0 Die Steuerung muss in Echtzeit erfolgen. DS3231 Ja Nico Kasprik 12.11.2022 Jonas Loddenkemper 12.11.2022
2.0 Die Anwesenheit einer Person wird über einen Ultraschallsensor geprüft (Schaltabstand ca. 30 cm). HC-SR 04 Ja Nico Kasprik 02.12.2022 Jonas Loddenkemper 02.12.2022
3.0 Uhrzeit soll nur angezeigt werden, wenn beabsichtigt (kleine Bewegungen sollen kein Auslösen hervorrufen). HC-SR 04 Ja Nico Kasprik 12.12.2022 Jonas Loddenkemper 12.12.2022
4.0 Zu besonderen Uhrzeit, soll ein Farbwechsel eingestellt werden. WS2812 Ja Nico Kasprik 16.12.2022 Jonas Loddenkemper 16.12.2022

Zusammenfassung

Zusammenfassung & Lessons Learned

Ein Prototyp der bewegungsaktivierten Wortuhr konnte erfolgreich gefertigt werden. Von Anfang an stellte sich heraus, dass die Teammitglieder gut zusammenarbeiten konnten und alle Absprachen funktionierten Reibungslos. Aufgrund verschiedener Erfahrungen im Bereich der Konstruktion bzw. Programmierung von Arduinos konnten die unterschiedlichen Aufgaben fair und effizient aufgeteilt werden. Bereits nach kurzer Zeit stand das Grundgerüst hinsichtlich Design und zu nutzenden Komponenten. Kleinere Komplikationen gab es zunächst bei der Konnektivität des Arduinos, welche allerdings in Rücksprache mit Herrn Professor Schneider und mithilfe von Herrn Ebmeyer gelöst werden konnten. Die für die LEDs benötigte Library war in Simulink leider nicht nutzbar, weshalb in Rücksprache mit Herrn Schneider auf die Arduino IDE zurückgegriffen wurde. Sowohl die RTC als auch der Ultraschallsensor inklusive Filterung ließen sich ebenfalls in der Arduino IDE programmieren, wodurch letztlich alle softwareseitigen Anforderungen erfüllt wurden. Der Aufbau des Prototyps hat sich als sehr zeitaufwendig herausgestellt, konnte aber ebenfalls problemlos ausgeführt werden. Während der ersten Inbetriebnahme fielen kleinere und größere Optimierungspotenziale auf. Kleinigkeiten, wie zum Beispiel die Nutzung zusätzlicher Diffusoren um das Licht besser zu streuen oder die Umpositionierung einzelner LEDs wurden direkt umgesetzt. Größere Optimierungspotenziale umfassen zum Beispiel die Anpassung der Konstruktion. Bei dem Bau einer weiteren Wortuhr wäre es zum Beispiel sinnvoll, die Materialstärke der Frontblende zu reduzieren. Dadurch kann eine noch bessere Lesbarkeit der Uhr erreicht werden.

Zusammenfassend wird auf ein erfolgreiches Projekt zurückgeblickt, welches mit einem voll funktionsfähigen Prototyp abgeschlossen wurde.

Projektunterlagen

Projektplan

Der Projektplan

Projektdurchführung

Tabelle 4: Darstellung des Lösungswegs
Schritt Aufgabe Lösung
1 Mögliche Projekte finden Brainstorming, verschiedene Ideen wurden gesammelt und auf Umsetzbarkeit/Interesse für Modul „Angewandte Elektrotechnik“ geprüft

• Automatisch schwenkbare Fernsehhalterung • Bewegungsaktivierte Wortuhr • Selbstfahrender Legoroboter • Laserhockey

2 Festlegung auf ein Projekt Projekt „Bewegungsaktivierte Wortuhr“ wurde aufgrund Komplexität, Anwendung verschiedener elektrotechnischer Komponenten, kompakter Abmaße und weiterer Nutzbarkeit im Privaten ausgewählt
3 Projektplan erstellen Projektplan wurde zuerst in Excel erstellt, aufgrund der geforderten Programme in Gantt finalisiert
4 Erster Entwurf Erstellung eines 3D-Modells zur Visualisierung/besseren Vorstellung
5 Auflisten der notwendigen Anforderungen/Bauteile Entscheidungen für LED-Strip, 3D-Druck, Ultraschallsensor, RTC (Real Time Clock) und deren Aufgaben wurden gefällt
6 Auswahl sinnvoller Komponenten Nach Recherche für ausreichend leistungsstarke, kompakte und gut zu modifizierende Komponenten und Materialen wurden LED-Strip „WS2812“, Ultraschallsensor „HC-SR04“, PLA (3D-Druck-Material), RTC „DS3231“, Arduino-Nano ausgewählt
7 Softwareplanung Programmablaufplan wurde erstellt
8 Programmierung Auswahl der passenden Library für den LED-Strip, Filterung des Ultraschallsensors, Programmierung der Zeitanzeige
9 3D-Druck 3D-Modell als .stl-Datei für 3D-Druck optimiert und vorbereitet, anschließend gedruckt
10 Zusammenbau • LED-Strip auf passende Länge zugeschnitten & verlötet

• Platine, Ultraschallsensor, RTC verlötet • Diffusor zugeschnitten und in Gehäuse geklebt • LED-Strip verklebt

11 Testlauf • Verschiedene Uhrzeiten angesteuert, überprüft ob die korrekten LEDs leuchten

• Funktion des Ultraschallsensors geprüft • Lesbarkeit der Uhrzeit überprüft

12 Optimierung nach Testlauf • Weitere Diffusoren eingeklebt

• Position einzelner LEDs angepasst

13 Videodreh Video zur Veranschaulichung der Funktionsweise gedreht
14 Vorbereitung Messestand Infos gesammelt, Plakat gestaltet und in Druck gegeben


YouTube Video

Video der bewegungsaktivierten Wortuhr

Literatur


→ zurück zur Übersicht: Kategorie:ProjekteET MTR BSE WS2022

  1. Hagemann, Florian, Zäh, Michael, 1963-: Wirtschaftliche Fertigung mit Rapid-Technologien : Anwender-Leitfaden zur Auswahl geeigneter Verfahren. Hanser, München 2006, ISBN 3-446-22854-3
  2. https://www.3dnatives.com/de/feature-story-3d-druck-material-pla-nachhaltig-230720191/#!
  3. https://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC
  4. Datenblatt DS321: https://www.analog.com/media/en/technical-documentation/data-sheets/DS3231.pdf
  5. Datenblatt HC-SR 04: https://cdn.sparkfun.com/datasheets/Sensors/Proximity/HCSR04.pdf
  6. Datenblatt WS2812: https://cdn-shop.adafruit.com/datasheets/WS2812B.pdf