Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

Thermostat intelligent, contrôle d'aération et d'éclairage avec Bluetooth

Composants et fournitures

Arduino Nano R3
× 1
Module Bluetooth HC-05
× 1
Thermomètre numérique à 1 fil à résolution programmable DS18B20 intégré maximum
× 1
oled 1306 I2C bicolor
× 1
ControlEverything.com CONTRLEUR DE RELAIS 4 CANAUX POUR I2C
× 1

Applications et services en ligne

Morich Serial Bluetooth Terminal pour Android
Périphérique de contrôle Bluetooth Arduino pour Android

À propos de ce projet

Présentation

Projet de thermostat Arduino DIY simple mais utile avec Bluetooth.

Une routine de thermostat intelligent contrôle la chaudière à gaz de chauffage, et le système allume mes lumières de cuisine et mon ventilateur de salle de bain avec des relais - peut être contrôlé par des boutons et un appareil Android ou un ordinateur via Bluetooth. Celsius et Fahrenheit version également disponible ! Toutes les pièces sont faites à la main.

Développé sur une carte Arduino Nano (ou supérieure), utilise un capteur de température Dallas DS18B20, un adaptateur Bluetooth HC-05/06, un écran OLED bicolore I2C 128X64 - vous pouvez choisir différents écrans LCD/OLED, l'u8glib prend en charge de nombreux types.

Vidéo

La vidéo montre toutes les méthodes de travail importantes, vous donne des idées sur la façon de construire le projet depuis le début.

Modes de fonctionnement du chauffage

1 : Mode chronométré de chauffage unique (15 minutes), utile les soirs de printemps/automne

2 : Mode thermostat (priorité plus élevée) , la température cible ajustée stockée dans la mémoire EEPROM

Algorithme d'économie de chaudière

Des commutations fréquentes et à court terme réduiraient la durée de vie de la chaudière à gaz de chauffage, pour continuer à l'éviter, le programme utilise des valeurs de correction - celles-ci déclarent le degré de surchauffe et de refroidissement. Une température plus basse exige des valeurs de correction plus élevées, car les murs sont plus froids et absorbent mieux la chaleur de l'air fraîchement réchauffé, de sorte que l'effet décrit ci-dessus serait plus fort.

Détection de fenêtre ouverte

Le programme détecte si une fenêtre est ouverte, ainsi la température chute d'au moins -0, 2°C (-0, 36F) en une minute - le chauffage s'arrête ou ne démarre pas, et le ventilateur d'aération se met en marche pour aider à rafraîchir l'air. Lorsque l'air est devenu plus chaud d'au moins +0, 12°C (+0, 216F) en raison de la capacité calorifique de l'environnement, le système revient en mode normal et l'événement « Window Alert » est rejeté.

Détection d'erreur

Une température mesurée inférieure à 0 °C (32 F) ou supérieure à 40 °C (104 F) sera évaluée comme un dysfonctionnement ou un autre problème (erreur, fenêtre cassée, incendie, etc.) et tous les appareils s'éteindront.

Communication Bluetooth

L'application GUI Android dispose de 8 boutons, envoie des lettres majuscules et minuscules afin d'allumer ("A") ou d'éteindre ("a") le chauffage temporisé, "B" et "b" allument la diffusion, "C ' et 'c' les lumières…

L'autre point fort de mon projet est l'utilisation du terminal série Bluetooth par un ami geek. Discutez simplement avec le système via Bluetooth à l'aide d'un terminal série - il peut s'agir d'une application Android, mais même un PC normal fera l'affaire - par exemple le moniteur série de l'IDE Arduino.

Le contrôleur envoie automatiquement des rapports de température toutes les minutes et des rapports instantanés sur tous les événements, tels qu'un appareil connecté a été allumé/éteint, la routine du thermostat activée, etc.

Codes de contrôle

Il accepte les codes de contrôle et envoie des messages de confirmation. Ma structure de commande basée sur des nombres à deux chiffres comme « XY » - où ;

« X » est le code de l'appareil et « Y » est le code d'opération

30, 31, 32 :éclairage Off / On / flip état logique

40, 41, 42 :diffusion Off / On / flip état logique

