Halbsmartes Bad-Modul: Unterschied zwischen den Versionen

Aus HSHL Mechatronik
Zur Navigation springen Zur Suche springen
 
(72 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 3: Zeile 3:
<!--  -->
<!--  -->
'''Autoren: [[Benutzer: Lukas-Erich Mücke|Lukas Mücke]] & [[Benutzer: Dominik Sumkötter|Dominik Sumkötter]]''' <br/>
'''Autoren: [[Benutzer: Lukas-Erich Mücke|Lukas Mücke]] & [[Benutzer: Dominik Sumkötter|Dominik Sumkötter]]''' <br/>
'''Betreuer: [[Benutzer:Mirekgoebel | Prof. Dr.-Ing. Mirek Göbel]] & [[Benutzer:Ulrich_Schneider | Prof. Dr.-Ing. Ulrich Schneider]]''' <br/>
'''Betreuer: [[Benutzer:Ulrich_Schneider | Prof. Dr.-Ing. Ulrich Schneider]]''' <br/>




→ zurück zur Übersicht: [[:Kategorie:ProjekteET_MTR_BSE_WS2021|WS 21/22: Angewandte Elektrotechnik]]
→ zurück zur Übersicht: [[:Kategorie:ProjekteET_MTR_BSE_WS2021|WS 21/22: Angewandte Elektrotechnik]]
[[Datei:Logo.jpg|thumb|rechts|Abb.1: Das Halbsmarte Bad-Modul]]




== Einleitung ==
== Einleitung ==
Unser Ziel ist es ein multifunktionales System zu entwickeln, dass allerlei Features rund ums Bett bietet. Dabei darf es gerade im Bezug auf eine Weckfunktion auch mal unangenehm und "böse" werden. Der Name soll daher auf einerseits auf den Einsatzbereich "Bett" und andereseits auf die unangenehmen Weckeigenschaften hindeuten.
Dieses Projekt wurde im Rahmen des Elektrotechnik-Paktikums (5.Semester Mechatronik) entwickelt. Unser Ziel ist es ein multifunktionales System zu entwickeln, dass allerlei Features rund ums Bett bietet. Dabei darf es gerade im Bezug auf eine Weckfunktion auch mal unangenehm und "böse" werden. Der Name soll daher auf einerseits auf den Einsatzbereich "Bett" und andererseits auf die unangenehmen Weckeigenschaften hindeuten.
Darüber hinaus soll das System aber auch eine freundliche Seite haben und in gedämpften Licht den Bodenbereich ausleuchten, sobald nachts Bewegung detektiert wird.
Darüber hinaus soll das System aber auch eine freundliche Seite haben und in gedämpften Licht den Bodenbereich ausleuchten, sobald nachts Bewegung detektiert wird.


== Anforderungen ==
== Die wesentlichen Features ==
Folgende Aufgaben soll es bewältigen:  
Folgende Aufgaben soll das Modul bewältigen:
# Licht im Fußbereich einschalten
* Licht soll nur ab einer bestimmten Dunkelheit angehen
* Licht soll bei dunklem Zimmer, gedämpft und bei relativ hellen Zimmer hell leuchten


1. Licht im Fußbereich einschalten
* Licht soll nur ab einer bestimmten Dunkelheit angehen.
* Licht soll bei dunkler Umgebung gedämpft und bei relativ heller Umgebung heller leuchten.


# Wecken in verschiedenen Stufen
 
2. Wecken in verschiedenen Stufen
* Licht wird langsam heller, Licht blinkt, Farben wechseln von Blau nach Rot
* Licht wird langsam heller, Licht blinkt, Farben wechseln von Blau nach Rot
* Ton wird dazu geschaltet, Lautstärke steigt
* Ton wird dazu geschaltet, Lautstärke steigt
* Wecker soll deaktiviert werden, wenn es im Zimmer hell ist (Person ist schon aufgestanden), oder über einen Taster. Eventuell über einen Bewegungsmelder
* Wecker soll über einen Taster deaktiviert werden.
* Eventuell Sleep-Funktion
 
==Anforderungen==
 
 
{| class="mw-datatable"
! style="font-weight: bold;" | ID
! style="font-weight: bold;" | Anforderung
 
|+ style = "text-align: left"|Tabelle: Anforderungen an das halbsmarte Bad-Modul
|-
| '''1''' || '''Design'''
|-
| 1.1 || Das Modul muss kompakt sein, um gut unter jedes Bett zu passen.
|-
| 1.2 || Es muss möglichst einfach zu montieren sein.
|-
| 1.3 || Die Bauelemente (Arduino, Sensoren usw.) sollen vor z.B. Fußtritten geschützt sein.
|-
| 1.4 || Das Modul darf beim Aufstehen nicht im Weg sein.
|-
| '''2''' || '''Funktionen'''
|-
| 2.1 || Fußbodenbeleuchtung: Das System registriert Bewegungen vor dem Bett und schaltet das Licht ein, wenn die Umgebung dunkel genug ist. Das Licht soll automatisch erlöschen, wenn längere Zeit keine Bewegung vor dem Sensor erfolgt.
|-
| 2.2 || Automatische Dimmung : Das System wählt eine unterschiedliche Lichtintensität, je nachdem wie dunkel es ist, um in völliger Dunkelheit nicht zu blenden und bei gedämpftem Licht trotzdem für bessere Sicht zu sorgen.
|-
| 2.3 || Wecksystem: Das Modul soll erst sanfte Weckversuche über optische Reize (heller werdendes Licht, blinken) starten und über die Zeit intensiver, und über auditive und optische Signale Wecken.
|-
| '''3''' || '''Bedienung'''
|-
| 3.1 || Die Weckzeit soll direkt am Modul eingestellt und abgelesen werden können.  
|-
| 3.2 || Die Bedienung soll möglichst intuitiv und unkompliziert sein.
|}


== Funktionaler Systementwurf/Technischer Systementwurf ==
== Funktionaler Systementwurf/Technischer Systementwurf ==
Wir haben uns gegen eine Sleep-Funktion entschieden, weil diese dem Konzept des "Bad" Moduls nicht gerecht wird. Schließlich soll es zuverlässig wecken und nicht ermöglichen lange im Bett zu bleiben. Gegen dieses Prinzip spricht auch ein Ausschalten des Weckers per Bewegungsmelder. Ein Abschalten des Weckers bei zu hoher Umgebungshelligkeit (Person bereits wach, oder aufgestanden) wurde weggelassen, da das Leuchten des Moduls selbst ein Abschalten verursachen könnte.
Weiter wäre denkbar gewesen eine geschlossene Box für den Wecker herzustellen, die dann frei im Raum zu positionieren ist. Das hätte zum Vorteil gehabt, dass alle Kabel sicher im Gehäuse untergebracht wären. Eine Bodenbeleuchtung per Bewegungsmelder macht aber nur Sinn, wenn das Modul unter dem Bett angebracht wird und den Boden vor dem Bett beleuchtet und dort Bewegungen erfasst. Zur einfachen Unterbringung wurde dann entschieden, dass Modell so zu designen, wie es im CAD-Modell zu sehen ist.


<gallery widths="600" heights="300" perrow="2">
Bad-Modul_Systementwurf.jpg|Abb.2: Systementwurf des Bad-Modul
Halbsmartes-Bad-Modul.png|Abb.3: PAP des Bad-Modul
</gallery>


<!-- Füllen Sie Ihre Projektskizze bis hierher aus. Fügen Sie einen Projektplan unten ein.  -->
<!-- Füllen Sie Ihre Projektskizze bis hierher aus. Fügen Sie einen Projektplan unten ein.  -->
[[Datei:Bad-Modul-pap|links|mini|PAP des Bad-Modul]]


== Komponentenspezifikation ==
== Komponentenspezifikation ==
Vorläufige Komponentenlist:
[[Datei:Bad-Modul Kosten.jpeg|thumb|rechts|Tab.1: Kostenkalkulation und Auswahl der Komponenten für das Halbsmarte Bad-Modul]]
# Bewegungsmelder: HC-SR501
 
# Piezo-Speaker
Komponentenliste:
# Passiver IR-Bewegungsmelder: HC-SR501
# Passiver Lautsprecher
# Passiver Lautsprecher
# LED-Taster
# Kurzhubtaster 12x12x6mm
# LED-Ring: WS2812 (als Schauobjekt, in der Praxis eventuell 10m-Leuchtband)
# LED-Ring: WS2812 (als Schauobjekt, in der Praxis eventuell 10m-Leuchtband)
# Fotowidertand
# Fotowiderstand
# DS1307 I2C RTC Modul (Uhrzeitmodul)
# DS1307 I2C RTC Modul (Uhrzeitmodul)
# Breadboard (830 Kontakte)
# Gehäuse Arduino Uno R3 (transparent)
Die Komponenten wurden so gewählt, dass sie a) auch nach dem Projekt noch nützlich sind und b) eine kostengünstige Umsetzung erlauben. Ein RGB-Leuchtband anstatt des LED-Rings wäre eindrucksvoll, aber auch teuer gewesen und nachher nicht mehr genutzt worden. Daher haben wir uns für den LED-Ring entschieden, der das Potential des Moduls ausreichend darstellt. Eine ähnliche Entscheidung wurde bezüglich der Taster getroffen. Es gibt beleuchtete und vandalismusgeschützte Taster, die das Modul optisch aufgewertet hätten, diese sind aber auch vergleichsweise kostenintensiv. Das Breadboard, dass natürlich viel zu lang für die Anwendung ist, wurde gewählt, da gleichwertige Boards in halber Größe im bevorzugten Shop nicht lieferbar waren. Auf ein spanendes Kürzen wurde verzichtet, da das Board auch nach dem Projekt noch anderweitig genutzt werden soll.


