Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Laboratorio de Programación 2
Proyecto Final
Casa domótica
Expediente: 297970
Grupo: 45
Fecha: 23/08/2022
1
1. Objetivo
2. MATERIALES Y EQUIPAMIENTO
2
• Leds para la iluminación
• Push button
3. METODOLOGÍA
3
Fig. 1.1 Recepción de datos.
Una vez tenida nuestra trama completa lo que se hace es separar cada uno de los datos que
esta contenga para poder guardarlos y utilizarlos después. Al primer valor guardado de
nuestra cadena de caracteres lo conoceremos como identificador. Este identificador lo que
hace es clasificar el tipo de datos dependiendo del valor de este como se ve en la siguiente
tabla.
Para ir avanzando a lo largo de la trama de datos completa es necesario crear una variable
que se utiliza para saber en que dato de la trama estamos para poder guardarlo. Los
caracteres de las tramas se separan por comas al cambiar de dato, esto sirve para diferenciar
que ya se ha cambiado de dato dentro de la misma trama completa.
Identificador Apartado
0 Cambio de hora de reloj
1 Horas encendido/apagado luces
2 Estado de la alarma
3 Temperatura máxima
4 Persianas
5
Temperatura máxima
La trama de temperatura máxima es muy parecida a la de la alarma ya que únicamente se
manda un dato que es el valor de la temperatura enviada desde el celular viéndose de esta
manera: #3,35&. El tres indica que es el identificador de la temperatura y al moverse a la
segunda posición se guarda el dato en la variable T_max.
Persianas
Para la trama de las persianas se requieren 3 datos además del identificador los cuales
establecen si la persiana correspondiente está abierta o cerrada de la siguiente manera #4, 0,
1,0& indicando que se quiere que la segunda persiana se abra y las demás se cierren. Se
guardan en sus respectivas variables mientras cont_dato avanza en la trama de datos.
2. CONTROL DE ILUMINACIÓN
Para el control de la rutina de iluminación debemos tener en cuenta que esta depende del
tiempo que indique el reloj de tiempo real DS1307, para ello se debo generar una base de
tiempo de 1 segundo para ser capaces de leer la hora en tiempo real.
6
Para realizar esto se utilizó la interrupción del Timer 1, recordemos que ésta va de 0 a 65535
cuentas y no es capaz de generar un periodo de 1 segundo sin usar lógica de programación,
por lo que se cálculo para un periodo de 100 ms con la siguiente fórmula:
4
𝑇= ∗ 𝑝𝑟𝑒𝑒𝑠𝑐𝑎𝑙𝑒𝑟 ∗ (65535 − 𝑐𝑎𝑟𝑔𝑎)
𝑓 𝑜𝑠𝑐
Utilizando un preescaler de 2, un cristal oscilador de 4MHz y una carga de 15535 se obtiene
un periodo de 100 ms.
Una vez obtenido el periodo de 100 ms se utilizó lógica de programación para generar la base
de tiempo de 1 segundo utilizando un contador y una bandera, estableciendo que cuando el
valor del contador sea 10 la bandera se ponga en alto, esto indicaría que la interrupción del
timer se repitió diez veces por lo que ahora tendríamos una base de 1 segundo.
Se debe recordar que la interrupción de los timers debe configurarse dentro de la función
principal antes del ciclo infinito utilizando la función setup_timer_1 () y deben habilitarse con
la función enable_interrupts (), esto se realiza antes del ciclo infinito debido a que solo es
necesario configurarse y habilitarse una vez.
Recordemos que para utilizar el reloj de tiempo real debe incluirse su respectiva librería, para
hacerlo basta con escribir #include "DS1307.c" en el apartado de las librerías, recordemos
que la librería es independiente del conjunto de librerías ya preestablecidas para el
microcontrolador por lo que debe ponerse en la misma carpeta donde está nuestro código y
ponerse entre comillas para mandarla a llamar.
El reloj de tiempo real también se configura en la función principal antes del ciclo infinito con la
función DS1307_OSC_ENABLE (1), teniendo al 1 como significado de que se quiere
encendido y el 0 como apagado.
Una vez configurado nuestro timer y el reloj de tiempo real ya podemos empezar con el
apartado de la iluminación.
7
Dentro del ciclo infinito evaluamos el estado de la bandera del reloj de tiempo real para
verificar que haya pasado un segundo, si la bandera está en alto significa que ha pasado un
segundo, al haber pasado un segundo debe establecerse que el valor la bandera sea cero
para que empiece a contar nuevamente para generar la base de tiempo de un segundo.
Dentro de esta base de tiempo se debe leer la hora del reloj, esto se realiza con la función
DS1307_GET_DATE_TIME (), donde deben establecerse las variables para guardar la hora,
minuto, segundo, día de la semana, día, mes y año.
Para determinar el encendido de las luces necesita compararse la hora y minuto actual con los
valores de la hora y minuto de encendido enviados desde la aplicación. Para esto se declaró
una variable llamada segundos cuyo valor era igual al de la hora actual del reloj del tiempo
real multiplicado por el número de segundos que hay en una hora más el valor de minutos
actual del reloj del tiempo real multiplicado por el número de segundos que hay en un minuto
más el valor de segundos actual del reloj del tiempo real. Una vez obtenido este dato se
compara con el valor en segundos de la hora y minuto de encendido enviados desde la
aplicación, si el valor de la variable segundos es igual al valor en segundos de la hora de
encendido enviada por la aplicación se ponen en alto los pines de la iluminación.
Se utiliza la misma lógica para la hora de apagado; el valor de la variable segundos se
compara con el valor en segundos de la hora y minuto de apagado enviada desde el celular, si
el valor de la variable segundos es igual al valor en segundos de la hora de apagado enviada
por la aplicación se ponen en bajo los pines de la iluminación.
Para mandar los datos de la hora de encendido y apagado desde el celular se mandó una
trama de datos en la cuál el primer dato mejor conocido como el identificador (1 para el caso
de las horas y minutos de encendido y apagado) determinaba que los datos siguientes serían
la hora y minuto de encendido y seguido la hora y minuto de apagado todos separados de la
siguiente manera: #1, hora_encendido, minuto_encendido, hora_apagado,
minuto_apagado& .
8
Fig. 2.2 Encendido y apagado de luces con reloj de tiempo real.
9
Para el encendido y apagado de luces de manera independiente del reloj se implementó una
lógica diferente, para empezar como este no depende del reloj de tiempo real podemos
sacarlo de la base de tiempo que se generó, esto con la finalidad de que al mandar la
instrucción de encender o apagar una luz no se tenga que esperar un segundo para que se
encienda o apague y sea casi inmediato.
Se asignó una combinación diferente para cada instrucción de encendido y apagado de cada
una de las luces, teniendo 2 combinaciones por luz, 8 combinaciones en total. Esto con la
finalidad de que al mandar una combinación se apague o encienda la luz correspondiente.
Para esto se utilizó un switch donde el valor a evaluar es el primer dato recibido de la trama
de datos completa que en el apartado de envío y recepción de datos se habla más a detalle.
10
3. SISTEMA DE VENTILACIÓN
Para el sistema de ventilación se utilizó el módulo ADC del microcontrolador para leer la
resistencia variable que se utilizó como potenciómetro para simular a un sensor de
temperatura. El ADC se configuró para usarse con 10 bits por lo que su valor varía entre 0 y
1023. Se debe configurar el ADC con la función SETUP_ADC (ADC_CLOCK_INTERNAL)
para que trabaje con el reloj interno del microcontrolador y la función SETUP_ADC_PORTS
(AN0, VSS_VDD) cuyos parámetros son el número de canales que se utilizarán y los voltajes
de referencia.
Una vez configurado el ADC se lee el canal del ADC que desea utilizarse para después
realizar conversiones (Fig. 3.1) para que el valor leído por el canal únicamente fuera de 0 a
40, esto con la finalidad de guardar el dato recibido como la temperatura actual que va de 0° a
40°.
Una vez obtenido el valor de la temperatura máxima permitida se compara con el valor actual
de la temperatura leída por el canal del ADC, si el valor actual de la temperatura es mayor o
igual a la temperatura máxima establecida, se pone en alto el pin del ventilador, de lo contrario
el pin del ventilador permanece en bajo como se ve en la Fig. 3.2.
11
Una vez obtenido el valor de la temperatura máxima, se guarda en la memoria EEPROM del
microcontrolador con la función write_eeprom (2, T_max) siendo el 2 el lugar que ocupa en la
memoria, y T_max el valor de la temperatura máxima, para que se guarde apropiadamente,
se debe leer la posición de la memoria donde se guardó la temperatura máxima antes del ciclo
infinito y debe guardarse nuevamente en la variable T_max como se hizo en el caso de la
hora de encendido y apagado de las luces.
4. CONTROL DE PERSIANAS
Para el control de las persianas y de los servomotores en general se utilizó la interrupción del
timer 3. Es necesario explicar el funcionamiento de un servomotor ya que es diferente de los
motores de corriente directa, para hacer funcionar un servomotor se tiene que programar una
base de tiempo generalmente de 25 ms. Para mover el servomotor a 180° se debe generar un
pulso positivo de 2.5 ms, si se quisiese mover el servomotor a 0° el pulso generado debe ser
de 0.5 ms, todo esto cuando únicamente se utiliza un servomotor, si se llegaran a utilizar más
se debe dividir la base de tiempo de 25 ms entre el número de servomotores que se tienen,
para fines del proyecto se necesitaron 4 servomotores por lo que se generó la base de tiempo
de 6 ms para una f. de oscilación de 4 MHz un preescaler de 1, la carga calculada es de
59535. Esto quiere decir que tenemos 6000 cuentas, con estas cuentas se hace una regla de
3; Si a 6000 corresponde un periodo de 6 ms, a .5 le corresponde de 500 y a 2.5 le
corresponde de 2500, pero debe tomarse en cuenta que al dividir el periodo de 25 ms entre 4
se redondeó el resultado a 6 por lo que se le resta 100 y se le suman 100 a los valores
correspondientes de .5 y 2.5 respectivamente con la finalidad de hacer más preciso el
movimiento del servomotor.
12
Para modificar el ancho de pulso dentro de la interrupción del timer se necesita establecer dos
cargas diferentes las cuales modifican el ancho de pulso de .5 a 2.5 ms que es el rango que
utiliza el servomotor como se muestra en la Fig. 4.1. Como únicamente se necesita que el
servomotor se mueva de 0° a 90° la cantidad de cuentas que se necesitan para moverlo 90°
es aproximadamente de 1100. Entonces cada que se quiera abrir alguna persiana o
servomotor debe restarse al total de cuentas del timer el valor de cuentas que se necesita
para poner el servo motor en 0° menos la cantidad de cuentas que se necesiten para poner el
servomotor en el grado deseado (Fig. 4.2) siendo este último 0 si se quiere que el servomotor
se quede en 0° o 1100 si se quiere que se mueva a 90° aproximadamente.
13
mismas y después enviarse, en este caso se utilizaron 4 variables para guardar los estados (3
ventanas, 1 puerta).
Este valor guardado se envía al celular y acorde al valor se muestra en el apartado de los
estados si la ventana está abierta o cerrada.
Si el garaje está cerrado (pgarage = 0), la carga se establece nuevamente en 1100 para que
el servomotor se mueva a 90° y se abra el garaje. Se actualiza nuevamente el valor de
pgarage a 1.
Otra manera de abrir el garaje es con el sensor de presencia, cuando hay algo frente al sensor
y la alarma está desactivada se establece nuevamente la carga calculada para que el
servomotor del garaje se mueva y abra el garaje y en la variable pgarage se guarda un 1 ya
que está abierto el garaje.
Para abrir o cerrar la puerta con el botón se implementó un delay de 300ms, esto debido a
que al presionarlo sin el delay el servomotor oscilaba ya que realizaba la lectura del pin más
de una vez por lo que abría y cerraba la puerta muy rápidamente.
15
Fig. 6.3 Evaluando variable alarma = 0.
Otra de las cosas que se realiza cuando está apagada la alarma es establecer en cero la
bandera que activa al buzzer y poner en bajo los pines de este.
16
Fig. 7.1 Conexión de leds con resistencia para iluminación.
Para el reloj de tiempo real se conectaron dos de sus pines a alimentación y tierra, los otros
dos pines se conectaron a los pines 15 y 16 del microcontrolador.
Para conectar el módulo bluetooth se conectó la salida TX del módulo al pin RX del
microcontrolador de manera directa, se conectó también del pin RX del módulo al pin TX del
microcontrolador con una resistencia de por medio y otra resistencia conectada hacia tierra
como se ven en la siguiente imagen.
17
Fig. 7.3 Conexión de motor de directa.
NOTA: la fuente de voltaje depende del motor, el pin de base va conectado con una
resistencia de un kilo al pin del microcontrolador.
El sensor de presencia tiene 3 pines, dos de ellos son para alimentación y tierra, el tercero se
conecta al pin 27 del microcontrolador.
El push button por uno de sus pines se conecta a +5V mientras que la otra va al
microcontrolador con una resistencia a tierra (pull down).
18
Para cada uno de los servomotores se utilizó un transistor 2N2222 conectados de la siguiente
manera:
• Iluminación
Para el apartado de la iluminación se implementaron switches, primero se evalúa que el switch
haya cambiado, después se evalúa si el switch está prendido o apagado, acorde a esto se
manda una trama de datos con solo un valor el cual ya se tiene registrado en el programa
realizado, este dato puede ser 11,21,31 y 41 para encender los focos o 10,20,30 y 40 para
apagarlos esto dependiendo claro de que switch sea el que se active o desactive (véase el
apartado de iluminación independiente del reloj de tiempo real) como se muestra en la figura
7.6. Esto se realizó con cada uno de los 4 switches diferentes.
19
Fig. 7.6 Encendido y apagado de luces desde aplicación
• Control de persianas
Para el control de persianas de igual manera se implementó el uso de los switches solo que
para estos se utilizó una diferente lógica. Recordemos que la trama de datos mandada para la
posición de las persianas es la siguiente #4,0,0,0& siendo 4 el identificador y los ceros
representan que todas las persianas están cerradas. Se guardó en una variable el valor que
tenía la persiana después de haber un cambio en el switch, esto con la finalidad de usar esa
variable con los otros switch a la hora de presionarlos y que el valor de la persiana que se
había cambiado previamente permaneciera sin modificarse como se muestra en la siguiente
imagen.
• Gráfica temperatura
Para la gráfica del valor de la temperatura se envió en una trama diferente los valores leídos
por el ADC cada 200 ms, esto debido a que si se enviaban cada un segundo la gráfica
tardaba bastante en dibujarse, y si se enviaban más rápido la aplicación se trababa.
Este dato al igual que los demás se enviaba con una Letra identificadora la cual indicaba la
llegada del valor del ADC en la aplicación.
Para la gráfica primero se creó un proceso en la aplicación para pintar los ejes:
21
Después, una vez recibido la letra identificadora del valor del ADC se guarda el dato de 4 bits
que viene después de esta letra, este dato se multiplica por un factor de conversión para que
su valor varíe de 0 a 40 y se guarda en una variable que luego es utilizada para modificar el
texto de una etiqueta la cual cambia al valor de la variable.
Para graficar se dibujan los ejes primero, y después se dibuja la línea utilizando una función
para ir dibujando una línea cada que se actualice el valor de y2, al actualizarse y2, se
actualizan también las variables x1 y y2 con los nuevos valores que acaban de obtenerse en
x2 y y2 esto para que la siguiente línea empiece dónde termino la última línea dibujada como
se muestra en la siguiente imagen
22
Fig. 7.11 Envío de temperatura máxima al microcontrolador.
• Rutina de luces
Para la rutina de luces se implementó un switch con el cuál al presionarlo aparecen en
pantalla 3 botones el primero recopila la hora y minuto encendido de las luces, el segundo
recopila hora y minuto de apagado de las luces, el tercer botón manda la trama de datos al
microcontrolador con los datos recién recopilados, como se puede apreciar en la siguiente
imagen.
• Alarma
Para el activado de la alarma se implementó un switch donde se evalúa que este cambie,
después se evalúa si está encendido de ser así manda la trama de datos para encenderá la
alarma, de lo contrario manda la trama de datos para apagar la alarma.
23
Fig. 7.13 Envío de estado de alarma.
24
• Aplicación final
25
8. RESULTADOS SIMULACIÓN
• Iluminación
26
• Ventilación
Resultados ventilación.
27
• Estados puertas y ventanas
28
• Persianas/garage
Resultados persianas.
29
Resultados garaje.
30
• Alarma
Encendido de alarma.
31
• Base de tiempo de un segundo y de 200 ms
32
Resultado final.
4. CONCLUSIONES
33
Interpretación de resultados
No hubo problema con la iluminación, la trama que se mandaba ya fuera la de iluminación
dependiente o independiente funcionaron correctamente.
La ventilación funcionaba correctamente, el motor encendía después de sobrepasar el 52% de
la resistencia variable utilizando 21 como la temperatura máxima, se apaga el motor
reduciendo el porcentaje de la resistencia variable o cambiando la temperatura por una más
alta.
El estado de las ventanas y puertas era correctamente enviado por la trama de datos después
de apretar o soltar los botones que representan los limit switch.
Las persianas se mueven correctamente de acuerdo con la trama de datos enviados con un
rango de movimiento de 0 a 97.92° al igual que el garaje al mandar un cero con un botón en
configuración pull down para simular el sensor de presencia, el funcionamiento del botón ya
fuese para abrir o cerrar la puerta dependiendo de si la alarma está o no encendida es el
correcto.
El sonido intermitente del buzzer una vez abierta una puerta o ventana al estar activada la
alarma se simuló con un buzzer y un foco que prendían de manera intermitente 2 veces por
segundo.
Las bases de tiempo calculadas para los distintos procesos que se llevan a cabo en el
programa fueron las esperadas, se utilizó un osciloscopio digital para medir dichas señales y
al código se le agregó un par de funciones dentro de estas para que estuviera cambiando el
valor de un pin con el fin de medir cada cuanto tiempo cambiaba.
Se logró cumplir el objetivo del proyecto final satisfactoriamente, se aprendió las diferentes
maneras en las que puede ser utilizado el envío y recepción de datos a través de un módulo
bluetooth, las aplicaciones de este tipo de proyectos incluyen viviendas, supermercados,
estacionamientos, alumbrados de calle a ciertas horas del día, etc. Una de las dificultades que
se tuvo a la hora de programar fue que los datos para la gráfica se enviaban de manera muy
rápida ya que no se tenía una base de tiempo establecida para el envío de estos por lo que se
enviaban cada iteración del ciclo infinito lo que hacía que la aplicación colapsara y dejara de
funcionar, esto se resolvió generando una base de tiempo para mandar los datos de la gráfica
cada 200 ms.
34