50, 51, 52 : programme de chauffage unique Arrêt/Marche/état logique de retournement

10 à 24 chiffres seront acceptés comme température cible pour la fonction thermostat

'r' - rapport sur l'état de fonctionnement des appareils contrôlés

« w » - désactive manuellement l'événement « alerte de fenêtre », si vous ne voulez pas attendre sa suppression automatique

« A, a… H, h » - les lettres sont acceptées comme l'application GUI aurait envoyé

Version Fahrenheit

J'ai converti toutes les variables de correction, les valeurs de référence et de rapport, de sorte que le système a conservé ses particularités de calcul et de fonctionnement.

Seulement quelques modifications. Les nouveaux codes d'appareil de la version Fahrenheit :

1 - Éclairage (10 : éteint, 11 : allumé, 12 :état flip)

2 - Diffusion

3 - Chauffage

50 - 76 chiffres sont des valeurs de température cibles

La suite

MISE À JOUR :un système domotique complet avec liaison Bluetooth interne et commande vocale !

DallasTemperature, elapsedMillis, OneWire, SoftwareSerial, olikraus/u8glib

Si vous utilisez différentes résistances de bouton ou si vous avez besoin de vérifier les lectures A0, je vous suggère de vérifier ceci :

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

Code

  • Thermostat v11 - Celsius version.ino
  • Thermostat v11 - Fahrenheit version.ino
