Eine elegante automatische Treppenbeleuchtung (Teil1)

Im ersten Teil einer neuen spannenden Reihe eine elegante automatische Treppenbeleuchtung für bis zu maximal 16 Stufen auf, bei der jede einzelne Stufe der Treppe nacheinander als Lauflicht beleuchtet wird, sobald einer der beiden Infrarotmelder, die jeweils einzeln am oberen und am unteren Ende der Treppe angebracht sind, eine Bewegung melden. Dabei wird jede einzelne Treppe dazu noch sanft per PWM Steuerung auf die maximale Helligkeit hochgedimmt und später bis um erlöschen wieder heruntergedimmt. Der Zeiträume, in der die Treppe eingeschaltet bleibt, oder die eine Stufe herauf- oder herabdimmt ist dabei frei im Sketch nach eigenem Belieben einstellbar. Eine solche Lösung gibt es bereits schon kommerziell (hier im Video im Betrieb zu sehen).

Heute zeige ich, wie man eine in der Funktion ähnliche Steuerung mithilfe des Arduinos und einiger externen Bauteilen selbst bauen kann.

 

Wir brauchen für unsere do-it-yourself Treppenbeleuchtung folgende Elektronik-Teile:

 

Anzahl

Beschreibung

Anmerkung

2

PIR Modul HC-SR501 PIR

Bewegungssensor

1

PCA9685 16 Kanal 12 Bit PWM Driver

 

1

Nano V3

 

1

MB102 Netzteil Adapter

Für Breadboardaufbau

bis 16

IRF520 MOS Driver Modul 0-24V 5A

Anzahl je nach Treppenzahl

1

Netzteil für LED/Lampen für die Stufen

Maximal 24 Volt

 

Im folgenden Schaltplan ist die Kernsteuerung zu sehen. Exemplarisch sind jedoch nur 2 Treiberstufen der maximal möglichen 16 Treiberstufen zu sehen. Falls mehr Treiberstufen benötigt werden, werden diese sinngemäß wie die beiden eingezeichneten angeschlossen. Zu beachten ist unbedingt eine sicherheitsgerechte Verwendung von Stromkabeln und Leitungen sowie ein ausreichend dimensioniertes Netzteil. Das Netzteil muss Überlast geschützt sein und alle Treppenstufenlichter und den Arduino mit stabilisierter Gleichspannung versorgen können ohne überlastet zu werden! Es besteht Brandgefahr bei nicht sachgerechtem Einbau und/oder Betrieb!

 

Wir bauen die Schaltung für unsere Treppe wie folgt auf einem Breadboard zum testen auf:

 

Aufbau auf Steckbrett

 

Im nächsten Schritt passen wir den Quellcode des Arduinos an die eigenen Bedürfnisse an. Interessant sind die folgenden 3 Zeilen im Code:

#define Num_Stages 15
#define Delay_Stages 10
#define Delay_ON_to_OFF 5

 

Num_Stages

Definiert die Anzahl der zu beleuchtenden Treppen (maximal 16, von 0 anzählend zu beginnen. Maximalwert: 15)

Delay_Stages

Fade Zeitraum für jede Treppenstufe -> je kleiner der Wert desto größer der Zeitraum, desto langsamer.

Delay_ON_to_OFF

Zeitraum der vergeht indem die Treppe im Status „an“ verbleibt.

 

Nachdem wir die werte den eigenen Vorlieben angepasst habe, kann der Code auf den Arduino hochgeladen werden :

 

 

// 2019 Tobias Kuch GPL 3.0
#include <Wire.h>

#define PWM_Module_Base_Addr 0x40 //10000000b  Das letzte Bit des Adressbytes definiert die auszuführende Operation. Bei Einstellung auf logisch 1  0x41 Modul 2
//wird ein Lesevorgang auswählt, während eine logische 0 eine Schreiboperation auswählt.
#define OE_Pin  8           // Pin für Output Enable
#define PIRA_Pin 2
#define PIRB_Pin 3

#define Num_Stages  15
#define Delay_Stages  10
#define Delay_ON_to_OFF  30  // Minimum Delay_ON_to_OFF in Seconds

byte Pwm_Channel = 0;
int Pwm_Channel_Brightness = 0;

