Entwicklung einer bewegungsaktivierten Wortuhr

Aus HSHL Mechatronik
Zur Navigation springen Zur Suche springen

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


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 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.

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

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


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

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 (s. Datenblatt). Dies geschieht über einen I2C-Bus. 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. 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. 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. 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. 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.

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.

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;
  }

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. Nach einer ersten Testung fiel auf, dass es unregelmäßig zu Ausreißern in den Messungen kam. Daraufhin wurden die Messwerte über einen Exponentialfilter mit einem Alpha von 0,75 gefiltert. Eine erneute Testung ergab, dass die Ausreißer eliminiert wurden. 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 (siehe Bild). 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.

Ergebnis

Tabelle 2: 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

Lessons Learned

Projektunterlagen

Projektplan

Projektdurchführung

YouTube Video

Weblinks

Literatur


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