Arduino Domo

post

Arduino DOMO

presentamos un proyecto domotico totalmente funcional.

Proyecto by : ExControl

Se maneja desde una aplicación android y al configuración del mismo es realmente sencillo. Tan solo necesitas de un Arduino Mega y un Arduino Ethernet shield, (para trabajor con horarios ademas en necesario Real Time Clock Module RTC DS1307 ) para poder comenzar a configurar el sistema .

Con un solo arduino mega podemos controlar:

  • 6 zonas de iluminación con control de potencia.
  • 6 zonas Control on off.
  • 7 zonas Control de persianas o toldos
  • 3 Control de climatización con temperaturas de consigna.
  • 3 Control de Calefacción con temperaturas de consignas.
  • 2 zonas Control de riego automático.
  • Programación de horarios.
  • Programación de escenas o ambientes.
  • Control por voz.
  • Posibilidad de control desde fuera de la red local sin ip fija.
Instalaciones Domoticas con Arduino

Puedes adaptarla a cada aplicación en concreto modificando el programa base para arduino y configurando la aplicación android.

En la sección descargas dispones a enlaces a los diferentes programas, aplicación android para manejo y código para shield arduino.

Configuración Incial del Sistema

Como es natural lo primeros que necesitamos para poder trabajar con el sistema es el hardware necesario, los requisitos minimos son:

Para poder utiliara los horaros ademas sera necesario un modulo ds1307 rtc, Si ya dispones del hardware necesario lo siguiente es configurar el sistema.


Configuración Librerias.

No es necesario la descarga de ninguna librería adicional, no obstante si que es precisa una modificación en la librería EthernetUdp.

Esta modificación es necesaria ya que librería EthernetUdp tiene por defecto un tamaño máximo de 24 bytes para los paquetes.

Para que el sistema funcione completamente es necesario aumentar ese valor hasta 340, veamos como hacemos esto:

Abrir el archivo EthernetUdp.h, para encontrar este archivo entramos dentro de la carpeta del programa ARDUINO, una vez dentro de esta carpeta la ruta seria:

Libraries\Ethernet\EthernetUdp.h.

Una vez abierto el archivo buscamos la linea donde pone :

#define UDP_TX_PACKET_MAX_SIZE 24

y la modificamos por:

#define UDP_TX_PACKET_MAX_SIZE 340

Guardamos los camios realizados y listo.


Configurando el programa arduino.

Lo único que debemos configurar para comenzar a utilizar el sistema domótico es la parte correspondiente a nuestra red local, para esto buscamos lo siguiente en el programa, Si todavía no lo ha descargado pulsa aqui.

// NETWORK CONFIGURATION // IP Address, ADJUST TO YOUR LOCAL NETWORK
//If you change the IP address will have to adjust in android application
//If you change the Local Port address will have to adjust in android application
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 200);
unsigned int localPort = 5000; // puerto local para eschucha de paquete

Como podemos ver esta parte corresponde a la configuración Ip de la tarjeta arduino, la dirección mac, y el puerto para la recepción de paquetes.
Téngase en cuenta que en la mayoría de los casos esta configuración funcionara sin ningún tipo de problema.
Para empezar a funcionar lo mejor es modificar solamente la direccion IP por una que este dentro de nuestro rango (Si fuera necesario)


Instala la Aplicación de Control Domotico Android

Esta es la aplicación para gestionar el sistema domotico, puede ser instalada en cualquier dispositivo android, y puede ser descargada a través del playstore, pulsa para descargar.

Instalaciones Domoticas con Arduino

Instalamos la aplicación desde el PlayStore y la ejecutamos. Cuando ejecutemos el sistema por primera vez este nos preguntar por la IP y el puerto de comunicaciones configuradas en la tarjeta arduino, si esta no fue modificada en el paso anterior simplemente aceptamos la que viene por defecto.

Eliminar y añadir Circuitos

Cuando instalamos la aplicación de control para android este presenta una configuración de zonas de control a modo de demostración, pero como es natural es totalmente personalizable a nuestra instalación.

El sistema por defecto trae configuradas todas las zonas de control. Para adaptar esta configuración entramos en el menú administrador, para llegar a este desde la pantalla principal pulsamos sobre la el botón Configuración.

Instalaciones Domoticas con Arduino

Cuando pulsemos este entraremos en el menú de configuración del sistema, nos vamos a la parte de abajo del mismo y pulsamos sobre Menú Administrador, es posible que nos solicite una contraseña, aceptamos la que nos ofrece por defecto.

Menu administrador Domoticas con Arduino

Llegados a este punto nos aparece una pantalla con diferentes opciones, buscamos la ultima en la que nos indica configuración de circuitos, hacemos una pulsación larga sobre este para activar.

Una vez realizado esto nos encontramos con una pantalla en la cual vienen representados todos los circuitos y zonas de control, para eliminar un circuito hacemos una pulsación sobre el circuito en cuestión, con esto el presenta el sistema un lista de opciones, buscamos la ultima que pone borrar circuito, con esto ya no aparecerá en ninguna de las opciones del sistema (horarios, escenas….)

Una vez borrado el circuito vemos en la lista como sus campo nombre y descripción están vacíos, pues bien para que vuelva a aparecer el circuito en el sistema solo tenemos que definir un nombre al circuito, esto se puede hacer en este mismo menú, pulsando sobre la zona de control y seleccionando cambiar Nombre.

Cuando este todo configurado a nuestro gusto pulsamos sobre el botón guardar situado en la parte de abajo del sistema para que los cambios queden reflejados.

Modificar nombres de circuitos y zonas.

Cuando instalamos la aplicación de control para android este presenta una configuración de zonas de control a modo de demostración, pero como es natural es totalmente personalizable a nuestra instalación.

