Elegant automatic stair lighting (part5)

Hello and welcome to the last of the part of the series "elegant automatic stair lighting".

 

Today, we round off our control system with a convenient configuration option for all operating parameters. All operating parameters can now be conveniently set via the serial interface at rest (all stair lights inactive) and are stored in the internal EEPROM of the uC's. Thus, all settings are maintained even in the event of a restart or a power failure. All adjustable parameters are explained individually at the end of the document. Since the function is completely realized in software, the technical structure does not change compared to part 4 of the series. Nevertheless, for the sake of completeness, this should be presented again:

Picture from Part 4

 

The list of components for the project and all hints from the previous parts do not change:

 

Number

Description

Note

2

Pir Module HC-SR501 PIR

Motion sensor

up to 62

PCA9685 16 Channel 12 Bit PWM Driver

Number depending on the number of stairs /16

1

Nano V3

 

1

MB102 Power Supply Adapter

For breadboard setup

up to 992

IRF520 MOS Driver Module 0-24V 5A

Number depending on the number of stairs

1

Power supply for LED/lamps for the steps

Maximum 24 volts

1

10 KOhm Rematch

 

1

Ldr

Photo re-stand

 

It can be WITHOUT prior adjustment the following code can be uploaded to the Arduino:

 

 

#include <Wire.H>
#include <Eeprom.H>

#define PWM_Module_Base_Addr 0x40 10000000b The last bit of the address byte defines the operation to be performed. When set to logical 1 0x41 module 2 etc.. Address range0x40 - 0x47 
selects a read operation while a logical 0 selects a write operation.
#define OE_Pin  8                 Pin for Output Enable 
#define CPU_LED_Pin 13            Internal board LED to pin 13 (for debugging purposes)
#define PIRA_Pin 2
#define PIRB_Pin 3
#define Num_Stages_per_Module 16
#define LDR_Pin A2                Analog pin to measure brightness. (LDR Re-energism)
#define DEBUG
#define L_Sens_Scope 50
#define MaxInputBufferSize 5 maximum 255 characters to adapt to vlcdr


Struct WiFiEEPromData
{   Adjustable operating parameters (constants)   Int Delay_ON_to_OFF = 10;          Minimum waiting time to the "Off Sequence" in seconds   Int Overall_Stages =  8;         maximum number of steps: 62 x 16 = 992   Int delay_per_Stage_in_ms = 100;   Int DayLight_Brightness_Border = 600; Brightness Limit Automatic - Higher Value - Higher Brightness   Byte Delay_Stages_ON = 20;   Byte Delay_Stages_OFF = 20;   Char ConfigValid[3]; If Config is Vaild, tag "TK" is required"
};


Global variables
Int Pwm_Channel = 0;
Int Pwm_Channel_Brightness = 0;
Bool Motion_Trigger_Down_to_Up = False;
Bool Motion_Trigger_Up_to_Down = False;
Bool On_Delay = False;
Bool DayLight_Status = True;
Bool DLightCntrl = True;
Byte PWMModules = 0;
Byte StagesLeft = 0;
interrupt Control
volatile Byte A60telSeconds24 = 0;
volatile Byte Seconds24;
Serial Input Handling
Char TBuffer;
Char Cbuffer[MaxInputBufferSize + 1];     USB Code Input Buffer
String Sbuffer = "";                      USB String Input Buffer
Int Value;                                USB Nummeric Input Buffer
Byte Ccount { 0 };                          Number received Chars
Byte Inptype = 0;
Boolean StrInput = False;
Boolean NumberInput = False;
Boolean DataInput = False;
Boolean EnterInput = False;
Byte MenueSelection = 0;
Byte MnuState = 0;            Maximum menu depth 255 icl Sub
WiFiEEPromData MyConfig;


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)   {     If (!(Motion_Trigger_Up_to_Down) and !(Motion_Trigger_Down_to_Up))     {       digitalWrite(CPU_LED_Pin, High);       Motion_Trigger_Down_to_Up = True;     } PIR A triggered   } else   {     digitalWrite(CPU_LED_Pin, Low);   }
}

