Hola y bienvenidos a la penúltima parte de la serie "elegante iluminación de escalera automática".
Hoy estamos ampliando nuestro sistema de control con una resistencia sensible a la luz, que debería actuar como un sensor de brillo. A partir de un valor de brillo que se puede establecer en el código con el parámetro "DayLight_Brightness_Border", mediante el cual un número más alto simboliza un brillo más alto, la escalera automática se desactiva a partir de este valor, de modo que las escaleras solo se iluminan cuando está oscuro. Al usar un LDR en lugar de un sensor I2C, todo es algo menos sensible a la interferencia externa.
Como una pequeña mejora adicional en esta versión, el tiempo de desvanecimiento entre dos niveles al encender y apagar se puede configurar por separado con los parámetros "Delay_Stages_ON" y "Delay_Stages_OFF". Se pueden lograr resultados respetables, por ejemplo, seleccionando el parámetro para apagar los pasos individuales más altos que para encender.
La siguiente imagen muestra cómo se deben conectar el LDR y la resistencia previa:
Para la parte actual del proyecto necesitamos:
Numero |
Descripción |
Nota |
2 |
Sensor de movimiento |
|
a 62 |
Número dependiendo del número de escaleras / 16 |
|
1 |
|
|
1 |
Para la construcción de paneles |
|
a 992 |
Número dependiendo del número de escaleras. |
|
1 |
Fuente de alimentación para LED / lámparas para los escalones |
24 voltios máximo |
1 |
Resistencia de 10 KOhm |
|
1 |
Resistencia a la foto |
Todas las referencias de las partes anteriores también se aplican en la parte de hoy.
Después de hacer sus propios ajustes y agregar los LDR, el código se puede cargar:
#include <Alambre.h> #definir PWM_Module_Base_Addr 0x40 // 10000000b El último bit del byte de dirección define la operación a realizar. Cuando se establece en lógico 1 0x41 módulo 2, etc. Rango de direcciones 0x40 - 0x47 // se selecciona una operación de lectura, mientras que un 0 lógico selecciona una operación de escritura. #definir OE_Pin 8 // Pin para salida habilitada #definir CPU_LED_Pin 13 // LED de la placa interna en el pin 13 (para fines de depuración) #definir PIRA_Pin 2 #definir PIRB_Pin 3 #definir Num_Stages_per_Module 16 #definir LDR_Pin A2 // Pin analógico, a través del cual se debe medir el brillo. (Resistencia LDR) #definir DEPURACIÓN #definir L_Sens_Scope 50 // Parámetros de operación adaptables (constantes) int Delay_ON_to_OFF = 10; // Tiempo mínimo de espera hasta "De la secuencia" en segundos int General_Etapas = 8; // número máximo de pasos: 62 x 16 = 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_Stage_ON = 20; byte Delay_Stage_OFF = 20; // 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 = cierto; bool DLightCntrl = cierto; byte Módulos PWM = 0; byte Etapas Izquierda = 0; // interrumpir el control volátil byte A60telSeconds24 = 0; volátil byte Segundos24; ISR(TIMER1_COMPA_vect) { A60telSeconds24++; si (A60telSeconds24 > 59) { A60telSeconds24 = 0; Segundos24++; si (Segundos24 > 150) { Segundos24 = 0; } } } nulo 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 = cierto; } // PIR A activado } otra cosa { digitalWrite(CPU_LED_Pin, BAJA); } } nulo 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 = cierto; } // PIR B ausgelöst } más { digitalWrite(CPU_LED_Pin, BAJO); } } vacío Init_PWM_Module(byte PWM_ModuleAddr) { digitalWrite(OE_Pin, ALTO); // Active LOW-Ausgangsaktivierungs-Pin (OE) activo. Cable.beginTransmission(PWM_ModuleAddr); // Datentransfer initiieren Cable.escribir(0x00); // Cable.escribir(0x06); // Reinicio de software Cable.endTransmission(); // Stoppe Kommunikation - Bit de parada Sende retrasar(400); Cable.beginTransmission(PWM_ModuleAddr); // Datentransfer initiieren Cable.escribir(0x01); // Registro del modo 2 de Wähle (registro de comandos) Cable.escribir(0x04); // Chip Konfiguriere: 0x04: tótem Ausgang 0x00: drenaje abierto Ausgang. Cable.endTransmission(); // Stoppe Kommunikation - Bit de parada Sende Cable.beginTransmission(PWM_ModuleAddr); // Datentransfer initiieren Cable.escribir(0x00); // Registro del modo 1 de Wähle (registro de comandos) Cable.escribir(0x10); // Konfiguriere SleepMode Cable.endTransmission(); // Stoppe Kommunikation - Bit de parada Sende Cable.beginTransmission(PWM_ModuleAddr); // Datentransfer initiieren Cable.escribir(0xFE); // Registro de Wähle PRE_SCALE (registro de comando) Cable.escribir(0x03); // Establecer Prescaler. El maximale PWM Frecuente es 1526 Hz wenn das PRE_SCALEer Regsiter auf "0x03h" gesetzt wird. Estándar: 200 Hz Cable.endTransmission(); // Stoppe Kommunikation - Bit de parada Sende Cable.beginTransmission(PWM_ModuleAddr); // Datentransfer initiieren Cable.escribir(0x00); // Registro del modo 1 de Wähle (registro de comandos) Cable.escribir(0xA1); // Konfiguriere Chip: ERrlaube All Call I2C Adressen, verwende interne Uhr, // Función de incremento automático de Erlaube Cable.endTransmission(); // Stoppe Kommunikation - Bit de parada Sende } vacío Init_PWM_Outputs(byte PWM_ModuleAddr) { digitalWrite(OE_Pin, ALTO); // Active LOW-Ausgangsaktivierungs-Pin (OE) activo. para ( En t z = 0; z < 16 + 1; z++) { Cable.beginTransmission(PWM_ModuleAddr); Cable.escribir(z * 4 + 6); // Registro de Wähle PWM_Channel_ON_L Cable.escribir(0x00); // Wert für o.g. Registrarse Cable.endTransmission(); Cable.beginTransmission(PWM_ModuleAddr); Cable.escribir(z * 4 + 7); // Registro Wähle PWM_Channel_ON_H Cable.escribir(0x00); // Wert für o.g. Registrarse Cable.endTransmission(); Cable.beginTransmission(PWM_ModuleAddr); Cable.escribir(z * 4 + 8); // Registro de Wähle PWM_Channel_OFF_L Cable.escribir(0x00); // Wert für o.g. Registrarse Cable.endTransmission(); Cable.beginTransmission(PWM_ModuleAddr); Cable.escribir(z * 4 + 9); // Registro de Wähle PWM_Channel_OFF_H Cable.escribir(0x00); // Wert für o.g. Registrarse Cable.endTransmission(); } digitalWrite(OE_Pin, BAJO); // Active LOW-Ausgangsaktivierungs-Pin (OE) activo. } vacío preparar() { // Initalisierung De serie.empezar(9600); pinMode(PIRA_Pin, ENTRADA); pinMode(PIRB_Pin, ENTRADA); pinMode(OE_Pin, SALIDA); pinMode(CPU_LED_Pin, SALIDA); pinMode(LDR_Pin, ENTRADA); PWMModules = General_Etapas / 16; Etapas Izquierda = (General_Etapas % 16) - 1; Si (Etapas Izquierda >= 1) { PWMModules++; } Cable.empezar(); // Initalisiere 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); } noInterrupts(); adjuntarInterrumpir(0, ISR_PIR_A, CAMBIO); adjuntarInterrumpir(1, ISR_PIR_B, CAMBIO); TCCR1A = 0x00; TCCR1B = 0x02; TCNT1 = 0; // Registrarse mit 0 initialisieren OCR1A = 33353; // Salida Comparar Registro vorbelegen TIMSK1 |= (1 << OCIE1A); // Temporizador Comparar interrupción aktivieren interrumpe(); De serie.println(F("Init_Complete")); } bool DayLightStatus () { En t Valor del sensor = 0; bool Valor de retorno = cierto; Valor del sensor = analogRead(LDR_Pin); #ifdef DEPURAR De serie.impresión(F("DayLightStatus:")); De serie.impresión(Valor del sensor); #terminara si Si (Valor del sensor > DayLight_Brightness_Border) { Si ((DayLight_Status) y (Valor del sensor > DayLight_Brightness_Border + L_Sens_Scope)) { Valor de retorno = falso; DayLight_Status = falso; } más Si (!(DayLight_Status)) { Valor de retorno = falso; DayLight_Status = falso; } #ifdef DEPURAR De serie.println(F(" APAGADO")); #terminara si } más { Si ((DayLight_Status) y (Valor del sensor > DayLight_Brightness_Border - L_Sens_Scope)) { Valor de retorno = cierto; DayLight_Status = cierto; } más Si (!(DayLight_Status)) { Valor de retorno = cierto; DayLight_Status = cierto; } #ifdef DEPURAR De serie.println(F(" EN")); #terminara si } regreso Valor de retorno; } vacío Down_to_Up_ON() { #ifdef DEPURAR De serie.println(F("Down_to_Up_ON")); #terminara si 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 ((Etapas Izquierda >= 1) y (ModuleCount == PWMModules - 1)) { Calc_Num_Stages_per_Module = Etapas Izquierda; } 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) { Cable.beginTransmission( PWM_Module_Base_Addr + ModuleCount); Cable.escribir(Pwm_Channel * 4 + 8); // Wähle PWM_Channel_0_OFF_L registrarse Cable.escribir((byte)Pwm_Channel_Brightness & 0xFF); // Wert für o.g. Registrarse Cable.endTransmission(); Cable.beginTransmission( PWM_Module_Base_Addr + ModuleCount); Cable.escribir(Pwm_Channel * 4 + 9); // Registro Wähle PWM_Channel_0_OFF_H Cable.escribir((Pwm_Channel_Brightness >> 8)); // Wert für o.g. Registrarse Cable.endTransmission(); Si (Pwm_Channel_Brightness < 4095) { Pwm_Channel_Brightness = Pwm_Channel_Brightness + Delay_Stage_ON; Si (Pwm_Channel_Brightness > 4095) { Pwm_Channel_Brightness = 4095; } } más Si ( Pwm_Channel < Num_Stages_per_Module + 1) { Pwm_Channel_Brightness = 0; retrasar(delay_per_Stage_in_ms); Pwm_Channel++; } } } } vacío Up_to_DOWN_ON() { #ifdef DEPURAR De serie.println(F("Up_to_DOWN_ON")); #terminara si byte Calc_Num_Stages_per_Module = Num_Stages_per_Module; En t ModuleCount = PWMModules - 1; mientras (ModuleCount >= 0) { Pwm_Channel_Brightness = 0; Si ((Etapas Izquierda >= 1) y (ModuleCount == PWMModules - 1)) { Calc_Num_Stages_per_Module = Etapas Izquierda; } más { Calc_Num_Stages_per_Module = Num_Stages_per_Module; } Pwm_Channel = Calc_Num_Stages_per_Module; mientras (Pwm_Channel > -1) { Cable.beginTransmission( PWM_Module_Base_Addr + ModuleCount); Cable.escribir(Pwm_Channel * 4 + 8); // Wähle PWM_Channel_0_OFF_L registrarse Cable.escribir((byte)Pwm_Channel_Brightness & 0xFF); // Wert für o.g. Registrarse Cable.endTransmission(); Cable.beginTransmission(PWM_Module_Base_Addr + ModuleCount); Cable.escribir(Pwm_Channel * 4 + 9); // Registro Wähle PWM_Channel_0_OFF_H Cable.escribir((Pwm_Channel_Brightness >> 8)); // Wert für o.g. Registrarse Cable.endTransmission(); Si (Pwm_Channel_Brightness < 4095) { Pwm_Channel_Brightness = Pwm_Channel_Brightness + Delay_Stage_ON; Si (Pwm_Channel_Brightness > 4095) { Pwm_Channel_Brightness = 4095; } } más Si ( Pwm_Channel >= 0) { Pwm_Channel_Brightness = 0; retrasar(delay_per_Stage_in_ms); Pwm_Channel--; Si ( Pwm_Channel < 0) { Pwm_Channel = 0; descanso; } } } ModuleCount = ModuleCount - 1; } } vacío Down_to_Up_OFF() { #ifdef DEPURAR De serie.println(F("Down_to_Up_OFF")); #terminara si 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 ((Etapas Izquierda >= 1) y (ModuleCount == PWMModules - 1)) { Calc_Num_Stages_per_Module = Etapas Izquierda; } más { Calc_Num_Stages_per_Module = Num_Stages_per_Module; } mientras (Pwm_Channel < Calc_Num_Stages_per_Module + 1) { Cable.beginTransmission( PWM_Module_Base_Addr + ModuleCount); Cable.escribir(Pwm_Channel * 4 + 8); // Wähle PWM_Channel_0_OFF_L registro de Alambre de.escribir((byte)Pwm_Channel_Brightness & 0xFF); // Wert für o.g. Registro de Alambre.endTransmission(); Alambre.beginTransmission(PWM_Module_Base_Addr + ModuleCount); Alambre de.escribir(Pwm_Channel * 4 + 9); // Wähle PWM_Channel_0_OFF_H registro de Alambre de.escribir((Pwm_Channel_Brightness >> 8)); // Wert für o.g. Registro de Alambre.endTransmission(); si (Pwm_Channel_Brightness > 0) { Pwm_Channel_Brightness = Pwm_Channel_Brightness - 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(delay_per_Stage_in_ms); Pwm_Channel++; } } } } vacío 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; 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.beginTransmission(PWM_Module_Base_Addr + ModuleCount); Alambre de.escribir(Pwm_Channel * 4 + 8); // Wähle PWM_Channel_0_OFF_L registro de Alambre de.escribir((byte)Pwm_Channel_Brightness & 0xFF); // Wert für o.g. Registro de Alambre.endTransmission(); Alambre.beginTransmission(PWM_Module_Base_Addr + ModuleCount); Alambre de.escribir(Pwm_Channel * 4 + 9); // Wähle PWM_Channel_0_OFF_H registro de Alambre de.escribir((Pwm_Channel_Brightness >> 8)); // Wert für o.g. Registro de Alambre.endTransmission(); si (Pwm_Channel_Brightness > 0) { Pwm_Channel_Brightness = Pwm_Channel_Brightness - Delay_Stages_OFF; 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; } } } 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 = verdadero; Down_to_Up_ON(); } más { Motion_Trigger_Down_to_Up = false; } } 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)) { DLightCntrl = DayLightStatus(); si (DLightCntrl) { Seconds24 = 0; On_Delay = verdadero; Up_to_DOWN_ON(); } más { Motion_Trigger_Up_to_Down = false; } } 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; } } void loop() { Stages_Light_Control (); }
Zur Fehlerdiagnose steht eine serielle Schnittstelle mit 9600 Baudios zur Verfügung an der einige Informationen zum aktuellen Estado ausgegeben werden:
Ich wünsche viel Spaß beim Nachbau und bis zum letzten Teil der Reihe.
Wie immer findet Ihr auch alle vorherigen Projekte unter der GitHub Seite https://github.com/kuchto
1 comentario
Arnie
Servus an alle Treppenbeleuchter,
wer den neuen Code so übernimmt:
- auf 8 Stufen eingestellt
- Ausschaltzeit beträgt 10 sec
- die Überblendungen sind sehr flott
- ich habe einen LDR von 3,9 kohm eingesetzt