Elegante iluminación de escalera automática (parte 4)

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:

Circuito con fotorresistencia

 

Para la parte actual del proyecto necesitamos:

Numero

Descripción

Nota

2

PIR Modulo HC-SR501 PIR

Sensor de movimiento

a 62

PCA9685 Controlador PWM de 16 bits y 12 canales

Número dependiendo del número de escaleras / 16

1

Nano V3

 

1

Adaptador de fuente de alimentación MB102

Para la construcción de paneles

a 992

Módulo controlador IRF520 MOS 0-24V 5A

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

LDR

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:

Salida en el monitor serial

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

 

 

Für arduinoProjekte für fortgeschritteneSensoren

1 comentario

Arnie

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

Deja un comentario

Todos los comentarios son moderados antes de ser publicados