El sistema por defecto trae configuradas los nombres  de todas las zonas de control. Para adaptar esta configuración entramos en el menú administrador, para llegar a este desde la pantalla principal pulsamos sobre la el botón Configuración.

Instalaciones Domoticas con Arduino

Cuando pulsemos este entraremos en el menú de configuración del sistema, nos vamos a la parte de abajo del mismo y pulsamos sobre Menú Administrador, es posible que nos solicite una contraseña, aceptamos la que nos ofrece por defecto.

Menu administrador Domoticas con Arduino

Llegados a este punto nos aparece una pantalla con diferentes opciones, buscamos la ultima en la que nos indica configuración de circuitos, hacemos una pulsación larga sobre este para activar.

Una vez realizado esto nos encontramos con una pantalla en la cual vienen representados todos los circuitos y zonas de control, para modificar el nombre de un circuito hacemos una pulsación sobre el circuito en cuestión, con esto el presenta el sistema un lista de opciones, buscamos la primera en la  que pone cambiar nombre.

Con esto aparece un cuadro de dialogo donde podemos introducir un nuevo nombre para la zona de control, escribimos el nuevo valor para el campo nombre y pulsamos aceptar.

Cuando este todo configurado a nuestro gusto pulsamos sobre el botón guardar situado en la parte de abajo del sistema para que los cambios queden reflejados.

Modificar descripción de circuitos y zonas.

Cuando instalamos la aplicación de control para android este presenta una configuración de zonas de control a modo de demostración, pero como es natural es totalmente personalizable a nuestra instalación.

El sistema por defecto trae configuradas las descripciones  de las zonas de control. Para adaptar esta configuración entramos en el menú administrador, para llegar a este desde la pantalla principal pulsamos sobre la el botón Configuración.

Instalaciones Domoticas con Arduino

Cuando pulsemos este entraremos en el menú de configuración del sistema, nos vamos a la parte de abajo del mismo y pulsamos sobre Menú Administrador, es posible que nos solicite una contraseña, aceptamos la que nos ofrece por defecto.

Menu administrador Domoticas con Arduino

Llegados a este punto nos aparece una pantalla con diferentes opciones, buscamos la ultima en la que nos indica configuración de circuitos, hacemos una pulsación larga sobre este para activar.

Una vez realizado esto nos encontramos con una pantalla en la cual vienen representados todos los circuitos y zonas de control, para modificar la descripción de un circuito hacemos una pulsación sobre el circuito en cuestión, con esto el presenta el sistema un lista de opciones, buscamos la segunda en la que pone cambiar descripción.

Con esto aparece un cuadro de dialogo donde podemos introducir un nuevo valor para la descripción de la zona de control, escribimos el nuevo valor y pulsamos aceptar.

Cuando este todo configurado a nuestro gusto pulsamos sobre el botón guardar situado en la parte de abajo del sistema para que los cambios queden reflejados.

**

Importante : Las Librerías

librerias

No es necesario la descarga de ninguna librería adicional.
No obstante si que es precisa una modificación en la librería EthernetUdp.

Esta modificación es necesaria ya que librería EthernetUdp tiene por defecto un tamaño máximo de 24 bytes para los paquetes.
Para que el sistema funcione completamente es necesario aumentar ese valor hasta 340, veamos como hacemos esto:

Abrir el archivo EthernetUdp.h, para encontrar este archivo entramos dentro de la carpeta del programa ARDUINO.
Una vez dentro de esta carpeta la ruta seria:
Libraries\Ethernet\EthernetUdp.h.

Una vez abierto el archivo buscamos la linea donde pone : #define UDP_TX_PACKET_MAX_SIZE 24

y la modificamos por:
#define UDP_TX_PACKET_MAX_SIZE 340 Guardamos los camios realizados y listo.

Codigo Arduino:

[code lang=”arduino”]

#include // needed for Arduino versions later than 0018

<em id="__mceDel"> #include
#include // UDP library from: bjoern@cs.stanford.edu 12/30/2008
#include
#include
#include
#include
#define DS1307_I2C_ADDRESS 0x68 //Direccion Reloj
#define ONE_WIRE_BUS 3 //Pin one wire
/***********************************************************************************************************************/
/***********************************************************************************************************************/
/***********************************************************************************************************************/
/***********************************************************************************************************************/
//ZONA DE CONFIGURACIONES
//Define numero de entradas salidas
//Configuracion Red</em>

/******************************************************************************************************************************/

//SETTINGS ZONE
//Defines number of inputs and outputs
//Network configuration
//Set or Restet Daylight saving time o DST
/***********************************************************************************************************************/
/***********************************************************************************************************************/
/***********************************************************************************************************************/
/***********************************************************************************************************************/
//Activa o desactiva cambio hora automatico invierno verano
//Set or Restet Daylight saving time o DST
//El modo dts esta configurado para europa
//Dts mode is set to europe
//Para otros paises configure funcion CargaHora()
//For other countries configure function CargaHora()
const boolean Enable_DaylightSavingTime = true;

//Numero de Entradas
//Number of Inputs
const int Number_Input = 10;
//Numero de Salidas
//Number of Outputs
const int Number_Output = 16;
//Numero de Persianas
//Number of blind
const int NumeroPersianas = 2;

//CONFIGURACION DE RED
//Direccion IP ES MUY PROBABLE QUE TENGAS QUE AJUSTARLO A TU RED LOCAL
//Cambia la ip por una dentro de tu rango, tambien debes actualizarla en tu aplicacion android
//Tambien puedes cambiar el puerto, por defecto 5000

