This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm whether you accept or reject these cookies being set.

A cookie will be stored in your browser regardless of choice to prevent you being asked this question again. You will be able to change your cookie settings at any time using the link in the footer.

  • 0 voto(s) - 0 Media
  • 1
  • 2
  • 3
  • 4
  • 5
comunicador upd
#1
Hola a todos
Estoy haciendo un comunicador udp para un sistema de alarmas de casa. La idea es que cuando se dispara la sirena de la alarma, me active un relay que abre un circuito y el arduino me envia la informacion de la zona que esta abierta en la alarma.

Lo que deseo hacer es que si la alarma esta sonando, el arduino que tendra conectado 9 pines en serie con las zonas de la alarma, comience a revisar cuales zonas estan abiertas y me envie la informacion. en intervalos de 30 segundos, durante los 4 minutos que normalmente dura sonando la alarma.


Problemas:
Lograr que haga la revision de todas las zonas y me vaya enviando los datos segun los va revisando.
lograr que haga la revision de todas las zonas cada 30 segundos
lograr enviar los datos a una direccion dyndns.

-Hasta ahora he podido lograr que envie el dato de la zona abierta, pero luego espera 30 segundos para poder registrar la otra, se que me falta otra variable, pero estoy bloqueado y agradecere su ayuda. aqui va el codigo:


Código:
#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.h>         // UDP library from: bjoern@cs.stanford.edu 12/30/2008


// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {  
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 69, 200);

//IPAddress remip(10, 0, 0, 2);
unsigned int localPort = 5015;      // local port to listen on
// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,
char  ReplyBuffer[] = "acknowledged";       // a string to send back

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

int pinSensor[]= {7,8};
const int pinled = 3;
const int sirena = 4;
int n=0;
int sonando;  // para estado del pin que monitorea la sirena de la alarma
char alarma[] ="30120001BA0";  //codigo a ser enviado, solo dejando espacio para la zona


void setup(){
// start the Ethernet and UDP:
  Ethernet.begin(mac,ip);
  Udp.begin(localPort);
// Udp.remoteIP=(remip);
// Udp.remotePort(rport);
  Serial.begin(9600);

for (int i=0; i<2; i++){  
pinMode(pinSensor[i],INPUT);
}
pinMode(pinled,OUTPUT);
pinMode(sirena,INPUT);
digitalWrite(pinled,LOW);
}
void loop(){
IPAddress destinationIP(192,168,69,122);  // Address of target machine //este quiero cambiarlo por una direccion ejemplo http://luk2009.dyndns.biz
unsigned int destinationPort = 5003;      // puerto udp al que se envia el dato
sonando = digitalRead(sirena);

if (sonando==LOW){

for (n=0;n<2;n++){
if (digitalRead(pinSensor[n])==LOW) {
digitalWrite(pinled, HIGH);// este led es solo para pruebas y saber que el sistema esta detectando los cambios
Udp.beginPacket(destinationIP, destinationPort);
//Udp.write(alarma);
Udp.print(alarma);
Udp.print(pinSensor[n]); // esto seria el equivalente a la zona del sistema de alarmas
Udp.endPacket();
delay (30000); // para controlar que no este enviando señales durante 4 minutos continuos, la idea es que revise todos los pines antes de hacer la pausa
}
else{
digitalWrite(pinled, LOW);  //led para pruebas solamente
}
}
}
}
  Responder
#2
No se si te entiendo. ¿Te refieres a que el problema es que revisa una zona, espera 30 segundos, y revisa la otra zona, y tu quieres que revise y envíe todas y entonces espere los 30 segundos?

Si es eso, tendrías que hacer este cambio:

Código:
void loop(){
IPAddress destinationIP(192,168,69,122);  // Address of target machine //este quiero cambiarlo por una direccion ejemplo http://luk2009.dyndns.biz
unsigned int destinationPort = 5003;      // puerto udp al que se envia el dato
sonando = digitalRead(sirena);

if (sonando==LOW){
    for (n=0;n<2;n++){
        if (digitalRead(pinSensor[n])==LOW) {
            digitalWrite(pinled, HIGH);// este led es solo para pruebas y saber que el sistema esta detectando los cambios
            Udp.beginPacket(destinationIP, destinationPort);
            //Udp.write(alarma);
            Udp.print(alarma);
            Udp.print(pinSensor[n]); // esto seria el equivalente a la zona del sistema de alarmas
            Udp.endPacket();
            // El delay está en la comprobación de zona, lo comentas para que no lo haga
            //delay (30000); // para controlar que no este enviando señales durante 4 minutos continuos, la idea es que revise todos los pines antes de hacer la pausa
        }
        else{
            digitalWrite(pinled, LOW);  //led para pruebas solamente
        }
    }
// Este delay está en el "if", con lo que sólo se ejecuta tras mirar todas las zonas...
delay (30000); // para controlar que no este enviando señales durante 4 minutos continuos, la idea es que revise todos los pines antes de hacer la pausa
}
}

Y deberías indentar el código. Lo hace mucho más legible y claro, y en casos como este, verás mucho más fácil donde están las cosas... Y si tienes que pedir ayuda, los que te lean lo agradecerán Guiño
  Responder
#3
Otra recomendacion, es que no uses delays(), ya que estos mantienen el micro retenido, usa una rutina con millis(), hace millis() a una variable, lo almacenas, y miras que cuando milllis(), sobrepase esa variable+30segundos, ejecutes el codigo, asi no tienes parado el micro.

Un saludo¡¡
  Responder
#4
gracias por sus respuestas, voy a probar lo que me dicen y le comento como me funciona.

el problema 3, que es el de enviar el string a una direccion ip dinamica tipo dyndns. Alguien tiene alguna idea de como hacer el siguiente cambio:

DestinationIP IPAddress (192,168,69,122);

por:
DestinationIP IPAddress (luk2009.dyndns.biz);
  Responder
#5
he logrado la comunicacion via internet utilizando dnsClient.getHostByName, Escafandra un amigo del foro delphiaccess me dio algunas guias. Ahora estoy depurando el codigo usando millis y usando delay lo menos posible. Ahora tengo el problema de que en la parte del codigo que detecta una alarma, no lo hace hasta que pasan 30 segundos.

La idea es que lo haga de inmediato y que luego lo haga cada 30 segundos. Lo ideal seria que detectara cualquier cambio en los piines de manera independiente. Como un hilo de ejecucion aparte para cada pin, pero en principio me conformo con que la primera vez no espere 30 segundos para enviar el mensaje.

Código:
#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.h>         // UDP library from: bjoern@cs.stanford.edu 12/30/2008
#include <Dns.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {  
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
//IPAddress destip(0, 0, 0, 0);
IPAddress destip(192,168,69,122);  // para pruebas en la red local  
unsigned int localPort = 5015;      // local port to listen on
// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,
char  ReplyBuffer[] = "acknowledged";       // a string to send back
// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;
char alarma[] ="30120745BA0";
char cierre[]=  "30120001CL40";
char apertura[]="30120001OP40";
int estado =0;  // estado del sistema de alarmas
int estadoanterior =0; //estado anterior de la alarma;
int salida =0;  // 0 indica apertura   1 indica cierre
int pinSensor[]= {7,8,9};
int n=0;
long previousMillis = 0;
long interval = 30000;


void setup(){
// start the Ethernet and UDP:

if (Ethernet.begin(mac) == 0) {  // start Ethernet by DHCP conf.
     Serial.println("Failed to configure Ethernet using DHCP");}
     Udp.begin(localPort);
     Serial.begin(9600);
     for (int i=0; i<3; i++){  
           pinMode(pinSensor[i],INPUT);
         }
     pinMode(6,INPUT);

}