== Umsetzung (HW/SW) ==
== Umsetzung (HW/SW) ==
=== Hardware ===
Das Bad-Modul soll unkompliziert am Bett angebracht werden können. Hierfür wurde eine T-förmige Halterung mithilfe von Solidworks erstellt und per 3D-Druck realisiert.
Bei der Konstruktion wurde das Prinzip "Form follows Function" angewandt, damit das Modul nachher auch Problemlos anwendbar ist. Die Form des Moduls ist somit speziell auf die von uns ausgewählten Bauteile ausgelegt. Durch diese Konstruktionsmethodik gestaltete sich die Anbringung der Bauteile sehr einfach und es musste wenig nachgebessert werden am Modul.
[[Datei:Screenshot Bad-Modul.jpg|thumb|rechts|Abb.4: CAD-Modell des Halbsmarten Bad-Moduls]]
Nach erfolgreichen Test der Komponenten und fertigem Aufbau der Schaltung auf dem Breadboard, wurden die einzelnen Bauelementen an der Halterung befestigt.
Ursprünglich war geplant vandalismusgeschützte Schalter zu verwenden; diese Idee wurde aus Kostengründen verworfen.
=== Software ===
Zur Ansteuerung der Komponenten wurden folgende Bibliotheken genutzt:
*Wire von Arduino
*Adafruit_NeoPixel von "Phil "Paint Your Dragon" Burgess" (für Adafruit Industries)
*Time von Paul Stoffregen
*DS1307RTC von Paul Stoffregen
*LiquidCrystal I2C von Marco Schwartz
Grundsätzlich werden in einer Endlosschleife die verschiedenen Eingänge eingelesen:
* Taster A und B
* Bewegungsmelder
* Spannungsabfall am Photowiderstand
und über I2C die aktuelle Uhrzeit vom RTC-Modul eingelesen.
Anschließend wird passend zu den eingelesenen Werten, in verschiedenen if-Abfragen entschieden, welche Funktion aktiviert wird.
Ist es zum Beispiel dunkel (geringer Wert am Photowiderstand) und der Bewegungsmelder reagiert, wird die Bodenbeleuchtung aktiviert. Die Helligkeit ergibt sich aus folgender Formel:
:<math> LHmax = 7.184 \cdot e^{0.01\cdot UH} </math>
Mit der maximalen Helligkeit <i> LHmax </i> und der aus der Spannung am Photowiderstand errrechnete Wert <i> UH </i> für die Helligkeit der Umgebung.
Und aus dieser Formel ergibt sich, um welchen Betrag sich die Helligkeit erhöhen soll:
:<math> Step = LHmax \cdot \left( \frac{DimPause}{DimTime} \right) </math>
<i> Step </i> ist Schrittgröße mit der das Licht heller wird. <i> DimTime </i>, die Zeit, bis das Licht die maximale Helligkeit haben soll und <i> DimPause </i> die Zeit zwischen den Dimmschritten.
Nach definierter Zeit geht das Licht wieder aus, außer es wird weiter eine Bewegung detektiert. Falls das Licht in unter fünf Sekunden ausgehen würde, werden dann weitere fünf Sekunden bis zum Abschalten des Lichts addiert.
Das Licht wird dann in gleicher Schrittweite runtergedimmt.
Wenn die Uhrzeit mit der eingestellten Weckzeit übereinstimmt, werden Weckmaßnahmen in fünf verschiedenen Intensitäten aktiviert:
# Langsames aufdimmen des Lichts (weißes Licht)
# Langsam blinkendes Licht (weißes Licht)
# Langsam blinkendes Licht und Signalton (weißes Licht)
# Langsam blinkendes Licht und Signalton (rotes Licht)
# Schnell wechselndes Licht in verschiedenen Farben und Signalton
Die einzelnen "Stages" werden auf dem LCD-Display ausgegeben.
Wenn der Wecker nach einer gewissen Weckdauer nicht deaktiviert wurde, geht er von selbst aus. Dies soll verhindern, dass der Wecker ewig weiter weckt, auch wenn zum Beispiel niemand zu Hause ist.
Mit den Tastern kann der Wecker aktiviert, bzw. deaktiviert werden und die Weckzeit eingestellt werden.
Beim Einstellen der Weckzeit, wird erfasst, wie lange der Knopf gedrückt wird. Bei einmaliger Betätigung wird die Weckzeit um eine Minute erhöht. Bei längerer Betätigung um 10 Minuten und schließlich um 60 Minuten.
== Programmcode ==
<div style="width:1000px; height:600px; overflow:scroll; border: hidden">
<pre>
// // // // // // // // // // // // // // // // // // // // //
// Projekt: Halbsmartes Bad-Modul                          //
// Elektortechnik Fachpraktikum: Hochschule Hamm-Lippstadt  //
// Autoren: Dominik Sumkötter und Lukas Mücke              //
// Letze Änderung: 10.01.2021                              //
// // // // // // // // // // // // // // // // // // // // //
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);  //Initialisierung LCD
#define NPIXELS 12      // Pixel 0 - ...
#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NPIXELS, 10, NEO_GRB + NEO_KHZ800); //Anzahl Pixel, Port Nr, Settings
#ifdef __AVR__
#include <avr/power.h>
#endif
#include <Time.h>
#include <DS1307RTC.h>
#define POWERMAX 150
#define ButtonA 2    //Ports definieren
#define ButtonB 4
#define BewegungsM 7
#define PhotoR A0
#define Speaker 13
#define DimTime 1000    //Wie lange soll es dauern, bis der Dimmer volle Helligkeit erreicht
#define DimPause 50    //Wie lange sind die Intervalle in denen gedimmt werden soll
bool  AlarmOn = 0;      //Wecker standardmäßig aus
bool  Bewegung = 0;    //Bewegungsmelder
int  AlarmMinute = 0;
int  AlarmHour = 12;
short Power = 0;
bool  Sound = false;
void setup() {
  pinMode(ButtonA, INPUT);
  pinMode(ButtonB, INPUT);
  pinMode(BewegungsM, INPUT);
  pinMode(PhotoR, INPUT);
  lcd.init();  //Initialisieren LCD
  lcd.backlight();  //LCD Backlight standardmäßig an
  pixels.begin();  //Initialisieren Neo-Pixel Ring
  Serial.begin(9600); //Initialisieren Übertragung an Seriellen Monitor
}
void loop()
{
  bool A = digitalRead(ButtonA);                //ButtonB gedrückt?
  bool B = digitalRead(ButtonB);                //ButtonB gedrückt?
  bool Bewegung = digitalRead(BewegungsM);      //Bewegung detektiert?
  int  Helligkeit = analogRead(PhotoR);        //Auslesen Spannung am Photowiderstand
  Serial.print("Bewegung ");                    //Debugging für Bewegungsmelder
  Serial.println(Bewegung);
  Serial.print("PhotoR ");                      //Debugging für Photowiderstand
  Serial.println(Helligkeit);
  noTone(Speaker);                              //Speaker standardmäßig aus
  tmElements_t tm;                              //Variable für Uhrzeitspeicher anlegen
  RTC.read(tm);                                //Uhrzeit auslesen
  int Hour = tm.Hour;                          //Übertragen der Uhrzeit in int Format
  int Minute = tm.Minute;
  lcd.setCursor(0, 0);                          //Standardmäßig Uhrzeit ausgeben
  lcdprinttime(Hour, Minute);
  if (Minute == AlarmMinute && Hour == AlarmHour && AlarmOn)      //Wecken, wenn Alarm an und AlarmZeit = Uhrzeit
  {
    double start = millis();                                      //Wann wurde der Wecker gestartet?
    bool quit = false;
    short stage = 0;                              //Starten mit Stage 0
    while (quit == false)                        //Wecken bis Abbruch
    {
      Serial.println( ( (start + 10000) - millis() ));      //Debugging: "Wie lange ist die Stage noch aktiv?"
      if ((start + 10000) < millis() )            //Nächste Stage, nach 10 Sekunden (Als Demo-Modus; in der Praxis natürlich länger)
      {
        stage = (stage < 4) ? stage + 1 : 4;
        Power = 0;
        start += 10000;
      }
      WakeUp(stage);          //Weckprogramm für die aktuelle Stage starten
      quit = digitalRead(ButtonB);      //Wecken mit Taste B abbrechen?
      if ((start + 120000) < millis())    //Wenn der Wecker seit 2 Minuten weckt, ist anzunehmen dass keiner da ist -> Abbruch
      {
        quit = true;
      }
      delay(50);
    }
    AlarmOn = 0;          //Wenn Wecken abgebrochen -> Wecker aus
    for (int i = 0; i < NPIXELS; i++)      //LED aus
    {
      pixels.setPixelColor(i, pixels.Color(0, 0, 0));
      pixels.show();
    }
  }
  if (A && !B)  //Taster A gedrückt? Wecker An, oder Aus
  {
    lcd.backlight();
    lcd.setCursor(0, 0);
    if (!AlarmOn)
    {
      lcd.clear();
      lcd.print("Wecker EIN: ");
      lcd.setCursor(0, 1);
      lcdprinttime(AlarmHour, AlarmMinute);
      delay(1000);
      lcd.clear();
      AlarmOn = 1;
    }
    else
    {
      lcd.clear();
      lcd.print("Wecker AUS");
      delay(1000);
      lcd.clear();
      AlarmOn = 0;
    }
  }
  if (B && !A)      //Taste B gedrückt? Weckzeit einstellen
  {
    lcd.clear();
    int start = millis();    //Seit wann ist die Taste gedrückt?
    int increment = 1;        //Standartinkrement
    lcd.setCursor(0, 0);      //Weckzeit ausgeben
    lcd.print("Weckzeit: ");
    lcd.setCursor(0, 1);
    lcdprinttime(AlarmHour, AlarmMinute);
    while (B)
    {
      int pressdur = millis() - start;
      if (3000 < pressdur && pressdur < 8000) {    //Inkrement erhöhen, wenn Taste länger als 3s gedrückt
        increment = 10;
      }
      else if (pressdur > 8000) {                //Stundenweise weiter, wenn seit 8s gedrückt
        increment = 60;
      }
     
      B = digitalRead(ButtonB);    //Wird B noch gedrückt?
     
      if(!B);
      {
      AlarmMinute += increment;
      }
     
      if (AlarmMinute >= 60)      //61 Minuten machen keinen Sinn. Daher Stunde +1
      {
        AlarmMinute = 0;
        AlarmHour += 1;
      }
      AlarmHour = (AlarmHour >= 24) ? 0 : AlarmHour; // Wir wollen auch keine 25 Stunden...
      lcd.setCursor(0, 0); //Neue Weckzeit angeben
      lcd.print("Weckzeit: ");
      lcd.setCursor(0, 1);
      lcdprinttime(AlarmHour, AlarmMinute);
      delay(750);
      B = digitalRead(ButtonB);
      lcd.clear();
    }
  }
  if (Bewegung && Helligkeit < 140) // 375  //Wenn die Helligkeit größer als 140 und der Bewegungsmelder Bewegung registriert -> Boden beleuchten! Für Präsentation auf 140 gesetzt. Sonst ca. 375, aber Ortsabhängig
  {
    Dimmer(Helligkeit);    //Helligkeit wird übergeben
  }
} //Programm Ende
void WakeUp(int Stage)  //Weckfunktion
{
  lcd.clear();
  switch (Stage)      //in welcher Stage sind wir?
  {
    case 0:
      lcd.clear();        //LCD Ausgabe der Stage und dezenter Handlungshinweis
      lcd.setCursor(0, 0);
      lcd.print("Aufstehen!");
      lcd.setCursor(0, 1);
      lcd.print("Stage 1");
      Power = (Power < POWERMAX) ? Power + 1 : Power;      //Powermax wurde für Präsentation auf 150 gedrosselt (max. 255), Jeden Durchlauf etwas heller!
      for (int i = 0; i < NPIXELS; i++)     
      {
        pixels.setPixelColor(i, pixels.Color(Power, Power, Power));
        pixels.show();
      }
      delay(300);
      break;
    case 1:
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Aufstehen!");
      lcd.setCursor(0, 1);
      lcd.print("Stage 2");
      Power = (Power == 0) ? POWERMAX : 0;      //Maximale Power und blinken
      for (int i = 0; i < NPIXELS; i++)
      {
        pixels.setPixelColor(i, pixels.Color(Power, Power, Power));
        pixels.show();
      }
      delay(500);
      break;
    case 2:
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Aufstehen!");
      lcd.setCursor(0, 1);
      lcd.print("Stage 3");
      Power = (Power == 0) ? POWERMAX : 0;
      Sound = !Sound;    //Jetzt gibt es noch Ton dabei!
      if (Sound)        //Kein durchgängier Ton, sondern Intervalle
      {
        tone(Speaker, 500);
      }
      else
      {
        noTone(Speaker);
      }
      for (int i = 0; i < NPIXELS; i++)
      {
        pixels.setPixelColor(i, pixels.Color(Power, Power, Power));
        pixels.show();
      }
      delay(500);
      break;
    //Blinken und Ton
    case 3:
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Aufstehen!");
      lcd.setCursor(0, 1);
      lcd.print("Stage 4");
      Power = (Power == 0) ? POWERMAX : 0;
      Sound = !Sound;
      if (Sound)
      {
        tone(Speaker, 500);
      }
      else
      {
        noTone(Speaker);
      }
      for (int i = 0; i < NPIXELS; i++)
      {
        pixels.setPixelColor(i, pixels.Color(Power, 0, 0));    //Diesmal rot blinken
        pixels.show();
      }
      delay(500);
      break;
    case 4:
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Aufstehen!");
      lcd.setCursor(0, 1);
      lcd.print("Stage 5");
      Power = POWERMAX;
      Sound = !Sound;
      if (Sound)
      {
        tone(Speaker, 500);
      }
      else
      {
        noTone(Speaker);
      }
        for (int i = 0; i < NPIXELS; i++)
        {
          pixels.setPixelColor( i, pixels.Color( random(0, POWERMAX), random(0, POWERMAX), random(0, POWERMAX) ) );        //Power wird auf einen Wert zwischen 0 und 150 gesetzt aber zufällig, damit es nervig blinkt
          pixels.show();
        }
        delay(300);
        break;
  }
} //Weckfunktion Ende
void Dimmer(int UH) //Bodenbeleuchtung
{
  double LHmax = 7.742*pow(2.17828,(0.01*UH)); // Helligkeitsmaximum berechnen
 
  LHmax = (LHmax > 255) ? 255 : LHmax;  //Wenn größer 255, LHmax  = 255, sonst nichts.
  LHmax = (LHmax < 1) ? 1 : LHmax;      //Wenn negativ, oder kleiner 1, dann 1
  double PWMout = 0;                        //Variablen anlegen
  double Step = LHmax / (DimTime / DimPause);  //Schrittgröße für das Dimmen anlegen
  while (PWMout < LHmax)                  //Aufhellen der LED bis maximum erreicht
  {
    PWMout += Step;
    PWMout = (PWMout >= POWERMAX) ? POWERMAX : PWMout;  //Wenn größer 255, PWMout  = 255, sonst nichts.; hier auf 150 begrenzt für Präsentation
    for (int i = 0; i < NPIXELS; i++)
    {
      pixels.setPixelColor( i, pixels.Color( PWMout, PWMout, PWMout ) );
      pixels.show();
    }
    delay(50);
  }
  Serial.print("Check PWMout: ");            //PWMout ausgeben
  Serial.println(PWMout);
  double timenow = millis();
  double stoptime = timenow + 5000;
  while (timenow < stoptime)
  {
    Bewegung = digitalRead(BewegungsM);
    timenow = millis();
    if (Bewegung && stoptime - timenow < 5000)
    {
      stoptime += 5000;
    }
    Serial.print("Bewegung: ");
    Serial.println(Bewegung);
    Serial.print("Noch an: ");
    Serial.println(stoptime - timenow);
    delay(50);
  }
  while (PWMout > 0)                        //Abdunkeln der LED bis aus
  {
    PWMout -= Step;
    PWMout = (PWMout < 0) ? 0 : PWMout;
    for (int i = 0; i < NPIXELS; i++)
    {
      pixels.setPixelColor( i, pixels.Color( PWMout, PWMout, PWMout ) );
      pixels.show();
    }
    delay(50);
  }
  pixels.clear();
} //BodenbeleuchtungEnde
void lcdprinttime(int Hour, int Minute) //Zeitausgabe mit führender Null
{
  if (Hour < 10)
  {
    lcd.print("0");
    lcd.print(Hour);
  }
  else lcd.print(Hour);
  lcd.print(":");
  if (Minute < 10)
  {
    lcd.print("0");
    lcd.print(Minute);
  }
  else lcd.print(Minute);
}  //Zeitausgabe mit führender Null
</pre>
</div>
<br clear = all>


