Proyecto Luces Automáticas

Buenas noches, estoy realizando un proyecto con luces automáticas y han surgido varias complicaciones (cabe aclarar que soy novato). Pero antes que nada dejo la lista de los materiales que estoy empleando
Materiales:

2 Arduino Nano
6 relevadores (1 Modulo de 4 reles y 1 Modulo de 2)
6 Lamparas a 127V CA
4 Sensores Ultrasonicos HC-SR04
Cable en general

El objetivo es realizar unas luces automáticas para una escalera en una casa de 3 pisos (anexo el diagrama)


Los problemas comienza cuando trato de hacer todo con un solo arduino ya que el programa tiene varias variantes de operación las cuales son:
1 solo Arduino
1.- Subida de la planta baja: Cuando sube uno, el sensor 4 manda la señal y activa las lamparas 1,2,3 y 4

2.- Segundo Piso: Este piso tiene 2 variantes:
2.1.- Cuando vas de bajada el sensor 2 manda a activar las lamparas 1,2,3 y 4
2.2.- Cuando subes al tercer piso el sensor 3 manda a activar las lamparas 5 y 6

3.- Tercer Piso: Cuando vas de bajada solo activa las lamparas 5 y 6

Al emplear solo un arduino los problemas comienzan cuando uso la función delay para la activación, poniendo un ejemplo hipotetico:
Voy de subida desde la planta baja y el sensor 4 activa las lamparas 1,2,3 y 4 y yo quisiera seguir subiendo al tercer piso. Debido a la activación de las primeras 4 el arduino se queda pasmado por el delay y pasa por alto que active el sensor 3. Otro problema que me surge es al momento de las cargas, ya que la fuente que uso no alcanza activar todos los reles (solo prenden los leds pero no conmutan)

2 Arduinos
Mi opción de novato fue usar un segundo arduino donde el primer arduino se ocupe de los primeros 2 pisos (Ultrasonico 2 y 4) y el segundo arduino se emplee solo para el tercer piso (Ultrasonico 1 y 3).

Anexo el codigo que empleo para el primer arduino

int ledPin1 = 2;
int ledPin2 = 3;
int ledPin3 = 4;
int ledPin4 = 5;

int trigPin1 = 6;
int echoPin1 = 7;

int trigPin2 = 8;
int echoPin2 = 9;


void setup() {
  Serial.begin (9600);
  pinMode(trigPin1, OUTPUT);
  pinMode(echoPin1, INPUT);
 
  pinMode(trigPin2, OUTPUT);
  pinMode(echoPin2, INPUT);
 
 
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);
  pinMode(ledPin4, OUTPUT);
}

void firstsensor(){ // Piso 1.
  int duration1, distance1;
  digitalWrite (trigPin1, HIGH);
  delayMicroseconds (10);
  digitalWrite (trigPin1, LOW);
  duration1 = pulseIn (echoPin1, HIGH);
  distance1 = (duration1/2) / 29.1;

      Serial.print("Planta Baja: ");
      Serial.print(distance1); 
      Serial.print("cm    ");

  if (distance1 > 15) {  
    digitalWrite (ledPin1, HIGH);
    delay(100);
    digitalWrite (ledPin2, HIGH);
    delay(100);
    digitalWrite (ledPin3, HIGH);
    delay(100);
    digitalWrite (ledPin4, HIGH);
  } else {
    digitalWrite (ledPin1, LOW);
    delay(100);
    digitalWrite (ledPin2, LOW);
    delay(100);
    digitalWrite (ledPin3, LOW);
    delay(100);
    digitalWrite (ledPin4, LOW);
    delay(3000);
  }   
}
void secondsensor(){ // Piso 2.
    int duration2, distance2;
    digitalWrite (trigPin2, HIGH);
    delayMicroseconds (10);
    digitalWrite (trigPin2, LOW);
    duration2 = pulseIn (echoPin2, HIGH);
    distance2 = (duration2/2) / 29.1;
 
      Serial.print("Segundo Piso: ");
      Serial.print(distance2); 
      Serial.print("cm    ");
  
    if (distance2 > 15) {  
    digitalWrite (ledPin1, HIGH);
    delay(100);
    digitalWrite (ledPin2, HIGH);
    delay(100);
    digitalWrite (ledPin3, HIGH);
    delay(100);
    digitalWrite (ledPin4, HIGH);
  } else {
    digitalWrite (ledPin1, LOW);
    delay(100);
    digitalWrite (ledPin2, LOW);
    delay(100);
    digitalWrite (ledPin3, LOW);
    delay(100);
    digitalWrite (ledPin4, LOW);
    delay(3000);
    }   
}

void loop() {
Serial.println("\n");
firstsensor();
secondsensor();

delay(100);
} 

El codigo anterior es el mismo para el segundo arduino solo que en ese caso solo activa las lamparas 5 y 6 (del diagrama). Eh visto acerca de la función millis pero veo que es para blinky leds donde las pausas son tiempos exactos predeterminados, en mi caso esas pausas que requiero son cuando se mande manda la señal del sensor.

