Treppenbeleuchtung mit 2 PIR Sensoren und FastLED

Servus Leute,

ich habe bereits schon einige Beiträge hier durch, aber komme nicht sorecht weiter.

Ich komme eigentlich aus der PHP Ecke und tue mich mit der Arduino Programmierung noch etwas schwer.

Würde mich daher freuen, wenn man hier gemeinsam einen Code basteln könnte.

Ich denke, dass ich nicht nur jede Menge OverHead im Programm habe, sondern man auch wesentlich einfacher zum Ziel kommen könnte :wink:

Vorhanden ist:
1x Arduino Uno
2x PIR HC-SR501
1x WS2801 LED Strip
1x Netzteil 5V 10A

Script: (veraltet, aktueller Lauffähiger Code unter http://forum.arduino.cc/index.php?topic=381205.msg2629362#msg2629362)

#include "FastLED.h"

#define DATA_PIN 11
#define CLOCK_PIN 12

#define serialRate 115200

#define sensor1PIN 2
#define sensor2PIN 3

#define LEDHUE 50
#define LEDSAT 255

#define DIR_UP 1
#define DIR_DOWN 2

#define ACTION_ON 1
#define ACTION_OFF 2

#define FADE_STEPS 15

byte nAnzahlLEDjeStufe[] = {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; // Von unten nach oben

int nAnzahlLEDsGesamt;
int nAnzahlStufen;
int nAktuelleLED;
int nDirection;
int nAction;

bool bBelAn;

CRGB leds[44]; //TO-DO

void setup() {

  Serial.begin(serialRate);
  Serial.print("Initialisieren\n");
  delay(500);

  nAnzahlStufen = sizeof nAnzahlLEDjeStufe;
  
  for(int i=0;i<nAnzahlStufen;i++){
    nAnzahlLEDsGesamt += nAnzahlLEDjeStufe[i];
  }
  
  FastLED.addLeds<WS2801, DATA_PIN, CLOCK_PIN, RBG>(leds, nAnzahlLEDsGesamt);
  LEDS.showColor(CRGB(0, 0, 0));

  // Interne LED ansteuern
  pinMode(13, OUTPUT);
  pinMode(sensor1PIN, INPUT);
  pinMode(sensor2PIN, INPUT);

  alleLEDsDurchfaden();
}

void StufenFadenEin(int d)
{
  int nStufe;
  bBelAn = true;
  
  for(int i=0;i<nAnzahlStufen;i++)
  { //Schleife durch die einzelnen Stufen/Strips
    nStufe = i;
    
    if(d = DIR_DOWN)
      nStufe = nAnzahlStufen-i;
      
    for (int FADE = 0; FADE <= 255; FADE+=FADE_STEPS)
    { //Schleife durch 255 Helligkeitsstufen
      for(int j=0;j<nAnzahlLEDjeStufe[nStufe];j++)
      { //Schleife durch die LEDs des Strips/je Stufe
        leds[nAktuelleLED+j].setHSV(LEDHUE, LEDSAT, FADE);
      }
      FastLED.show();
    }
    nAktuelleLED += nAnzahlLEDjeStufe[i];
    delay(500);
    if(int dirTMP = getDirection() > 0 && dirTMP != nDirection)
    { // Benutzer hat den zweiten PIR erreicht
      setDirection(dirTMP);
      Serial.print("LEDS ausschalten\n");
      StufenFadenAus(DIR_DOWN);
      break;
    }
  }
  nAktuelleLED = 0;
}

void StufenFadenAus(int d)
{
  nAktuelleLED = nAnzahlLEDsGesamt;
  
  for(int i=nAnzahlStufen;i>=0;i--)
  { //Schleife durch die einzelnen Stufen/Strips
    for (int FADE = 255; FADE >= 0; FADE-=FADE_STEPS)
    { //Schleife durch 255 Helligkeitsstufen
      for(int j=nAnzahlLEDjeStufe[i];j>=0;j--)
      { //Schleife durch die LEDs des Strips/je Stufe
        leds[nAktuelleLED-j].setHSV(LEDHUE, LEDSAT, FADE);
      }
      FastLED.show();
    }
    nAktuelleLED -= nAnzahlLEDjeStufe[i];
    delay(500);
  }
  nAktuelleLED = 0;
}

int getDirection()
{  
  if(readPIR() == sensor1PIN)
  { // von unten anfangen
    Serial.print("Laufrichtung Hoch\n");
    return DIR_UP;
  }
  else if(readPIR() == sensor2PIN)
  { // von oben anfangen
    Serial.print("Laufrichtung Runter\n");
    return DIR_DOWN;
  }
  
  return 0;
}

int readPIR()
{
  if(digitalRead(sensor1PIN) == HIGH)
  { // von unten anfangen
    return sensor1PIN;
  }
  else if(digitalRead(sensor2PIN) == HIGH)
  { // von oben anfangen
    return sensor2PIN;
  }
  
  return false;
}

void setDirection(int d)
{
  nDirection = d;
}

void setAction(int a)
{
  nAction = a;
}

void alleLEDsDurchfaden()
{
  bBelAn = true;
  for(int j=1;j<=nAnzahlLEDsGesamt;j++)
  {
    for (int FADE = 0; FADE <= 255; FADE+=FADE_STEPS)
    {
      leds[j].setHSV(LEDHUE, LEDSAT, FADE);
      FastLED.show();
    }
  }

  for(int j=nAnzahlLEDsGesamt;j>=0;j--)
  {
    for (int FADE = 255; FADE >= 0; FADE-=FADE_STEPS)
    {
      leds[j].setHSV(LEDHUE, LEDSAT, FADE);
      FastLED.show();
    }
  }

  bBelAn = false;
}

void loop()
{
  setDirection(getDirection());

  switch (nDirection) {
    case 1:
    case 2:
      digitalWrite(13, HIGH);
      
      if(!bBelAn)
        StufenFadenEin(nDirection);
      else
        StufenFadenAus(nDirection);
      break;
    
    default: 
      digitalWrite(13, LOW);
    break;
  }
}

Ziel ist es, dass man PIR1 passiert, und das Licht von dort in die andere Richtung hochläuft und beim passieren von PIR2 die LEDs wieder ausfaden.

Genauso andersrum.

Das Array oben wird mit den entsprechenden LEDs je Stufe gefüllt. Seit dem letzt Update startet der Arduino beim aufrufen der Funktion StufenFadenAus() leider neu.

Kann man in der Arduino IDE irgendwie ein debugging aktivieren?

Grüsse

Du kannst nur seriell debuggen. Neustart kann auf Speicherengpass hindeuten. Wieviel hast Du noch frei? Oder die Stromversorgung muckt.

Kann ein Fehler beim Zugriff auf Array sein. z.B. hier:

leds[nAktuelleLED-j].setHSV(LEDHUE, LEDSAT, FADE);

Vielleicht mal aktuelleLED - j vorher berechnen und schauen ob der Index gültig ist

for(int i=nAnzahlStufen;i>=0;i--)

müßte nicht

for(int i=(nAnzahlStufen-1);i>=0;i--)

heißen? Grüße Uwe

Mal ein alternativer Vorschlag: Du nimmst einen Ultraschallsensor, läßt dir den Abstand in cm ausgeben und rechnest das entsprechend dem Abstand der LEDs zueinander um. Damit kannst du auch darauf reagieren, wenn jemand auf der TReppe umkehrt oder langsamer oder schneller läuft....

Klaus_ww: Du kannst nur seriell debuggen. Neustart kann auf Speicherengpass hindeuten. Wieviel hast Du noch frei? Oder die Stromversorgung muckt.

olay, nur seriell, das ist sehr schade. Speicher sollte noch genug sein. Glaub waren gerade mal 26% belegt.

MaHa76: Mal ein alternativer Vorschlag: Du nimmst einen Ultraschallsensor, läßt dir den Abstand in cm ausgeben und rechnest das entsprechend dem Abstand der LEDs zueinander um. Damit kannst du auch darauf reagieren, wenn jemand auf der TReppe umkehrt oder langsamer oder schneller läuft....

Ultraschall wollte ich zum einen wegen evtl Haustiere nicht nehmen. Keine Ahnung, wie die das evtl aufnehmen. Zudem ist die Treppe 2x um 45 Grad gewendelt.

@serenifly und uwefed: Danke fürs das Feedback. Prüfe ich gleich morgen.

Na gut, dem Wendel könnte man mit einem 2. Ultraschallsensor begegnen. Wie Haustiere reagieren kann der Tierarzt sagen...

Kann man machen... muss man aber nicht. ;-)

So exakt müssen das Ding nachher nicht laufen. Wenn es bei 100 Treppenläufen mal 2x vor oder nachläuft, ist das okay. Wer weiß, wie oft das Ding nachher im Alltag wirklich mitläuft, oder nachher doch einfach nur indirekt weiss leuchtet. ;-)