== Komponententest ==
== Komponententest ==
Es wurde für jede Komponente ein Testprogramm geschrieben, um die für das fertige Bad-Module notwendigen Funktionen zu testen. Anschließenden wurden die Komponenten an den Arduino angeschlossen und die Programme optimiert.
Anschließend wurden immer mehr Module zusammen angeschlossen und der finale Code um die entsprechenden Funktionen ergänzt, bis das gesamte Modul betriebsbereit war.


== Ergebnis ==
== Ergebnis ==
Das Bad-Modul ist funktionsbereit und enthält alle Funktionen, die auf jeden Fall eingebracht werden sollten.
<gallery widths="600" heights="300" perrow="2">
Bad-Modul Front mini.jpg|Abb.5: Vorderseite des Halbsmarten Bad-Moduls
Bad-Modul Back mini.jpg|Abb.6: Rückseite des Halbsmarten Bad-Moduls
</gallery>


== Zusammenfassung ==
== Zusammenfassung ==
=== Lessons Learned ===
=== Lessons Learned ===
Es wurden folgende Kenntnisse und Fähigkeiten vertieft, bzw. erlernt:
* Planung und Entwurf eines Projektes
* Projektmanagement
* Aufbau einer Schaltung
* Erstellen eines CAD-Modells für den 3D-Druck
* Programmierung eines Mikrocontrollers
Für einen weiteres Projekt sollte bereits zu Beginn stärker über das optische Erscheinungsbild des Endprodukts nachgedacht werden, gerade in Hinblick auf die Kabelführung hat sich zum Ende des Projekts keine vollständige Zufriedenheit eingestellt, während andere Mängel (zu langes Breadboard, Taster) durch ein höheres Budget einfach auszubessern wären.


