Bienvenidos a la segunda parte de nuestra serie "elegante control de luz de escalera". Como siempre en la serie de proyectos, las siguientes partes se trata de mejorar o ampliar la función. Por parte de hoy, estamos mejorando la función primero.
Básicamente, nuestras escaleras van lentamente de abajo a arriba, si se introduce de arriba a abajo o viceversa, de abajo a arriba. Sin embargo, sería mejor si nuestras escaleras se encienden exactamente en la dirección como una luz corriente, en la que entramos en las escaleras y luego lentamente se apagan de nuevo.
Esto es precisamente de lo que se trata esta ampliación en la parte actual de la serie. La luz de la escalera sigue nuestros pasos tan pronto como entramos en las escaleras, independientemente de la dirección.
Los parámetros y el circuito pueden ser de la primera parte de la serie ser tomado. Es una extensión de software puro.
#define Num_Stages 15
#define Delay_Stages 10
#define Delay_ON_to_OFF 5
Num_Stages |
Define el número de escaleras a iluminar (máximo 16, contando desde 0 hasta el inicio. Valor máximo: 15) |
Delay_Stages |
Período de desvanecimiento para cada paso de escalera -> cuanto menor sea el valor, mayor será el período, más lento. |
Delay_ON_to_OFF |
Período que pasa dejando las escaleras en el estado "encendido". |
Después de que los valores se hayan personalizado según sus propias preferencias, el código extendido se puede cargar en el Arduino:
2019 Tobias Kuch GPL 3.0 incluír <Alambre.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 el módulo lógico 1 0x41 2 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 #define PIRA_Pin 2 #define PIRB_Pin 3 #define Num_Stages 15 #define Delay_Stages 5 #define Delay_ON_to_OFF 30 Mínimo Delay_ON_to_OFF en segundos #define delay_per_Stage_in_ms 200 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; interrumpir el control Byte A60telSeconds24 = 0; Byte Seconds24; 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) { pinMode(OE_Pin, Salida); pinMode(CPU_LED_Pin, Salida); 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); Serial.Comenzar(9600); Alambre.Comenzar(); Initalisia I2C Bus A4 (SDA), A5 (SCL) Init_PWM_Module(PWM_Module_Base_Addr); Init_PWM_Outputs(PWM_Module_Base_Addr); noInterrupts(); adjuntarInterrupt(0, ISR_PIR_A, cambio); adjuntarInterrupt(1, ISR_PIR_B, cambio); TCCR1A = 0x00; TCCR1B = 0x02; TCNT1 = 0; Inicializar registro con 0 OCR1A = 33353; Predocumentos Registro de Comparación de Salida TIMSK1 |= (1 << OCIE1A); Activar interrupción de comparación de temporizadores Interrumpe(); } Vacío Down_to_Up_ON() { Pwm_Channel = 0; Pwm_Channel_Brightness = 0; Mientras (Pwm_Channel < Num_Stages + 1) { Alambre.beginTransmisión( PWM_Module_Base_Addr); Alambre.Escribir(Pwm_Channel * 4 + 8); Seleccione PWM_Channel_0_OFF_L registrarse Alambre.Escribir((Byte)Pwm_Channel_Brightness & 0xff); Valor para el registro anterior Alambre.endTransmission(); Alambre.beginTransmisión( PWM_Module_Base_Addr); Alambre.Escribir(Pwm_Channel * 4 + 9); Seleccione PWM_Channel_0_OFF_H registrar Alambre.Escribir((Pwm_Channel_Brightness >> 8)); Valor para el registro anterior Alambre.endTransmission(); Si (Pwm_Channel_Brightness < 4095) { Pwm_Channel_Brightness = Pwm_Channel_Brightness + Delay_Stages; Si (Pwm_Channel_Brightness > 4095) { Pwm_Channel_Brightness = 4095; } } Más Si ( Pwm_Channel < Num_Stages + 1) { Pwm_Channel_Brightness = 0; Retraso(delay_per_Stage_in_ms); Pwm_Channel++; } } } Vacío Down_to_Up_OFF() { Pwm_Channel = 0; Pwm_Channel_Brightness = 4095; Mientras (Pwm_Channel < Num_Stages + 1) { Alambre.beginTransmisión( PWM_Module_Base_Addr); Alambre.Escribir(Pwm_Channel * 4 + 8); Seleccione PWM_Channel_0_OFF_L registrarse Alambre.Escribir((Byte)Pwm_Channel_Brightness & 0xff); Valor para el registro anterior Alambre.endTransmission(); Alambre.beginTransmisión(PWM_Module_Base_Addr); Alambre.Escribir(Pwm_Channel * 4 + 9); Seleccione PWM_Channel_0_OFF_H registrar Alambre.Escribir((Pwm_Channel_Brightness >> 8)); Valor para el registro anterior Alambre.endTransmission(); Si (Pwm_Channel_Brightness > 0) { Pwm_Channel_Brightness = Pwm_Channel_Brightness - Delay_Stages; Si (Pwm_Channel_Brightness < 0) { Pwm_Channel_Brightness = 0; } } Más Si ( Pwm_Channel < Num_Stages + 1) { Pwm_Channel_Brightness = 4095; Retraso(delay_per_Stage_in_ms); Pwm_Channel++; } } } Vacío Up_to_DOWN_ON() { Pwm_Channel = Num_Stages; Pwm_Channel_Brightness = 0; Mientras (Pwm_Channel > -1) { Alambre.beginTransmisión( PWM_Module_Base_Addr); Alambre.Escribir(Pwm_Channel * 4 + 8); Seleccione PWM_Channel_0_OFF_L registrarse Alambre.Escribir((Byte)Pwm_Channel_Brightness & 0xff); Valor para el registro anterior Alambre.endTransmission(); Alambre.beginTransmisión(PWM_Module_Base_Addr); Alambre.Escribir(Pwm_Channel * 4 + 9); Seleccione PWM_Channel_0_OFF_H registrar Alambre.Escribir((Pwm_Channel_Brightness >> 8)); Valor para el registro anterior Alambre.endTransmission(); Si (Pwm_Channel_Brightness < 4095) { Pwm_Channel_Brightness = Pwm_Channel_Brightness + Delay_Stages; Si (Pwm_Channel_Brightness > 4095) { Pwm_Channel_Brightness = 4095; } } Más Si ( Pwm_Channel >= 0) { Pwm_Channel_Brightness = 0; Retraso(delay_per_Stage_in_ms); Pwm_Channel--; Si ( Pwm_Channel < 0) { Pwm_Channel = 0; Romper; } } } } Vacío Up_to_DOWN_OFF() { Pwm_Channel = Num_Stages; Pwm_Channel_Brightness = 4095; Mientras (Pwm_Channel > -1) { Alambre.beginTransmisión(PWM_Module_Base_Addr); Alambre.Escribir(Pwm_Channel * 4 + 8); Seleccione PWM_Channel_0_OFF_L registrarse Alambre.Escribir((Byte)Pwm_Channel_Brightness & 0xff); Valor para el registro anterior Alambre.endTransmission(); Alambre.beginTransmisión(PWM_Module_Base_Addr); Alambre.Escribir(Pwm_Channel * 4 + 9); Seleccione PWM_Channel_0_OFF_H registrar Alambre.Escribir((Pwm_Channel_Brightness >> 8)); Valor para el registro anterior Alambre.endTransmission(); Si (Pwm_Channel_Brightness > 0) { Pwm_Channel_Brightness = Pwm_Channel_Brightness - Delay_Stages; Si (Pwm_Channel_Brightness < 0) { Pwm_Channel_Brightness = 0; } } Más Si ( Pwm_Channel >= 0) { Pwm_Channel_Brightness = 4095; Retraso(delay_per_Stage_in_ms); Pwm_Channel--; Si ( Pwm_Channel < 0) { Pwm_Channel = 0; Romper; } } } } Vacío Bucle() { Si ((Motion_Trigger_Down_to_Up) Y !(On_Delay) ) { Seconds24 = 0; On_Delay = Verdad; Down_to_Up_ON(); } Si ((On_Delay) Y (Seconds24 > 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) ) { Seconds24 = 0; On_Delay = Verdad; Up_to_DOWN_ON(); } Si ((On_Delay) Y (Seconds24 > 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; } }
Les deseo mucha diversión reconstruyendo este proyecto y hasta la siguiente parte.
6 comentarios
Peter Wenk
Hallo Freunde im Blog,
ich habe mir die Treppenbeleuchtung auf dem Steckbrett nachgebaut und es funktioniert wunderbar.
Jetzt würde ich gern die helligkeit aller leds reduzieren. Es müsste doch über die PWM Taktung funktionieren also nicht mit 100% sondern nach wunsch nur 50% Taktung.
Kann mir einer helfen wie ich den Skretch umschreiben muss?
Würde mich über Hilfe freuen.
LG
Peter
Maik
@Thomas
Realisiere das doch mit einer separaten Steuerung, dann kannst Du dir den Flur nach deinen Wünschen ausleuchten.
Strotty
Hallo,
ich bekomme bei ISR folgende Fehlermeldung:
exit status 1
expected unqualified-id before string constant
kann mir jemand einen Tipp geben?
Thomas
Das Treppenlicht ist eine wirklich tolle Idee, mit der ich schon viele Jahre liebäugele. Aber wie es immer so ist, das, was man sucht, findet man dann doch in der Form nicht und sich zu kompletter Eigenentwicklung aufzuraffen bleibt bei mir meist auf der Strecke. Ich habe nun auch mit dem Kommentar bis zum 2. Teil gewartet, da mir im 1. Teil die Beschränkung auf die eine „Einschaltrichtung“ auffiel und die erwartungsgemäß nun ergänzt wurde. Jetzt würde ich gerne meine Idee anbringen, die mit dem Rettungsdienst-Kommentar von Wolfgang konform geht:
Unser Flur im 1. OG ist nachts erbärmlich dunkel und auf dem Weg durch den Flur auch ohne Treppenbenutzung wäre es super, wenn eben am oberen Ende der Treppe die Beleuchtung der obersten Stufe mit einem zusätzlichen (dritten) Sensor verbunden wäre, der eben nur die eine Stufe schaltet, wenn sich jemand oben im Flur bewegt. Damit hat man dann nachts ausreichend Orientierung im Flur und es ist als Funktion abgegrenzt von der Treppenbenutzung. Aber die Stufe sollte trotzdem wie in der beschriebenen Lösung integriert bleiben.
Ein Ausschalten am Ende des „Treppenganges“ wäre für mich nicht sinnvoll, da es wegen mehrerer Bewohner und Hund zwangsläufig zu Situation kommen wird, wo jemand dann im Dunklen auf der Treppe steht.
Markus
Was ist wenn ich mir auf der hälfte der Treppe einfällt ich muss noch mal runter ?
Wolfgang Hauf
Hi,
du hast in der ersten Zeile die “#” vergessen !!