void loop(){
IPAddress destinationIP(destip);  // Address of target machine
unsigned int destinationPort = 5003;      // Port to send to
estado=digitalRead(6);   //leer estado del sistema de alarmas
     if ((estado ==HIGH) && (estadoanterior== LOW)) {
          salida = 1;
         }
        if ((estado ==LOW) && (estadoanterior== HIGH)) {
            salida=0;
            }
     estadoanterior= estado;

           if ((salida == 1)&& (estado==HIGH)){
              //digitalWrite(2, HIGH);  
               Udp.beginPacket(destinationIP, destinationPort);
              //Udp.write(alarma);
               Udp.print(cierre);
               Udp.endPacket();
               salida=0;
               delay(30);
               }
           if ((salida == 0)&& (estado==LOW)){
               //digitalWrite(2, LOW);
              // Serial.println(estado);
               //Serial.println(destinationIP,destinationPort);
               Udp.beginPacket(destinationIP, destinationPort);
               Udp.print(apertura);
               Udp.endPacket();
               salida=1;
               delay(30);
               }
              unsigned long currentMillis = millis();
              if(currentMillis - previousMillis > interval){
                  previousMillis = currentMillis;    
                if (estado== HIGH){
                    for (n=0;n<2;n++){
                         if (digitalRead(pinSensor[n])==LOW) {
                              Serial.println(pinSensor[n]);
                              Udp.beginPacket(destinationIP, destinationPort);
                              Udp.print(alarma);
                              Udp.print(pinSensor[n]); // esto seria el equivalente a la zona del sistema de alarmas
                              Udp.endPacket();
                             }
                      }
          
                }  
                    
         }
                      
}

esta es una version para pruebas en mi red local. La idea es que si el pin 6 indica que la alarma esta activada(CIERRE), cualquier cambio en algun pin(zona) sea enviado y que luego sea reenviado cada 30 segundos en un intervalo de 4 minutos, si es que la condicion permanece.

espero haberme explicado bien.

gracias por adelantado.
  Responder
#6
Fíjate donde tienes los delays... ¿Es donde los quieres? Entiendo que no, que quieres 30 segundos entre envios, luego el delay debería ir detrás de "Udp.endPacket();". ¿Pero el tema de los millis no es para no usar delay?

EDIT: Si, parece que lo de los millis se encarga, yo creo que con comentar los delays irá como quieres...
  Responder
#7
Los delays estan bien, porque es para evitar unos rebotes y solo son de 30 milisegundos. El problema lo tengo con el millis y el interval. Lo que he hecho es establecer el valor de interval en 10 al principio, antes del void setup. La idea es que detecte inmediatamente si hay un cambio en los pines utilizados como zonas.

Funciona, pero luego de detectar el pinSensor en LOW, el interval cambia y hay que esperar 30 segundos para que detecte si hay algun cambio, aun sea en otro pinSensor. Lo que quisiera es que si es la misma zona el interval valga 30000 milisegundos, pero si es otra zona el interval valga 10 y se envie el mensaje de una vez. Lo he intentado con algunas variables , pero luego de detectar el cambio y enviar el primer mensaje, los demas tardan 30 segundos.
Código:
#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.h>         // UDP library from: bjoern@cs.stanford.edu 12/30/2008
#include <Dns.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {  
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
//IPAddress destip(0, 0, 0, 0);
IPAddress destip(192,168,69,122);  // para pruebas en la red local  
unsigned int localPort = 5015;      // local port to listen on
// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,
char  ReplyBuffer[] = "acknowledged";       // a string to send back
// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;
char alarma[] ="30120745BA0";
char cierre[]=  "30120001CL40";
char apertura[]="30120001OP40";
int estado =0;  // estado del sistema de alarmas
int estadoanterior =0; //estado anterior de la alarma;
int salida =0;  // 0 indica apertura   1 indica cierre
int pinSensor[]= {7,8,9};
int n=0;
long previousMillis = 0;
long interval = 10;
int zonadisparo=0;
int zonadisparoanterior= 0;