Asi que para no hacer mas larga la cosa mis dudas son las siguientes:

1.- ¿Habría la posibilidad de hacer todo con 1 solo arduino empleando la función millis?
2.- ¿Para los componentes empleados ya sea con 1 arduino o dos que fuente me recomiendan emplear?
3.- Dado que son 3 pisos otra cuestion que me preocupa es la distancia, del piso 3 al 1 son como 12 metros de recorrido de cable, ¿tendria algun problema con las señales de los sensores o su alimentación? ya que todo iria en un gabinete en el tercer piso (arduinos, reles y fuente/s)

Gracias de antemano y saludos :slight_smile:

El retardo no es recomendado hacerlo bloqueando la operación del microcontrolador. En general puedes hacer algo sin bloquear del siguente modo:

const long retardo=100 //o lo que sea
unsigned long previo = 0;
void funcion(){
unsigned long tiempo= millis();
if(tiempo-previo>=retardo){
previo=tiempo;
//ejecutar codigo
}

Dependiendo del consumo de corriente, puede haber problema con que la alimentación de los sensores sea lejana, si es baja un condensador de unos 1000uF en la enterada del sensor puede ser suficiente, si el consumo es alto es necesario una fuente cercana al sensor.
Mas complicado es la transmisión de las señales, en este post estiman que es sensor no debería estar a más de 5 metros del microcontrolador.
En conclusión, usar 2 arduinos.

Exacto, delay() es el mayor generador de problemas cuando empezamos a programar "en serio".

Te recomiendo que leas el tutorial sobre millis() que encuentras en la sección Documentación

Agrego: Por el largo de los cables vas a tener también problemas de ruidos eléctricos, inducciones y demás. Tienes varios desafíos por solucionar en tu proyecto.

Saludos

Ve a documentacion y estudia

  1. Máquina de estados
  2. milllis()
    Hay muy buenos tutoriales en esa sección.
    Necesitas ambas cosas. Leelos y luego conversamos. Entre todos te ayudaremos.

Por supuesto que se puede pero.. ¿ Es necesario pausar ya sea con delays o millis?. No le veo sentido para tu proyecto.

8 relés a 100mA, (tirando muy por lo alto), = 800 mA . Si vamos a una fuente de 1A te sobran 200mA para sensores y arduino, suficiente. Cualquier cargador de celular de unos grandes almacenes de 5V 1A te va sobrado, no te compliques más.

Usandoun buen cable de ethernet cat-7 no creo que tengas problemas. ¿No tienes un gabinete en el 2º piso para instalar el arduino?, acortarías las distancias y los posibles problemas por dos.

Perdon mi ignorancia, pero eso que escribes sirve para hacer pausas estilo delay?

Respecto a las distancias pretendo emplear cable calibre 20 AWG

Si! El delay es un dolor de cabeza, lo checare y les comentare nuevamente :slight_smile:

Perdón pero no entiendo, acado hay otra forma de hacer esas activaciones de los reles un cierto tiempo sin emplear ni delay ni millis?

Es lo mismo que estaba considerando, instalar un gabinete en el segundo piso para acortar distancias

¿Y porque un cierto tiempo?, El / los reles yo solo los activaria cuando los sensores correspondientes detecten algo, si no es el caso para que tener más tiempo encendidas las luces.
Una pregunta: ¿cual es la distancia las larga a medir?.

Exacto, pausas sin bloquear el micro, mide el tiempo en vez de hacer esperar.
Como dice gatul un cable largo trae problemas de ruido también, se transforma en una buena antena, de modo que debe estar bién blindado.

Perdon la tardanza :sweat_smile: el dia de ayer me dedique a instalar un gabinete en el segundo piso, pero ya quedo, ahora el hc-sr04 mas lejano es de el segundo al primer piso, ahora seran como 5 metros (antes eran 12 metros del gabinete del 3er piso al primero)
De igual modo aun ando leyendo pero me cuesta entender como hacer las pausas sin millis ni delay,

Asi es como empotre los sensores en las tapas de luz

Pues usare cable (no alambre) de calibre 20 supongo que es buen cable asi que espero no tenga problemas, ademas ya instale otro gabinete en el segundo piso asi que ahora el tramo mas largo son somo 5metros del arduino al sensor

Bueno no es la mejor solución pero debería funcionar mas o menos bien.
Prueba a ver



#include <NewPing.h>

int ledPin1 = 2;
int ledPin2 = 3;
int ledPin3 = 4;
int ledPin4 = 5;

#define TRIGGER1_PIN   6  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO1_PIN      7  // Arduino pin tied to echo pin on the ultrasonic sensor.

#define TRIGGER2_PIN   8  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO2_PIN      9  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping.

NewPing sonar[2] = {   // Sensor object array.
  NewPing(TRIGGER1_PIN, ECHO1_PIN, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping. 
  NewPing(TRIGGER2_PIN, ECHO2_PIN, MAX_DISTANCE) 
};

void parpadeo(byte tipo, unsigned long t1, unsigned long t2, unsigned long t3, unsigned long t4, 
               bool estado1, bool estado2, bool estado3, bool estado4){

   static int modo[2] = {0,0};
   static unsigned long startTime[2];

   switch (modo[tipo]) {
      case 0:  digitalWrite (ledPin1, estado1);
               startTime[tipo] = millis();
               modo[tipo] = 1;
               break;
      case 1:  if (millis() - startTime[tipo] > t1) {
                  digitalWrite (ledPin2, estado2);
                  startTime[tipo] = millis();
                  modo[tipo] = 2;      
               }
               break;
      case 2:  if (millis() - startTime[tipo] > t2) {
                  digitalWrite (ledPin3, estado3);
                  startTime[tipo] = millis();
                  modo[tipo] = 3;      
               }
               break;
      case 3:  if (millis() - startTime[tipo] > t3) {
                  digitalWrite (ledPin4, estado4);
                  startTime[tipo] = millis();
                  modo[tipo] = 4;      
               }
               break;
      case 4:  if (millis() - startTime[tipo] > t4) {
                  modo[tipo] = 0;      
               }
               break;               

   }
   printf("tipo %1d modo = %1d tiempo %6ld\n", tipo, modo[tipo], millis() - startTime[tipo]);
}

void sensor(byte tipo){ // Piso 1.
   static int distancia[2] = {0,0};

   distancia[tipo] = sonar[tipo].ping_cm();
   Serial.print("Planta Baja: ");
   Serial.print(distancia[tipo]); 
   Serial.println("cm    ");
   
   if (distancia[tipo] > 15) {  
         parpadeo(tipo, 100, 100, 100, 100, HIGH, HIGH, HIGH, HIGH);
   } else {
         parpadeo(tipo, 100, 100, 100, 3000, LOW, LOW, LOW, LOW);
   }   
}

void setup() {
  Serial.begin (115200);
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);
  pinMode(ledPin4, OUTPUT);
}

void loop() {
   Serial.println("\n");
   sensor(0);
   sensor(1);
}

No se admiten delay() de ningún tipo cuando se usa millis()
Hay cosas que no me gustan del todo pero es digamos una solución que usa millis() y máquina de estados.
tipo es para poder separar los tiempos de 1 y otro grupo o sea de lo que esta arriba del arduino y lo que esta debajo.
El sistema es flexible puedes cambiar el comportamiento a tu gusto.
Me hubiera gustado no tener que usar tipo para elegir entre dos variables startTime[] pero fue lo que se me ocurrió.
A ver si un mejor programador tiene una mejor idea.
Por otro lado esta seguramente puedas comprenderla.

EDITO 1: Corrí el programa con un par de distancias y comprobé que las variables modo tmb tenian que ser dependientes del llamado o sea de tipo sea sensor1 o 2. Solo que sensor1 es 0 y sensor2 es 1.

EDITO 2 y 3: He hecho cambios para simplificar aún mas el código.
También vi que en la secuencia algo había puesto mal respecto de como queria el autor mostrar los estados de las luces. Ahora refleja lo que el quiere.

EDITO 4: Otro error mas en la definición de los dos sensores ultrasonicos. copie y pegué el mismo. Corregido.

Que tal amugo, esta bueno el código pero estoy obtenido estos resultados
https://drive.google.com/drive/folders/18yUfZoL6n0_dzsssmvjVhm9WaCg4bwI6

Subi por favor las cosas a Youtube para que se vea directamente.

@emmgamm Estás subiendo los videos con un formato que no se puede ver en cualquier dispositivo.
No solo son "qt" (que en definitiva es "mov" pero no tan "mov") sino que están en formato "HEV".
Vos los ves en tu mac o iphone sin inconvenientes pero el resto de los mortales "no apple" estamos en problemas y por lo visto Pepe Google tampoco los puede reproducir, de hecho uno de los videos hace horas que dice que "todavía se está procesando".
Guárdalos como mp4 o, como te dice @Surbyte, súbelos a YouTube.

Saludos

Lo siento por lo de los videos, aqui estan de youtube

Ya los subi a Youtube :slight_smile:

EDITADO:
Acabo de darme cuenta que uno trabaja haciendo un código y del otro lado, mas alla que puedan o no entenderlo (cosa que comprendo), no lo hacemos con ánimos de superioridad, solo buscamos mejorar las cosas. Digo esto porque de tanto en tanto (no es tu caso) recibimos comentarios de algunos que así lo indican.
Me pareció oportuno escribirlo y no se porque lo escribí tampoco. Creo que quise darle otro sentido y ahora quedó como dispersa la idea.

La máquina de estados es tan rapida que olvidé que ahora chequea muchas veces el estado del sensor ultrasónico, haciendo que ocurran situaciones intermedias que antes no pasaban.
Entonces voy a intentar bloquear su consulta durante todo un ciclo de la máquina de estados pero si lo hago la volveré bloqueante, lo cual parece un contrasentido.
El dilema es que se deteca una persona subiendo o bajando escaleras. y en tu código esto seguia hasta completar todos los leds. En el mio no.. porque vuelve a detectar que la distancia es distinta de 15 y entonces hace otra cosa.
Voy a ver como corregirlo.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.