Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

Control inteligente de termostato, ventilación y luces con Bluetooth

Componentes y suministros

Arduino Nano R3
× 1
Módulo Bluetooth HC-05
× 1
Termómetro digital de 1 cable de resolución programable DS18B20 de Maxim Integrated
× 1
oled 1306 I2C bicolor
× 1
ControlEverything.com CONTROLADOR DE RELÉ DE 4 CANALES PARA I2C
× 1

Aplicaciones y servicios en línea

Terminal Bluetooth serie Morich para Android
Dispositivo de control Bluetooth Arduino para Android

Acerca de este proyecto

Introducción

Proyecto de termostato Arduino DIY simple pero útil con Bluetooth.

Una rutina de termostato inteligente controla la caldera de gas del calentador, y el sistema enciende las luces de mi cocina y el ventilador de ventilación de mi baño con relés; se puede controlar mediante botones y un dispositivo Android o una computadora a través de Bluetooth. Celsius y Fahrenheit versión también disponible! Todas las piezas están hechas a mano.

Desarrollado en placa Arduino Nano (o superior), utiliza sensor de temperatura Dallas DS18B20, adaptador Bluetooth HC-05/06, pantalla OLED bicolor I2C 128X64:puede elegir diferentes pantallas LCD / OLED, el u8glib admite muchos tipos.

Video

El video muestra todas las formas de trabajo importantes, le brinda ideas sobre cómo construir el proyecto desde el principio.

Formas de funcionamiento del calentador

1: Modo temporizado de calentamiento único (15 minutos), útil en las tardes de primavera / otoño

2: Modo termostato (prioridad más alta) , la temperatura objetivo ajustada almacenada en la memoria EEPROM

Algoritmo de ahorro de caldera

El cambio frecuente a corto plazo acortaría la vida útil de la caldera de gas del calentador; para evitarlo, el programa utiliza valores de corrección, que declaran el grado de sobrecalentamiento y enfriamiento. Una temperatura más baja exige valores de corrección mayores, porque las paredes son más frías y absorben mejor el calor del aire recién calentado, por lo que el efecto descrito anteriormente sería más fuerte.

Detección de ventana abierta

El programa detecta si una ventana está abierta, por lo que la temperatura desciende al menos -0, 2 ° C (-0, 36F) en un minuto:el calentador se detiene o no se enciende, y el ventilador de ventilación se encenderá para ayudar a refrescar el aire. Cuando el aire se vuelve más cálido al menos +0, 12 ° C (+0, 216F) debido a la capacidad de calor del ambiente, el sistema volverá al modo normal y el evento 'Alerta de ventana' se descartará.

Detección de errores

La temperatura medida por debajo de 0 ° C (32F) o por encima de 40 ° C (104F) se evaluará como un mal funcionamiento u otro problema (error, ventana rota, incendio, etc.) y todos los dispositivos se apagarán.

Comunicación Bluetooth

La aplicación GUI de Android tiene 8 botones, envía letras mayúsculas y minúsculas para encender ('A') o apagar ('a') el calentador temporizado, 'B' y 'b' encienden la ventilación, 'C 'y' c 'las luces ...

La otra fortaleza de mi proyecto es el uso del terminal serie Bluetooth de un amigo geek. Simplemente chatee con el sistema a través de Bluetooth utilizando un terminal en serie; puede ser una aplicación de Android, pero incluso una PC normal servirá, por ejemplo, el monitor en serie del IDE de Arduino.

El controlador envía informes de temperatura en cada minuto de forma automática e informes instantáneos sobre todos los eventos, como que un dispositivo conectado se ha encendido / apagado, la rutina del termostato activada, etc.

Códigos de control

Acepta códigos de control y envía mensajes de confirmación. Mi estructura de comando se basa en números de dos dígitos como "XY" - donde;

"X" es el código del dispositivo e "Y" es el código de operación

30, 31, 32:iluminación apagada / encendida / cambio de estado lógico

40, 41, 42:transmitiendo apagado / encendido / cambio de estado lógico

50, 51, 52:programa de calentador de una sola vez Apagado / Encendido / cambio de estado lógico

Se aceptarán de 10 a 24 números como temperatura objetivo para la función del termostato

"R":informe sobre el estado de funcionamiento de los dispositivos controlados

"W":desactiva manualmente el evento de "alerta de ventana", si no desea esperar a que se elimine automáticamente

"A, a ... H, h":las letras se aceptan como las habría enviado la aplicación GUI

Versión Fahrenheit

Se convirtieron todas las variables de corrección, valores de referencia y razón, por lo que el sistema mantuvo sus particularidades de cálculo y funcionamiento.

Solo unas pocas modificaciones. Los nuevos códigos de dispositivo de la versión Fahrenheit:

1 - Iluminación (10:apagado, 11:encendido, 12:estado de volteo)

2 - Transmitiendo

3 - Calentador

50 - 76 números son valores de temperatura objetivo

La secuela

ACTUALIZACIÓN:¡un sistema completo de automatización del hogar con enlace Bluetooth interno y control por voz!

DallasTemperature, elapsedMillis, OneWire, SoftwareSerial, olikraus / u8glib

Si usa diferentes resistencias de botón, o necesita verificar las lecturas A0, le sugiero que revise esto:

http://blog.codebender.cc/2015/07/20/tutorial-multiple-buttons-on-1-analog-pin/

Código

  • Termostato v11 - versión Celsius.ino
  • Termostato v11 - Versión Fahrenheit.ino