Thermostat v11 - Celsius version.inoArduino
Le code du programme s'explique tout seul, utile pour les débutants. Bien commenté, décrit toutes les étapes importantes ; quoi, pourquoi et comment. Divisé en modules par fonctions, c'est pourquoi facile à voir.
// Version Celsius v1.1// Code de programme d'une solution de thermostat intelligent Arduino smarthome, // basé sur la carte Arduino Nano (ou supérieure), le capteur thermique DS18B20, Adaptateur Bluetooth HC-05, écran OLED bicolore I2C 128X64.// Le système peut être contrôlé par boutons et smartphone Android via bluetooth.//// Il gère la chaudière à gaz HEATER, le ventilateur d'AIRING de la salle de bain et l'ÉCLAIRAGE de la cuisine - commuté avec des relais .// Le radiateur a deux modes de fonctionnement. 1 :mode chronométré de chauffage unique (15 min), 2 :mode thermostat (priorité plus élevée). La température cible ajustée // stockée dans l'EEPROM. Le programme détecte les erreurs matérielles et l'ouverture de la fenêtre - dans ces cas, le chauffage s'arrête et/ou ne démarre pas.//// Conçu et programmé par Gyula Osi.// Tous droits réservés.// --------- -------------------------------------------------- -------------------------------------------------- -----------------------// ---- Affichage Bus I2C, SDA(TX) -> A4, SCL(RX) -> A5#include "U8glib.h"U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); // affiche le cadre de l'octet du constructeur =0; // start logo pointer// ---- Ports et déclarations associées const byte buzzer =9; // buzzer vers D9int btnVal; // stocke les valeurs analogiques des boutonsconst byte relayA =11; // airingbool aState =0;bool aStateByCmd; // si "window alert" a disparu, le contrôle de diffusion revient à l'octet stateconst d'origine relayL =13; // lightingbool lState =0;const byte relayH =10; // octet heatconst ledH =6; // Les ports PWM permettent le réglage du niveau de sortie utilisé pour modifier l'octet de luminosité const ledA =5 ; const byte ledL =3;const byte bright[3] ={0, 10, 100};byte brightHeat =bright[2];#define ledInterval 1000 // intervalle de clignotement de la led de chauffage unsigned long prev =0;// ---- Chaînes pour l'affichage et les rapports série #define STATE_ITEMS 3 // chaînes d'indicateur d'état du périphérique pour les sorties// i -> 0 1 2const Chaîne state_str[STATE_ITEMS] ={"on.", "off.", "auto."} ; Réchauffeur de chaîneState ; 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] ={"Le chauffage est ", " La diffusion est ", " L'éclairage est ", " La fenêtre Alert!", "Erreur matérielle!", "Appuyez sur une touche>>", "ou envoyez un code!", "Target tempr =", "Temperature =", " * ", " -"};// -- -- Mesure de la température et fonctionnalités liées au chauffage#include  elapsedMillis timer0 ; // Minuterie PWM 8 bits, utilisée par la fonction elapsedMillis()#define sftyTmrInterval 15 * 60000 // un temps de chauffage (15 minutes) intervalle de mode chronométré [ms]bool sftyTmrEnded ; // démarrage booléen, le timer0 est terminé#include byte tTarget; // cible ajustée temprconst int addr =0; // l'adresse actuelle de la variable tTarget dans la mémoire EEPROM hState =0; // réchauffeur booléen statebool hThermostat =0; // état booléen du thermostat#include "OneWire.h" #include "DallasTemperature.h"#define DS18B20 2 // configurer le bus OneWire sur D2OneWire temprWire(DS18B20); // configuration du DS18B20 pour qu'il fonctionne sur les capteurs de température du bus OneWireDallas(&temprWire);float tempr; // valeur mesuréefloat temprPrev; // copie de la valeur mesurée pour l'analyse des tendancesbool windowAlrt =0; // degré spécifié de tempr dropbool measError =0; // la valeur tempr mesurée est hors de la plage spécifiée comme normalconst long temprInterval =60000; // intervalle de mesure de tempr cyclique [ms] unsigned long temprTmrPrev =0; // le temps écoulé sera le précédent lorsque temprMeas() a appelé float heatCorrVal ; // déclare le degré de surchauffe et de refroidissement, voir la fonction tempMeas() // ---- Configuration de la communication série sur le RXD/TXD virtuel#include  // SW broches série RX &TX pour HC-05const int RX1 =8;const int TX1 =4;SoftwareSerial sUART(RX1,TX1); caractère RX[2] ; // stocker les données série reçues errMsgSentBySys =0; booléen démarrage =1 ; // garder éviter un rapport BT en double au démarrageconst 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, 0x3F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0 , 0x7F, 0x00, 0xFC, 0xFF, 0x7F, 0xF0, 0x3F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFC, 0xFF, 0x7F 0x8xF0, , 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF1, 0x , 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, 0xFFx, 0x00, 0xFE, 0x00, 0xFE, 0 , 0x18, 0xC0, 0x8F, 0xFF, 0x1F, 0x1F, 0x0C, 0x3E, 0x1E, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0x31, 0xFE, 0x7F, 0xFC, 0x8F, 0x3x, 0x1F, 0x3xE, 0x1F, , 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0x31, 0xFE, 0x7F, 0xFC, 0x0F, 0x0E, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0xFC, 0x00, 0xF8, 0x1F, 0x, 0x7, , 0x0F, 0x0E, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0xFC, 0x00, 0xF8, 0x1F, 0x7C, 0x30, 0xFE, 0x7F, 0xF0, 0x0F, 0xFE, 0x18, 0, 0,1F, 0x1 , 0xF8, 0x1F, 0x7C, 0xF0, 0x00, 0x7E, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x, 0x0, 0xF, 0x7C, 0xF, 0xF , 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0, 0x3E, 0x3E, 0x0, 0x3E, 0x3E , 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, 0x7, 0xF0x 0x7E, 0x00, 0x3C, 0x80, 0x07, 0xF0, 0x00, 0xF8, 0x7F, 0x00, 0x3C, 0x00, 0x1E, 0xC0, 0x3F, 0x00, 0x7E, 0x00, 0x3C, 0x80, 0x, 0,07, 0x, 0x 0x00, 0x3C, 0x00, 0x1E, 0xC0, 0xFF, 0xFF, 0xFF, 0x1F, 0xFC, 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, 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, 0,xFF, 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, 0,xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0,xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF00, 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, 0,x30, 0x06x 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x30, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x0600, 0x60, 0x00, 0x00, 0x30, 0x1E, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x30, 0x3E, 0x66, 0x60, 0,x06, 0x66 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, 0x3, 0x3F,C, 0xE0, 0x3x3F,C, 0x00, 0x00, 0x3C, 0xDE, 0xE7, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x1D, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x3C, 0x1E, 0x, 0,70x07, 0x 0x70, 0xE0, 0x31, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x3C, 0x1E, 0xE6, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x61, 0x3C, 0,1E, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x61, 0x3C, 0,1E, 0x00, 0x00 0x3C, 0x1E, 0xE6, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x61, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x7F, 0x1E, 0xE6, 0x3F, 0, 0x, 0x70, 03F 0x61, 0x7E, 0xFE, 0xE7, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,00 0x , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,00 0x , 0x00, 0x00, 0x00, };configuration vide() { sUART.begin(9600); pinMode(relaisH, SORTIE); relaisHandlerH(4); // obtient l'état de fonctionnement pinMode(ledH, OUTPUT); pinMode(relaisA, SORTIE); relaisHandlerA(4) ; pinMode(ledA, SORTIE); pinMode(relayL, OUTPUT); relaisHandlerL(4); pinMode(ledL, SORTIE); pinMode(buzzer, SORTIE); capteurs.begin(); // démarrer DS18B20 temprMeas(); // n'attendez pas le meas.timer, appelez la fonction une fois au démarrage tTarget =EEPROM.read(addr); // lit la valeur tTarget précédemment stockée à partir de l'adresse actuelle de l'EEPROM au démarrage startup =0; if (!measError) { sTX(8); // appel pour un rapport instantané des états de fonctionnement après le démarrage } else { sTX(2); }}boucle vide() { temprTimer(); ledHandler(); btnLectures(); sRX(); sécuritéTmr(); u8g.premièrePage(); // boucle scr do { draw(); } while( u8g.page suivante() ); if (frame ==0) { delay(3000); cadre =1 ; clrScr(); }}void btnReadings() { // --------- Lectures Btn btnVal =analogRead(A0); // lit la valeur analogique de A0 if (btnVal>=510 &&btnVal <=516) { // btn Lighting delay(100); // btn debounce buzz(3, 1); relaisHandlerL(2); // appelle la fonction appropriée avec l'opcode de retournement d'état logique comme paramètre } else if (btnVal>=849 &&btnVal <=855){ // btn Airing if (windowAlrt ==1) { // si le système est en mode Window Alert, désactivez-le windowAlrt =0; bourdonner (4, 3); relaisHandlerA(3); } else { // else activer/désactiver le délai du ventilateur d'aération (100); bourdonner (3, 1); relaisHandlerA(2); } } else if (btnVal>=927 &&btnVal <=933){ // btn One Time Heating (15 mins) temporisé mode delay (100); bourdonner (3, 1); relaisHandlerH(2); } else if (btnVal>=767 &&btnVal <=777) { // btn diminue le délai tTarget (100); tTargetHandler(0) ; } else if (btnVal>=687 &&btnVal <=697) { // btn augmente le délai tTarget (100); tTargetHandler(1); } else if (btnVal>=856 &&btnVal <=862) { // inc &dec btns en même temps tTarget =14; // <====valeur initiale - appuyez sur ces boutons au tout premier démarrage ! }}void sRX() { // ------------- Recevoir des données série tandis que (sUART.available()> 0) { // si les données sont disponibles pour la lecture (octet i =0; i <2; i++) { RX[i] =sUART.read(); } } int iRX[2]; for (octet i =0; i <2; i++) { iRX[i] =RX[i] - '0'; } switch (RX[0]) { // ------------ acceptent les codes de contrôle SINGLE ALPHABETICAL case 'A':relayHandlerH(1); // 1 =en pause; cas 'a' :relayHandlerH(0) ; // 0 =hors pause ; // Les données série reçues peuvent être une seule lettre alphabétique de l'application Android "Arduino case 'B' :// Bluetooth Control Device". Si un relayHandlerA(1) alphabétique approprié ; // le caractère arrive, le code du programme n'attendra pas le second, break; // mais appelle la fonction applicable avec un code d'opération approprié. case 'b' :// Les cas de données numériques combinées peuvent être vus ci-dessous. relaisHandlerA(0); Pause; cas 'C' :relayHandlerL(1) ; Pause; cas 'c' :relayHandlerL(0) ; Pause; cas 'D' :cas 'd' :tCible =21 ; tCibleEEPROM(); bourdonner (3, 1); Pause; cas 'E' :cas 'e' :tCible =19 ; tCibleEEPROM(); bourdonner (3, 1); Pause; cas 'F' :cas 'f' :tCible =14 ; tCibleEEPROM(); bourdonner (3, 1); Pause; case 'R' :// demande un rapport de synthèse sur les appareils contrôlés case 'r' :sTX(8) ; Pause; case 'W' :// désactiver l'état d'alerte de fenêtre case 'w' :windowAlrt =0 ; bourdonner (4, 3); relaisHandlerA(3); Pause; } // ----------------------- accepter les codes de contrôle NUMÉRIQUES COMBINÉS // Dans ce cas, un code de contrôle numérique à deux chiffres arrive au format char, // à partir d'une application série Bluetooth Android par exemple. Après une conversion // char en entier (uniquement si le premier caractère est '1' ou '2'), un processus de fusion suivra, // et le système de conditions et d'instructions prendra une décision et l'exécutera. // Les codes numériques appropriés sont :// // ---------------- Température cible :// 10 à 24 valeurs seront acceptées comme température cible pour la fonction de thermostat. // // ---------------- Codes de contrôle d'appareil :// Premier =code d'appareil, Second =code opérateur // 30, 31, 32 allume l'éclairage :30 =éteint, 31=on // 32=inverser l'état logique (on -> off / off -> on) // 40, 41, 42 feront de même pour le ventilateur d'aération // 50, 51, 52 gère le chauffage unique (15 min) programme de chauffage minuté comme ci-dessus // // ---------------- Codes d'opérateur classifiés :// X3, X4 sont classifiés, utilisés uniquement pour les appels de fonction par des séquences de programme internes 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)) { // n'accepte que les valeurs numériques entre 10 et 24 tTarget =iRX[0] * 10 + iRX[1] ; // fusionne deux entiers et définit le tTarget tTargetEEPROM(); // après avoir défini, appelez la fonction de gestion EEPROM et buzz(3, 1); // écrit la valeur tTarget dans l'octet approprié de l'EEPROM } if (RX[0] =='0') { // teste pour (byte i =1; i <5; i++) { buzz(5, 2); } } for (byte i =0; i <2; i++) { // vide tous les récepteurs de messages et variables de conversion RX[i] ='Z'; } }void relayHandlerL(byte lOperator) { // Les opérateurs de séquence de gestion d'éclairage // sont :0=off, 1=on, 2=inverser l'état, 4=remplir/remplir l'état d'éclairage var. if ((measError) &&((lOperator ==1) || (lOperator ==2))) { sTX(4); retourner; } if ((lOperator ==2) || (lOperator ==0) &&(lState) || (lOperator ==1) &&(!lState)) { lState =!lState; digitalWrite(relayL, lState); bourdonner (2, 1); } if (lOperator>=0) { // remplit le caractère de l'état de fonctionnement avec la chaîne d'indicateur d'état appropriée if (lState) { lightingState =state_str[0]; } else { lightingState =state_str[1]; } if (!startup) { sTX(7); } }}void relayHandlerA(byte aOperator) { // Séquence du gestionnaire de diffusion if ((measError) &&((aOperator ==1) || (aOperator ==2))) { // les opérateurs sont :0=off, 1=on, 2 =inverser l'état, sTX(4) ; // 3=appelé par la fonction temprMeas(), 4=remplir/remplir l'état de diffusion char var. retourner; } aState =digitalRead(relayA); if (!windowAlrt) { if ((aOperator ==2) || (aState) &&(aOperator ==0) || (!aState) &&(aOperator ==1)) { aState =!aState; digitalWrite(relayA, aState); aStateByCmd =digitalRead(relayA); bourdonner (2, 1); } } if (aOperator ==3) { // appelé par la fonction temprMeas(), 'windowAlrt' s'est terminé ou a commencé 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 // les opérateurs sont :0=off, 1=on, 2=inverser l'état, // 3=appelé par la fonction temprMeas(), 4=fill/refill l'état de chauffage car var. if ((measError) &&((hOperator ==1) || (hOperator ==2))) { sTX(4); retourner; } if ((!hThermostat) &&(!windowAlrt) &&(!measError)) { // activer/désactiver le mode de chauffage unique (15 min) if ((hOperator ==2) || (hOperator ==1 ) &&(!hState) || (!hOperator) &&(hState)) { buzz(2, 1); hEtat =!hEtat; sftyTmrEnded =0; minuteur0 =0 ; digitalWrite(relayH, hState); } } if (windowAlrt) { sTX(3); } if (hOperator ==3) { // cette fonction appelée par la fonction temprMeas() (op 3) // afin d'examiner windowAlrt &measError booleans if ((windowAlrt) &&(hState)) { // une fenêtre est ouvert et le radiateur fonctionne digitalWrite(relayH, 0); bourdonner (5, 3); } if ((!windowAlrt) &&(!measError)) { if ((hThermostat) || (!hThermostat) &&(hState) &&(sftyTmrEnded)) { digitalWrite(relayH, hThermostat); // exécuter la commande de la routine Thermostat } } } hState =digitalRead(relayH); if (hOperator>=0) { if (hState) { if (hThermostat) { heatState =state_str[2]; } else { heatState =state_str[0]; } } else { heatState =state_str[1]; } if ((((!windowAlrt) &&(hOperator !=3)) || (hState)) &&(!startup)) { sTX(5); } }}void safetyTmr () { // Minuterie pour le mode de chauffage unique (15 minutes chronométrées) if ((hState) &&(!sftyTmrEnded) &&(timer0> sftyTmrInterval) &&(!hThermostat)) { sftyTmrEnded =1; relaisHandlerH(0); for (octet i =1; i <5; i++) { buzz(i, 2); } }}void temprTimer() { // Minuteur cyclique pour temprMeas() non signé long temprTmrCurr =millis(); if (temprInterval <=temprTmrCurr - temprTmrPrev) { temprTmrPrev =temprTmrCurr; temprMeas(); } }void temprMeas() { // ----------- Séquence de mesure et de comparaison de température temprPrev =tempr; // enregistre la valeur pour la prochaine comparaison sensor.requestTemperatures(); // mettre à jour les lectures du capteur tempr =sensor.getTempCByIndex(0); // lecture de la température if ((tempr>=40) || (tempr <=0)) { // valeurs extrêmes de la mesure :if (!errMsgSentBySys) { // -127, -196.60 sont des erreurs matérielles, +85 est typiquement SW erreur, mais sTX(4) ; // peut être un incendie ou une fenêtre cassée } errMsgSentBySys =1; hThermostat =0 ; if (hState) { relayHandlerH(0); } if (aState) { relayHandlerA(0); } if (lState) { relayHandlerL(0); } measError =1; for (octet i =1; i <10; i++) { buzz(4, 1); retard (50); } } else { temprPrev =tempr; measError =0; errMsgSentBySys =0 ; } if (!measError) { // ------------ Début de la séquence d'analyse de la température if (tempr <=17) { // La commutation fréquente et à court terme de la chaudière à gaz de chauffage serait interrompue sa durée de vie, la heatCorrVal =0,5 ; // La valeur heatCorrVal aide à l'éviter. Déclare le degré de surchauffe et de refroidissement. } // Une température plus basse demande une plus grande heatCorrVal, car les murs sont plus froids et adsorbent mieux le if ((tempr> 17) &&(tempr <19)) { // chaleur de l'air fraîchement réchauffé, donc l'effet décrit ci-dessus serait plus efficace. HeatCorrVal =0,4 ; } if (tempr>=19) { heatCorrVal =0.3; } if (tTarget - tempr>=heatCorrVal) { // soustrait la valeur mesurée de la cible, si la différence est égale ou supérieure à heatCorrVal sftyTmrEnded =1; // désactiver le programme temporisé Chauffage unique (15 min) s'il est en cours d'exécution hThermostat =1; // allume le thermostat buzz(1, 1); } if ((tCible - tempr <=-1 * heatCorrVal) &&(hThermostat)) { hThermostat =0; } if ((temprPrev - tempr>=0.2) &&(!windowAlrt) &&(tempr <=20)) { // dans un cycle de mesure et en saison de chauffage la température windowAlrt =1; // tombe, il sera évalué lorsqu'une fenêtre est ouverte sftyTmrEnded =1; for (octet i =1; i <5; i++) { buzz(4, 1); retard (50); } relayHandlerA(3); // appelle la fonction de diffusion (opcode =3), pour aider à rafraîchir l'air } if ((temprPrev - tempr <=-0.12) &&(windowAlrt)) { // le tempr. la chute est terminée, l'air est devenu plus chaud windowAlrt =0; // en raison de la capacité calorifique de l'environnement, buzz(4, 3); // donc revenez en mode normal relayHandlerA(3); } relaisHandlerH(3); // la fonction examinera l'appelant 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 <24) { // until it reaches the upper limit tTarget++; buzz(3, 1); } else { buzz(2, 3); } } else { // decr if (tTarget> 10) { 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("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]); Pause; case 1:sUART.print(funct_str[8]); // Tempr. sUART.print(tempr); sUART.print(char(176)); sUART.println("C"); Pause; case 2:sUART.print(funct_str[7]); // TTemp sUART.print(tTarget); sUART.print(char(176)); sUART.println("C"); Pause; case 3:sUART.print(funct_str[3]); // Window Alert sUART.print(funct_str[9]); sUART.print(tempr); sUART.print(char(176)); sUART.println("C"); Pause; case 4:sUART.println(funct_str[4]); // Error report break; case 5:sUART.print(funct_str[0]); // Working state of devices sUART.println(heaterState); Pause; case 6:sUART.print(funct_str[1]); sUART.println(airingState); Pause; case 7:sUART.print(funct_str[2]); sUART.println(lightingState); Pause; case 8:// Overview report sTX(0); relayHandlerH(4); relayHandlerA(4); relayHandlerL(4); sTX(2); if (measError) { sTX(4); } Pause; }}
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); capteurs.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); Pause; case 'C':relayHandlerL(1); Pause; case 'c':relayHandlerL(0); Pause; case 'D':case 'd':tTarget =21; tTargetEEPROM(); buzz(3, 1); Pause; case 'E':case 'e':tTarget =19; tTargetEEPROM(); buzz(3, 1); Pause; case 'F':case 'f':tTarget =14; tTargetEEPROM(); buzz(3, 1); Pause; case 'R':// call for an overview report about controlled devices case 'r':sTX(8); Pause; case 'W':// disable Window Alert state case 'w':windowAlrt =0; buzz(4, 3); relayHandlerA(3); Pause; } // ----------------------- 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); retourner; } 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. retourner; } 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); retourner; } 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); retard (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); retard (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]); Pause; case 1:sUART.print(funct_str[8]); // Tempr. sUART.print(tempr); //sUART.print(char(176)); sUART.println("F"); Pause; case 2:sUART.print(funct_str[7]); // TTemp sUART.print(tTarget); //sUART.print(char(176)); sUART.println("F"); Pause; case 3:sUART.print(funct_str[3]); // Window Alert sUART.print(funct_str[9]); sUART.print(tempr); //sUART.print(char(176)); sUART.println("F"); Pause; case 4:sUART.println(funct_str[4]); // Error report break; case 5:sUART.print(funct_str[0]); // Working state of devices sUART.println(heaterState); Pause; case 6:sUART.print(funct_str[1]); sUART.println(airingState); Pause; case 7:sUART.print(funct_str[2]); sUART.println(lightingState); Pause; case 8:// Overview report sTX(0); relayHandlerH(4); relayHandlerA(4); relayHandlerL(4); sTX(2); if (measError) { sTX(4); } Pause; }}

Schémas

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

Processus de fabrication

  1. Contrôle d'accès avec QR, RFID et vérification de la température
  2. Télécommande universelle utilisant Arduino, 1Sheeld et Android
  3. Contrôler l'accepteur de pièces avec Arduino
  4. Système d'arrosage automatique des plantes avec Arduino
  5. Arduino avec Bluetooth pour contrôler une LED !
  6. Chaussures intelligentes (laçage automatique et génération d'électricité)
  7. Arduino Nano :contrôler 2 moteurs pas à pas avec joystick
  8. Contrôle du servomoteur avec Arduino et MPU6050
  9. Appareils Bluetooth à commande vocale avec OK Google