== Projektunterlagen ==
== Projektunterlagen ==
=== Projektplan ===
=== Projektplan ===
[[Datei:Gantt-Chart_Bad-Modul.jpg|thumb|rechts|Abb.6: Gantt-Chart]]
Das Gantt-Chart wurde mithilfe von Libre Calc realisiert, da keine Office-Software sich in unserem Besitz befindet.
Die geplante Zeiteinteilung aus dem Gantt-Chart wurde nur leicht durch die etwas späte Freigabe des Projektes belastet.
Dennoch konnte das Projekt ohne zeitliche Komplikationen umgesetzt werden.
=== Projektdurchführung ===
=== Projektdurchführung ===
Das Projekt des Halbsmarten Bad-Moduls startete mit der Ideenfindung und anschließender Anfertigung der Liste mit den benötigten Teilen.
Nach einer Kostenkalkulation und ersten Zeichnung, wurde die Auswahl der Teile präzisiert, welche konkreten Bauteile bestellt und im Bad-Modul verbaut werden.
Nach Lieferung der Teile, wurden Programme für die einzelnen Module geschrieben, um die Funktion zu überprüfen und sich mit der Programmierung und Möglichkeiten, sowie Limitierungen vertraut zu machen.
Anschließend wurden die einzelnen Elemente zum gewünschten System zusammengeführt.
Um dieses System auch anwendbar zu gestalten wurde eine Halterung entwickelt, sodass alle Elemente Funktionsgerecht im Modul integriert werden konnten.
Schlussendlich wurden die Elemente am der Halterung zum vollständigen Modul zusammengeführt und das Modul wurde finalen Tests unterzogen um die Funktionen nochmals sicher zu stellen.