Termostato v11 - Versión Celsius.ino Arduino
El código del programa se explica solo, útil para principiantes. Bien comentado, describe todos los pasos importantes; qué, por qué y cómo. Dividido en módulos por funciones, es por eso que es fácil de ver.
 // Versión Celsius v1.1 // Código de programa de una solución de termostato inteligente Arduino smarthome, // basado en placa Arduino Nano (o superior), sensor térmico DS18B20, Adaptador Bluetooth HC-05, pantalla OLED bicolor I2C 128X64.// El sistema se puede controlar mediante botones y smartphone Android vía bluetooth.//// Maneja la caldera de gas HEATER, el ventilador AIRING del baño y la ILUMINACIÓN de la cocina - conmutada con relés .// El calefactor tiene dos formas de funcionamiento. 1:Modo temporizado de calefacción única (15 minutos), 2:Modo termostato (prioridad más alta). La temperatura objetivo ajustada // almacenada en EEPROM. El programa detecta errores de hardware y apertura de la ventana; en estos casos, el calentador se detiene y / o no se enciende .//// Diseñado y programado por Gyula Osi.// Todos los derechos reservados.// --------- -------------------------------------------------- -------------------------------------------------- ----------------------- // ---- Mostrar bus I2C, SDA (TX) -> A4, SCL (RX) -> A5 # incluido "U8glib.h" U8GLIB_SSD1306_128X64 u8g (U8G_I2C_OPT_NONE); // muestra constructorbyte frame =0; // puntero del logo de inicio // ---- Puertos y declaraciones relacionadasconst byte buzzer =9; // zumbador a D9int btnVal; // almacena valores analógicos de los botones const byte relayA =11; // airingbool aState =0; bool aStateByCmd; // si desaparece la "alerta de ventana", el control de transmisión vuelve al estado original byte de estado constante relayL =13; // iluminaciónbool lState =0; const byte relayH =10; // byte de resistencia del calentador ledH =6; // Los puertos PWM permiten el ajuste del nivel de salida utilizado para cambiar el byte de brilloconst ledA =5; const byte ledL =3; const byte bright [3] ={0, 10, 100}; byte brightHeat =bright [2]; # define ledInterval 1000 // intervalo de parpadeo del led del calentadorunsigned long prev =0; // ---- Cadenas para visualización e informes seriales #define STATE_ITEMS 3 // Cadenas de indicadores de estado del dispositivo para salidas // i -> 0 1 2const String state_str [STATE_ITEMS] ={"on.", "Off.", "Auto."}; String HeatingState; String airingState; String lightingState; #define FUNCT_ITEMS 11 // i -> 0 1 2 3 4 5 6 7 8 9 10 String funct_str [FUNCT_ITEMS] ={"El calentador es", "El aire es", "La iluminación es", "Ventana ¡Alerta! "," ¡Error de hardware! "," Pulse una tecla>> "," ¡o envíe un código! "," Target tempr ="," Temperature ="," * "," - "}; // - - Características relacionadas con la medición de temperatura y el calentador # incluyen  elapsedMillis timer0; // Temporizador PWM de 8 bits, utilizado por la función elapsedMillis () # define sftyTmrInterval 15 * 60000 // Calentamiento único (15 minutos) intervalo de modo temporizado [ms] bool sftyTmrEnded; // inicio booleano, el timer0 ha finalizado # include  byte tTarget; // temprconst objetivo ajustado int addr =0; // la dirección actual de la variable tTarget en la EEPROM memorybool hState =0; // calentador booleano statebool hThermostat =0; // estado booleano del termostato # incluye "OneWire.h" #include "DallasTemperature.h" #define DS18B20 2 // configura el bus OneWire en D2OneWire temprWire (DS18B20); // configurar DS18B20 para que funcione en los sensores de temperatura busDallas de OneWire (&temprWire); float tempr; // valor medidofloat temprPrev; // copia del valor medido para el análisis de tendencias bool windowAlrt =0; // grado especificado de tempr dropbool MeasError =0; // el valor de temperatura medido está fuera del rango especificado como normalconst long temprInterval =60000; // intervalo de medición de tempr cíclico [ms] unsigned long temprTmrPrev =0; // el transcurrido será el anterior cuando temprMeas () llame a flotar heatCorrVal; // declara el grado de sobrecalentamiento y enfriamiento, ver función tempMeas () // ---- Configuración de comunicación serial en RXD / TXD virtual # incluye  // SW serial RX y pines TX para HC-05const int RX1 =8; const int TX1 =4; SoftwareSerial sUART (RX1, TX1); char RX [2]; // almacenar datos de serie recibidos bool errMsgSentBySys =0; inicio bool =1; // evitar un informe BT duplicado en startupconst uint8_t frame1 [] U8G_PROGMEM ={// mapa XBM 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF , 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF , 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF , 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x07, 0xFFx, 0xFF, 0x7F, 0x00, 0xFC, 0xFF, 0x7F, 0xF0, 0x3F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFC, 0xFF, 0x7xF, 0xF0, 0xF0, , 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF, 0xFF, 0xFF, 0xFF , 0xF1, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0x1F, 0x7F, 0x8C , 0x3F, 0x1E, 0xFF, 0x00, 0xFE, 0x1F, 0xFF, 0xF1, 0x00, 0x18, 0xC0, 0x8F, 0xFF, 0x1F, 0x7F, 0x8C, 0x3F, 0x1E, 0xFF, 0x00x, 0xFE, 0xFF, 0x00x, 0xFE, 0xFF, 0x00x, 0xFE, 0xFF , 0x18, 0xC0, 0x8F, 0xFF, 0x1F, 0x1F, 0x0C, 0x3E, 0x1E, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0x31, 0xFE, 0x7F, 0xFC, 0x8F, 0xFF, 0x1x1x , 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0x31, 0xFE, 0x7F, 0xFC, 0x0F, 0x0E, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0xFC, 0x00, 0xF8, 0x1F, 0x30, 0x7C, , 0x0F, 0x0E, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0xFC, 0x00, 0xF8, 0x1F, 0x7C, 0x30, 0xFE, 0x7F, 0xF0, 0x0F, 0xFE, 0x18, 0x3E, 0x0E , 0xF8, 0x1F, 0x7C, 0xF0, 0x00, 0x7E, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0 , 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x1x3E, 0x1F, 0x0C, 0x1x3E , 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0x3xF0, 0x7C, 0x3xF0, 0x7C, 0x3xF0, 0x7E, 0x00, 0x3C, 0x80, 0x07, 0xF0, 0x00, 0xF8, 0x7F, 0x00, 0x3C, 0x00, 0x1E, 0xC0, 0x3F, 0x00, 0x7E, 0x00, 0x3C, 0x80, 0xF07, 0x3C, 0x80, 0xF07, 0x00, 0x3C, 0x00, 0x1E, 0xC0, 0xFF, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x06, 0xE6, 0x3F, 0x06, 0xC6, 0x7F, 0xFE, 0xE7, 0x3F, 0x7E, 0xFE, 0xC7, 0x7F, 0x00, 0x00, 06x30, 0x00, 0x00, 06x30, 0x66 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x30, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x60, 0x06, 0x06 0x00, 0x00, 0x30, 0x1E, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x30, 0x3E, 0x66, 0x60, 0x06, 0x06 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0xE6, 0x61, 0x1E, 0 xC7, 0x3F, 0x70, 0xE0, 0x3F, 0x3C, 0xFE, 0xC3, 0x3F, 0x00, 0x00, 0x3C, 0x7E, 0xE6, 0x61, 0x1E, 0xC7, 0x3F, 0x70, 0xF0, 0x3C, 0x3x3, 0x00, 0x00, 0x3C, 0xDE, 0xE7, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x1D, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x3C, 0x1E, 0x61, 0x07, 0 0x70, 0xE0, 0x31, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x3C, 0x1E, 0xE6, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x61, 0x3C, 0x00, 0x70, 0x 0x3C, 0x1E, 0xE6, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x61, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x7F, 0x1E, 0xE6, 0x3F, 0x3E, 0xE6, 0x3F, 0x3, 0x70 0x61, 0x7E, 0xFE, 0xE7, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00,}; configuración vacía () {sUART.begin (9600); pinMode (reléH, SALIDA); relayHandlerH (4); // obtener el estado de trabajo pinMode (ledH, OUTPUT); pinMode (reléA, SALIDA); relayHandlerA (4); pinMode (ledA, SALIDA); pinMode (reléL, SALIDA); relayHandlerL (4); pinMode (ledL, SALIDA); pinMode (zumbador, SALIDA); sensores.begin (); // iniciar DS18B20 temprMeas (); // no espere el temporizador de medición, llame a la función una vez al inicio tTarget =EEPROM.read (addr); // leer el valor tTarget almacenado previamente de la dirección actual de la EEPROM en el inicio de inicio =0; if (! error de medición) {sTX (8); // solicitar un informe instantáneo de los estados de trabajo después del inicio} else {sTX (2); }} bucle vacío () {TemprTimer (); ledHandler (); btnReadings (); sRX (); safetyTmr (); u8g.firstPage (); // scr bucle hacer {dibujar (); } while (u8g.nextPage ()); if (frame ==0) {delay (3000); marco =1; clrScr (); }} void btnReadings () {// --------- Btn Readings btnVal =analogRead (A0); // leer val analógico de A0 if (btnVal> =510 &&btnVal <=516) {// btn Retardo de iluminación (100); // btn antirrebote buzz (3, 1); relayHandlerL (2); // llamar a la función adecuada con el estado lógico flip opcode como parámetro} else if (btnVal> =849 &&btnVal <=855) {// btn Airing if (windowAlrt ==1) {// si el sistema está en modo de alerta de ventana, desactivarlo windowAlrt =0; zumbido (4, 3); relayHandlerA (3); } else {// else enciende / apaga el retraso del ventilador de aireación (100); zumbido (3, 1); relayHandlerA (2); }} else if (btnVal> =927 &&btnVal <=933) {// btn Retardo de modo temporizado de calentamiento único (15 minutos) (100); zumbido (3, 1); relayHandlerH (2); } else if (btnVal> =767 &&btnVal <=777) {// btn reduce tTarget delay (100); tTargetHandler (0); } else if (btnVal> =687 &&btnVal <=697) {// btn aumenta tTarget delay (100); tTargetHandler (1); } else if (btnVal> =856 &&btnVal <=862) {// inc &dec btns al mismo tiempo tTarget =14; // <====valor inicial - ¡presione estos botones en el primer encendido! }} void sRX () {// ------------- Recibir datos en serie mientras (sUART.available ()> 0) {// si hay datos disponibles para leer (byte i =0; i <2; i ++) {RX [i] =sUART.read (); }} int iRX [2]; para (byte i =0; i <2; i ++) {iRX [i] =RX [i] - '0'; } switch (RX [0]) {// ------------ aceptar códigos de control ALFABÉTICOS ÚNICOS caso 'A':relayHandlerH (1); // 1 =en descanso; caso 'a':relayHandlerH (0); // 0 =fuera de descanso; // Los datos en serie recibidos pueden ser una sola letra alfabética de la aplicación de Android "Arduino case 'B':// Bluetooth Control Device". Si un relayHandlerA alfabético adecuado (1); // llega el carácter, el código del programa no esperará al segundo, romper; // pero llama a la función aplicable con un código de operación adecuado. case 'b':// Los casos de datos numéricos combinados se pueden ver a continuación. relayHandlerA (0); descanso; caso 'C':relayHandlerL (1); descanso; caso 'c':relayHandlerL (0); descanso; caso 'D':caso 'd':tTarget =21; tTargetEEPROM (); zumbido (3, 1); descanso; caso 'E':caso 'e':tTarget =19; tTargetEEPROM (); zumbido (3, 1); descanso; caso 'F':caso 'f':tTarget =14; tTargetEEPROM (); zumbido (3, 1); descanso; case 'R':// llame para obtener un informe general sobre los dispositivos controlados case 'r':sTX (8); descanso; case 'W':// deshabilitar el estado de alerta de ventana case 'w':windowAlrt =0; zumbido (4, 3); relayHandlerA (3); descanso; } // ----------------------- aceptar códigos de control NUMÉRICOS COMBINADOS // En este caso, llega un código de control numérico de dos dígitos en formato char, // desde una aplicación de serie bluetooth de Android, por ejemplo. Después de una conversión de carácter a entero // (solo si el primer carácter es '1' o '2') seguirá un proceso de fusión, // y el sistema de condiciones y declaraciones tomará una decisión y la ejecutará. // Los códigos numéricos apropiados son:// // ---------------- Temperatura objetivo:// Se aceptarán valores de 10 a 24 como temperatura objetivo para la función del termostato. // // ---------------- Códigos de control del dispositivo:// Primero =código del dispositivo, Segundo =código del operador // 30, 31, 32 apaga la iluminación:30 =apaga, 31 =encendido // 32 =cambio de estado lógico (encendido -> apagado / apagado -> encendido) // 40, 41, 42 harán lo mismo con el ventilador de aireación // 50, 51, 52 maneja el calentamiento único (15 minutos) programa de calentador temporizado como arriba // // ---------------- Códigos de operador clasificados:// X3, X4 están clasificados, usados ​​solo para llamadas de función por secuencias de programa internas si ( RX [0] =='3') {relayHandlerL (iRX [1]); } if (RX [0] =='4') {relayHandlerA (iRX [1]); } if (RX [0] =='5') {relayHandlerH (iRX [1]); } if ((iRX [0] * 10 + iRX [1] <=24) &&(iRX [0] * 10 + iRX [1]> =10)) {// acepta solo valores numéricos entre 10 y 24 tTarget =iRX [0] * 10 + iRX [1]; // fusiona dos enteros y establece tTarget tTargetEEPROM (); // después de establecer, llamar a la función del controlador EEPROM y buzz (3, 1); // escribe el valor tTarget en el byte apropiado de la EEPROM} if (RX [0] =='0') {// prueba para (byte i =1; i <5; i ++) {buzz (5, 2); }} for (byte i =0; i <2; i ++) {// vaciar todos los receptores de mensajes y las variables de conversión RX [i] ='Z'; }} void relayHandlerL (byte lOperator) {// Secuencia del controlador de iluminación // Los operadores son:0 =desactivado, 1 =activado, 2 =cambiar el estado, 4 =llenar / rellenar el estado de iluminación char var. if ((error de medición) &&((lOperador ==1) || (lOperador ==2))) {sTX (4); regreso; } if ((lOperator ==2) || (lOperator ==0) &&(lState) || (lOperator ==1) &&(! lState)) {lState =! lState; digitalWrite (reléL, lState); zumbido (2, 1); } if (lOperator> =0) {// completa el estado de trabajo char con la cadena indicadora de estado adecuada if (lState) {lightingState =state_str [0]; } else {estado de iluminación =state_str [1]; } si (! inicio) {sTX (7); }}} void relayHandlerA (byte aOperator) {// Airing Handler Sequence if ((MeasError) &&((aOperator ==1) || (aOperator ==2))) {// Los operadores son:0 =desactivado, 1 =encendido, 2 =cambiar el estado, sTX (4); // 3 =llamado por la función temprMeas (), 4 =llenar / rellenar el estado de emisión char var. regreso; } aState =digitalRead (relayA); if (! windowAlrt) {if ((aOperator ==2) || (aState) &&(aOperator ==0) || (! aState) &&(aOperator ==1)) {aState =! aState; digitalWrite (relayA, aState); aStateByCmd =digitalRead (reléA); zumbido (2, 1); }} if (aOperator ==3) {// llamado por la función temprMeas (), 'windowAlrt' terminó o comenzó if ((! aState) &&(windowAlrt) || (aState) &&(! windowAlrt) &&(! aStateByCmd )) {digitalWrite (relayA, windowAlrt); }} aState =digitalRead (relayA); if (aOperator> =0) {if (aState) {if (windowAlrt) {airingState =state_str [2]; } else {airingState =state_str [0]; }} else {airingState =state_str [1]; }} if (! inicio) {sTX (6); }} void relayHandlerH (byte hOperator) {// Secuencia del controlador del calentador // Los operadores son:0 =apagado, 1 =encendido, 2 =cambiar el estado, // 3 =llamado por la función temprMeas (), 4 =llenar / rellenar el estado del calentador char var. if ((error de medición) &&((hOperador ==1) || (hOperador ==2))) {sTX (4); regreso; } if ((! hThermostat) &&(! windowAlrt) &&(! MeasError)) {// enciende / apaga el modo temporizado de calentamiento único (15 minutos) if ((hOperator ==2) || (hOperator ==1 ) &&(! hState) || (! hOperator) &&(hState)) {buzz (2, 1); hState =! hState; sftyTmrEnded =0; timer0 =0; digitalWrite (reléH, hState); }} if (ventanaAlrt) {sTX (3); } if (hOperator ==3) {// esta función es llamada por la función temprMeas () (op 3) // para examinar los valores booleanos windowAlrt &MeasError if ((windowAlrt) &&(hState)) {// una ventana es abierto y el calentador está funcionando digitalWrite (reléH, 0); zumbido (5, 3); } if ((! windowAlrt) &&(! MeasError)) {if ((hThermostat) || (! hThermostat) &&(hState) &&(sftyTmrEnded)) {digitalWrite (relayH, hThermostat); // proceda con el comando de la Rutina del Termostato}}} hState =digitalRead (relayH); if (hOperator> =0) {if (hState) {if (hThermostat) {calentadorState =state_str [2]; } más {estado_calentador =estado_str [0]; }} else {estado_calentador =estado_str [1]; } if ((((! windowAlrt) &&(hOperator! =3)) || (hState)) &&(! startup)) {sTX (5); }}} void safetyTmr () {// Temporizador para el modo de calentamiento único (15 minutos cronometrado) if ((hState) &&(! sftyTmrEnded) &&(timer0> sftyTmrInterval) &&(! hThermostat)) {sftyTmrEnded =1; relayHandlerH (0); para (byte i =1; i <5; i ++) {buzz (i, 2); }}} void temprTimer () {// Temporizador cíclico para temprMeas () unsigned long temprTmrCurr =millis (); if (temprInterval <=temprTmrCurr - temprTmrPrev) {temprTmrPrev =temprTmrCurr; temprMeas (); }} void temprMeas () {// ----------- Secuencia de comparación y medición de temperatura temprPrev =tempr; // guarda el valor para la siguiente comparación senstors.requestTemperatures (); // actualiza las lecturas del sensor tempr =sensors.getTempCByIndex (0); // lee la temperatura si ((tempr> =40) || (tempr <=0)) {// valores extremos de medición:if (! errMsgSentBySys) {// -127, -196.60 son errores de HW, +85 es típicamente SW error, pero sTX (4); // puede ser un incendio o una ventana rota} errMsgSentBySys =1; hTermostato =0; if (hState) {relayHandlerH (0); } if (un Estado) {relayHandlerA (0); } if (lState) {relayHandlerL (0); } MeasError =1; para (byte i =1; i <10; i ++) {buzz (4, 1); retraso (50); }} else {temprPrev =tempr; MeasError =0; errMsgSentBySys =0; } if (! MeasError) {// ------------ Inicio de la secuencia de análisis de temperatura if (tempr <=17) {// La conmutación frecuente y breve de la caldera de gas del calentador se interrumpiría su vida, el heatCorrVal =0.5; // El valor de heatCorrVal ayuda a evitarlo. Declara el grado de recalentamiento y enfriamiento. } // Una temperatura más baja exige más calorCorrVal, porque las paredes son más frías y absorben mejor el if ((tempr> 17) &&(tempr <19)) {// calor del aire recién calentado, por lo que el efecto descrito anteriormente sería más efectivo. heatCorrVal =0.4; } if (tempr> =19) {heatCorrVal =0.3; } if (tTarget - tempr> =heatCorrVal) {// restar el valor medido del objetivo, si la diferencia es igual o mayor que heatCorrVal sftyTmrEnded =1; // desactivar el programa cronometrado de calentamiento único (15 minutos) si está funcionando hThermostat =1; // enciende el termostato buzz (1, 1); } if ((tTarget - tempr <=-1 * heatCorrVal) &&(hThermostat)) {hThermostat =0; } if ((temprPrev - tempr> =0.2) &&(! windowAlrt) &&(tempr <=20)) {// en un ciclo de medición y en temporada de calefacción la temperatura windowAlrt =1; // cae, se evaluará como una ventana está abierta sftyTmrEnded =1; para (byte i =1; i <5; i ++) {buzz (4, 1); retraso (50); } relayHandlerA (3); // llamar a la función de transmisión (opcode =3), para ayudar a refrescar el aire} if ((temprPrev - tempr <=-0.12) &&(windowAlrt)) {// the tempr. la caída terminó, el aire se volvió más cálido windowAlrt =0; // debido a la capacidad calorífica del ambiente, buzz (4, 3); // así que vuelve al modo normal relayHandlerA (3); } relayHandlerH (3); // la función examinará el param (3) de la persona que llama &windowAlrt &MeasError booleanos if (! windowAlrt) {sTX (1); }}} void tTargetHandler (bool set) {// establece el tempr necesario aumentando o disminuyendo if (! set) {// incr if (tTarget <24) {// hasta que alcance el límite superior tTarget ++; zumbido (3, 1); } else {buzz (2, 3); }} else {// decr if (tTarget> 10) {tTarget--; zumbido (3, 1); } else {buzz (2, 3); } } tTargetEEPROM();}void tTargetEEPROM() { EEPROM.write(addr, tTarget); // after incr/decr/set, write the tTarget value to the appropriate byte of the EEPROM delay(10); sTX(2);}void draw(void) { // logo handler if (frame ==0) { u8g.drawXBMP( 0, 0, 128, 64, frame1); } else if (frame ==1) screenFunctState(); } void screenFunctState(void) { // function state screen temprWriteOut(0, 64); u8g.drawHLine(0, 46, 128); u8g.setFont(u8g_font_unifont); if (!windowAlrt) { u8g.setPrintPos( 0, 14); u8g.print(funct_str[0]); u8g.setPrintPos(84, 14); u8g.print(heaterState); } else { u8g.setPrintPos( 0, 14); u8g.print(funct_str[3]); } u8g.setPrintPos( 0, 28); u8g.print(funct_str[1]); u8g.setPrintPos(88, 28); u8g.print(airingState); u8g.setPrintPos( 0, 42); u8g.print(funct_str[2]); u8g.setPrintPos(95, 42); u8g.print(lightingState); if ((!hState) &&(!aState) &&(!lState)) { screenStndby(); // if all of controlled devices are in off, call standby screen }}void screenStndby() { // standby scr u8g.firstPage(); do { u8g.setFontRefHeightText(); u8g.setFont(u8g_font_unifont); if (!measError) { u8g.setPrintPos(33, 52); u8g.print(funct_str[5]); u8g.setPrintPos( 8, 64); u8g.print(funct_str[6]); } else { u8g.setPrintPos( 4, 48); u8g.print(funct_str[4]); } temprWriteOut(0, 16); } while( u8g.nextPage() );}void temprWriteOut (byte tX, byte tY) { // draw tempr &tTarget variables onto different coordinates u8g.setFont(u8g_font_courB14);//u8g.setFont(u8g_font_6x12); // you can save ~10% of prog.memory using this font with 2x2 scale char buftTarget[9]; sprintf (buftTarget, "%d", tTarget); // int to char//u8g.setScale2x2();//tY =tY / 2; u8g.setPrintPos(tX, tY); u8g.print(buftTarget); u8g.setPrintPos(tX+18, tY); u8g.print(funct_str[9]); u8g.setPrintPos(tX+50, tY); u8g.print(tempr); u8g.print(char(176)); u8g.print("C");//u8g.undoScale();}void clrScr(){ u8g.firstPage(); do { } while( u8g.nextPage() );}void ledHandler() { // the brightness of a led is low, if the indicated device is off, and high, if its on if (aState) { analogWrite(ledA, bright[2]); } else { analogWrite(ledA, bright[1]); } if (lState) { analogWrite(ledL, bright[2]); } else { analogWrite(ledL, bright[1]); } if (hState) { if (!hThermostat) { ledBlnk(); // the heater led blinks when the One Time Heating (15 mins) timed mode is activated, } else { brightHeat =bright[2]; // and constant bright, if the thermostat routine is active } } else { brightHeat =bright[1]; } analogWrite(ledH, brightHeat);}void ledBlnk() { unsigned long curr =millis(); if (ledInterval <=curr - prev) { // subtract prev value from current, if the difference equals or greater than ledInterval const. prev =curr; // overwrite the earlier value with the current and flip brightness level if (brightHeat ==bright[1]) { brightHeat =bright[2]; } else { brightHeat =bright[1]; } } analogWrite(ledH, brightHeat);}void buzz(byte b, byte d) { // call with frequency and delay parameters tone(buzzer, b * 1000); delay(d * 100); noTone(buzzer);}void sTX(byte reportTX) { // sending serial reports switch (reportTX) { case 0:for (byte i =0; i <9; i++) { sUART.print(funct_str[10]); } sUART.println(funct_str[10]); descanso; case 1:sUART.print(funct_str[8]); // Tempr. sUART.print(tempr); sUART.print(char(176)); sUART.println("C"); descanso; case 2:sUART.print(funct_str[7]); // TTemp sUART.print(tTarget); sUART.print(char(176)); sUART.println("C"); descanso; case 3:sUART.print(funct_str[3]); // Window Alert sUART.print(funct_str[9]); sUART.print(tempr); sUART.print(char(176)); sUART.println("C"); descanso; case 4:sUART.println(funct_str[4]); // Error report break; case 5:sUART.print(funct_str[0]); // Working state of devices sUART.println(heaterState); descanso; case 6:sUART.print(funct_str[1]); sUART.println(airingState); descanso; case 7:sUART.print(funct_str[2]); sUART.println(lightingState); descanso; case 8:// Overview report sTX(0); relayHandlerH(4); relayHandlerA(4); relayHandlerL(4); sTX(2); if (measError) { sTX(4); } descanso; }} 