bool Motion_Trigger_Down_to_Up = false;
bool On_Delay = false;

// interrupt Control
byte A60telSeconds24 = 0;
byte Seconds24;

ISR(TIMER1_COMPA_vect)
{
  A60telSeconds24++;
  if (A60telSeconds24 > 59)
  {
    A60telSeconds24 = 0;
    Seconds24++;
    if (Seconds24 > 150)
    {
      Seconds24 = 0;
    }
  }
}

void ISR_PIR_A()
{
  bool PinState = digitalRead(PIRA_Pin);
  if (PinState)
  {
    Motion_Trigger_Down_to_Up = true; // PIR A ausgelöst
  }
}

void ISR_PIR_B()
{
  bool PinState = digitalRead(PIRB_Pin);
  if (PinState)
  {
    Motion_Trigger_Down_to_Up = true; // PIR B ausgelöst
  }
}

void Init_PWM_Module(byte PWM_ModuleAddr)
{
  pinMode(OE_Pin, OUTPUT);
  digitalWrite(OE_Pin, HIGH); // Active LOW-Ausgangsaktivierungs-Pin (OE).
  Wire.beginTransmission(PWM_ModuleAddr); // Datentransfer initiieren
  Wire.write(0x01);                       // Wähle  Mode 2 Register (Command Register)
  Wire.write(0x04);                       // Konfiguriere Chip: 0x04:  totem pole Ausgang 0x00: Open drain Ausgang.
  Wire.endTransmission();                 // Stoppe Kommunikation - Sende Stop Bit
  Wire.beginTransmission(PWM_ModuleAddr); // Datentransfer initiieren
  Wire.write(0x00);                      // Wähle Mode 1 Register (Command Register)
  Wire.write(0x10);                      // Konfiguriere SleepMode
  Wire.endTransmission();                // Stoppe Kommunikation - Sende Stop Bit
  Wire.beginTransmission(PWM_ModuleAddr); // Datentransfer initiieren
  Wire.write(0xFE);                       // Wähle PRE_SCALE register (Command Register)
  Wire.write(0x03);                       // Set Prescaler. Die maximale PWM Frequent ist 1526 Hz wenn das PRE_SCALEer Regsiter auf "0x03h" gesetzt wird. Standard : 200 Hz
  Wire.endTransmission();                 // Stoppe Kommunikation - Sende Stop Bit
  Wire.beginTransmission(PWM_ModuleAddr); // Datentransfer initiieren
  Wire.write(0x00);                       // Wähle Mode 1 Register (Command Register)
  Wire.write(0xA1);                       // Konfiguriere Chip:  ERrlaube All Call I2C Adressen, verwende interne Uhr,                                           // Erlaube Auto Increment Feature
  Wire.endTransmission();                 // Stoppe Kommunikation - Sende Stop Bit
}


void Init_PWM_Outputs(byte PWM_ModuleAddr)
{
  digitalWrite(OE_Pin, HIGH); // Active LOW-Ausgangsaktivierungs-Pin (OE).
  for ( int z = 0; z < 16 + 1; z++)
  {
    Wire.beginTransmission(PWM_ModuleAddr);
    Wire.write(z * 4 + 6);      // Wähle PWM_Channel_ON_L register
    Wire.write(0x00);                     // Wert für o.g. Register
    Wire.endTransmission();
    Wire.beginTransmission(PWM_ModuleAddr);
    Wire.write(z * 4 + 7);      // Wähle PWM_Channel_ON_H register
    Wire.write(0x00);                     // Wert für o.g. Register
    Wire.endTransmission();
    Wire.beginTransmission(PWM_ModuleAddr);
    Wire.write(z * 4 + 8);   // Wähle PWM_Channel_OFF_L register
    Wire.write(0x00);        // Wert für o.g. Register
    Wire.endTransmission();
    Wire.beginTransmission(PWM_ModuleAddr);
    Wire.write(z * 4 + 9);  // Wähle PWM_Channel_OFF_H register
    Wire.write(0x00);             // Wert für o.g. Register
    Wire.endTransmission();
  }
  digitalWrite(OE_Pin, LOW); // Active LOW-Ausgangsaktivierungs-Pin (OE).
}