== YouTube Video ==
== YouTube Video ==
Hier können die Funktionen des Moduls angesehen werden:
{{#ev:youtube|https://youtu.be/BZxESY3_REA| 600 | |}}
[https://youtu.be/BZxESY3_REA]


== Weblinks ==
== Weblinks ==

Aktuelle Version vom 16. Februar 2022, 10:28 Uhr

Autoren: Lukas Mücke & Dominik Sumkötter
Betreuer: Prof. Dr.-Ing. Ulrich Schneider


→ zurück zur Übersicht: WS 21/22: Angewandte Elektrotechnik

Abb.1: Das Halbsmarte Bad-Modul


Einleitung

Dieses Projekt wurde im Rahmen des Elektrotechnik-Paktikums (5.Semester Mechatronik) entwickelt. Unser Ziel ist es ein multifunktionales System zu entwickeln, dass allerlei Features rund ums Bett bietet. Dabei darf es gerade im Bezug auf eine Weckfunktion auch mal unangenehm und "böse" werden. Der Name soll daher auf einerseits auf den Einsatzbereich "Bett" und andererseits auf die unangenehmen Weckeigenschaften hindeuten. Darüber hinaus soll das System aber auch eine freundliche Seite haben und in gedämpften Licht den Bodenbereich ausleuchten, sobald nachts Bewegung detektiert wird.

Die wesentlichen Features

Folgende Aufgaben soll das Modul bewältigen:

1. Licht im Fußbereich einschalten

  • Licht soll nur ab einer bestimmten Dunkelheit angehen.
  • Licht soll bei dunkler Umgebung gedämpft und bei relativ heller Umgebung heller leuchten.


2. Wecken in verschiedenen Stufen

  • Licht wird langsam heller, Licht blinkt, Farben wechseln von Blau nach Rot
  • Ton wird dazu geschaltet, Lautstärke steigt
  • Wecker soll über einen Taster deaktiviert werden.

Anforderungen

ID Anforderung
Tabelle: Anforderungen an das halbsmarte Bad-Modul
1 Design
1.1 Das Modul muss kompakt sein, um gut unter jedes Bett zu passen.
1.2 Es muss möglichst einfach zu montieren sein.
1.3 Die Bauelemente (Arduino, Sensoren usw.) sollen vor z.B. Fußtritten geschützt sein.
1.4 Das Modul darf beim Aufstehen nicht im Weg sein.
2 Funktionen
2.1 Fußbodenbeleuchtung: Das System registriert Bewegungen vor dem Bett und schaltet das Licht ein, wenn die Umgebung dunkel genug ist. Das Licht soll automatisch erlöschen, wenn längere Zeit keine Bewegung vor dem Sensor erfolgt.
2.2 Automatische Dimmung : Das System wählt eine unterschiedliche Lichtintensität, je nachdem wie dunkel es ist, um in völliger Dunkelheit nicht zu blenden und bei gedämpftem Licht trotzdem für bessere Sicht zu sorgen.
2.3 Wecksystem: Das Modul soll erst sanfte Weckversuche über optische Reize (heller werdendes Licht, blinken) starten und über die Zeit intensiver, und über auditive und optische Signale Wecken.
3 Bedienung
3.1 Die Weckzeit soll direkt am Modul eingestellt und abgelesen werden können.
3.2 Die Bedienung soll möglichst intuitiv und unkompliziert sein.

Funktionaler Systementwurf/Technischer Systementwurf

Wir haben uns gegen eine Sleep-Funktion entschieden, weil diese dem Konzept des "Bad" Moduls nicht gerecht wird. Schließlich soll es zuverlässig wecken und nicht ermöglichen lange im Bett zu bleiben. Gegen dieses Prinzip spricht auch ein Ausschalten des Weckers per Bewegungsmelder. Ein Abschalten des Weckers bei zu hoher Umgebungshelligkeit (Person bereits wach, oder aufgestanden) wurde weggelassen, da das Leuchten des Moduls selbst ein Abschalten verursachen könnte. Weiter wäre denkbar gewesen eine geschlossene Box für den Wecker herzustellen, die dann frei im Raum zu positionieren ist. Das hätte zum Vorteil gehabt, dass alle Kabel sicher im Gehäuse untergebracht wären. Eine Bodenbeleuchtung per Bewegungsmelder macht aber nur Sinn, wenn das Modul unter dem Bett angebracht wird und den Boden vor dem Bett beleuchtet und dort Bewegungen erfasst. Zur einfachen Unterbringung wurde dann entschieden, dass Modell so zu designen, wie es im CAD-Modell zu sehen ist.


Komponentenspezifikation

Tab.1: Kostenkalkulation und Auswahl der Komponenten für das Halbsmarte Bad-Modul

Komponentenliste:

  1. Passiver IR-Bewegungsmelder: HC-SR501
  2. Passiver Lautsprecher
  3. Kurzhubtaster 12x12x6mm
  4. LED-Ring: WS2812 (als Schauobjekt, in der Praxis eventuell 10m-Leuchtband)
  5. Fotowiderstand
  6. DS1307 I2C RTC Modul (Uhrzeitmodul)
  7. Breadboard (830 Kontakte)
  8. Gehäuse Arduino Uno R3 (transparent)

Die Komponenten wurden so gewählt, dass sie a) auch nach dem Projekt noch nützlich sind und b) eine kostengünstige Umsetzung erlauben. Ein RGB-Leuchtband anstatt des LED-Rings wäre eindrucksvoll, aber auch teuer gewesen und nachher nicht mehr genutzt worden. Daher haben wir uns für den LED-Ring entschieden, der das Potential des Moduls ausreichend darstellt. Eine ähnliche Entscheidung wurde bezüglich der Taster getroffen. Es gibt beleuchtete und vandalismusgeschützte Taster, die das Modul optisch aufgewertet hätten, diese sind aber auch vergleichsweise kostenintensiv. Das Breadboard, dass natürlich viel zu lang für die Anwendung ist, wurde gewählt, da gleichwertige Boards in halber Größe im bevorzugten Shop nicht lieferbar waren. Auf ein spanendes Kürzen wurde verzichtet, da das Board auch nach dem Projekt noch anderweitig genutzt werden soll.

Umsetzung (HW/SW)

Hardware

Das Bad-Modul soll unkompliziert am Bett angebracht werden können. Hierfür wurde eine T-förmige Halterung mithilfe von Solidworks erstellt und per 3D-Druck realisiert. Bei der Konstruktion wurde das Prinzip "Form follows Function" angewandt, damit das Modul nachher auch Problemlos anwendbar ist. Die Form des Moduls ist somit speziell auf die von uns ausgewählten Bauteile ausgelegt. Durch diese Konstruktionsmethodik gestaltete sich die Anbringung der Bauteile sehr einfach und es musste wenig nachgebessert werden am Modul.

Abb.4: CAD-Modell des Halbsmarten Bad-Moduls

Nach erfolgreichen Test der Komponenten und fertigem Aufbau der Schaltung auf dem Breadboard, wurden die einzelnen Bauelementen an der Halterung befestigt. Ursprünglich war geplant vandalismusgeschützte Schalter zu verwenden; diese Idee wurde aus Kostengründen verworfen.

Software

Zur Ansteuerung der Komponenten wurden folgende Bibliotheken genutzt:

  • Wire von Arduino
  • Adafruit_NeoPixel von "Phil "Paint Your Dragon" Burgess" (für Adafruit Industries)
  • Time von Paul Stoffregen
  • DS1307RTC von Paul Stoffregen
  • LiquidCrystal I2C von Marco Schwartz

Grundsätzlich werden in einer Endlosschleife die verschiedenen Eingänge eingelesen:

  • Taster A und B
  • Bewegungsmelder
  • Spannungsabfall am Photowiderstand

und über I2C die aktuelle Uhrzeit vom RTC-Modul eingelesen.

Anschließend wird passend zu den eingelesenen Werten, in verschiedenen if-Abfragen entschieden, welche Funktion aktiviert wird. Ist es zum Beispiel dunkel (geringer Wert am Photowiderstand) und der Bewegungsmelder reagiert, wird die Bodenbeleuchtung aktiviert. Die Helligkeit ergibt sich aus folgender Formel:

Mit der maximalen Helligkeit LHmax und der aus der Spannung am Photowiderstand errrechnete Wert UH für die Helligkeit der Umgebung.

Und aus dieser Formel ergibt sich, um welchen Betrag sich die Helligkeit erhöhen soll:

Step ist Schrittgröße mit der das Licht heller wird. DimTime , die Zeit, bis das Licht die maximale Helligkeit haben soll und DimPause die Zeit zwischen den Dimmschritten.

Nach definierter Zeit geht das Licht wieder aus, außer es wird weiter eine Bewegung detektiert. Falls das Licht in unter fünf Sekunden ausgehen würde, werden dann weitere fünf Sekunden bis zum Abschalten des Lichts addiert. Das Licht wird dann in gleicher Schrittweite runtergedimmt.

Wenn die Uhrzeit mit der eingestellten Weckzeit übereinstimmt, werden Weckmaßnahmen in fünf verschiedenen Intensitäten aktiviert:

  1. Langsames aufdimmen des Lichts (weißes Licht)
  2. Langsam blinkendes Licht (weißes Licht)
  3. Langsam blinkendes Licht und Signalton (weißes Licht)
  4. Langsam blinkendes Licht und Signalton (rotes Licht)
  5. Schnell wechselndes Licht in verschiedenen Farben und Signalton

Die einzelnen "Stages" werden auf dem LCD-Display ausgegeben.

Wenn der Wecker nach einer gewissen Weckdauer nicht deaktiviert wurde, geht er von selbst aus. Dies soll verhindern, dass der Wecker ewig weiter weckt, auch wenn zum Beispiel niemand zu Hause ist.

Mit den Tastern kann der Wecker aktiviert, bzw. deaktiviert werden und die Weckzeit eingestellt werden. Beim Einstellen der Weckzeit, wird erfasst, wie lange der Knopf gedrückt wird. Bei einmaliger Betätigung wird die Weckzeit um eine Minute erhöht. Bei längerer Betätigung um 10 Minuten und schließlich um 60 Minuten.

Programmcode


// // // // // // // // // // // // // // // // // // // // // 
// Projekt: Halbsmartes Bad-Modul                           //
// Elektortechnik Fachpraktikum: Hochschule Hamm-Lippstadt  //
// Autoren: Dominik Sumkötter und Lukas Mücke               //
// Letze Änderung: 10.01.2021                               //
// // // // // // // // // // // // // // // // // // // // // 

#include <Wire.h>

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);   //Initialisierung LCD

