Hola y bienvenidos a la última parte de la serie "iluminación automática de escalera elegante".
Hoy en día, completamos nuestro sistema de control con una opción de configuración conveniente para todos los parámetros de funcionamiento. Todos los parámetros de funcionamiento ahora se pueden configurar convenientemente a través de la interfaz serie en reposo (todas las luces de escalera inactivas) y se almacenan en el EEPROM interno de los uC. Por lo tanto, todos los ajustes se mantienen incluso en caso de un reinicio o un fallo de alimentación. Todos los parámetros ajustables se explican individualmente al final del documento. Dado que la función se realiza completamente en software, la estructura técnica no cambia en comparación con la parte 4 de la serie. Sin embargo, en aras de la exhaustividad, esto debe ser presentado de nuevo:
La lista de componentes para el proyecto y todos los consejos de las partes anteriores no cambiar:
Número |
Descripción |
Nota |
2 |
Sensor de movimiento |
|
hasta 62 |
Número dependiendo del número de escaleras /16 |
|
1 |
|
|
1 |
Para la configuración de la placa de pan |
|
hasta 992 |
Número dependiendo del número de escaleras |
|
1 |
Fuente de alimentación para LED/lámparas para los pasos |
Máximo 24 voltios |
1 |
10 KOhm Revancha |
|
1 |
Re-stand fotográfico |
Puede ser SIN ajuste previo el siguiente código se puede cargar en el Arduino:
#include <Alambre.H> #include <Eeprom.H> #define PWM_Module_Base_Addr 0x40 10000000b El último bit del byte de dirección define la operación que se va a realizar. Cuando se establece en lógico 1 0x41 módulo 2 etc. Rango de direcciones0x40 - 0x47 selecciona una operación de lectura mientras que un 0 lógico selecciona una operación de escritura. #define OE_Pin 8 Pin para el activador de salida #define CPU_LED_Pin 13 LED de placa interna al pin 13 (para fines de depuración) #define PIRA_Pin 2 #define PIRB_Pin 3 #define Num_Stages_per_Module 16 #define LDR_Pin A2 Pin analógico para medir el brillo. (Reenergización LDR) #DEFINE DEBUG #define L_Sens_Scope 50 #define MaxInputBufferSize 5 máximo 255 caracteres para adaptarse a vlcdr Estructura WiFieePromData { Parámetros de funcionamiento ajustables (constantes) Int Delay_ON_to_OFF = 10; Tiempo de espera mínimo a la "Secuencia desactivada" en segundos Int Overall_Stages = 8; número máximo de pasos: 62 x 16 x 992 Int delay_per_Stage_in_ms = 100; Int DayLight_Brightness_Border = 600; Límite de brillo automático - Valor más alto - Brillo más alto Byte Delay_Stages_ON = 20; Byte Delay_Stages_OFF = 20; Char ConfigValid[3]; Si Config es Vaild, se requiere la etiqueta "TK"" }; Variables globales Int Pwm_Channel = 0; Int Pwm_Channel_Brightness = 0; Bool Motion_Trigger_Down_to_Up = Falso; Bool Motion_Trigger_Up_to_Down = Falso; Bool On_Delay = Falso; Bool DayLight_Status = Verdad; Bool DLightCntrl = Verdad; Byte PWMModules = 0; Byte StagesLeft = 0; interrumpir el control Volátil Byte A60telSeconds24 = 0; Volátil Byte Seconds24; Manejo de entradas serie Char TBuffer; Char Cbuffer[MaxInputBufferSize + 1]; Búfer de entrada de código USB Cadena Sbuffer = ""; Búfer de entrada de cadena USB Int Valor; Búfer de entrada Nummeric USB Byte Ccount { 0 }; Número recibido Chars Byte Inptype = 0; Booleana StrInput = Falso; Booleana NumberInput = Falso; Booleana DataInput = Falso; Booleana EnterInput = Falso; Byte MenueSelection = 0; Byte MnuState = 0; Profundidad máxima del menú 255 icl Sub WiFieePromData MyConfig; Isr(TIMER1_COMPA_vect) { A60telSeconds24++; Si (A60telSeconds24 > 59) { A60telSeconds24 = 0; Seconds24++; Si (Seconds24 > 150) { Seconds24 = 0; } } } Vacío ISR_PIR_A() { Bool PinState = digitalRead(PIRA_Pin); Si (PinState) { Si (!(Motion_Trigger_Up_to_Down) Y !(Motion_Trigger_Down_to_Up)) { digitalWrite(CPU_LED_Pin, Alto); Motion_Trigger_Down_to_Up = Verdad; } PIR A activado } Más { digitalWrite(CPU_LED_Pin, Bajo); } } Vacío ISR_PIR_B() { Bool PinState = digitalRead(PIRB_Pin); Si (PinState) { Si (!(Motion_Trigger_Down_to_Up) Y !(Motion_Trigger_Up_to_Down)) { digitalWrite(CPU_LED_Pin, Alto); Motion_Trigger_Up_to_Down = Verdad; } PIR B activado } Más { digitalWrite(CPU_LED_Pin, Bajo); } } Vacío Init_PWM_Module(Byte PWM_ModuleAddr) { digitalWrite(OE_Pin, Alto); Pin de activación de salida BAJO activo (OE). Alambre.beginTransmisión(PWM_ModuleAddr); Iniciar la transferencia de datos Alambre.Escribir(0x00); // Alambre.Escribir(0x06); Restablecimiento de software Alambre.endTransmission(); Detener comunicación - Enviar bit de parada Retraso(400); Alambre.beginTransmisión(PWM_ModuleAddr); Iniciar la transferencia de datos Alambre.Escribir(0x01); Seleccionar el registro del modo 2 (registro de comandos) Alambre.Escribir(0x04); Configurar chip: 0x04: salida de polo muerto 0x00: Salida de drenaje abierta. Alambre.endTransmission(); Detener comunicación - Enviar bit de parada Alambre.beginTransmisión(PWM_ModuleAddr); Iniciar la transferencia de datos Alambre.Escribir(0x00); Seleccionar el registro del modo 1 (registro de comandos) Alambre.Escribir(0x10); Configurar SleepMode Alambre.endTransmission(); Detener comunicación - Enviar bit de parada Alambre.beginTransmisión(PWM_ModuleAddr); Iniciar la transferencia de datos Alambre.Escribir(0xFE); Seleccione PRE_SCALE registrarse Alambre.Escribir(0x03); Establezca Prescaler. La frecuencia máxima de PWM es de 1526 Hz si el PRE_SCALEer el operador se establece en "0x03h". Estándar: 200 Hz Alambre.endTransmission(); Detener comunicación - Enviar bit de parada Alambre.beginTransmisión(PWM_ModuleAddr); Iniciar la transferencia de datos Alambre.Escribir(0x00); Seleccionar el registro del modo 1 (registro de comandos) Alambre.Escribir(0xA1); Configurar chip: ERrlaube Todas las direcciones I2C de la llamada, utilice el reloj interno, / permita la característica del incremento automático Alambre.endTransmission(); Detener comunicación - Enviar bit de parada } Vacío Init_PWM_Outputs(Byte PWM_ModuleAddr) { digitalWrite(OE_Pin, Alto); Pin de activación de salida BAJO activo (OE). Para ( Int Z = 0; Z < 16 + 1; Z++) { Alambre.beginTransmisión(PWM_ModuleAddr); Alambre.Escribir(Z * 4 + 6); Seleccione PWM_Channel_ON_L registrarse Alambre.Escribir(0x00); Valor para el registro anterior Alambre.endTransmission(); Alambre.beginTransmisión(PWM_ModuleAddr); Alambre.Escribir(Z * 4 + 7); Seleccione PWM_Channel_ON_H registrarse Alambre.Escribir(0x00); Valor para el registro anterior Alambre.endTransmission(); Alambre.beginTransmisión(PWM_ModuleAddr); Alambre.Escribir(Z * 4 + 8); Seleccione PWM_Channel_OFF_L registrar Alambre.Escribir(0x00); Valor para el registro anterior Alambre.endTransmission(); Alambre.beginTransmisión(PWM_ModuleAddr); Alambre.Escribir(Z * 4 + 9); Seleccione PWM_Channel_OFF_H registrarse Alambre.Escribir(0x00); Valor para el registro anterior Alambre.endTransmission(); } digitalWrite(OE_Pin, Bajo); Pin de activación de salida BAJO activo (OE). } Vacío Configuración() { Initalización Serial.Comenzar(9600); pinMode(PIRA_Pin, Entrada); pinMode(PIRB_Pin, Entrada); pinMode(OE_Pin, Salida); pinMode(CPU_LED_Pin, Salida); pinMode(LDR_Pin, Entrada); PWMModules = MyConfig.Overall_Stages / 16; StagesLeft = ( MyConfig.Overall_Stages % 16) - 1; Si (StagesLeft >= 1) { PWMModules++; } Alambre.Comenzar(); Initalisia I2C Bus A4 (SDA), A5 (SCL) Para (Byte ModuleCount = 0; ModuleCount < PWMModules; ModuleCount++) { Init_PWM_Module(PWM_Module_Base_Addr + ModuleCount); Init_PWM_Outputs(PWM_Module_Base_Addr + ModuleCount); } Si (!(loadEEPROM_Config())) Cargar filtraciones de EEPROM { Serial.println(Q("Configuración estándar de EEPROM guardada.")); MyConfig.Delay_ON_to_OFF = 10; Mínimo Wartezeit bis zur "Aus Sequenz" en Sekunden MyConfig.Overall_Stages = 8; maximale Stufenanzahl: 62 x 16 x 992 MyConfig.delay_per_Stage_in_ms = 100; MyConfig.DayLight_Brightness_Border = 600; Helligkeitsgrenze Automatik - Heherer Wert - Hehere Helligkeit MyConfig.Delay_Stages_ON = 20; saveEEPROM_Config(); } noInterrupts(); adjuntarInterrupt(0, ISR_PIR_A, cambio); adjuntarInterrupt(1, ISR_PIR_B, cambio); TCCR1A = 0x00; TCCR1B = 0x02; TCNT1 = 0; Registrar mit 0 initialisieren OCR1A = 33353; Salida Comparar Registro vorbelegen TIMSK1 |= (1 << OCIE1A); Timer Compare Interrupt aktivieren Interrumpe(); Serial.println(F("Init_Complete")); } /** Guardar configuración en EEPROM */ Bool loadEEPROM_Config() { Bool RetValue; Eeprom.Obtener(0, MyConfig); Eeprom.Final(); Si (Cadena(MyConfig.ConfigValid) = Cadena("Tk")) { RetValue = Verdad; } Más { RetValue = Falso; No se han encontrado los ajustes. } devolución RetValue; } /** Almacenar configuración a EEPROM */ Bool saveEEPROM_Config() { strncpy( MyConfig.ConfigValid , "Tk", Sizeof(MyConfig.ConfigValid) ); Eeprom.Poner(0, MyConfig); Eeprom.Final(); devolución Verdad; } Bool DayLightStatus () { Int SensorValue = 0; Bool ReturnValue = Verdad; SensorValue = analogRead(LDR_Pin); #ifdef Depuración Serial.Impresión(F("DayLightStatus: ")); Serial.Impresión(SensorValue); #endif Si (SensorValue > MyConfig.DayLight_Brightness_Border) { Si ((DayLight_Status) Y (SensorValue > MyConfig.DayLight_Brightness_Border + L_Sens_Scope)) { ReturnValue = Falso; DayLight_Status = Falso; } Más Si (!(DayLight_Status)) { ReturnValue = Falso; DayLight_Status = Falso; } #ifdef Depuración Serial.println(F("Off")); #endif } Más { Si ((DayLight_Status) Y (SensorValue > MyConfig.DayLight_Brightness_Border - L_Sens_Scope)) { ReturnValue = Verdad; DayLight_Status = Verdad; } Más Si (!(DayLight_Status)) { ReturnValue = Verdad; DayLight_Status = Verdad; } #ifdef Depuración Serial.println(F("ON")); #endif } devolución ReturnValue; } Vacío Down_to_Up_ON() { #ifdef Depuración Serial.println(F("Down_to_Up_ON")); #endif Byte Calc_Num_Stages_per_Module = Num_Stages_per_Module; Para (Byte ModuleCount = 0; ModuleCount < PWMModules; ModuleCount++) { Pwm_Channel = 0; Pwm_Channel_Brightness = 4095; Si ((StagesLeft >= 1) Y (ModuleCount == PWMModules - 1)) { Calc_Num_Stages_per_Module = StagesLeft; } Más { Calc_Num_Stages_per_Module = Num_Stages_per_Module; } Pwm_Channel = 0; Pwm_Channel_Brightness = 0; Mientras (Pwm_Channel < Calc_Num_Stages_per_Module + 1) { Alambre.beginTransmisión( PWM_Module_Base_Addr + ModuleCount); Alambre.Escribir(Pwm_Channel * 4 + 8); Registro de PWM_Channel_0_OFF_L de Wuhle Alambre.Escribir((Byte)Pwm_Channel_Brightness & 0xFF); Registro de registros Alambre.endTransmission(); Alambre.beginTransmisión( PWM_Module_Base_Addr + ModuleCount); Alambre.Escribir(Pwm_Channel * 4 + 9); Registro de PWM_Channel_0_OFF_H de Wuhle Alambre.Escribir((Pwm_Channel_Brightness >> 8)); Registro de registros Alambre.endTransmission(); Si (Pwm_Channel_Brightness < 4095) { Pwm_Channel_Brightness = Pwm_Channel_Brightness + MyConfig.Delay_Stages_ON; Si (Pwm_Channel_Brightness > 4095) { Pwm_Channel_Brightness = 4095; } } Más Si ( Pwm_Channel < Num_Stages_per_Module + 1) { Pwm_Channel_Brightness = 0; Retraso(MyConfig.delay_per_Stage_in_ms); Pwm_Channel++; } } } } Vacío Up_to_DOWN_ON() { #ifdef Depuración Serial.println(F("Up_to_DOWN_ON")); #endif Byte Calc_Num_Stages_per_Module = Num_Stages_per_Module; Int ModuleCount = PWMModules - 1; Mientras (ModuleCount >= 0) { Pwm_Channel_Brightness = 0; Si ((StagesLeft >= 1) Y (ModuleCount == PWMModules - 1)) { Calc_Num_Stages_per_Module = StagesLeft; } Más { Calc_Num_Stages_per_Module = Num_Stages_per_Module; } Pwm_Channel = Calc_Num_Stages_per_Module; Mientras (Pwm_Channel > -1) { Alambre.beginTransmisión( PWM_Module_Base_Addr + ModuleCount); Alambre.Escribir(Pwm_Channel * 4 + 8); Registro de PWM_Channel_0_OFF_L de Wuhle Alambre.Escribir((Byte)Pwm_Channel_Brightness & 0xFF); Registro de registros Alambre.endTransmission(); Alambre.beginTransmisión(PWM_Module_Base_Addr + ModuleCount); Alambre.Escribir(Pwm_Channel * 4 + 9); Registro de PWM_Channel_0_OFF_H de Wuhle Alambre.Escribir((Pwm_Channel_Brightness >> 8)); Registro de registros Alambre.endTransmission(); Si (Pwm_Channel_Brightness < 4095) { Pwm_Channel_Brightness = Pwm_Channel_Brightness + MyConfig.Delay_Stages_ON; Si (Pwm_Channel_Brightness > 4095) { Pwm_Channel_Brightness = 4095; } } Más Si ( Pwm_Channel >= 0) { Pwm_Channel_Brightness = 0; Retraso(MyConfig.delay_per_Stage_in_ms); Pwm_Channel--; Si ( Pwm_Channel < 0) { Pwm_Channel = 0; Romper; } } } ModuleCount = ModuleCount - 1; } } Vacío Down_to_Up_OFF() { #ifdef Depuración Serial.println(F("Down_to_Up_OFF")); #endif Byte Calc_Num_Stages_per_Module = Num_Stages_per_Module; Para (Byte ModuleCount = 0; ModuleCount < PWMModules; ModuleCount++) { Pwm_Channel = 0; Pwm_Channel_Brightness = 4095; Si ((StagesLeft >= 1) Y (ModuleCount == PWMModules - 1)) { Calc_Num_Stages_per_Module = StagesLeft; } Más { Calc_Num_Stages_per_Module = Num_Stages_per_Module; } Mientras (Pwm_Channel < Calc_Num_Stages_per_Module + 1) { Alambre.beginTransmisión( PWM_Module_Base_Addr + ModuleCount); Alambre.Escribir(Pwm_Channel * 4 + 8); Registro de PWM_Channel_0_OFF_L de Wuhle Alambre.Escribir((Byte)Pwm_Channel_Brightness & 0xFF); Registro de registros Alambre.endTransmission(); Alambre.beginTransmisión(PWM_Module_Base_Addr + ModuleCount); Alambre.Escribir(Pwm_Channel * 4 + 9); Registro de PWM_Channel_0_OFF_H de Wuhle Alambre.Escribir((Pwm_Channel_Brightness >> 8)); Registro de registros Alambre.endTransmission(); Si (Pwm_Channel_Brightness > 0) { Pwm_Channel_Brightness = Pwm_Channel_Brightness - MyConfig.Delay_Stages_OFF; Si (Pwm_Channel_Brightness < 0) { Pwm_Channel_Brightness = 0; } } Más Si ( Pwm_Channel < Num_Stages_per_Module + 1) { Pwm_Channel_Brightness = 4095; Retraso(MyConfig.delay_per_Stage_in_ms); Pwm_Channel++; } } } } Vacío Up_to_DOWN_OFF() { #ifdef Depuración Serial.println(F("Up_to_DOWN_OFF")); #endif Byte Calc_Num_Stages_per_Module = Num_Stages_per_Module; Int ModuleCount = PWMModules - 1; Mientras (ModuleCount >= 0) { Pwm_Channel_Brightness = 4095; Si ((StagesLeft >= 1) Y (ModuleCount == PWMModules - 1)) { Calc_Num_Stages_per_Module = StagesLeft; } Más { Calc_Num_Stages_per_Module = Num_Stages_per_Module; } Pwm_Channel = Calc_Num_Stages_per_Module; Mientras (Pwm_Channel > -1) { Alambre.beginTransmisión(PWM_Module_Base_Addr + ModuleCount); Alambre.Escribir(Pwm_Channel * 4 + 8); Registro de PWM_Channel_0_OFF_L de Wuhle Alambre.Escribir((Byte)Pwm_Channel_Brightness & 0xFF); Registro de registros Alambre.endTransmission(); Alambre.beginTransmisión(PWM_Module_Base_Addr + ModuleCount); Alambre.Escribir(Pwm_Channel * 4 + 9); Registro de PWM_Channel_0_OFF_H de Wuhle Alambre.Escribir((Pwm_Channel_Brightness >> 8)); Registro de registros Alambre.endTransmission(); Si (Pwm_Channel_Brightness > 0) { Pwm_Channel_Brightness = Pwm_Channel_Brightness - MyConfig.Delay_Stages_OFF; Si (Pwm_Channel_Brightness < 0) { Pwm_Channel_Brightness = 0; } } Más Si ( Pwm_Channel >= 0) { Pwm_Channel_Brightness = 4095; Retraso(MyConfig.delay_per_Stage_in_ms); Pwm_Channel--; Si ( Pwm_Channel < 0) { Pwm_Channel = 0; Romper; } } } ModuleCount = ModuleCount - 1; } } Vacío Stages_Light_Control () { Si ((Motion_Trigger_Down_to_Up) Y !(On_Delay)) { DLightCntrl = DayLightStatus(); Si (DLightCntrl) { Seconds24 = 0; On_Delay = Verdad; Down_to_Up_ON(); } Más { Motion_Trigger_Down_to_Up = Falso; } } Si ((On_Delay) Y (Seconds24 > MyConfig.Delay_ON_to_OFF) Y (Motion_Trigger_Down_to_Up) ) { Down_to_Up_OFF(); Motion_Trigger_Down_to_Up = Falso; On_Delay = Falso; Seconds24 = 0; } Si ((Motion_Trigger_Up_to_Down) Y !(On_Delay)) { DLightCntrl = DayLightStatus(); Si (DLightCntrl) { Seconds24 = 0; On_Delay = Verdad; Up_to_DOWN_ON(); } Más { Motion_Trigger_Up_to_Down = Falso; } } Si ((On_Delay) Y (Seconds24 > MyConfig.Delay_ON_to_OFF) Y (Motion_Trigger_Up_to_Down)) { Up_to_DOWN_OFF(); Motion_Trigger_Up_to_Down = Falso; On_Delay = Falso; Seconds24 = 0; } } Funciones del intérprete de comandos ------------------------------- Vacío ClearCBuffer () { Para (Byte Un = 0; MaxInputBufferSize - 1; Un++) Cbuffer[Un] = 0; } Booleana CheckforserialEvent() { Mientras (Serial.Disponible()) { obtener el nuevo byte: TBuffer = Serial.Leer(); Si (TBuffer > 9 && TBuffer < 14) { Cbuffer[Ccount] = 0; TBuffer = 0; Serial.Impresión(Char(13)); Serial.rubor(); Serial.println(""); Sbuffer = ""; Valor = 0; EnterInput = Verdad; devolución Verdad; } Más Si (TBuffer > 47 && TBuffer < 58 ) { Si ( Ccount < MaxInputBufferSize) { Cbuffer[Ccount] = TBuffer; Ccount++; } Más { Serial.Impresión("#"); } Número Entrada detectada NumberInput = Verdad; } Más Si (TBuffer > 64 && TBuffer < 123 ) { Si ( Ccount < MaxInputBufferSize) { Cbuffer[Ccount] = TBuffer; Ccount++; Serial.Impresión(Char(TBuffer)); Serial.rubor(); } Entrada de carácter Char detectada StrInput = Verdad; } Más Si ( (TBuffer == 127 ) | (TBuffer == 8 ) ) { Si ( Ccount > 0) { Ccount--; Cbuffer[Ccount] = 0; Serial.Impresión("-"); Serial.rubor(); } } Más { Si ( Ccount < MaxInputBufferSize) { Cbuffer[Ccount] = TBuffer; Ccount++; Serial.Impresión(Char(TBuffer)); Serial.rubor(); Entrada de datos detectada DataInput = Verdad; } devolución Falso; } devolución Falso; } } Byte SerInputHandler() { Byte Resultado = 0; Int C; Int D; Int Un; Int B; Resultado = 0; Si (CheckforserialEvent()) { Si ((NumberInput) Y No (DataInput) Y No (StrInput)) Sólo números { Sbuffer = ""; Valor = 0; StrInput = Falso; NumberInput = Falso; DataInput = Falso; EnterInput = Falso; Un = 0; B = 0; C = 0; D = 0; Sbuffer = Cbuffer; Zahl wird AUCH ! en SBUFFER-bernommen, cae bentigt. Si (Ccount == 1) { Valor = Cbuffer[0] - 48 ; } Si (Ccount == 2) { Un = Cbuffer[0] - 48 ; Un = Un * 10; B = Cbuffer[1] - 48 ; Valor = Un + B; } Si (Ccount == 3) { Un = Cbuffer[0] - 48 ; Un = Un * 100; B = Cbuffer[1] - 48 ; B = B * 10; C = Cbuffer[2] - 48 ; Valor = Un + B + C; } Si (Ccount == 4) { Un = Cbuffer[0] - 48 ; Un = Un * 1000; B = Cbuffer[1] - 48 ; B = B * 100; C = Cbuffer[2] - 48 ; C = C * 10; D = Cbuffer[3] - 48 ; Valor = Un + B + C + D; } Si (Ccount >= 5) { Sbuffer = ""; Valor = 0; Sbuffer = Cbuffer; ClearCBuffer; Resultado = 2; } Más { ClearCBuffer; Ccount = 0; Resultado = 1; Código de devolución del número NumberInput = Falso; StrInput = Falso; DataInput = Falso; EnterInput = Falso; Ccount = 0; devolución Resultado; } } Si ((StrInput) Y No (DataInput)) Sólo entrada de cadena { Sbuffer = ""; Sbuffer = Cbuffer; Valor = 0; StrInput = Falso; NumberInput = Falso; DataInput = Falso; EnterInput = Falso; Ccount = 0; ClearCBuffer; Resultado = 2; Código de devolución del número } Si (DataInput) { Sbuffer = ""; Sbuffer = Cbuffer; Valor = 0; StrInput = Falso; NumberInput = Falso; DataInput = Falso; EnterInput = Falso; Ccount = 0; ClearCBuffer; Resultado = 3; Código de devolución del número } Si ((EnterInput) Y No (StrInput) Y No (NumberInput) Y No (DataInput)) { Sbuffer = ""; Valor = 0; Ccount = 0; ClearCBuffer; Resultado = 4; Código de devolución del número } NumberInput = Falso; StrInput = Falso; DataInput = Falso; EnterInput = Falso; Ccount = 0; devolución Resultado; } devolución Resultado; Fin de CheckforSerialEvent } Vacío SerialcommandProcessor() { Int Un; Inptype = 0; Inptype = SerInputHandler(); 0 keine Rackgabe 1 Nummer 2 Cuerdas 3 Datos Si (Inptype > 0) { MenueSelection = 0; Si ((MnuState < 2) && (Inptype == 2)) { Sbuffer.toUpperCase(); Para facilitar la introducción de comandos } Si ((Sbuffer == "D") && (MnuState == 0) && (Inptype == 2)) { MenueSelection = 1; } Si ((Sbuffer == "O") && (MnuState == 0) && (Inptype == 2)) { MenueSelection = 2; } Si ((Sbuffer == "T") && (MnuState == 0) && (Inptype == 2)) { MenueSelection = 3; } Si ((Sbuffer == "B") && (MnuState == 0) && (Inptype == 2)) { MenueSelection = 4; } Si ((Sbuffer == "N") && (MnuState == 0) && (Inptype == 2)) { MenueSelection = 5; } Si ((Sbuffer == "F") && (MnuState == 0) && (Inptype == 2)) { MenueSelection = 6; } Si ((MnuState == 2) && (Inptype == 1)) { MenueSelection = 8; } Si ((MnuState == 3) && (Inptype == 1)) { MenueSelection = 9; } Si ((MnuState == 4) && (Inptype == 1)) { MenueSelection = 10; } Si ((MnuState == 5) && (Inptype == 1)) { MenueSelection = 11; } Si ((MnuState == 6) && (Inptype == 1)) { MenueSelection = 12; } Si ((MnuState == 7) && (Inptype == 1)) { MenueSelection = 13; } Si (MnuState == 10) { MenueSelection = 21; Conjunto de tiempo } Si (MnuState == 11) { MenueSelection = 24; Conjunto de tiempo } Si (MnuState == 12) { MenueSelection = 25; Conjunto de tiempo } Si (MnuState == 13) { MenueSelection = 27; Conjunto de fondo } Si (MnuState == 14) { MenueSelection = 29; Conjunto ClockFace } Interruptor (MenueSelection) { Caso 1: { Serial.println("Retraso on to OFF: (1-65000)"); MnuState = 2; Valor = 0; Sbuffer = ""; Romper; } Caso 2: { Serial.println("Etapas generales: (1-992)"); MnuState = 3; Valor = 0; Sbuffer = ""; Romper; } Caso 3: { Serial.println("Retraso por etapa en ms: (1-65000)"); MnuState = 4; Valor = 0; Sbuffer = ""; Romper; } Caso 4: { Serial.println("Borde de brillo de la luz diurna: (0-65000)"); MnuState = 5; Valor = 0; Sbuffer = ""; Romper; } Caso 5: { Serial.println("Etapas de retardo encendido: (1-254)"); MnuState = 6; Valor = 0; Sbuffer = ""; Romper; } Caso 6: { Serial.println("Etapas de retardo OFF: (1-254)"); MnuState = 7; Valor = 0; Sbuffer = ""; Romper; } Caso 8: { MyConfig.Delay_ON_to_OFF = Valor; saveEEPROM_Config(); Serial.Impresión(Q("Delay_ON_to_OFF establece en:")); Serial.println(MyConfig.Delay_ON_to_OFF); MnuState = 0; Sbuffer = ""; Valor = 0; Romper; } Caso 9: { MyConfig.Overall_Stages = Valor; saveEEPROM_Config(); Serial.Impresión(Q("Etapas generales establecidas en:")); Serial.println(MyConfig.Overall_Stages); MnuState = 0; Sbuffer = ""; Valor = 0; Romper; } Caso 10: { MyConfig.delay_per_Stage_in_ms = Valor; saveEEPROM_Config(); Serial.Impresión(Q("Retraso por etapa en ms establecido en:")); Serial.println(MyConfig.delay_per_Stage_in_ms); MnuState = 0; Sbuffer = ""; Valor = 0; Romper; } Caso 11: { MyConfig.DayLight_Brightness_Border = Valor; saveEEPROM_Config(); Serial.Impresión(Q("Borde de brillo de DayLight establecido en:")); Serial.println(MyConfig.DayLight_Brightness_Border); MnuState = 0; Sbuffer = ""; Valor = 0; Romper; } Caso 12: { MyConfig.Delay_Stages_ON = Valor; saveEEPROM_Config(); Serial.Impresión(Q("Etapas de retardo on establecidaen en:")); Serial.println(MyConfig.Delay_Stages_ON); MnuState = 0; Sbuffer = ""; Valor = 0; Romper; } Caso 13: { MyConfig.Delay_Stages_OFF = Valor; saveEEPROM_Config(); Serial.Impresión(Q("Etapas de retardo OFF establecidaen en:")); Serial.println(MyConfig.Delay_Stages_OFF); MnuState = 0; Sbuffer = ""; Valor = 0; Romper; } Predeterminado: { MnuState = 0; Serial.println(Q("-Control de luz de escalera -")); Serial.Impresión(Q("D - Retardo encendido a APAGADO / Valor actual:")); Serial.println(MyConfig.Delay_ON_to_OFF); Serial.Impresión(Q("O - Etapas generales / Valor actual:")); Serial.println(MyConfig.Overall_Stages); Serial.Impresión(Q("T - Retraso por etapa en ms / Valor actual:")); Serial.println(MyConfig.delay_per_Stage_in_ms); Serial.Impresión(Q("B - Borde de brillo de la luz diurna / Valor actual:")); Serial.println(MyConfig.DayLight_Brightness_Border ); Serial.Impresión(Q("N - Etapas de retardo ON / Valor actual:")); Serial.println(MyConfig.Delay_Stages_ON); Serial.Impresión(Q("F - Etapas de retardo OFF / Valor actual:")); Serial.println(MyConfig.Delay_Stages_OFF); Serial.println(Q("Escriba Cmd y pulse Intro")); Serial.rubor(); MnuState = 0; Valor = 0; Sbuffer = ""; } } } Entrada detectada } Vacío Bucle() { Stages_Light_Control(); SerialcommandProcessor(); }
Después de que el código ha sido cargado, podemos acceder al schni serial con 9600 baudiosTtPosición. Después de una entrada (e inactivo! Luz de escalera) aparece el siguiente menú de configuración:
Paramenter |
Declaración |
Retardo ENCENDIDO a OFF |
Tiempo en SEGUNDOS que mantiene la iluminación de la escalera completamente encendida |
Etapas generales |
Número de escaleras de las escaleras |
Retraso por etapa |
Tiempo en MILLISECONDS para esperar hasta que se acerca la siguiente escalera. |
Borde de brillo de luz diurna |
Brillo en el que la iluminación de la escalera se vuelve inactiva. Mayor valor -> mayor brillo |
Etapas de retardo ACTIVADAs |
Rel. Tiempo de desvanecimiento al cambiar las escaleras. Mayor valor - > menos tiempo |
Rel. Tiempo de desvanecimiento al CAMBIAR las escaleras. Mayor valor - > menos tiempo |
Te deseo mucha diversión con la réplica. Como siempre, puede encontrar todos los proyectos anteriores en la página de GitHub https://github.com/kuchto
11 comentarios
Andreas Wolter
@Jan: ich vermute, dass dafür die Variable Pwm_Channel_Brightness zuständig ist. Der Wert dafür ist hard codiert mit 4095. Man könnte dafür eine Variable einsetzen, um diesen Wert leichter einstellen zu können. Bitte testen Sie das mal aus.
Grüße,
Andreas Wolter
AZ-Delivery Blog
Jan
Habe das Projekt nachgebaut, funktioniert top!
Das einzige Problem das ich habe ist das meine gewählten LED-Stripes zu hell sind.
Gibt es eine Möglichkeit das ganze zu dimmen?
Im vorraus Danke für die Hilfe
Jan
Andreas Wolter
@MBK: ich bin eben kurz über den Quellcode geflogen. Die Delays sind einstellbare Parameter. Haben Sie versucht, diese zu verändern?
Grüße,
Andreas Wolter
AZ-Delivery Blog
MBK
Danke für die Anleitung, gibt es die Möglichkeit Unterstützung für das Projekt zu bekommen?
Ich habe das ganze nachgebaut mit 7 beleuchteten Stufen ( zur Probe auf dem Steckbrett, auf dem Tisch), allerdings arbeitetn die Sensoren nicht sauber. Nach Abdunklung des Fotosensors, kommt es nur gelegentlich zur Auslösung der Treppenbeleuchtung, immer in der richtigen Reihenfolge ( von oben nach unten oder umgekehrt) aber danach gibt es eine wartezeit von ca 1,5 Minuten bis das System sich wieder auslösen lässt. Die rote Debug LED leuchtet während dieser Zeit. Ich habe die Sensoren schon getauscht um fehlerhafte Sensoren auszuschließen, das Ergebniss bleibt gleich.
Klaus-Peter Weidner
Super interessantes Projekt.
Ich hätte nur zwei Anmerkungen / Wünsche.
1.) Im Menü die Anzeige der “aktuellen Daylight Brightness” um den Parameter besser zu bestimmen.
2.) Ein I2C-Shield mit LCD-Display und 5 Tasten, um die Einstellungen ohne PC o.ä. einzustellen.
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
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
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
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
Super Projekt !!
Das ganze jetzt noch mit Wlan,
dann wäre es perfekt !!!!
LG
Wolfgang
stsc
Ein NodeMCU mit Steuerung per MQTT wäre auch interessant. Dann könnte man die Treppe in das Homesteuerungssystem einbinden.