// NETWORK CONFIGURATION
// IP Address, ADJUST TO YOUR LOCAL NETWORK
//If you change the IP address will have to adjust in android application
//If you change the Local Port address will have to adjust in android application

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 200);
unsigned int localPort = 5000; // puerto local para eschucha de paquete

/***********************************************************************************************************************/
/***********************************************************************************************************************/
/***********************************************************************************************************************/
/***********************************************************************************************************************/
//FIN DE ZONAS DE CONFIGURACIONES
//END SETTINGS ZONE
/***********************************************************************************************************************/
/***********************************************************************************************************************/
/***********************************************************************************************************************/
/***********************************************************************************************************************/

OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
DallasTemperature sensorTemp(&amp;oneWire);// Pass our oneWire reference to Dallas Temperature.
DeviceAddress insideThermometer; // arrays to hold device address

// buffers para recepcion y envio de datos
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];

// Instanacia Ethernet UDP Para enviar y recibir paqueteP
EthernetUDP Udp;
//Varibles Reloj
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year,minutoMemory,TipoDia;
boolean HoraRetrasa;
unsigned long LastMsg;

//Variables Gestion Entradas Salidas
int PinInput[Number_Input]; //Asocia el pin a la entrada correspondiente
unsigned long LastTimeInput[Number_Input]; //Ultima vez que la entrada estaba en reposo
byte InState[Number_Input]; //Estado Entrada
int PinOutput[Number_Output]; //Asocia el pin a la entrada correspondiente

//Registros Salidas Circuitos
byte ElectricalCircuitValue[30];
byte Temperatura1=31;
byte Temperatura2=32;
byte Temperatura3=33;

/////////////////////////////////////////////////////////////////////////////////////////////////////////
//Configuracion Persianas
/////////////////////////////////////////////////////////////////////////////////////////////////////////
byte PosicionPersiana[NumeroPersianas]; //Controla la posicion de la persiana % Subida
unsigned long TiempoMovPersiana[NumeroPersianas]; //Tiempo de mov desde el ultimo refresco

//Memoria de tiempos y posicion respecto a tiempo
unsigned long TiempoPosPersianaUp[NumeroPersianas]; //Posicion persiana en subida
unsigned long TiempoPosPersianaDown[NumeroPersianas]; //Posicion persiana en Bajada
unsigned long TimUpPersiana[NumeroPersianas]; //Tiempo en MicrosSg subida persiana
unsigned long TimDowPersiana[NumeroPersianas]; //Tiempo en MicrosSg bajada persiana

//Variables para salidas y entradas
boolean OutUpPersiana[NumeroPersianas]; //Boleana para activar salida persiana
boolean OutDowPersiana[NumeroPersianas]; //Boleana para activar salida persiana
boolean InUpPersiana[NumeroPersianas]; //Boleana pulsador subida Persiana
boolean InDowPersiana[NumeroPersianas]; //Boleana pulsador bajada Persiana

void setup() {
/***********************************************************************************************************************/
/***********************************************************************************************************************/
/***********************************************************************************************************************/
/***********************************************************************************************************************/
//ZONA DE CONFIGURACIONES
//Configura pines de entrada
//Configura pines salida
/******************************************************************************************************************************/

//SETTINGS ZONE
//inputs PIN, number in arduino board
//Output Pin, number in arduino board
/***********************************************************************************************************************/
/***********************************************************************************************************************/
/***********************************************************************************************************************/
/***********************************************************************************************************************/

//Pines de entrada
PinInput[0]=40;
PinInput[1]=41;
PinInput[2]=42;
PinInput[3]=43;
PinInput[4]=44;
PinInput[5]=45;
PinInput[6]=46;
PinInput[7]=47;
PinInput[8]=48;
PinInput[9]=49;

//Pines de salida

PinOutput[0]=22;
PinOutput[1]=23;
PinOutput[2]=24;
PinOutput[3]=25;
PinOutput[4]=26;
PinOutput[5]=27;
PinOutput[6]=28;
PinOutput[7]=29;
PinOutput[8]=30;
PinOutput[9]=31;
PinOutput[10]=32;
PinOutput[11]=33;
PinOutput[12]=34;
PinOutput[13]=35;
PinOutput[14]=36;
PinOutput[15]=37;
/***********************************************************************************************************************/
/***********************************************************************************************************************/
//FIN DE ZONAS DE CONFIGURACIONES
/***********************************************************************************************************************/
/***********************************************************************************************************************/
/***********************************************************************************************************************/
/***********************************************************************************************************************/

//Serial.begin(9600);
// Inico Ethernet y UDP

Ethernet.begin(mac,ip);
Udp.begin(localPort);

//Inicio control Horarios
Wire.begin();
CargaHora();

//Iniciamos Entradas Salidas
for (int i =0; i&lt;30; i++){ElectricalCircuitValue[i]=0;}

//Fijamos pines entrada salida
unsigned long currenMillis = millis();
for (int i=0; i&lt;Number_Input;i++){pinMode(PinInput[i], INPUT);LastTimeInput[i]=currenMillis;InState[i]=0;}
for (int i=0; i&lt;Number_Output;i++){pinMode(PinOutput[i], OUTPUT);}

//Fijamos Temp. Consigna en Inicio
ElectricalCircuitValue[20]=20;
ElectricalCircuitValue[21]=20;
ElectricalCircuitValue[22]=20;

// Localizar sensores de temp. en bus
sensorTemp.begin();
// set the resolution to 9 bit (Each Dallas/Maxim device is capable of several different resolutions)
sensorTemp.getAddress(insideThermometer, 0);
sensorTemp.setResolution(insideThermometer, 9);

//Fijamo valores y posicion inicio persianas
//Fijamos el tiempo de subida bajada Persianas
//Se encuentran apartir de la direccion 3880
//
ReiniciarTiempoPersianas();

//Subimos las persianas a iniciar para ajustar posicion
for (int per=0; per&lt;NumeroPersianas; per++){
ReiniciarPosicionPersiana(per);
InDowPersiana[per]=false;
InUpPersiana[per]=false;
}

}
/***********************************************************************************************************************/
/***********************************************************************************************************************/
//EVENTOS CONTROL ENTRADAS SALIDAS
//INPUT OUTPUT CONTROL EVENTS