Void ISR_PIR_B()
{   Bool PinState = digitalRead(PIRB_Pin);   If (PinState)   {     If (!(Motion_Trigger_Down_to_Up) and !(Motion_Trigger_Up_to_Down))     {       digitalWrite(CPU_LED_Pin, High);       Motion_Trigger_Up_to_Down = True;     } PIR B triggered   } else   {     digitalWrite(CPU_LED_Pin, Low);   }
}

Void Init_PWM_Module(Byte PWM_ModuleAddr)
{   digitalWrite(OE_Pin, High); Active LOW Output Activation Pin (OE).   Wire.beginTransmission(PWM_ModuleAddr); Initiate data transfer   Wire.Write(0x00);                       //   Wire.Write(0x06);                       Software Reset   Wire.endTransmission();                 Stop Communication - Send Stop Bit   Delay(400);   Wire.beginTransmission(PWM_ModuleAddr); Initiate data transfer   Wire.Write(0x01);                       Select Mode 2 Register (Command Register)   Wire.Write(0x04);                       Configure Chip: 0x04: dead pole output 0x00: Open drain output.   Wire.endTransmission();                 Stop Communication - Send Stop Bit   Wire.beginTransmission(PWM_ModuleAddr); Initiate data transfer   Wire.Write(0x00);                      Select Mode 1 Register (Command Register)   Wire.Write(0x10);                      Configure SleepMode   Wire.endTransmission();                Stop Communication - Send Stop Bit   Wire.beginTransmission(PWM_ModuleAddr); Initiate data transfer   Wire.Write(0xFE);                       Select PRE_SCALE register   Wire.Write(0x03);                       Set Prescaler. The maximum PWM frequency is 1526 Hz if the PRE_SCALEer the operator is set to "0x03h". Standard: 200 Hz   Wire.endTransmission();                 Stop Communication - Send Stop Bit   Wire.beginTransmission(PWM_ModuleAddr); Initiate data transfer   Wire.Write(0x00);                       Select Mode 1 Register (Command Register)   Wire.Write(0xA1);                       Configure Chip: ERrlaube All Call I2C addresses, use internal clock, / Allow Auto Increment Feature   Wire.endTransmission();                 Stop Communication - Send Stop Bit
}


Void Init_PWM_Outputs(Byte PWM_ModuleAddr)
{   digitalWrite(OE_Pin, High); Active LOW Output Activation Pin (OE).   for ( Int Z = 0; Z < 16 + 1; Z++)   {     Wire.beginTransmission(PWM_ModuleAddr);     Wire.Write(Z * 4 + 6);      Select PWM_Channel_ON_L register     Wire.Write(0x00);                     Value for above register     Wire.endTransmission();     Wire.beginTransmission(PWM_ModuleAddr);     Wire.Write(Z * 4 + 7);      Select PWM_Channel_ON_H register     Wire.Write(0x00);                     Value for above register     Wire.endTransmission();     Wire.beginTransmission(PWM_ModuleAddr);     Wire.Write(Z * 4 + 8);   Select PWM_Channel_OFF_L register     Wire.Write(0x00);        Value for above register     Wire.endTransmission();     Wire.beginTransmission(PWM_ModuleAddr);     Wire.Write(Z * 4 + 9);  Select PWM_Channel_OFF_H register     Wire.Write(0x00);             Value for above register     Wire.endTransmission();   }   digitalWrite(OE_Pin, Low); Active LOW Output Activation Pin (OE).
}