#define NPIXELS 12      // Pixel 0 - ...
#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NPIXELS, 10, NEO_GRB + NEO_KHZ800); //Anzahl Pixel, Port Nr, Settings
#ifdef __AVR__
#include <avr/power.h>
#endif

#include <Time.h>
#include <DS1307RTC.h>

#define POWERMAX 150
#define ButtonA 2     //Ports definieren
#define ButtonB 4
#define BewegungsM 7
#define PhotoR A0
#define Speaker 13
#define DimTime 1000    //Wie lange soll es dauern, bis der Dimmer volle Helligkeit erreicht
#define DimPause 50     //Wie lange sind die Intervalle in denen gedimmt werden soll

bool  AlarmOn = 0;      //Wecker standardmäßig aus
bool  Bewegung = 0;     //Bewegungsmelder
int   AlarmMinute = 0; 
int   AlarmHour = 12;
short Power = 0;
bool  Sound = false;


void setup() {
  pinMode(ButtonA, INPUT);
  pinMode(ButtonB, INPUT);
  pinMode(BewegungsM, INPUT);
  pinMode(PhotoR, INPUT);

  lcd.init();   //Initialisieren LCD
  lcd.backlight();  //LCD Backlight standardmäßig an

  pixels.begin();   //Initialisieren Neo-Pixel Ring

  Serial.begin(9600); //Initialisieren Übertragung an Seriellen Monitor
}