//DOS EVENTOS PARA ENTRADAS DIGITALES
//PULSACION CORTA
//PULSACION LARGA, MAYOR DE 0.5 SEGUNDOS

// THREE EVENTS FOR DIGITAL INPUTS
// PRESS SHORT
// PRESS LONG, OVER 0.5 SECONDS
// LONG PRESS END.

/***********************************************************************************************************************/
/***********************************************************************************************************************/
/***********************************************************************************************************************/
/***********************************************************************************************************************/
void ShortInput(int NumberInput){
/*****************************************************************/
//Este evento se produce con una pulsación corta.
// This event occurs with a short press.
/*****************************************************************/
//Ejemplo de uso
// Example of use

//Iluminacion 1
if (NumberInput==0){
switch (ElectricalCircuitValue[0]) {
case 0:
ElectricalCircuitValue[0]=3; break;
case 1:
ElectricalCircuitValue[0]=3; break;
case 2:
ElectricalCircuitValue[0]=1; break;
case 3:
ElectricalCircuitValue[0]=2; break;
}
}
//Iluminacion 2
if (NumberInput==2){
switch (ElectricalCircuitValue[1]) {
case 0:
ElectricalCircuitValue[1]=3; break;
case 1:
ElectricalCircuitValue[1]=3; break;
case 2:
ElectricalCircuitValue[1]=1; break;
case 3:
ElectricalCircuitValue[1]=2; break;
}
}
//Enchufe 1
if (NumberInput==7){if (ElectricalCircuitValue[6]==1){ElectricalCircuitValue[6]=0;}else{ElectricalCircuitValue[6]=1;}}

//Enchfue 2
if (NumberInput==6){if (ElectricalCircuitValue[7]==1){ElectricalCircuitValue[7]=0;}else{ElectricalCircuitValue[7]=1;}}

//Persianas
//blind
//Ejemplo de uso
// Example of use
/*
//Persiana 1
if (NumberInput==1){ElectricalCircuitValue[23]=100;}
if (NumberInput==5){ElectricalCircuitValue[23]=0;}
//Persiana 2
if (NumberInput==9){ElectricalCircuitValue[24]=100;}
if (NumberInput==4){ElectricalCircuitValue[24]=0;}
*/
}
void LongInputEnd(int NumberInput){
/*****************************************************************/
//FINAL DE PULSACION LARGA
//LONG PRESS END, EVENT
// This event occurs with end a long press.
/*****************************************************************/

//Persianas
//blind
//Ejemplo de uso
// Example of use

/*
if (NumberInput==1){InUpPersiana[0]=false;}
if (NumberInput==5){InDowPersiana[0]=false;}
if (NumberInput==9){InUpPersiana[1]=false;}
if (NumberInput==4){InDowPersiana[1]=false;}
*/
}
void LongInput(int NumberInput){
/*****************************************************************/
//EVENTO PRODUCINO AL INICIO DE UNA PULSACION LARGA
// LONG PRESS START
// This event occurs with start a long press.
/*****************************************************************/
//Ejemplo de uso
// Example of use

//Pulsador Iluminacion 1
if (NumberInput==0){ElectricalCircuitValue[0]=0;}

//Pulsador Iluminacion 2
if (NumberInput==2){ElectricalCircuitValue[1]=0;}

//Pulsador Enchufe 1
if (NumberInput==7){ElectricalCircuitValue[6]=1;ElectricalCircuitValue[7]=1;ElectricalCircuitValue[8]=1;}

//Pulsador Enchfue 2
if (NumberInput==6){ElectricalCircuitValue[6]=0;ElectricalCircuitValue[7]=0;ElectricalCircuitValue[8]=0;}

//Persianas
//blind
//Ejemplo de uso
// Example of use
/*
if (NumberInput==1){InUpPersiana[0]=true;InDowPersiana[0]=false;}
if (NumberInput==5){InDowPersiana[0]=true;InUpPersiana[0]=false;}
if (NumberInput==9){InUpPersiana[1]=true;InDowPersiana[1]=false;}
if (NumberInput==4){InDowPersiana[1]=true;InUpPersiana[1]=false;}
*/
}
void OutControl()
{
/*************************************************************/
//Gestion Salidas
//Activamos los reles de control.

// Outputs Management
// Activate control relays.
/*************************************************************/
//Ejemplo de uso
// Example of use

// Circuito Numero 1
//Iluminacion Iluminacion con 3 puntos de luz controlados mediante 2 Reles.
switch (ElectricalCircuitValue[0]) {
case 0: // your hand is on the sensor
digitalWrite(PinOutput[1], LOW);
digitalWrite(PinOutput[3], LOW);
break;
case 1: // your hand is close to the sensor
digitalWrite(PinOutput[1], HIGH);
digitalWrite(PinOutput[3], LOW);
break;
case 2: // your hand is a few inches from the sensor
digitalWrite(PinOutput[1], LOW);
digitalWrite(PinOutput[3], HIGH);
break;
case 3:
digitalWrite(PinOutput[1], HIGH);
digitalWrite(PinOutput[3], HIGH);
break;
default:
ElectricalCircuitValue[0]=0;
break;
}

// Circuito Numero 2
//Iluminacion Iluminacion con 3 puntos de luz controlados mediante 2 Reles.
switch (ElectricalCircuitValue[1]) {
case 0:
digitalWrite(PinOutput[5], LOW);
digitalWrite(PinOutput[7], LOW);
break;
case 1:
digitalWrite(PinOutput[5], HIGH);
digitalWrite(PinOutput[7], LOW);
break;
case 2:
digitalWrite(PinOutput[5], LOW);
digitalWrite(PinOutput[7], HIGH);
break;
case 3:
digitalWrite(PinOutput[5], HIGH);
digitalWrite(PinOutput[7], HIGH);
break;
default:
ElectricalCircuitValue[1]=0;
break;
}
// Circuito Numero 7
//Enchufe
//Enchufes
switch (ElectricalCircuitValue[6]) {
case 0:
digitalWrite(PinOutput[15], HIGH);
break;
case 1:
digitalWrite(PinOutput[15], LOW);
break;
default:
ElectricalCircuitValue[6]=0;
}
// Circuito Numero 8
//Enchufe numero 1
switch (ElectricalCircuitValue[7]) {
case 0:
digitalWrite(PinOutput[13], HIGH);
break;
case 1:
digitalWrite(PinOutput[13], LOW);
break;
default:
ElectricalCircuitValue[7]=0;
}
// Circuito Numero 9
//Enchufe numero 1
switch (ElectricalCircuitValue[8]) {
case 0:
digitalWrite(PinOutput[11], HIGH);
break;
case 1:
digitalWrite(PinOutput[11], LOW);
break;
default:
ElectricalCircuitValue[8]=0;
}
// Circuito Numero 10
//Enchufe numero 1
if ((OutDowPersiana[0]==true)||(OutUpPersiana[0]==true))
{
if ((OutDowPersiana[0]==true)&amp;&amp;(OutUpPersiana[0]==false)){digitalWrite(PinOutput[2], LOW); digitalWrite(PinOutput[0], LOW); }
if ((OutDowPersiana[0]==false)&amp;&amp;(OutUpPersiana[0]==true)){digitalWrite(PinOutput[2], HIGH); digitalWrite(PinOutput[0], LOW); }
}
else{
digitalWrite(PinOutput[0], HIGH);
digitalWrite(PinOutput[2], HIGH);
}
//Persiana 2
if ((OutDowPersiana[1]==true)||(OutUpPersiana[1]==true))
{
if ((OutDowPersiana[1]==true)&amp;&amp;(OutUpPersiana[1]==false)){digitalWrite(PinOutput[6], LOW); digitalWrite(PinOutput[4], LOW); }
if ((OutDowPersiana[1]==false)&amp;&amp;(OutUpPersiana[1]==true)){digitalWrite(PinOutput[6], HIGH); digitalWrite(PinOutput[4], LOW); }
}
else{
digitalWrite(PinOutput[4], HIGH);
digitalWrite(PinOutput[6], HIGH);
}

//Reles de reserva
//Su estado de reposo corresponde a un nivel logico alto
digitalWrite(PinOutput[8], HIGH);
digitalWrite(PinOutput[10], HIGH);
digitalWrite(PinOutput[12], HIGH);
digitalWrite(PinOutput[14], HIGH);

}