Void Setup()
{   Initalization   Serial.Begin(9600);   pinMode(PIRA_Pin, Input);   pinMode(PIRB_Pin, Input);   pinMode(OE_Pin, Output);   pinMode(CPU_LED_Pin, Output);   pinMode(LDR_Pin, Input);   PWMModules = MyConfig.Overall_Stages / 16;   StagesLeft = ( MyConfig.Overall_Stages % 16) - 1;   If (StagesLeft >= 1) {     PWMModules++;   }   Wire.Begin(); Initalisia I2C Bus A4 (SDA), A5 (SCL)   for (Byte ModuleCount = 0; ModuleCount < PWMModules; ModuleCount++)   {     Init_PWM_Module(PWM_Module_Base_Addr + ModuleCount);     Init_PWM_Outputs(PWM_Module_Base_Addr + ModuleCount);   }   If (!(loadEEPROM_Config())) Load Seetings from EEPROM   {     Serial.println(Q("EEPROM Standard Settings saved."));     MyConfig.Delay_ON_to_OFF = 10;          // Minimum Wartezeit bis zur "Aus Sequenz" in Sekunden     MyConfig.Overall_Stages =  8;         // maximale Stufenanzahl: 62 x 16 = 992     MyConfig.delay_per_Stage_in_ms = 100;     MyConfig.DayLight_Brightness_Border = 600; // Helligkeitsgrenze Automatik - Höherer Wert - Höhere Helligkeit     MyConfig.Delay_Stages_ON = 20;     saveEEPROM_Config();   }   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();   Serial.println(F("Init_Complete"));
}

/** Save Config to EEPROM */

bool loadEEPROM_Config()
{   bool RetValue;   EEPROM.get(0, MyConfig);   EEPROM.end();   if (String(MyConfig.ConfigValid) = String("TK"))   {     RetValue = true;   } else   {     RetValue = false; // Settings not found.   }   return RetValue;
}

/** Store Config to EEPROM */
bool saveEEPROM_Config()
{   strncpy( MyConfig.ConfigValid , "TK", sizeof(MyConfig.ConfigValid) );   EEPROM.put(0, MyConfig);   EEPROM.end();   return true;
}

bool DayLightStatus ()
{   int SensorValue = 0;   bool ReturnValue = true;   SensorValue = analogRead(LDR_Pin);
#ifdef DEBUG   Serial.print(F("DayLightStatus: "));   Serial.print(SensorValue);
#endif   if (SensorValue > MyConfig.DayLight_Brightness_Border)   {     if ((DayLight_Status) and (SensorValue > MyConfig.DayLight_Brightness_Border + L_Sens_Scope))     {       ReturnValue = false;       DayLight_Status = false;     } else if (!(DayLight_Status))     {       ReturnValue = false;       DayLight_Status = false;     }
#ifdef DEBUG     Serial.println(F(" OFF"));
#endif   } else   {     if ((DayLight_Status) and (SensorValue > MyConfig.DayLight_Brightness_Border - L_Sens_Scope))     {       ReturnValue = true;       DayLight_Status = true;     } else if (!(DayLight_Status))     {       ReturnValue = true;       DayLight_Status = true;     }
#ifdef DEBUG     Serial.println(F(" ON"));
#endif   }   return ReturnValue;
}

void Down_to_Up_ON()
{
#ifdef DEBUG   Serial.println(F("Down_to_Up_ON"));
#endif   byte Calc_Num_Stages_per_Module = Num_Stages_per_Module;   for (byte ModuleCount = 0; ModuleCount < PWMModules; ModuleCount++)   {     Pwm_Channel = 0;     Pwm_Channel_Brightness = 4095;     if ((StagesLeft >= 1) and (ModuleCount == PWMModules - 1))     {       Calc_Num_Stages_per_Module = StagesLeft;     }     else     {       Calc_Num_Stages_per_Module = Num_Stages_per_Module;     }     Pwm_Channel = 0;     Pwm_Channel_Brightness = 0;     while (Pwm_Channel < Calc_Num_Stages_per_Module + 1)     {       Wire.beginTransmission( PWM_Module_Base_Addr + ModuleCount);       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 + ModuleCount);       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 + MyConfig.Delay_Stages_ON;         if (Pwm_Channel_Brightness > 4095) {           Pwm_Channel_Brightness = 4095;         }       } else if ( Pwm_Channel < Num_Stages_per_Module + 1)       {         Pwm_Channel_Brightness = 0;         delay(MyConfig.delay_per_Stage_in_ms);         Pwm_Channel++;       }     }   }
}

void Up_to_DOWN_ON()
{
#ifdef DEBUG   Serial.println(F("Up_to_DOWN_ON "));
#endif   byte Calc_Num_Stages_per_Module = Num_Stages_per_Module;   int ModuleCount = PWMModules - 1;   while (ModuleCount >= 0)   {     Pwm_Channel_Brightness = 0;     if ((StagesLeft >= 1) and (ModuleCount == PWMModules - 1))     {       Calc_Num_Stages_per_Module =  StagesLeft;     }     else     {       Calc_Num_Stages_per_Module = Num_Stages_per_Module;     }     Pwm_Channel = Calc_Num_Stages_per_Module;     while (Pwm_Channel > -1)     {       Wire.beginTransmission( PWM_Module_Base_Addr + ModuleCount);       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 + ModuleCount);       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 + MyConfig.Delay_Stages_ON;         if (Pwm_Channel_Brightness > 4095) {           Pwm_Channel_Brightness = 4095;         }       } else if ( Pwm_Channel >= 0)       {         Pwm_Channel_Brightness = 0;         delay(MyConfig.delay_per_Stage_in_ms);         Pwm_Channel--;         if ( Pwm_Channel < 0)         {           Pwm_Channel = 0;           break;         }       }     }     ModuleCount = ModuleCount - 1;   }
}

void Down_to_Up_OFF()
{
#ifdef DEBUG   Serial.println(F("Down_to_Up_OFF"));
#endif   byte Calc_Num_Stages_per_Module = Num_Stages_per_Module;   for (byte ModuleCount = 0; ModuleCount < PWMModules; ModuleCount++)   {     Pwm_Channel = 0;     Pwm_Channel_Brightness = 4095;     if ((StagesLeft >= 1) and (ModuleCount == PWMModules - 1))     {       Calc_Num_Stages_per_Module = StagesLeft;     }     else     {       Calc_Num_Stages_per_Module = Num_Stages_per_Module;     }     while (Pwm_Channel < Calc_Num_Stages_per_Module + 1)     {       Wire.beginTransmission( PWM_Module_Base_Addr + ModuleCount);       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 + ModuleCount);       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 - MyConfig.Delay_Stages_OFF;         if (Pwm_Channel_Brightness < 0) {           Pwm_Channel_Brightness = 0;         }       } else if ( Pwm_Channel < Num_Stages_per_Module + 1)       {         Pwm_Channel_Brightness = 4095;         delay(MyConfig.delay_per_Stage_in_ms);         Pwm_Channel++;       }     }   }
}

void Up_to_DOWN_OFF()
{
#ifdef DEBUG   Serial.println(F("Up_to_DOWN_OFF"));
#endif   byte Calc_Num_Stages_per_Module = Num_Stages_per_Module;   int ModuleCount = PWMModules - 1;   while (ModuleCount >= 0)   {     Pwm_Channel_Brightness = 4095;     if ((StagesLeft >= 1) and (ModuleCount == PWMModules - 1))     {       Calc_Num_Stages_per_Module = StagesLeft;     }     else     {       Calc_Num_Stages_per_Module = Num_Stages_per_Module;     }     Pwm_Channel = Calc_Num_Stages_per_Module;     while (Pwm_Channel > -1)     {       Wire.beginTransmission(PWM_Module_Base_Addr + ModuleCount);       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 + ModuleCount);       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 - MyConfig.Delay_Stages_OFF;         if (Pwm_Channel_Brightness < 0) {           Pwm_Channel_Brightness = 0;         }       } else if ( Pwm_Channel >= 0)       {         Pwm_Channel_Brightness =  4095;         delay(MyConfig.delay_per_Stage_in_ms);         Pwm_Channel--;         if ( Pwm_Channel < 0)         {           Pwm_Channel = 0;           break;         }       }     }     ModuleCount = ModuleCount - 1;   }
}

void Stages_Light_Control ()
{   if ((Motion_Trigger_Down_to_Up) and !(On_Delay))   {     DLightCntrl = DayLightStatus();     if (DLightCntrl)     {       Seconds24 = 0;       On_Delay = true;       Down_to_Up_ON();     } else {       Motion_Trigger_Down_to_Up = false;     }   }   if ((On_Delay) and (Seconds24 > MyConfig.Delay_ON_to_OFF) and (Motion_Trigger_Down_to_Up) )   {     Down_to_Up_OFF();     Motion_Trigger_Down_to_Up = false;     On_Delay = false;     Seconds24 = 0;   }   if ((Motion_Trigger_Up_to_Down) and !(On_Delay))   {     DLightCntrl = DayLightStatus();     if (DLightCntrl)     {       Seconds24 = 0;       On_Delay = true;       Up_to_DOWN_ON();     } else {       Motion_Trigger_Up_to_Down = false;     }   }   if ((On_Delay) and (Seconds24 > MyConfig.Delay_ON_to_OFF) and (Motion_Trigger_Up_to_Down))   {     Up_to_DOWN_OFF();     Motion_Trigger_Up_to_Down = false;     On_Delay = false;     Seconds24 = 0;   }
}

//Serial Command Interpreter Functions -------------------------------

void ClearCBuffer ()
{   for (byte a = 0; MaxInputBufferSize - 1; a++)     Cbuffer[a] = 0;
}

boolean CheckforserialEvent()
{   while (Serial.available()) {     // get the new byte:     TBuffer = Serial.read();     if (TBuffer > 9 && TBuffer < 14)     {       Cbuffer[Ccount] = 0;       TBuffer = 0;       Serial.print(char(13));       Serial.flush();       Serial.println("");       Sbuffer = "";       value = 0;       EnterInput = true;       return true;     } else if (TBuffer > 47 && TBuffer < 58 )     {       if ( Ccount < MaxInputBufferSize)       {         Cbuffer[Ccount] = TBuffer;         Ccount++;       } else {         Serial.print("#");       }       //Number Input detected       NumberInput = true;     }     else if (TBuffer > 64 && TBuffer < 123 )     {       if ( Ccount < MaxInputBufferSize)       {         Cbuffer[Ccount] = TBuffer;         Ccount++;         Serial.print(char(TBuffer));         Serial.flush();       }       //Character Char Input detected       StrInput = true;     }     else if ( (TBuffer == 127 )  |  (TBuffer == 8 ) )     {       if ( Ccount > 0)       {         Ccount--;         Cbuffer[Ccount] = 0;         Serial.print("-");         Serial.flush();       }     }     else     {       if ( Ccount < MaxInputBufferSize)       {         Cbuffer[Ccount] = TBuffer;         Ccount++;         Serial.print(char(TBuffer));         Serial.flush();         //Data Input detected         DataInput = true;       }       return false;     }     return false;   }
}

byte SerInputHandler()
{   byte result = 0;   int c;   int d;   int a;   int b;   result = 0;   if (CheckforserialEvent())   {     if ((NumberInput) and not (DataInput) and not (StrInput))    //Numbers only     {       Sbuffer = "";       value = 0;       StrInput = false;       NumberInput = false;       DataInput = false;       EnterInput = false;       a = 0;       b = 0;       c = 0;       d = 0;       Sbuffer = Cbuffer; // Zahl wird AUCH ! in SBUFFER übernommen, falls benötigt.       if (Ccount == 1) {         value  = Cbuffer[0] - 48 ;       }       if (Ccount == 2) {         a = Cbuffer[0] - 48 ;         a = a * 10;         b = Cbuffer[1] - 48 ;         value = a + b;       }       if (Ccount == 3) {         a = Cbuffer[0] - 48 ;         a = a * 100;         b = Cbuffer[1] - 48 ;         b = b * 10;         c = Cbuffer[2] - 48 ;         value = a + b + c;       }       if (Ccount == 4) {         a = Cbuffer[0] - 48 ;         a = a * 1000;         b = Cbuffer[1] - 48 ;         b = b * 100;         c = Cbuffer[2] - 48 ;         c = c * 10;         d = Cbuffer[3] - 48 ;         value = a + b + c + d;       }       if (Ccount >= 5)       {         Sbuffer = "";         value = 0;         Sbuffer = Cbuffer;         ClearCBuffer;         result = 2;       } else       {         ClearCBuffer;         Ccount = 0;         result = 1;                                                //Number Returncode         NumberInput = false;         StrInput = false;         DataInput = false;         EnterInput = false;         Ccount = 0;         return result;       }     }     if ((StrInput) and not (DataInput))                          //String Input only     {       Sbuffer = "";       Sbuffer = Cbuffer;       value = 0;       StrInput = false;       NumberInput = false;       DataInput = false;       EnterInput = false;       Ccount = 0;       ClearCBuffer;       result = 2;                                                 //Number Returncode     }     if (DataInput) {       Sbuffer = "";       Sbuffer = Cbuffer;       value = 0;       StrInput = false;       NumberInput = false;       DataInput = false;       EnterInput = false;       Ccount = 0;       ClearCBuffer;       result = 3;                                               //Number Returncode     }     if ((EnterInput) and not (StrInput) and not (NumberInput) and not (DataInput))     {       Sbuffer = "";       value = 0;       Ccount = 0;       ClearCBuffer;       result = 4;                                               //Number Returncode     }     NumberInput = false;     StrInput = false;     DataInput = false;     EnterInput = false;     Ccount = 0;     return result;   }   return result;   //End CheckforSerialEvent
}

void SerialcommandProcessor()
{   int a;   Inptype = 0;   Inptype = SerInputHandler();   // 0 keine Rückgabe   // 1 Nummer   // 2 String   // 3 Data   if (Inptype > 0)   {     MenueSelection = 0;     if ((MnuState < 2) && (Inptype == 2)) {       Sbuffer.toUpperCase();  // For Easy Entering Commands     }     if ((Sbuffer == "D") && (MnuState == 0) && (Inptype == 2))   {       MenueSelection = 1;     }     if ((Sbuffer == "O") && (MnuState == 0) && (Inptype == 2))       {       MenueSelection = 2;     }     if ((Sbuffer == "T") && (MnuState == 0) && (Inptype == 2))       {       MenueSelection = 3;     }     if ((Sbuffer == "B") && (MnuState == 0) && (Inptype == 2))       {       MenueSelection = 4;     }     if ((Sbuffer == "N") && (MnuState == 0) && (Inptype == 2))   {       MenueSelection = 5;     }     if ((Sbuffer == "F") && (MnuState == 0) && (Inptype == 2))       {       MenueSelection = 6;     }     If ((MnuState == 2) && (Inptype == 1))                          {       MenueSelection = 8;     }     If ((MnuState == 3) && (Inptype == 1))                          {       MenueSelection = 9;     }     If ((MnuState == 4) && (Inptype == 1))                          {       MenueSelection = 10;     }     If ((MnuState == 5) && (Inptype == 1))                          {       MenueSelection = 11;     }     If ((MnuState == 6) && (Inptype == 1))                          {       MenueSelection = 12;     }     If ((MnuState == 7) && (Inptype == 1))                          {       MenueSelection = 13;     }     If (MnuState == 10)                                              {       MenueSelection = 21; Time Set     }     If (MnuState == 11)                                              {       MenueSelection = 24; Time Set     }     If (MnuState == 12)                                              {       MenueSelection = 25; Time Set     }     If (MnuState == 13)                                              {       MenueSelection = 27; Background Set     }     If (MnuState == 14)                                              {       MenueSelection = 29; ClockFace Set     }     Switch (MenueSelection)     {       Case 1:         {           Serial.println("Delay ON to OFF: (1-65000)");           MnuState = 2;           Value = 0;           Sbuffer = "";           Break;         }       Case 2:         {           Serial.println("Overall Stages: (1-992)");           MnuState = 3;           Value = 0;           Sbuffer = "";           Break;         }       Case 3:         {           Serial.println("Delay per Stage in ms: (1-65000)");           MnuState = 4;           Value = 0;           Sbuffer = "";           Break;         }       Case 4:         {           Serial.println("DayLight Brightness Border: (0-65000)");           MnuState = 5;           Value = 0;           Sbuffer = "";           Break;         }       Case 5:         {           Serial.println("Delay Stages ON: (1-254)");           MnuState = 6;           Value = 0;           Sbuffer = "";           Break;         }       Case 6:         {           Serial.println("Delay Stages OFF: (1-254)");           MnuState = 7;           Value = 0;           Sbuffer = "";           Break;         }       Case 8:         {           MyConfig.Delay_ON_to_OFF = Value;           saveEEPROM_Config();           Serial.Print(Q("Delay_ON_to_OFF set to:"));           Serial.println(MyConfig.Delay_ON_to_OFF);           MnuState = 0;           Sbuffer = "";           Value = 0;           Break;         }       Case 9:         {           MyConfig.Overall_Stages = Value;           saveEEPROM_Config();           Serial.Print(Q("Overall Stages set to:"));           Serial.println(MyConfig.Overall_Stages);           MnuState = 0;           Sbuffer = "";           Value = 0;           Break;         }       Case 10:         {           MyConfig.delay_per_Stage_in_ms = Value;           saveEEPROM_Config();           Serial.Print(Q("Delay per Stage in ms set to:"));           Serial.println(MyConfig.delay_per_Stage_in_ms);           MnuState = 0;           Sbuffer = "";           Value = 0;           Break;         }       Case 11:         {           MyConfig.DayLight_Brightness_Border = Value;           saveEEPROM_Config();           Serial.Print(Q("DayLight Brightness Border set to:"));           Serial.println(MyConfig.DayLight_Brightness_Border);           MnuState = 0;           Sbuffer = "";           Value = 0;           Break;         }       Case 12:         {           MyConfig.Delay_Stages_ON = Value;           saveEEPROM_Config();           Serial.Print(Q("Delay Stages ON set to:"));           Serial.println(MyConfig.Delay_Stages_ON);           MnuState = 0;           Sbuffer = "";           Value = 0;           Break;         }       Case 13:         {           MyConfig.Delay_Stages_OFF = Value;           saveEEPROM_Config();           Serial.Print(Q("Delay Stages OFF set to:"));           Serial.println(MyConfig.Delay_Stages_OFF);           MnuState = 0;           Sbuffer = "";           Value = 0;           Break;         }       Default:         {           MnuState = 0;           Serial.println(Q("-Stair light control -"));           Serial.Print(Q("D - Delay ON to OFF / Current Value:"));           Serial.println(MyConfig.Delay_ON_to_OFF);           Serial.Print(Q("O - Overall Stages / Current Value:"));           Serial.println(MyConfig.Overall_Stages);           Serial.Print(Q("T - Delay per Stage in ms / Current Value:"));           Serial.println(MyConfig.delay_per_Stage_in_ms);           Serial.Print(Q("B - DayLight Brightness Border / Current Value:"));           Serial.println(MyConfig.DayLight_Brightness_Border );           Serial.Print(Q("N - Delay Stages ON / Current Value:"));           Serial.println(MyConfig.Delay_Stages_ON);           Serial.Print(Q("F - Delay Stages OFF / Current Value:"));           Serial.println(MyConfig.Delay_Stages_OFF);           Serial.println(Q("Type Cmd and press Enter"));           Serial.Flush();           MnuState = 0;           Value = 0;           Sbuffer = "";         }     }   } Input detected
}

Void Loop()
{   Stages_Light_Control();   SerialcommandProcessor();
}

 

After the code has been uploaded, we can access the serial schni with 9600 baudTtposition. After an Enter (and inactive! Stair light) the following configuration menu appears:

 

Part 5 - Configuration Menu

 

 

Paramenter

Declaration

Delay ON to OFF

Time in SECONDS that keeps the stair lighting fully on

Overall Stages

Number of stairs of the stairs

Delay per Stage

Time in MILLISECONDS to wait until the next staircase is approached.

Daylight Brightness Border

Brightness in which the stair lighting becomes inactive. Higher value -> higher brightness

Delay Stages ON

Rel. Fading time when changing the stairs. Higher value - > less time

Delay Stages OFF

Rel. Fading time when CHANGING the stairs. Higher value - > less time

 

I wish you a lot of fun with the replica. As always, you can find all previous projects under the GitHub page https://github.com/kuchto

For arduinoProjects for advancedSensors

6 comments

Eugen

Eugen

Hallo nochmal! Melde mich, wie versprochen zurück. Habe alles soweit nachgebaut, und es funktioniert alles, bis auf zwei Sachen. Im seriellen Monitor lassen sich die Parameter zwar verändern, leider haben die Änderungen keinerlei Auswirkungen auf den Ablauf des Sketches.
Man kann ändern, was man will, aber das Programm läuft immer nur das eine Szenario ab. Selbst wenn man im Sketch die Variablen verändert, bleibt alles so, wie an Anfang. Mit einer Ausnahme, und zwar die Stufenanzahl lässt sich ändern. Ich weiß nicht, wo der Fehler sich versteckt, vielleicht habe ich etwas falsch gemacht.
Aber: wenn ich den Sketch aus dem Teil 4 hochlade, läuft alles prima und alle Parameter lassen sich wunderbar ändern. Schade, dass es mit dem Seriellen Monitor nicht klappt, aber das Programm aus dem Teil 4 läuft, habe alle Parameter so eingestellt, wie es mir passt.
Vielen Dank für die tolle Anleitung, meine Eltern sind total begeistert!
Viele Grüße

Eugen

Eugen

Hallo Tobias!
Das ist ein super Projekt! So simpel erklärt, so verständlich aufgebaut, einfach toll! Ich bin schon seit 3 Jahren auf der Suche nach einer Anleitung für so eine Treppenbeleuchtung. Eigentlich wollte ich selbständig versuchen, so ein Projekt zu entwickeln, leider fehlte mir immer die Zeit dafür. Jetzt bin ich überzeugt, dass ich es auf jeden Fall nachbauen werde. Die Bauteile sind schon bestellt, ich kann es kaum abwarten, loszulegen! Ich melde mich auf jeden Fall wieder, wenn ich es geschafft habe. Möchte mich aber jetzt schon herzlich bedanken!

Sebastian

Sebastian

Super interessantes Projekt. Ich hoffe dass das Thema W-lan und MQTT noch aufgegriffen wird und genau so genial erklärt wird, wie die anderen Projekte.

Helmut Tack

Helmut Tack

Bei dem Uno (Auslieferung vor 2018) gibt es Problem mit dem Hochladen.
Lösung hier https://forum.digikey.com/t/january-2018-arduino-nano-bootloader-update/1194

Wolfgang

Wolfgang

Super Projekt !!

Das ganze jetzt noch mit Wlan,
dann wäre es perfekt !!!!

LG
Wolfgang

stsc

stsc

Ein NodeMCU mit Steuerung per MQTT wäre auch interessant. Dann könnte man die Treppe in das Homesteuerungssystem einbinden.

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. Install ESP32 now from the board manager
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - ESP programming via WLAN