void loop()
{
  bool A = digitalRead(ButtonA);                //ButtonB gedrückt?
  bool B = digitalRead(ButtonB);                //ButtonB gedrückt?
  bool Bewegung = digitalRead(BewegungsM);      //Bewegung detektiert?
  int  Helligkeit = analogRead(PhotoR);         //Auslesen Spannung am Photowiderstand
  Serial.print("Bewegung ");                    //Debugging für Bewegungsmelder
  Serial.println(Bewegung);
  Serial.print("PhotoR ");                      //Debugging für Photowiderstand
  Serial.println(Helligkeit);

  noTone(Speaker);                              //Speaker standardmäßig aus

  tmElements_t tm;                              //Variable für Uhrzeitspeicher anlegen
  RTC.read(tm);                                 //Uhrzeit auslesen
  int Hour = tm.Hour;                           //Übertragen der Uhrzeit in int Format
  int Minute = tm.Minute;

  lcd.setCursor(0, 0);                          //Standardmäßig Uhrzeit ausgeben
  lcdprinttime(Hour, Minute);

  if (Minute == AlarmMinute && Hour == AlarmHour && AlarmOn)      //Wecken, wenn Alarm an und AlarmZeit = Uhrzeit
  {
    double start = millis();                                      //Wann wurde der Wecker gestartet?
    bool quit = false;
    short stage = 0;                              //Starten mit Stage 0
    while (quit == false)                         //Wecken bis Abbruch
    {
      Serial.println( ( (start + 10000) - millis() ));      //Debugging: "Wie lange ist die Stage noch aktiv?"

      if ((start + 10000) < millis() )            //Nächste Stage, nach 10 Sekunden (Als Demo-Modus; in der Praxis natürlich länger)
      {
        stage = (stage < 4) ? stage + 1 : 4;
        Power = 0;
        start += 10000;
      }
      WakeUp(stage);          //Weckprogramm für die aktuelle Stage starten
      quit = digitalRead(ButtonB);      //Wecken mit Taste B abbrechen?

      if ((start + 120000) < millis())    //Wenn der Wecker seit 2 Minuten weckt, ist anzunehmen dass keiner da ist -> Abbruch
      {
        quit = true;
      }
      delay(50);
    }
    AlarmOn = 0;          //Wenn Wecken abgebrochen -> Wecker aus
    for (int i = 0; i < NPIXELS; i++)       //LED aus
    {
      pixels.setPixelColor(i, pixels.Color(0, 0, 0));
      pixels.show();
    }
  }


  if (A && !B)  //Taster A gedrückt? Wecker An, oder Aus
  {
    lcd.backlight();
    lcd.setCursor(0, 0);
    if (!AlarmOn)
    {
      lcd.clear();
      lcd.print("Wecker EIN: ");
      lcd.setCursor(0, 1);
      lcdprinttime(AlarmHour, AlarmMinute);

      delay(1000);
      lcd.clear();
      AlarmOn = 1;
    }
    else
    {
      lcd.clear();
      lcd.print("Wecker AUS");
      delay(1000);
      lcd.clear();
      AlarmOn = 0;
    }
  }

  if (B && !A)      //Taste B gedrückt? Weckzeit einstellen
  {
    lcd.clear();
    int start = millis();     //Seit wann ist die Taste gedrückt?
    int increment = 1;        //Standartinkrement
    lcd.setCursor(0, 0);      //Weckzeit ausgeben
    lcd.print("Weckzeit: ");
    lcd.setCursor(0, 1);
    lcdprinttime(AlarmHour, AlarmMinute);

    while (B)
    {
      int pressdur = millis() - start;
      if (3000 < pressdur && pressdur < 8000) {     //Inkrement erhöhen, wenn Taste länger als 3s gedrückt
        increment = 10;
      }
      else if (pressdur > 8000) {                 //Stundenweise weiter, wenn seit 8s gedrückt
        increment = 60;
      }
      
      B = digitalRead(ButtonB);     //Wird B noch gedrückt?
      
      if(!B);
      {
      AlarmMinute += increment;
      }
      
      if (AlarmMinute >= 60)      //61 Minuten machen keinen Sinn. Daher Stunde +1
      {
        AlarmMinute = 0;
        AlarmHour += 1;
      }
      AlarmHour = (AlarmHour >= 24) ? 0 : AlarmHour; // Wir wollen auch keine 25 Stunden...

      lcd.setCursor(0, 0); //Neue Weckzeit angeben
      lcd.print("Weckzeit: ");
      lcd.setCursor(0, 1);
      lcdprinttime(AlarmHour, AlarmMinute);
      delay(750);
      B = digitalRead(ButtonB);
      lcd.clear();
    }
  }

  if (Bewegung && Helligkeit < 140) // 375   //Wenn die Helligkeit größer als 140 und der Bewegungsmelder Bewegung registriert -> Boden beleuchten! Für Präsentation auf 140 gesetzt. Sonst ca. 375, aber Ortsabhängig
  {
    Dimmer(Helligkeit);     //Helligkeit wird übergeben
  }
} //Programm Ende



void WakeUp(int Stage)  //Weckfunktion
{
  lcd.clear();
  switch (Stage)      //in welcher Stage sind wir?
  {
    case 0:
      lcd.clear();        //LCD Ausgabe der Stage und dezenter Handlungshinweis 
      lcd.setCursor(0, 0);
      lcd.print("Aufstehen!");
      lcd.setCursor(0, 1);
      lcd.print("Stage 1");
      Power = (Power < POWERMAX) ? Power + 1 : Power;      //Powermax wurde für Präsentation auf 150 gedrosselt (max. 255), Jeden Durchlauf etwas heller!
      for (int i = 0; i < NPIXELS; i++)       
      {
        pixels.setPixelColor(i, pixels.Color(Power, Power, Power));
        pixels.show();
      }

      delay(300);
      break;

    case 1:
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Aufstehen!");
      lcd.setCursor(0, 1);
      lcd.print("Stage 2");
      Power = (Power == 0) ? POWERMAX : 0;       //Maximale Power und blinken
      for (int i = 0; i < NPIXELS; i++)
      {
        pixels.setPixelColor(i, pixels.Color(Power, Power, Power));
        pixels.show();
      }

      delay(500);
      break;


    case 2:
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Aufstehen!");
      lcd.setCursor(0, 1);
      lcd.print("Stage 3");
      Power = (Power == 0) ? POWERMAX : 0;
      Sound = !Sound;     //Jetzt gibt es noch Ton dabei!
      if (Sound)        //Kein durchgängier Ton, sondern Intervalle
      {
        tone(Speaker, 500);
      }
      else
      {
        noTone(Speaker);
      }

      for (int i = 0; i < NPIXELS; i++)
      {
        pixels.setPixelColor(i, pixels.Color(Power, Power, Power));
        pixels.show();
      }

      delay(500);
      break;
    //Blinken und Ton

    case 3:
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Aufstehen!");
      lcd.setCursor(0, 1);
      lcd.print("Stage 4");

      Power = (Power == 0) ? POWERMAX : 0;
      Sound = !Sound;
      if (Sound)
      {
        tone(Speaker, 500);
      }
      else
      {
        noTone(Speaker);
      }

      for (int i = 0; i < NPIXELS; i++)
      {
        pixels.setPixelColor(i, pixels.Color(Power, 0, 0));     //Diesmal rot blinken
        pixels.show();
      }
      delay(500);
      break;

    case 4:
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Aufstehen!");
      lcd.setCursor(0, 1);
      lcd.print("Stage 5");

      Power = POWERMAX;
      Sound = !Sound;
      if (Sound)
      {
        tone(Speaker, 500);
      }
      else
      {
        noTone(Speaker);
      }

        for (int i = 0; i < NPIXELS; i++)
        {
          pixels.setPixelColor( i, pixels.Color( random(0, POWERMAX), random(0, POWERMAX), random(0, POWERMAX) ) );        //Power wird auf einen Wert zwischen 0 und 150 gesetzt aber zufällig, damit es nervig blinkt
          pixels.show();
        }
        delay(300);
        break;
  }
} //Weckfunktion Ende