/***********************************************************************************************************************/
/***********************************************************************************************************************/
//FIN DE ZONAS DE CONFIGURACIONES
//NO ES NECESARIO PROGRAMAR NADA POR DEBAJO DE ESTE PUNTO

/***********************************************************************************************************************/
// END CONFIGURATION ZONE
// NO NEED TO SET ANYTHING BELOW THIS POINT
/***********************************************************************************************************************/
/***********************************************************************************************************************/
/***********************************************************************************************************************/
/***********************************************************************************************************************/
void loop(){

if(millis() &lt; LastMsg ) {CargaHora();} if((millis() – LastMsg) &gt;= 30000) {CargaHora();}

RecepcionPaqueteUDP();
InputState();
for (int p =0; p&lt;NumeroPersianas;p++){GestionMovPersianas(p);} //Control de movimiento persianas
OutControl();
}
void InputState(){
for (int i=0; i&lt;Number_Input;i++){ unsigned long InputMillis = millis()-LastTimeInput[i]; if (InState[i]&gt;=4){InState[i]=0;}
if (digitalRead(PinInput[i]) == LOW ) {
if ((InState[i]==0)&amp;&amp;(InputMillis&gt;=60)){LastTimeInput[i]=millis();InState[i]=1;}
if ((InState[i]==1)&amp;&amp;(InputMillis&gt;=440)){LongInput(i);InState[i]=2;}
if (InState[i]==2){LastTimeInput[i]=millis();}
if (InState[i]==3){LastTimeInput[i]=millis();InState[i]=1;}
}
else{

if (InState[i]==0){LastTimeInput[i]=millis();}
if (InState[i]==1){LastTimeInput[i]=millis();InState[i]=3;}
if ((InState[i]==2) &amp;&amp;(InputMillis&gt;=60)){LastTimeInput[i]=millis();InState[i]=0;LongInputEnd(i);}
if ((InState[i]==3)&amp;&amp;(InputMillis&gt;=60)){LastTimeInput[i]=millis();InState[i]=0;ShortInput(i);}
}
}
}