Grundsätzlich geht es hier ja erstmal darum, dass das vorhandene funktioniert. :-)

NightWatcher: Ziel ist es, dass man PIR1 passiert, und das Licht von dort in die andere Richtung hochläuft und beim passieren von PIR2 die LEDs wieder ausfaden.

Genauso andersrum.

Einer betritt die Treppe unten, etwas später jemand oben, dann stehen beide im Dunkeln, oder? Soll das auf einer realen Treppe laufen?

Ich habe mal Deinen Sketch getestet und erstmal nix gesehen. Nachdem ich dann Verzögerungen eingebaut habe, sah ich auch das Faden. Nur dauert das dann für die ganze Treppe doch recht lange. Wie ist da Dein Eindruck?

Einen Absturz hatte ich bislang nicht :)

Servus,

uwefed: for(int i=nAnzahlStufen;i>=0;i--)

müßte nicht

for(int i=(nAnzahlStufen-1);i>=0;i--)

heißen? Grüße Uwe

Du hast glaube ich recht. Das Array hat ja den Index immer -1 zur Menge, da er ab 0 ja bereits anfängt zu indexieren. Danke für den Hinweis auf den Fehler :-)

@agmue: ja in der Tat KANN es bei solchen in unserem Haushalt recht unüblichen Konstellationen zu Fehlverhalten kommen. Evtl. wird da später auch noch was umgebaut. Dafür ist der Arduino doch auch da. Man merkt dann im Alltag, wie man was ändern muss und kann dann dank offener Software wengistens reagieren :-)