Thermostat v11 - Fahrenheit version.inoArduino
The program code explains itself, useful for beginners. Well commented, describes every important steps; what, why and how. Divided into modules by functions, that’s why easy to overview.
Works in Fahrenheit, I changed only the Target temperature values (50-76), and the device codes (1, 2 and 3).
// Fahrenheit version v1.1// Program code of an intelligent Arduino smarthome thermostat solution, // based on Arduino Nano (or higher) board, DS18B20 thermo sensor, HC-05 Bluetooth adapter, I2C 128X64 bicolor OLED display.// The system can be controlled by buttons and Android smartphone via bluetooth.//// It handles the HEATER gas boiler, the bathroom AIRING ventilator and the kitchen LIGHTING - swithed with relays.// The heater has two working ways. 1:One Time Heating (15 mins) timed mode, 2:Thermostat mode (higher priority). The adjusted target tempr.// stored in EEPROM. The program detects hardware errors and window opening - in these cases the heater stops and/or will not start.//// Designed and programmed by Gyula Osi.// All rights reserved.// ------------------------------------------------------------------------------------------------------------------------------------// ---- Display I2C Bus, SDA(TX) -> A4, SCL(RX) -> A5#include "U8glib.h"U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); // display constructorbyte frame =0; // start logo pointer// ---- Ports and related declarationsconst byte buzzer =9; // buzzer to D9int btnVal; // stores analog values from buttonsconst byte relayA =11; // airingbool aState =0;bool aStateByCmd; // if "window alert" is gone, the airing control goes back to the original stateconst byte relayL =13; // lightingbool lState =0;const byte relayH =10; // heaterconst byte ledH =6; // PWM ports allow output level adjustment used to change brightnessconst byte ledA =5; const byte ledL =3;const byte bright[3] ={0, 10, 100};byte brightHeat =bright[2];#define ledInterval 1000 // heater led blinking intervalunsigned long prev =0;// ---- Strings for Display and Serial Reports #define STATE_ITEMS 3 // device state indicator strings for outputs// i -> 0 1 2const String state_str[STATE_ITEMS] ={"on.", "off.", "auto."}; String heaterState; String airingState;String lightingState;#define FUNCT_ITEMS 11// i -> 0 1 2 3 4 5 6 7 8 9 10 String funct_str[FUNCT_ITEMS] ={"Heater is ", "Airing is ", "Lighting is ", "Window Alert!", "Hardware Error!", "Hit a Key>>", "or send a Code!", "Target tempr =", "Temperature =", " * ", " -"};// ---- Temperature Measurement and Heater Related Features#include  elapsedMillis timer0; // 8-bit, PWM timer, used by function elapsedMillis()#define sftyTmrInterval 15 * 60000 // one Time Heating (15 mins) timed mode interval [ms]bool sftyTmrEnded; // boolean startup, the timer0 has ended#include byte tTarget; // adjusted target temprconst int addr =0; // the current address of the tTarget variable in the EEPROM memorybool hState =0; // heater boolean statebool hThermostat =0; // thermostat boolean state#include "OneWire.h" #include "DallasTemperature.h"#define DS18B20 2 // setup the OneWire bus on D2OneWire temprWire(DS18B20); // setup DS18B20 to work on the OneWire busDallasTemperature sensors(&temprWire);float tempr; // measured valuefloat temprPrev; // copy of measured value for trend analysisbool windowAlrt =0; // specified degree of tempr dropbool measError =0; // measured tempr value is out of the range specified as normalconst long temprInterval =60000; // cyclic tempr measurement interval [ms]unsigned long temprTmrPrev =0; // the elapsed will be the previous when temprMeas() calledfloat heatCorrVal; // declares the degree of overheating and cooling back, see tempMeas() function// ---- Configuration of Serial Communication on virtual RXD/TXD#include  // SW serial RX &TX pins for HC-05const int RX1 =8;const int TX1 =4;SoftwareSerial sUART(RX1,TX1); char RX[2]; // store received serial databool errMsgSentBySys =0; bool startup =1; // keep avoid a duplicate BT report at startupconst uint8_t frame1[] U8G_PROGMEM ={ // XBM map 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFC, 0xFF, 0x7F, 0xF0, 0x3F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFC, 0xFF, 0x7F, 0xF0, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0x1F, 0x7F, 0x8C , 0x3F, 0x1E, 0xFF, 0x00, 0xFE, 0x1F, 0xFF, 0xF1, 0x00, 0x18, 0xC0, 0x8F, 0xFF, 0x1F, 0x7F, 0x8C, 0x3F, 0x1E, 0xFF, 0x00, 0xFE, 0x1F, 0xFF, 0xF1, 0x00, 0x18, 0xC0, 0x8F, 0xFF, 0x1F, 0x1F, 0x0C, 0x3E, 0x1E, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0x31, 0xFE, 0x7F, 0xFC, 0x8F, 0xFF, 0x1F, 0x1F, 0x0C, 0x3E, 0x1E, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0x31, 0xFE, 0x7F, 0xFC, 0x0F, 0x0E, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0xFC, 0x00, 0xF8, 0x1F, 0x7C, 0x30, 0xFE, 0x7F, 0xF0, 0x0F, 0x0E, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0xFC, 0x00, 0xF8, 0x1F, 0x7C, 0x30, 0xFE, 0x7F, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x00, 0x7E, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x00, 0x7E, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x3F, 0x00, 0x7E, 0x00, 0x3C, 0x80, 0x07, 0xF0, 0x00, 0xF8, 0x7F, 0x00, 0x3C, 0x00, 0x1E, 0xC0, 0x3F, 0x00, 0x7E, 0x00, 0x3C, 0x80, 0x07, 0xF0, 0x00, 0xF8, 0x7F, 0x00, 0x3C, 0x00, 0x1E, 0xC0, 0xFF, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x06, 0xE6, 0x3F, 0x06, 0xC6, 0x7F, 0xFE, 0xE7, 0x3F, 0x7E, 0xFE, 0xC7, 0x7F, 0x00, 0x00, 0x30, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x30, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x30, 0x1E, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x30, 0x3E, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0xE6, 0x61, 0x1E, 0 xC7, 0x3F, 0x70, 0xE0, 0x3F, 0x3C, 0xFE, 0xC3, 0x3F, 0x00, 0x00, 0x3C, 0x7E, 0xE6, 0x61, 0x1E, 0xC7, 0x3F, 0x70, 0xE0, 0x3F, 0x3C, 0xFE, 0xC3, 0x3F, 0x00, 0x00, 0x3C, 0xDE, 0xE7, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x1D, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x3C, 0x1E, 0xE7, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x31, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x3C, 0x1E, 0xE6, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x61, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x3C, 0x1E, 0xE6, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x61, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x7F, 0x1E, 0xE6, 0x3F, 0xFC, 0xE3, 0x3F, 0x70, 0xE0, 0x61, 0x7E, 0xFE, 0xE7, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };void setup() { sUART.begin(9600); pinMode(relayH, OUTPUT); relayHandlerH(4); // get the working state pinMode(ledH, OUTPUT); pinMode(relayA, OUTPUT); relayHandlerA(4); pinMode(ledA, OUTPUT); pinMode(relayL, OUTPUT); relayHandlerL(4); pinMode(ledL, OUTPUT); pinMode(buzzer, OUTPUT); sensores.begin (); // start DS18B20 temprMeas(); // do not wait for the meas.timer, call the function once at startup tTarget =EEPROM.read(addr); // read the previously stored tTarget value from the current address of the EEPROM at startup startup =0; if (!measError) { sTX(8); // call for instant report of working states after startup } else { sTX(2); }}void loop() { temprTimer(); ledHandler(); btnReadings(); sRX(); safetyTmr(); u8g.firstPage(); // scr loop do { draw(); } while (u8g.nextPage ()); if (frame ==0) { delay(3000); frame =1; clrScr(); }}void btnReadings() { // --------- Btn Readings btnVal =analogRead(A0); // read analog val from A0 if (btnVal>=510 &&btnVal <=516) { // btn Lighting delay(100); // btn debounce buzz(3, 1); relayHandlerL(2); // call proper function with logical state flip opcode as parameter } else if (btnVal>=849 &&btnVal <=855){ // btn Airing if (windowAlrt ==1) { // if the system is in Window Alert mode, disable it windowAlrt =0; buzz(4, 3); relayHandlerA(3); } else { // else turn on/off the airing ventilator delay(100); buzz(3, 1); relayHandlerA(2); } } else if (btnVal>=927 &&btnVal <=933){ // btn One Time Heating (15 mins) timed mode delay(100); buzz(3, 1); relayHandlerH(2); } else if (btnVal>=767 &&btnVal <=777) { // btn decrease tTarget delay(100); tTargetHandler(0); } else if (btnVal>=687 &&btnVal <=697) { // btn increase tTarget delay(100); tTargetHandler(1); } else if (btnVal>=856 &&btnVal <=862) { // inc &dec btns at the same time tTarget =14; // <====initial value - press these buttons at the very first powerup! }}void sRX() { // ------------- Receive Serial Data while (sUART.available()> 0) { // if data is available to read for (byte i =0; i <2; i++) { RX[i] =sUART.read(); } } int iRX[2]; for (byte i =0; i <2; i++) { iRX[i] =RX[i] - '0'; } switch (RX[0]) { // ------------ accept SINGLE ALPHABETICAL control codes case 'A':relayHandlerH(1); // 1 =on break; case 'a':relayHandlerH(0); // 0 =off break; // Received serial data can be a single alphabetical letter from "Arduino case 'B':// Bluetooth Control Device" Android app. If a proper alphabetical relayHandlerA(1); // character arrives, the program code will not wait for the second one, break; // but calls the applicable function with a proper operation code. case 'b':// Cases of combined numeric data can be seen below. relayHandlerA(0); descanso; case 'C':relayHandlerL(1); descanso; case 'c':relayHandlerL(0); descanso; case 'D':case 'd':tTarget =21; tTargetEEPROM(); buzz(3, 1); descanso; case 'E':case 'e':tTarget =19; tTargetEEPROM(); buzz(3, 1); descanso; case 'F':case 'f':tTarget =14; tTargetEEPROM(); buzz(3, 1); descanso; case 'R':// call for an overview report about controlled devices case 'r':sTX(8); descanso; case 'W':// disable Window Alert state case 'w':windowAlrt =0; buzz(4, 3); relayHandlerA(3); descanso; } // ----------------------- accept COMBINED NUMERIC control codes // In this case a two-digit numeric control code arrives in char format, // from an Android bluetooth serial app for instance. After a char to integer // conversion (only if the first char is '1' or '2') a merge-process will follow, // and the system of conditions and statements will make a decision and execute it. // Appropriate numeric codes are:// // ---------------- Target Temperature:// 50 - 76 values will be accepted as a target temperature for the thermostat function. // // ---------------- Device Control Codes:// First =device code, Second =operator code // 10, 11, 12 turns the lighting:10=off, 11=on // 12=flip logical state (on -> off / off -> on) // 20, 21, 22 will do the same to the airing ventilator // 30, 31, 32 handles the One Time Heating (15 mins) timed heater program as above // // ---------------- Classified Operator Codes:// X3, X4 are classified, used only for function calls by inner program sequences if (RX[0] =='1') { relayHandlerL(iRX[1]); } if (RX[0] =='2') { relayHandlerA(iRX[1]); } if (RX[0] =='3') { relayHandlerH(iRX[1]); } if ((iRX[0] * 10 + iRX[1] <=76) &&(iRX[0] * 10 + iRX[1]>=50)) { // accept only numeric values between 50 &76 tTarget =iRX[0] * 10 + iRX[1]; // merge two integers and set tTarget tTargetEEPROM(); // after set, call the EEPROM handler function, and buzz(3, 1); // write the tTarget value to the appropriate byte of the EEPROM } if (RX[0] =='0') { // test for (byte i =1; i <5; i++) { buzz(5, 2); } } for (byte i =0; i <2; i++) { // empty all message receiver and conversion variables RX[i] ='Z'; } }void relayHandlerL(byte lOperator) { // Lighting Handler Sequence // operators are:0=off, 1=on, 2=flip the state, 4=fill/refill the lighting state char var. if ((measError) &&((lOperator ==1) || (lOperator ==2))) { sTX(4); regreso; } if ((lOperator ==2) || (lOperator ==0) &&(lState) || (lOperator ==1) &&(!lState)) { lState =!lState; digitalWrite(relayL, lState); buzz(2, 1); } if (lOperator>=0) { // fill up the working state char with the proper state indicator string if (lState) { lightingState =state_str[0]; } else { lightingState =state_str[1]; } if (!startup) { sTX(7); } }}void relayHandlerA(byte aOperator) { // Airing Handler Sequence if ((measError) &&((aOperator ==1) || (aOperator ==2))) { // operators are:0=off, 1=on, 2=flip the state, sTX(4); // 3=called by temprMeas() funct., 4=fill/refill the airing state char var. regreso; } aState =digitalRead(relayA); if (!windowAlrt) { if ((aOperator ==2) || (aState) &&(aOperator ==0) || (!aState) &&(aOperator ==1)) { aState =!aState; digitalWrite(relayA, aState); aStateByCmd =digitalRead(relayA); buzz(2, 1); } } if (aOperator ==3) { // called by the temprMeas() function, 'windowAlrt' ended or started if ((!aState) &&(windowAlrt) || (aState) &&(!windowAlrt) &&(!aStateByCmd)) { digitalWrite(relayA, windowAlrt); } } aState =digitalRead(relayA); if (aOperator>=0) { if (aState) { if (windowAlrt) { airingState =state_str[2]; } else { airingState =state_str[0]; } } else { airingState =state_str[1]; } } if (!startup) { sTX(6); }} void relayHandlerH(byte hOperator) { // Heater Handler Sequence // operators are:0=off, 1=on, 2=flip the state, // 3=called by temprMeas() funct., 4=fill/refill the heater state char var. if ((measError) &&((hOperator ==1) || (hOperator ==2))) { sTX(4); regreso; } if ((!hThermostat) &&(!windowAlrt) &&(!measError)) { // turn on/off the One Time Heating (15 mins) timed mode if ((hOperator ==2) || (hOperator ==1) &&(!hState) || (!hOperator) &&(hState)) { buzz(2, 1); hState =!hState; sftyTmrEnded =0; timer0 =0; digitalWrite(relayH, hState); } } if (windowAlrt) { sTX(3); } if (hOperator ==3) { // this function called by the temprMeas() function (op 3) // in order to examine windowAlrt &measError booleans if ((windowAlrt) &&(hState)) { // a window is open and the heater is running digitalWrite(relayH, 0); buzz(5, 3); } if ((!windowAlrt) &&(!measError)) { if ((hThermostat) || (!hThermostat) &&(hState) &&(sftyTmrEnded)) { digitalWrite(relayH, hThermostat); // proceed the command of the Thermostat Routine } } } hState =digitalRead(relayH); if (hOperator>=0) { if (hState) { if (hThermostat) { heaterState =state_str[2]; } else { heaterState =state_str[0]; } } else { heaterState =state_str[1]; } if ((((!windowAlrt) &&(hOperator !=3)) || (hState)) &&(!startup)) { sTX(5); } }}void safetyTmr () { // Timer for the One Time Heating (15 mins timed) mode if ((hState) &&(!sftyTmrEnded) &&(timer0> sftyTmrInterval) &&(!hThermostat)) { sftyTmrEnded =1; relayHandlerH(0); for (byte i =1; i <5; i++) { buzz(i, 2); } }}void temprTimer() { // Cyclic Timer for temprMeas() unsigned long temprTmrCurr =millis(); if (temprInterval <=temprTmrCurr - temprTmrPrev) { temprTmrPrev =temprTmrCurr; temprMeas(); } }void temprMeas() { // ----------- Temperature Measurement &Comparison Sequence temprPrev =tempr; // save the value for next comparison sensors.requestTemperatures(); // update sensor readings tempr =sensors.getTempFByIndex(0); // read remperature if ((tempr>=104) || (tempr <=32)) { // extreme meas values:if (!errMsgSentBySys) { // -127, -196.60 are HW errors, +85 is tipically SW error, but sTX(4); // can be fire, or a broken window } errMsgSentBySys =1; hThermostat =0; if (hState) { relayHandlerH(0); } if (aState) { relayHandlerA(0); } if (lState) { relayHandlerL(0); } measError =1; for (byte i =1; i <10; i++) { buzz(4, 1); retraso (50); } } else { temprPrev =tempr; measError =0; errMsgSentBySys =0; } if (!measError) { // ------------ Start of Temperature Analysis Sequence if (tempr <=62.6) { // Frequent, short-term switching of the heater gas boiler would cut short its lifetime, the heatCorrVal =0.9; // heatCorrVal value helps to keep avoid it. Declares the degree of overheating and cooling back. } // Lower temperature demands greater heatCorrVal, because the walls are colder and adsorb better the if ((tempr> 62.6) &&(tempr <66.2)) { // warmth from the freshly heated-up air, so the above described effect would more effective. heatCorrVal =0.72; } if (tempr>=66.2) { heatCorrVal =0.54; } if (tTarget - tempr>=heatCorrVal) { // subtract measured value from target, if the difference equals or greater than heatCorrVal sftyTmrEnded =1; // deactivate the One Time Heating (15 mins) timed program if it is running hThermostat =1; // turn on the thermostat buzz(1, 1); } if ((tTarget - tempr <=-1 * heatCorrVal) &&(hThermostat)) { hThermostat =0; } if ((temprPrev - tempr>=0.36) &&(!windowAlrt) &&(tempr <=68)) { // in a measurement cycle and in heating season the temperature windowAlrt =1; // drops, it will evaluate as a window is open sftyTmrEnded =1; for (byte i =1; i <5; i++) { buzz(4, 1); retraso (50); } relayHandlerA(3); // call airing function (opcode =3), to help refresh the air } if ((temprPrev - tempr <=-0.216) &&(windowAlrt)) { // the tempr. falling is over, the air became warmer windowAlrt =0; // due to the heat capacity of the environment, buzz(4, 3); // so switch back to normal mode relayHandlerA(3); } relayHandlerH(3); // the function will examine caller param(3) &windowAlrt &measError booleans if (!windowAlrt) { sTX(1); } }}void tTargetHandler (bool set) { // set the needed tempr by increasing or decreasing if (!set) { // incr if (tTarget <76) { // until it reaches the upper limit tTarget++; buzz(3, 1); } else { buzz(2, 3); } } else { // decr if (tTarget> 50) { tTarget--; buzz(3, 1); } else { buzz(2, 3); } } tTargetEEPROM();}void tTargetEEPROM() { EEPROM.write(addr, tTarget); // after incr/decr/set, write the tTarget value to the appropriate byte of the EEPROM delay(10); sTX(2);}void draw(void) { // logo handler if (frame ==0) { u8g.drawXBMP( 0, 0, 128, 64, frame1); } else if (frame ==1) screenFunctState(); } void screenFunctState(void) { // function state screen temprWriteOut(0, 64); u8g.drawHLine(0, 46, 128); u8g.setFont(u8g_font_unifont); if (!windowAlrt) { u8g.setPrintPos( 0, 14); u8g.print(funct_str[0]); u8g.setPrintPos(84, 14); u8g.print(heaterState); } else { u8g.setPrintPos( 0, 14); u8g.print(funct_str[3]); } u8g.setPrintPos( 0, 28); u8g.print(funct_str[1]); u8g.setPrintPos(88, 28); u8g.print(airingState); u8g.setPrintPos( 0, 42); u8g.print(funct_str[2]); u8g.setPrintPos(95, 42); u8g.print(lightingState); if ((!hState) &&(!aState) &&(!lState)) { screenStndby(); // if all of controlled devices are in off, call standby screen }}void screenStndby() { // standby scr u8g.firstPage(); do { u8g.setFontRefHeightText(); u8g.setFont(u8g_font_unifont); if (!measError) { u8g.setPrintPos(33, 52); u8g.print(funct_str[5]); u8g.setPrintPos( 8, 64); u8g.print(funct_str[6]); } else { u8g.setPrintPos( 4, 48); u8g.print(funct_str[4]); } temprWriteOut(0, 16); } while( u8g.nextPage() );}void temprWriteOut (byte tX, byte tY) { // draw tempr &tTarget variables onto different coordinates u8g.setFont(u8g_font_courB14);//u8g.setFont(u8g_font_6x12); // you can save ~10% of prog.memory using this font with 2x2 scale char buftTarget[9]; sprintf (buftTarget, "%d", tTarget); // int to char//u8g.setScale2x2();//tY =tY / 2; u8g.setPrintPos(tX, tY); u8g.print(buftTarget); u8g.setPrintPos(tX+18, tY); u8g.print(funct_str[9]); u8g.setPrintPos(tX+50, tY); u8g.print(tempr); //u8g.print(char(176)); u8g.print("F");//u8g.undoScale();}void clrScr(){ u8g.firstPage(); do { } while( u8g.nextPage() );}void ledHandler() { // the brightness of a led is low, if the indicated device is off, and high, if its on if (aState) { analogWrite(ledA, bright[2]); } else { analogWrite(ledA, bright[1]); } if (lState) { analogWrite(ledL, bright[2]); } else { analogWrite(ledL, bright[1]); } if (hState) { if (!hThermostat) { ledBlnk(); // the heater led blinks when the One Time Heating (15 mins) timed mode is activated, } else { brightHeat =bright[2]; // and constant bright, if the thermostat routine is active } } else { brightHeat =bright[1]; } analogWrite(ledH, brightHeat);}void ledBlnk() { unsigned long curr =millis(); if (ledInterval <=curr - prev) { // subtract prev value from current, if the difference equals or greater than ledInterval const. prev =curr; // overwrite the earlier value with the current and flip brightness level if (brightHeat ==bright[1]) { brightHeat =bright[2]; } else { brightHeat =bright[1]; } } analogWrite(ledH, brightHeat);}void buzz(byte b, byte d) { // call with frequency and delay parameters tone(buzzer, b * 1000); delay(d * 100); noTone(buzzer);}void sTX(byte reportTX) { // sending serial reports switch (reportTX) { case 0:for (byte i =0; i <9; i++) { sUART.print(funct_str[10]); } sUART.println(funct_str[10]); descanso; case 1:sUART.print(funct_str[8]); // Tempr. sUART.print(tempr); //sUART.print(char(176)); sUART.println("F"); descanso; case 2:sUART.print(funct_str[7]); // TTemp sUART.print(tTarget); //sUART.print(char(176)); sUART.println("F"); descanso; case 3:sUART.print(funct_str[3]); // Window Alert sUART.print(funct_str[9]); sUART.print(tempr); //sUART.print(char(176)); sUART.println("F"); descanso; case 4:sUART.println(funct_str[4]); // Error report break; case 5:sUART.print(funct_str[0]); // Working state of devices sUART.println(heaterState); descanso; case 6:sUART.print(funct_str[1]); sUART.println(airingState); descanso; case 7:sUART.print(funct_str[2]); sUART.println(lightingState); descanso; case 8:// Overview report sTX(0); relayHandlerH(4); relayHandlerA(4); relayHandlerL(4); sTX(2); if (measError) { sTX(4); } descanso; }} 

Esquemas

For jumper wire test... You have to solder it

Proceso de manufactura

  1. Control de acceso con QR, RFID y verificación de temperatura
  2. Control remoto universal usando Arduino, 1Sheeld y Android
  3. Controlar el aceptador de monedas con Arduino
  4. Sistema de riego automático de plantas con Arduino
  5. ¡Arduino con Bluetooth para controlar un LED!
  6. Zapatos inteligentes (autoajuste y generación de electricidad)
  7. Arduino Nano:Controla 2 motores paso a paso con joystick
  8. Control del servomotor con Arduino y MPU6050
  9. Dispositivos Bluetooth controlados por voz con OK Google
  10. Control de coche con Arduino Uno y Bluetooth
  11. Multiplexor de cargador de batería inteligente con pantalla inteligente