/*************************************************************/
//Gestion Persianas
/*************************************************************/
void GestionMovPersianas(int NPersiana){
if (InUpPersiana[NPersiana] || InDowPersiana[NPersiana])
{ //Funcionamiento Manual
if (InUpPersiana[NPersiana] &amp;&amp; InDowPersiana[NPersiana]){OutDowPersiana[NPersiana]=false;OutUpPersiana[NPersiana]=false;}
else{
if (InUpPersiana[NPersiana]){SubirPersiana(NPersiana);}
if (InDowPersiana[NPersiana]){BajarPersiana(NPersiana);}
ElectricalCircuitValue[23 + NPersiana]=PosicionPersiana[NPersiana];
}
}
else
{ //Funcionamiento Automatico;
if (ElectricalCircuitValue[23 + NPersiana]==PosicionPersiana[NPersiana]){OutDowPersiana[NPersiana]=false;OutUpPersiana[NPersiana]=false;}
else
{
if (ElectricalCircuitValue[23 + NPersiana] &gt; PosicionPersiana[NPersiana]){SubirPersiana(NPersiana);}
else {if (ElectricalCircuitValue[23 + NPersiana] &lt; PosicionPersiana[NPersiana]) {BajarPersiana(NPersiana);}}
}
}
}
void SubirPersiana(int NPersiana){
if (OutDowPersiana[NPersiana]==true){BajarPersiana(NPersiana);OutDowPersiana[NPersiana]=false;OutControl();delay(200);}
long TiempoActual = micros();
if (OutUpPersiana[NPersiana]==false){OutUpPersiana[NPersiana]=true;}
else{
long DiferenciaTiempo;
if (TiempoActual&lt;TiempoMovPersiana[NPersiana]){DiferenciaTiempo=TiempoActual;}else{DiferenciaTiempo = TiempoActual-TiempoMovPersiana[NPersiana];}
if ((TiempoPosPersianaUp[NPersiana] + DiferenciaTiempo)&lt;TimUpPersiana[NPersiana]){TiempoPosPersianaUp[NPersiana]=TiempoPosPersianaUp[NPersiana] + DiferenciaTiempo;}
else{TiempoPosPersianaUp[NPersiana]=TimUpPersiana[NPersiana];}
byte porcentajeSubida = TiempoPosPersianaUp[NPersiana] / (TimUpPersiana[NPersiana]/100);
byte porcentajeBajada=100-porcentajeSubida;
PosicionPersiana[NPersiana]=porcentajeSubida;
TiempoPosPersianaDown[NPersiana]=porcentajeBajada*(TimDowPersiana[NPersiana]/100);
}
TiempoMovPersiana[NPersiana]=TiempoActual;
}
void BajarPersiana(int NPersiana){
if (OutUpPersiana[NPersiana]==true){SubirPersiana(NPersiana);OutUpPersiana[NPersiana]=false;OutControl();delay(200);}
long TiempoActual = micros();
if (OutDowPersiana[NPersiana]==false){OutDowPersiana[NPersiana]=true;}
else{
long DiferenciaTiempo;
if (TiempoActual&lt;TiempoMovPersiana[NPersiana]){DiferenciaTiempo=TiempoActual;}else{DiferenciaTiempo = TiempoActual-TiempoMovPersiana[NPersiana];}
if ((TiempoPosPersianaDown[NPersiana] + DiferenciaTiempo)&lt;TimDowPersiana[NPersiana]){TiempoPosPersianaDown[NPersiana]=TiempoPosPersianaDown[NPersiana] + DiferenciaTiempo;}else{TiempoPosPersianaDown[NPersiana]=TimDowPersiana[NPersiana];}

byte porcentajeBajada = TiempoPosPersianaDown[NPersiana] / (TimDowPersiana[NPersiana]/100);
byte porcentajeSubida=100-porcentajeBajada;
PosicionPersiana[NPersiana]=porcentajeSubida;
TiempoPosPersianaUp[NPersiana]=porcentajeSubida*(TimUpPersiana[NPersiana]/100);
}
TiempoMovPersiana[NPersiana]=TiempoActual;
}
void ReiniciarTiempoPersianas(){for ( int c =0; c&lt;NumeroPersianas; c++){TimUpPersiana

[c][/c]

=(EEPROM.read(3880 + c))* 1000000; TimDowPersiana

[c][/c]

=(EEPROM.read(3890 + c))* 1000000;}}
void ReiniciarPosicionPersiana(int NumPersiana){ TiempoPosPersianaUp[NumPersiana]=0;TiempoPosPersianaDown[NumPersiana]=TimDowPersiana[NumPersiana];ElectricalCircuitValue[23+NumPersiana]=100;}