Mir reicht es ja, wenn es erstmal so läuft, wie gewünscht - auch um mal das Thema Arduino an einem praktischen Beispiel besser kennen zu lernen. Ich könnte hier im Haus noch dutzendfach weitere Arduinos verbauen :-D

Das Initiale Faden läuft bei mir einwandfrei. Die delays habe ich so eingebaut, wie es bei mir "smooth" aussieht.

Der Absturz kam immer, sobald ich einen PIN Eingang kurz auf High gesetzt habe (bzw. dies der PIR tat).

Innerhalb von void StufenFadenEin(int d) habe ich mir nAnzahlStufen ausgeben lssen, hatte einen Wert von über 33000. Dann habe ich es auf const geändert, nun steht da 11 drin. Grübel ... :confused:

NightWatcher: Evtl. wird da später auch noch was umgebaut. Dafür ist der Arduino doch auch da. Man merkt dann im Alltag, wie man was ändern muss und kann dann dank offener Software wengistens reagieren :-)

Wenn Du das so entspannt siehst, ist das prima. Und bis dahin hat die Familie halt immer eine Taschenlampe in der Hand, damit niemand stürzt und mich dann dafür verantwortlich macht. Ja, so geht es :)

Für die Familie gibt es noch stinknormale Wandlampen, die ja sogar jetzt auch vorhanden sind.