void setup()
{
  //Initalisierung
  pinMode(PIRA_Pin, INPUT);
  pinMode(PIRB_Pin, INPUT);
  Serial.begin(9600);
  Wire.begin(); // Initalisiere I2C Bus A4 (SDA), A5 (SCL)
  Init_PWM_Module(PWM_Module_Base_Addr);
  Init_PWM_Outputs(PWM_Module_Base_Addr);
  noInterrupts();
  attachInterrupt(0, ISR_PIR_A, CHANGE);
  attachInterrupt(1, ISR_PIR_B, CHANGE);
  TCCR1A = 0x00;
  TCCR1B = 0x02;
  TCNT1 = 0;      // Register mit 0 initialisieren
  OCR1A =  33353;      // Output Compare Register vorbelegen
  TIMSK1 |= (1 << OCIE1A);  // Timer Compare Interrupt aktivieren
  interrupts();
}

void Down_to_Up_ON()
{
  Pwm_Channel = 0;
  Pwm_Channel_Brightness = 0;
  while (Pwm_Channel < Num_Stages + 1)
  {
    Wire.beginTransmission( PWM_Module_Base_Addr);
    Wire.write(Pwm_Channel * 4 + 8);   // Wähle PWM_Channel_0_OFF_L register
    Wire.write((byte)Pwm_Channel_Brightness & 0xFF);        // Wert für o.g. Register
    Wire.endTransmission();
    Wire.beginTransmission( PWM_Module_Base_Addr);
    Wire.write(Pwm_Channel * 4 + 9);  // Wähle PWM_Channel_0_OFF_H register
    Wire.write((Pwm_Channel_Brightness >> 8));             // Wert für o.g. Register
    Wire.endTransmission();
    if (Pwm_Channel_Brightness < 4095)
    {
      Pwm_Channel_Brightness = Pwm_Channel_Brightness + Delay_Stages;
      if (Pwm_Channel_Brightness > 4095) {
        Pwm_Channel_Brightness = 4095;
      }
    } else if ( Pwm_Channel < Num_Stages + 1)
    {
      Pwm_Channel_Brightness = 0;
      delay(200);
      Pwm_Channel++;
    }

  }
}

void Down_to_Up_OFF()
{
  Pwm_Channel = 0;
  Pwm_Channel_Brightness = 4095;
  while (Pwm_Channel < Num_Stages + 1)
  {
    Wire.beginTransmission( PWM_Module_Base_Addr);
    Wire.write(Pwm_Channel * 4 + 8);   // Wähle PWM_Channel_0_OFF_L register
    Wire.write((byte)Pwm_Channel_Brightness & 0xFF);        // Wert für o.g. Register
    Wire.endTransmission();
    Wire.beginTransmission( PWM_Module_Base_Addr);
    Wire.write(Pwm_Channel * 4 + 9);  // Wähle PWM_Channel_0_OFF_H register
    Wire.write((Pwm_Channel_Brightness >> 8));             // Wert für o.g. Register
    Wire.endTransmission();
    if (Pwm_Channel_Brightness > 0)
    {
      Pwm_Channel_Brightness = Pwm_Channel_Brightness - Delay_Stages;
      if (Pwm_Channel_Brightness < 0) {
        Pwm_Channel_Brightness = 0;
      }
    } else if ( Pwm_Channel < Num_Stages + 1)
    {
      Pwm_Channel_Brightness = 4095;
      delay(200);
      Pwm_Channel++;
    }

  }
}

void loop() {
  if ((Motion_Trigger_Down_to_Up) and !(On_Delay))
  {
    Seconds24 = 0;
    On_Delay = true;
    Down_to_Up_ON();
    Motion_Trigger_Down_to_Up = false;
  }
  if ((On_Delay) and  (Seconds24 > Delay_ON_to_OFF))
  {
    Motion_Trigger_Down_to_Up = false;
    On_Delay = false;
    Down_to_Up_OFF();
  }
}

 

 

Ich wünsche viel Spaß beim Nachbauen dieses Projektes und bis zum nächsten Teil.

 

 

 

 