/*************************************************************/
//Gestion Comunicaciones
/*************************************************************/
void RecepcionPaqueteUDP()
{

// SI TENEMOS PAQUETES LEEMOS CONTENIDO
int packetSize = Udp.parsePacket();

if(packetSize)
{
//Leemos el paquete en packetBufffer

Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);

//Cargamos el String con los datos de entrada
char CadenaEntrada[packetSize + 1];
for (int c=0;c&lt;packetSize;c++){CadenaEntrada

[c][/c]

=packetBuffer

[c][/c]

;}
CadenaEntrada[packetSize]=’\0';
//Comprobamos la cadena de entrada gestionamos las salidas y enviamos la respuesta
String CadenaIn = (String)CadenaEntrada;

/***********************************************************************************/
//Gestion Trmas Entradas
/**********************************************************************************/

if (CadenaIn=="CLEARHORARIO"){for (int i = 1000; i &lt;= 3879; i++){EEPROM.write(i, 66);}EnviarRespuesta("HORARIOS BORRADOS"); return;}//Borra Horarios
if (CadenaIn=="CLEARESPCDAY"){for (int i = 3900; i &lt;= 3999; i++){EEPROM.write(i, 0);}EnviarRespuesta("DIAS ESPECIALES BORRADOS");return; }//Borra Dias Especiales if (CadenaIn.indexOf("SETFH")&gt;-1){
//Actuliza Fecha Y hora setDateDs1307(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year)
setDateDs1307(packetBuffer[5] ,packetBuffer[6], packetBuffer[7], packetBuffer[8], packetBuffer[9], packetBuffer[10], packetBuffer[11]);
CargaHora();
ReadDate();
return;
}
if (CadenaIn.indexOf("READDAY")&gt;-1){//Lectura Dia Especial
char Respuesta[325];
Respuesta[0]=’C';
Respuesta[1]=’F';
Respuesta[2]=’D';
Respuesta[3]=’A';

int PunteroRegistro;
if (packetBuffer[7]==’2′){PunteroRegistro=3950;}else{PunteroRegistro=3900;}
for (int i = 0; i&lt;50;i++){Respuesta[i+4]=EEPROM.read(PunteroRegistro + i); } Respuesta[324]=’\0'; EnviarRespuesta(Respuesta); return; } if (CadenaIn.indexOf("WRIDAYE")&gt;-1){//Escritura Dia Especial
int Reg;
int Pos=8;
if (packetBuffer[7]==2){Reg=3950;}else{Reg=3900;}
for (int i = Reg; i&lt;(Reg+50);i++){EEPROM.write(i,packetBuffer[Pos]);Pos++;} EnviarRespuesta("GUARDADO COMPLETO"); return; } if (CadenaIn.indexOf("READHOR")&gt;-1){//Lectura Horario
char Respuesta[325];
Respuesta[0]=’H';
Respuesta[1]=’O';
Respuesta[2]=’R';
Respuesta[3]=’A';
int Reg;
int Pos=4;
Reg=packetBuffer[7]*320+1000;
for (int i = Reg; i&lt;(Reg+320);i++){Respuesta[Pos]=EEPROM.read(i)+1;Pos++;} Respuesta[324]=’\0'; EnviarRespuesta(Respuesta); return; } if (CadenaIn.indexOf("WRITHOR")&gt;-1){//Escritura Horario
int Reg;
int Pos=8;
Reg=packetBuffer[7]*320+1000;
for (int i = Reg; i&lt;(Reg+320);i++){EEPROM.write(i,packetBuffer[Pos]);Pos++;} EnviarRespuesta("GUARDADO COMPLETO"); return; } if (CadenaIn.indexOf("SVAL")&gt;-1){ElectricalCircuitValue[packetBuffer[4]-1]=packetBuffer[5]-1;EnvioEstadoActual();return;} //Nuevo Valor registro salida

if (CadenaIn=="VACT"){EnvioEstadoActual();return;} //Lectura actual Salidas

if (CadenaIn.indexOf("SSCE")&gt;-1)//Seleccion Escena
{
int Dir;
Dir = (int)packetBuffer[4];
Dir = (Dir-1) * 30;

for (byte i =0 ; i&lt;30;i++){byte val =EEPROM.read(Dir+i); if (val&lt;250){ElectricalCircuitValue[i]=val;}} EnvioEstadoActual(); return; } if (CadenaIn.indexOf("WESC")&gt;-1)//Escritura escena
{
int Dir;
Dir = (int)packetBuffer[4];
Dir = (Dir-1) * 30;
for (byte i = 0; i&lt;30;i++){EEPROM.write(i+Dir, packetBuffer[5+i]-1);} EnviarRespuesta("GUARDADO COMPLETO"); return; } if (CadenaIn == "ESTADOINST"){ReadDate();return;}//Lectura Estado Instalacion Fecha y Hora if (CadenaIn.indexOf("RESC")&gt;-1)//Lectura Escena
{
int Dir;
Dir = (int)packetBuffer[4];
Dir = (Dir-1) * 30;

char Respuesta[36];
Respuesta[0]=’V';
Respuesta[1]=’E';
Respuesta[2]=’S';
Respuesta[3]=’C';
Respuesta[4]=packetBuffer[4]; //Numero de Escena

for (int i = 0; i &lt; 30;i++)
{
byte V=EEPROM.read(Dir+i);
if (V&lt;=254){V++;}
Respuesta[i + 5 ]=V;
}
Respuesta[35]=’\0';
EnviarRespuesta(Respuesta);
return;
}