Solche Stufenbeleuchtungen sind doch nur “spielerei”, wie eben sovieles in der Gebäudesteuerung. Es gibt immer ein “Fallback” bei mir. In dem Fall eben die normale Beleuchtung.

Aktueller Stand

#include "FastLED.h"

#define DATA_PIN 11
#define CLOCK_PIN 12

#define serialRate 115200

#define sensor1PIN 2
#define sensor2PIN 3

#define LEDHUE 50
#define LEDSAT 255

#define DIR_UP 1
#define DIR_DOWN 2

#define ACTION_ON 1
#define ACTION_OFF 2

#define FADE_STEPS 15

#define bDebug 0
#define bInitialesFaden 1

byte nAnzahlLEDjeStufe[] = {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; // Von unten nach oben

int nAnzahlLEDsGesamt;
int nAnzahlStufen;
int nAktuelleLED;
int nDirection;
int nAction;

bool bBelAn;

CRGB leds[44]; //TO-DO

void setup() {

  Serial.begin(serialRate);
  if(bDebug)
    Serial.print("Initialisieren\n");
  delay(500);

  nAnzahlStufen = sizeof nAnzahlLEDjeStufe;
  
  for(int i=0;i<nAnzahlStufen;i++){
    nAnzahlLEDsGesamt += nAnzahlLEDjeStufe[i];
  }
  
  FastLED.addLeds<WS2801, DATA_PIN, CLOCK_PIN, RBG>(leds, nAnzahlLEDsGesamt);
  LEDS.showColor(CRGB(0, 0, 0));

  // Interne LED ansteuern
  pinMode(13, OUTPUT);
  pinMode(sensor1PIN, INPUT);
  pinMode(sensor2PIN, INPUT);

  if(bInitialesFaden)
    alleLEDsDurchfaden();
}

void StufenFadenEin(int d)
{
  int nStufe;
  bBelAn = true;
  nAktuelleLED = 0;

  if(d == DIR_DOWN)
    nAktuelleLED = nAnzahlLEDsGesamt-1;

  if(bDebug)
    Serial.print("Stufenbeleuchtung einschalten\n");

  for(int i=0;i<nAnzahlStufen;i++)
  { //Schleife durch die einzelnen Stufen/Strips
    nStufe = i;
    
    if(d == DIR_DOWN)
      nStufe = (nAnzahlStufen-1)-i;
    
    for (int FADE = 0; FADE <= 255; FADE+=FADE_STEPS)
    { //Schleife durch 255 Helligkeitsstufen
      for(int j=0;j<nAnzahlLEDjeStufe[nStufe];j++)
      { //Schleife durch die LEDs des Strips/je Stufe
        if(d == DIR_DOWN)
          leds[nAktuelleLED-j].setHSV(LEDHUE, LEDSAT, FADE);
        else
          leds[nAktuelleLED+j].setHSV(LEDHUE, LEDSAT, FADE);
      }
      FastLED.show();
    }
    if(d == DIR_DOWN)
      nAktuelleLED -= nAnzahlLEDjeStufe[nStufe];
     else
      nAktuelleLED += nAnzahlLEDjeStufe[nStufe];
      
    delay(500);
    /*if(int dirTMP = getDirection() > 0 && dirTMP != nDirection)
    { // Benutzer hat den zweiten PIR erreicht
      setDirection(dirTMP);
      Serial.print("LEDS ausschalten\n");
      StufenFadenAus(DIR_DOWN);
      break;
    }*/
  }
}

void StufenFadenAus(int d)
{
  int nStufe;
  nAktuelleLED = nAnzahlLEDsGesamt;

  if(d == DIR_DOWN)
    nAktuelleLED = 0-1;

  if(bDebug)
    Serial.print("Stufenbeleuchtung ausschalten\n");
  
  for(int i=nAnzahlStufen;i>0;i--)
  { //Schleife durch die einzelnen Stufen/Strips
    nStufe = i-1;
    
    if(d == DIR_DOWN)
      nStufe = nAnzahlStufen-i;
    
    for (int FADE = 255; FADE >= 0; FADE-=FADE_STEPS)
    { //Schleife durch 255 Helligkeitsstufen
      for(int j=nAnzahlLEDjeStufe[nStufe];j>0;j--)
      { //Schleife durch die LEDs des Strips/je Stufe        
        if(d == DIR_DOWN)
          leds[nAktuelleLED+j].setHSV(LEDHUE, LEDSAT, FADE);
        else
          leds[nAktuelleLED-j].setHSV(LEDHUE, LEDSAT, FADE);
      }
      FastLED.show();
    }
    if(d == DIR_DOWN)
      nAktuelleLED += nAnzahlLEDjeStufe[nStufe];
    else
      nAktuelleLED -= nAnzahlLEDjeStufe[nStufe];
    
    delay(500);
  }

  bBelAn = false;
}

int getDirection()
{  
  if(readPIR() == sensor1PIN)
  { // von unten anfangen
    if(bDebug)
      Serial.print("Laufrichtung Hoch\n");
    return DIR_UP;
  }
  else if(readPIR() == sensor2PIN)
  { // von oben anfangen
    if(bDebug)
      Serial.print("Laufrichtung Runter\n");
    return DIR_DOWN;
  }
  
  return 0;
}

int readPIR()
{
  if(digitalRead(sensor1PIN) == HIGH)
  { // von unten anfangen
    return sensor1PIN;
  }
  else if(digitalRead(sensor2PIN) == HIGH)
  { // von oben anfangen
    return sensor2PIN;
  }
  
  return false;
}

void setDirection(int d)
{
  nDirection = d;
}

void setAction(int a)
{
  nAction = a;
}

void alleLEDsDurchfaden()
{
  bBelAn = true;
  for(int j=1;j<=nAnzahlLEDsGesamt;j++)
  {
    for (int FADE = 0; FADE <= 255; FADE+=FADE_STEPS)
    {
      leds[j].setHSV(LEDHUE, LEDSAT, FADE);
      FastLED.show();
    }
  }

  for(int j=nAnzahlLEDsGesamt;j>=0;j--)
  {
    for (int FADE = 255; FADE >= 0; FADE-=FADE_STEPS)
    {
      leds[j].setHSV(LEDHUE, LEDSAT, FADE);
      FastLED.show();
    }
  }

  bBelAn = false;
}

void loop()
{
  setDirection(getDirection());

  switch (nDirection) {
    case DIR_UP:
    case DIR_DOWN:
      digitalWrite(13, HIGH);
      
      if(!bBelAn)
        StufenFadenEin(nDirection);
      else
        StufenFadenAus(nDirection);
      break;
    
    default: 
      digitalWrite(13, LOW);
      
      if(bDebug)
        Serial.print("Warte auf Bewegung am PIR\n");
        
    break;
  }
}

Läuft bei mir nun soweit.

NightWatcher:
Für die Familie gibt es noch stinknormale Wandlampen, die ja sogar jetzt auch vorhanden sind.

Das lese ich gerne :smiley:

NightWatcher:
Läuft bei mir nun soweit.

Das freut mich für Dich! Bei mir auch, aber wer zu spät kommt … :frowning: … kann Anmerkungen machen:
In alleLEDsDurchfaden()

 for (int j = 0; j < nAnzahlLEDsGesamt; j++)
...
  for (int j = nAnzahlLEDsGesamt - 1; j >= 0; j--)

Grundsätzlich: Du machst Datenverarbeitung, der Arduino möchte Echtzeitverarbeitung. Das Faden geht über blockierende for-Schleifen. Während dieser Zeit können keine Signale von den PIRs verarbeitet werden.

Stimmt, deshalb ist in der forschleife auch bereits ein auskommentierter Block, der dort nach jedem Durchgang die PIR abfragt, ob sich was geändert hat.

Das ist aber noch TODO, weil noch nicht getestet und dahingeschrieben, damit ich dran denke und weiss, wo ich angesetzt hatte :-D