void setup(){
// start the Ethernet and UDP:

if (Ethernet.begin(mac) == 0) {  // start Ethernet by DHCP conf.
Serial.println("Failed to configure Ethernet using DHCP");}
// Ethernet.begin(mac,ip);
  Udp.begin(localPort);
  Serial.begin(9600);
for (int i=0; i<3; i++){  
pinMode(pinSensor[i],INPUT);
}
pinMode(6,INPUT);
//pinMode(2,OUTPUT);
}
void loop(){
IPAddress destinationIP(destip);  // Address of target machine
unsigned int destinationPort = 5003;      // Port to send to
estado=digitalRead(6);   //leer estado del sistema de alarmas
     if ((estado ==HIGH) && (estadoanterior== LOW)) {
          salida = 1;
         }
        if ((estado ==LOW) && (estadoanterior== HIGH)) {
            salida=0;
            }
     estadoanterior= estado;

           if ((salida == 1)&& (estado==HIGH)){
              //digitalWrite(2, HIGH);  
               Udp.beginPacket(destinationIP, destinationPort);
              //Udp.write(alarma);
               Udp.print(cierre);
               Udp.endPacket();
               salida=0;
              delay(30);
               }
           if ((salida == 0)&& (estado==LOW)){
               Udp.beginPacket(destinationIP, destinationPort);
               Udp.print(apertura);
               Udp.endPacket();
               salida=1;
              delay(30);
               }
              unsigned long currentMillis = millis();
              if(currentMillis - previousMillis > interval){
                  previousMillis = currentMillis;    
                if (estado== HIGH){
                    for (n=0;n<3;n++){
                          zonadisparo=pinSensor[n];
                      if (digitalRead(pinSensor[n])==LOW) {  // establecer si es un pinSensor diferente y en ese caso interval volveria a cero
                              zonadisparoanterior=pinSensor[n];
                              Serial.println(pinSensor[n]);
                              Serial.println(interval);
                              Udp.beginPacket(destinationIP, destinationPort);
                              Udp.print(alarma);
                              Udp.print(pinSensor[n]); // esto seria el equivalente a la zona del sistema de alarmas
                              Udp.endPacket();
                              //interval = 30000;
                              Serial.println(interval);
                              Serial.println(zonadisparo);
                              Serial.println(zonadisparoanterior);
                              if (zonadisparo == zonadisparoanterior){
                                  interval=30000; }
                              else{interval=10;
                                  
                                   }
                              }  
                              
            
         }                        
                                  
                               }
                                                   }
}
deberia ser sencillo de hacer, pero la verdad es que estoy bloqueado.
  Responder
#8
Es lo que tiene leer por encima...

¿Que ves en la depuración? Lo digo por que parece que te has colado con el valor de "Interval" cuando es distinto y has puesto 10 en vez de 10000:
Código:
if (zonadisparo == zonadisparoanterior){
interval=30000; }
else{interval=10;

¿Puede ser que entre, según sale y como en 10ms no habrá cambiado, ponga entonces Interval a 30? Por eso pregunto lo de la depuración: si pasa eso, deberías tener la info "duplicada" cada vez por pasar dos veces consecutivas por el if.

De todos modos: ¿No es más sencillo montarte una estructura similar por "canal" de alarma? Me refiero a tener un "previousMillis" por cada pin, y asegurarte de que nunca se entra antes de 30 segundos tras un envío, y fuera de eso un previousMillis general que se encargue de que no se produzcan comunicaciones en menos de 10s (O lo que decidas para espaciar las tramas).
  Responder
#9
La asignacion de interval la haces despues de todo el for, como dice thoromir yo leeria cada una separado, interval en el for adquirira el valor de la ultima comprobacion siempre ya que no sales hasta que pasas por el ultimo sensor... Es lo que veo asi rapido desde el movil

Enviado desde mi Nexus 4 mediante Tapatalk
  Responder