if (CadenaIn == "ENABLEHOR")//Lectura Horarios Abilitados
{
char Respuesta[36];
Respuesta[0]=’E';
Respuesta[1]=’N';
Respuesta[2]=’H';
Respuesta[3]=’O';
Respuesta[4]=’R';

for (int i = 0; i &lt; 30;i++){Respuesta[i + 5 ]=EEPROM.read(970+i)+1;} Respuesta[35]=’\0'; EnviarRespuesta(Respuesta); return; } if (CadenaIn.indexOf("WHOR")&gt;-1)//Escritura ABILITACION HORARIOS
{
for (byte i = 0; i&lt;30;i++){EEPROM.write(i+970, packetBuffer[4+i]-1);}
EnviarRespuesta("GUARDADO COMPLETO");
return;
}

if (CadenaIn == "TIMPERSIANA")//Lectura Tiempos Persianas
{
char Respuesta[26];
Respuesta[0]=’L';
Respuesta[1]=’E';
Respuesta[2]=’C';
Respuesta[3]=’P';
Respuesta[4]=’E'; //Numero de Escena

for (int i = 0; i &lt; 20;i++){ Respuesta[i + 5 ]=EEPROM.read(3880+i)+1;} Respuesta[25]=’\0'; EnviarRespuesta(Respuesta); return; } if (CadenaIn.indexOf("WPERS")&gt;-1)//Escritura Valores Persianas
{
for (byte i = 0; i&lt;20;i++){EEPROM.write(i+3880, packetBuffer[5+i]-1);} ReiniciarTiempoPersianas(); EnviarRespuesta("GUARDADO COMPLETO"); return; } //Reiniciar persiana posicion Inicio if (CadenaIn.indexOf("RESTPER")&gt;-1){
ReiniciarPosicionPersiana(packetBuffer[7]-1);
EnviarRespuesta("RESETEANDO PERSIANA");
return;
}
//Si llegasmos aki el menaje es erroneo
EnviarRespuesta("REPETIRMSG");
}
}
void ReadDate(){
char Respuesta[26];
Respuesta[0]=’E';
Respuesta[1]=’S';
Respuesta[2]=’T';
Respuesta[3]=’A';
Respuesta[4]=’C';
Respuesta[5]=’T';

Respuesta[6]=TipoDia + 1;
Respuesta[7]=hour + 1;
Respuesta[8]=minute + 1;
Respuesta[9]=dayOfMonth + 1;
Respuesta[10]=month + 1;
Respuesta[11]=year + 1;

Respuesta[12]=’\0';

EnviarRespuesta(Respuesta);
}
void EnvioEstadoActual()//Envia el estado actual de la instalación
{
char Respuesta[38];
Respuesta[0]=’E';
Respuesta[1]=’V';
Respuesta[2]=’A';
Respuesta[3]=’L';

for (byte i = 4; i&lt;34;i++) { Respuesta[i]=ElectricalCircuitValue[i-4]+1; } //Temp. Consigna Respuesta[34]= Temperatura1 + 1; Respuesta[35]= Temperatura2 + 1; Respuesta[36]= Temperatura3 + 1; Respuesta[37]=’\0'; EnviarRespuesta(Respuesta); } void EnviarRespuesta(char ReplyBuffer[]) { // send a reply, to the IP address and port that sent us the packet we received Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); Udp.write(ReplyBuffer); Udp.endPacket(); } /******************************************************************************************************************/ //Funciones control Horarios /******************************************************************************************************************/ void CargaHora() { getDateDs1307(&amp;second, &amp;minute, &amp;hour, &amp;dayOfWeek, &amp;dayOfMonth, &amp;month, &amp;year); LastMsg=millis(); if (minute != minutoMemory){ActualizaMinuto(); } } void ActualizaMinuto() { if(Enable_DaylightSavingTime==true) { //Adelanta la hora.Apartir del dia 25 de Marzo, busca el primer domingo //y cuando se han las 2 de la noche adelanta el reloj una hora if (month==3) { if (dayOfMonth &gt;= 26)
{
if (dayOfWeek = 7)
{
if (hour==2)
{
hour = 3;
setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
}
}

}
}
//Retrasa la hora.Apartir del dia 25 de Octubre, busca el primer domingo
//y cuando se han las 2 de la noche retrasa el reloj una hora
if (month==10)
{
if (dayOfMonth &gt;= 26)
{
if (dayOfWeek = 7)
{
if ((hour==2)&amp;&amp;(HoraRetrasa==false))
{
hour = 1;
HoraRetrasa=true;
setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
}
}

}
}
}
if (hour==3){HoraRetrasa=false;}
minutoMemory=minute;

//Calculo Tipo Dia Especial o Semanal
TipoDia=dayOfWeek;
int Reg;

for (Reg=3900; Reg&lt;=3948;Reg=Reg+2){if (month == EEPROM.read(Reg)){if (dayOfMonth== EEPROM.read(Reg+1)){TipoDia=8;}}}//Verificacion Dia Especial 1
for (Reg=3950; Reg&lt;=3998;Reg=Reg+2){if (month == EEPROM.read(Reg)){if (dayOfMonth== EEPROM.read(Reg+1)){TipoDia=9;}}}//Verificacion Dia Especial 2
//Verificacion Horarios para este Estado
int R= ((TipoDia-1)*320)+1000;
for (Reg=R; Reg&lt;=(R+316);Reg=Reg+4) {if ((hour==EEPROM.read(Reg))&amp;&amp;(minute==EEPROM.read(Reg+1))){byte ci=EEPROM.read(Reg+2);if ((ci&lt;30) &amp;&amp; (EEPROM.read(ci+970)==1)){ElectricalCircuitValue[ci]=EEPROM.read(Reg+3);}}}

//Actualzamos Temp.
sensorTemp.requestTemperatures(); // Send the command to get temperatures
float tempC = sensorTemp.getTempC(insideThermometer);
Temperatura1=(byte)tempC;
}
/******************************************************************/
// FUNCIONES RELOJ
/*****************************************************************/

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}

// Stops the DS1307, but it has the side effect of setting seconds to 0
// Probably only want to use this for testing
/*void stopDs1307()
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0);
Wire.send(0x80);
Wire.endTransmission();
}*/

// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you’re passing in valid numbers
void setDateDs1307(byte second, // 0-59
byte minute, // 0-59
byte hour, // 1-23
byte dayOfWeek, // 1-7
byte dayOfMonth, // 1-28/29/30/31
byte month, // 1-12
byte year) // 0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(second)); // 0 to bit 7 starts the clock
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour)); // If you want 12 hour am/pm you need to set
// bit 6 (also need to change readDateDs1307)
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}

// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
// Reset the register pointer
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();

Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

// A few of these need masks because certain bits are control bits
*second = bcdToDec(Wire.read() &amp; 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() &amp; 0x3f); // Need to change this if 12 hour am/pm
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}
[/code]

Aplicación Android :

https://play.google.com/store/apps/details?id=arduino.domotics.home.excontrol.free

Demo APK :

Aquí

Esperamos que os guste !

Gracias a Roberto de excontrol.es por el aporte.

One comentario en “Arduino Domo

  • Eficiencia energetica on agosto 29th, 2013

    He leido vuestro articulo con mucha atecion y me ha parecido practico ademas de claro en su contenido. No dejeis de cuidar esta web es buena.
    Saludos

Dejar una respuesta

Categorías

Entradas recientes

Comentarios recientes

Archivos

Meta