Letzter Artikel Eine elegante automatische Treppenbeleuchtung (Teil2)
Neuer Artikel LED Echtzeituhr mit RTC Modul, alternierender Temperatur in Celsius und Fahrenheit, Luftfeuchteanzeige, Helligkeitssteuerung und Netzwerksyc. (Teil 5)

Kommentar

Wolfgang - Januar 23, 2020

Die Idee finde ich toll und ein Anstoß für das Zusammenwirken von Komponenten (auch für andere Projekte.
Aber:
Das Zusammenwirken von Steuerungen mit Lichtstrom (Netzstrom) ist eine echte Herausforderung, weil in unserer technischen Welt alles diesbezüglich mit Sicherheitsvorschriften geregelt ist, deren Nichtbeachtung fatale Folgen haben kann. In diesem Falle trifft die VDE für Kleinspannungen zu. Damit meine ich nicht die ARDUINO Steuerung sondern die Leistungssteuerung. Deswegen unterstütze ich die Kommentare meiner Vorgänger, die Beleuchtung auf LED im Kleinleistungsbereich (<5W) gegenüber X* max ca.100W vorschlagen. Abgesehen von der Wärmeentwicklung. Bei allen Projekten sollte auch die “Klimaverträglichkeit” mitspielen. Etwas, woran sich die “Maker-Szene” heran tasten sollte.

In einigen Kommentaren war die Aktivierung mit Lichtempfindlichkeit angesprochen: Die PIR Module haben 2 Einstellungen: Pulslänge bei Aktivierung und Umgebungshelligkeit.

Im Rettungsdienst sind wir immer wieder mit Verunglückten konfrontiert, die auf Treppen stürzen. Kabel sind nicht selten dabei ein Grund. Bitte, im eigenen Interesse, wenige Kabel und sichere Verlegung, gerade bei Stiegen und Treppen!

Udo Schulz - Januar 23, 2020

Es wäre schön, wenn die Lampen , wenn man oben an der Treppe ist, von oben nach unten angehen und wenn man unten ist, von unten nach oben angehen und entsprechend auch ausgehen.

Tobias - Januar 7, 2020

vielen Dank für die ganze positive Rückmeldung ! Das Projekt kann ganz einfach auch mit LED Streifen ohne Änderung der Schaltung oder des Codes verwendet werden. Einfach an den Ausgang ein LED Streifen hängen, das wars..

Tim - Januar 7, 2020

Hallo
Ich bekomme nur Fehlermeldungen beim Kompilieren.
Arduino: 1.8.10 (Windows 10), Board: “Arduino Nano, ATmega328P”

treppenlicht1:58:16: error: expected primary-expression before ‘,’ token

pinMode(OE_Pin8, OUTPUT); ^

treppenlicht1:59:21: error: expected primary-expression before ‘,’ token

digitalWrite(OE_Pin8, HIGH); // Active LOW-Ausgangsaktivierungs-Pin (OE). ^

C:\Users\frogg\Documents\Arduino\treppenlicht1\treppenlicht1.ino: In function ‘void Init_PWM_Outputs(byte)’:

treppenlicht1:81:21: error: expected primary-expression before ‘,’ token

digitalWrite(OE_Pin8, HIGH); // Active LOW-Ausgangsaktivierungs-Pin (OE). ^

treppenlicht1:101:21: error: expected primary-expression before ‘,’ token

digitalWrite(OE_Pin8, LOW); // Active LOW-Ausgangsaktivierungs-Pin (OE). ^

C:\Users\frogg\Documents\Arduino\treppenlicht1\treppenlicht1.ino: In function ‘void Down_to_Up_ON()’:

treppenlicht1:128:22: error: ‘Num_Stages’ was not declared in this scope

while (Pwm_Channel < Num_Stages + 1) ^~~~~~~~~~

C:\Users\frogg\Documents\Arduino\treppenlicht1\treppenlicht1.ino:128:22: note: suggested alternative: ‘Num_Stages15’

while (Pwm_Channel < Num_Stages + 1) ^~~~~~~~~~ Num_Stages15

treppenlicht1:140:51: error: ‘Delay_Stages’ was not declared in this scope

Pwm_Channel_Brightness = Pwm_Channel_Brightness + Delay_Stages; ^~~~~~~~~~~~

C:\Users\frogg\Documents\Arduino\treppenlicht1\treppenlicht1.ino:140:51: note: suggested alternative: ‘Delay_Stages10’

Pwm_Channel_Brightness = Pwm_Channel_Brightness + Delay_Stages; ^~~~~~~~~~~~ Delay_Stages10

C:\Users\frogg\Documents\Arduino\treppenlicht1\treppenlicht1.ino: In function ‘void Down_to_Up_OFF()’:

treppenlicht1:158:22: error: ‘Num_Stages’ was not declared in this scope

while (Pwm_Channel < Num_Stages + 1) ^~~~~~~~~~

C:\Users\frogg\Documents\Arduino\treppenlicht1\treppenlicht1.ino:158:22: note: suggested alternative: ‘Num_Stages15’

while (Pwm_Channel < Num_Stages + 1) ^~~~~~~~~~ Num_Stages15

treppenlicht1:170:51: error: ‘Delay_Stages’ was not declared in this scope

Pwm_Channel_Brightness = Pwm_Channel_Brightness – Delay_Stages; ^~~~~~~~~~~~

C:\Users\frogg\Documents\Arduino\treppenlicht1\treppenlicht1.ino:170:51: note: suggested alternative: ‘Delay_Stages10’

Pwm_Channel_Brightness = Pwm_Channel_Brightness – Delay_Stages; ^~~~~~~~~~~~ Delay_Stages10

C:\Users\frogg\Documents\Arduino\treppenlicht1\treppenlicht1.ino: In function ‘void loop()’:

treppenlicht1:192:32: error: ‘Delay_ON_to_OFF’ was not declared in this scope

if ((On_Delay) and(Seconds24 > Delay_ON_to_OFF)) ^~~~~~~~~~~~~~~

C:\Users\frogg\Documents\Arduino\treppenlicht1\treppenlicht1.ino:192:32: note: suggested alternative: ‘Delay_ON_to_OFF30’

if ((On_Delay) and(Seconds24 > Delay_ON_to_OFF)) ^~~~~~~~~~~~~~~ Delay_ON_to_OFF30

Mehrere Bibliotheken wurden für “Wire.h” gefunden
Benutzt:
expected primary-expression before ‘,’ token

Diddi - Januar 5, 2020

Das Projekt finde ich sehr gelungen, aber es fehlt noch ein Lichtsensor um bei Tageslicht nicht unnötig Strom zu verbrauchen.
Ein Kombisensor wäre die ideale Ergänzung.

Andreas - Januar 5, 2020

Ich kann Mustafa Sari nur zustimmen, eine Umsetzung mit LED wäre super.

HJThom - Januar 5, 2020

Hallo zusammen, ich finde das Thema auch total spannend. Direkt habe ich mir den Aufbau mal angeschaut und stellte mir wie Mustafa die Frage, warum das Geraffel wenn man das Ganze auch mitWS2812B realisieren kann? Die Möglichkeiten sind hier vielfältiger. Die HC-SR501 sind mir persönlich zu großflächig und somit ungenau aber das ist je nach Anwendung verschieden, ich würde auf eine Lichtschranke setzten. Ich verfolge das Thema mal weiter.

Danke und Gruß
HJThom

Dirk - Januar 5, 2020

ein toller Sketch den ich ähnlich auch bei YouTube gesehen habe. Was mir fehlt sind ein paar Erklärungen um den Sketch nachvollziehen zu können. Ich werde es auf jeden Fall bauen uns ausprobieren.

Stephan Strittmatter - Januar 5, 2020

Tolles Projekt! Ich kann mich da nur anschließen: ich fände eine Variante mit LED-Streifen auch super finden!
Ich bin gespannt.

Mustafa sari - Dezember 30, 2019

Hi es wäre super, wenn ihr die Beleuchtung mal mit dem LED Streifen umsetzt.
Ich hatte schon lange überlegt ein Lauflicht pro Stufe zu realisieren und ich glaube das würde den meisten auch gefallen.
Über das PWM kann man die einzelnen Stufen dann nach und nach immer heller werden lassen.

Hinterlasse einen Kommentar

Kommentare müssen vor der Veröffentlichung überprüft werden

Erforderliche Angabe