void Dimmer(int UH) //Bodenbeleuchtung
{
  double LHmax = 7.742*pow(2.17828,(0.01*UH)); // Helligkeitsmaximum berechnen
  
  LHmax = (LHmax > 255) ? 255 : LHmax;  //Wenn größer 255, LHmax   = 255, sonst nichts.
  LHmax = (LHmax < 1) ? 1 : LHmax;      //Wenn negativ, oder kleiner 1, dann 1

  double PWMout = 0;                        //Variablen anlegen
  double Step = LHmax / (DimTime / DimPause);  //Schrittgröße für das Dimmen anlegen

  while (PWMout < LHmax)                   //Aufhellen der LED bis maximum erreicht
  {
    PWMout += Step;
    PWMout = (PWMout >= POWERMAX) ? POWERMAX : PWMout;  //Wenn größer 255, PWMout   = 255, sonst nichts.; hier auf 150 begrenzt für Präsentation

    for (int i = 0; i < NPIXELS; i++)
    {
      pixels.setPixelColor( i, pixels.Color( PWMout, PWMout, PWMout ) );
      pixels.show();
    }
    delay(50);
  }

  Serial.print("Check PWMout: ");             //PWMout ausgeben
  Serial.println(PWMout);

  double timenow = millis();
  double stoptime = timenow + 5000;

  while (timenow < stoptime)
  {
    Bewegung = digitalRead(BewegungsM);
    timenow = millis();

    if (Bewegung && stoptime - timenow < 5000)
    {
      stoptime += 5000;
    }
    Serial.print("Bewegung: ");
    Serial.println(Bewegung);
    Serial.print("Noch an: ");
    Serial.println(stoptime - timenow);
    delay(50);
  }

  while (PWMout > 0)                         //Abdunkeln der LED bis aus
  {
    PWMout -= Step;
    PWMout = (PWMout < 0) ? 0 : PWMout;
    for (int i = 0; i < NPIXELS; i++)
    {
      pixels.setPixelColor( i, pixels.Color( PWMout, PWMout, PWMout ) );
      pixels.show();
    }

    delay(50);
  }
  pixels.clear();
} //BodenbeleuchtungEnde

void lcdprinttime(int Hour, int Minute) //Zeitausgabe mit führender Null
{
  if (Hour < 10)
  {
    lcd.print("0");
    lcd.print(Hour);
  }
  else lcd.print(Hour);

  lcd.print(":");

  if (Minute < 10)
  {
    lcd.print("0");
    lcd.print(Minute);
  }
  else lcd.print(Minute);
}   //Zeitausgabe mit führender Null


Komponententest

Es wurde für jede Komponente ein Testprogramm geschrieben, um die für das fertige Bad-Module notwendigen Funktionen zu testen. Anschließenden wurden die Komponenten an den Arduino angeschlossen und die Programme optimiert.

Anschließend wurden immer mehr Module zusammen angeschlossen und der finale Code um die entsprechenden Funktionen ergänzt, bis das gesamte Modul betriebsbereit war.

Ergebnis

Das Bad-Modul ist funktionsbereit und enthält alle Funktionen, die auf jeden Fall eingebracht werden sollten.

Zusammenfassung

Lessons Learned

Es wurden folgende Kenntnisse und Fähigkeiten vertieft, bzw. erlernt:

  • Planung und Entwurf eines Projektes
  • Projektmanagement
  • Aufbau einer Schaltung
  • Erstellen eines CAD-Modells für den 3D-Druck
  • Programmierung eines Mikrocontrollers

Für einen weiteres Projekt sollte bereits zu Beginn stärker über das optische Erscheinungsbild des Endprodukts nachgedacht werden, gerade in Hinblick auf die Kabelführung hat sich zum Ende des Projekts keine vollständige Zufriedenheit eingestellt, während andere Mängel (zu langes Breadboard, Taster) durch ein höheres Budget einfach auszubessern wären.

Projektunterlagen

Projektplan

Abb.6: Gantt-Chart

Das Gantt-Chart wurde mithilfe von Libre Calc realisiert, da keine Office-Software sich in unserem Besitz befindet. Die geplante Zeiteinteilung aus dem Gantt-Chart wurde nur leicht durch die etwas späte Freigabe des Projektes belastet. Dennoch konnte das Projekt ohne zeitliche Komplikationen umgesetzt werden.

Projektdurchführung

Das Projekt des Halbsmarten Bad-Moduls startete mit der Ideenfindung und anschließender Anfertigung der Liste mit den benötigten Teilen.

Nach einer Kostenkalkulation und ersten Zeichnung, wurde die Auswahl der Teile präzisiert, welche konkreten Bauteile bestellt und im Bad-Modul verbaut werden. Nach Lieferung der Teile, wurden Programme für die einzelnen Module geschrieben, um die Funktion zu überprüfen und sich mit der Programmierung und Möglichkeiten, sowie Limitierungen vertraut zu machen. Anschließend wurden die einzelnen Elemente zum gewünschten System zusammengeführt. Um dieses System auch anwendbar zu gestalten wurde eine Halterung entwickelt, sodass alle Elemente Funktionsgerecht im Modul integriert werden konnten.

Schlussendlich wurden die Elemente am der Halterung zum vollständigen Modul zusammengeführt und das Modul wurde finalen Tests unterzogen um die Funktionen nochmals sicher zu stellen.

YouTube Video

Hier können die Funktionen des Moduls angesehen werden:

[1]

Weblinks

Literatur


→ zurück zur Übersicht: WS 21/22: Angewandte Elektrotechnik