Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Manufacturing Technology >> Herstellungsprozess

Smarte Thermostat-, Lüftungs- und Lichtsteuerung mit Bluetooth

Komponenten und Verbrauchsmaterialien

Arduino Nano R3
× 1
HC-05 Bluetooth-Modul
× 1
Maxim Integrated DS18B20 1-Draht-Digitalthermometer mit programmierbarer Auflösung
× 1
oled 1306 I2C bicolor
× 1
ControlEverything.com 4-KANAL-RELAIS-CONTROLLER FÜR I2C
× 1

Apps und Onlinedienste

Serielles Bluetooth-Terminal von Morich für Android
Arduino Bluetooth-Steuergerät für Android

Über dieses Projekt

Einführung

Einfaches, aber nützliches DIY-Arduino-Thermostat-Projekt mit Bluetooth.

Eine intelligente Thermostatroutine steuert den Gasboiler der Heizung, und das System schaltet mit Relais meine Küchenbeleuchtung und meinen Badezimmerlüfter – steuerbar per Tasten und Android-Gerät oder Computer über Bluetooth. Celsius und Fahrenheit Ausführung auch erhältlich! Alle Teile sind handgefertigt.

Entwickelt auf Arduino Nano (oder höher) Board, verwendet Dallas DS18B20 Temperatursensor, HC-05/06 Bluetooth Adapter, I2C 128X64 zweifarbiges OLED Display – Sie können verschiedene LCD/OLED Displays auswählen, das u8glib unterstützt viele Typen.

Video

Das Video zeigt alle wichtigen Arbeitsweisen, gibt Ihnen Ideen, wie Sie das Projekt von Anfang an aufbauen können.

Funktionsweise der Heizung

1:Zeitgesteuerter Modus für einmaliges Heizen (15 Minuten), nützlich an Frühlings-/Herbstabenden

2: Thermostatmodus (höhere Priorität) , die eingestellte Solltemperatur im EEPROM-Speicher gespeichert

Algorithmus zum Speichern des Kessels

Häufiges, kurzzeitiges Schalten würde die Lebensdauer des Gasheizkessels verkürzen, um dies zu vermeiden, verwendet das Programm Korrekturwerte – diese deklarieren den Grad der Überhitzung und Rückkühlung. Niedrigere Temperaturen erfordern größere Korrekturwerte, da die Wände kälter sind und die Wärme der frisch erwärmten Luft besser aufnehmen, sodass der oben beschriebene Effekt stärker wäre.

Erkennung offener Fenster

Das Programm erkennt, wenn ein Fenster geöffnet ist, dadurch sinkt die Temperatur in einer Minute um mindestens -0, 2°C (-0, 36F) – die Heizung stoppt oder startet nicht, und das Lüftungsgebläse schaltet sich ein, um helfen, die Luft zu erfrischen. Wenn die Luft aufgrund der Wärmekapazität der Umgebung um mindestens +0,12°C (+0,216F) wärmer wurde, schaltet das System zurück in den Normalmodus und das Ereignis „Fensteralarm“ wird verworfen.

Fehlererkennung

Gemessene Temperaturen unter 0 °C (32 °F) oder über 40 °C (104 °F) werden als Fehlfunktion oder anderes Problem (Fehler, zerbrochenes Fenster, Feuer usw.) gewertet und alle Geräte werden heruntergefahren.

Bluetooth-Kommunikation

Die Android-GUI-App hat 8 Tasten, sendet Groß- und Kleinbuchstaben, um die zeitgesteuerte Heizung ein- ('A') oder auszuschalten ('a'), 'B' und 'b' schalten die Lüftung ein, 'C ' und 'c' die Lichter…

Die andere Stärke meines Projekts ist die Verwendung des seriellen Bluetooth-Terminals für Computerfreaks. Chatten Sie einfach über Bluetooth mit dem System über ein serielles Terminal – es kann eine Android-App sein, aber auch ein normaler PC reicht aus – zum Beispiel der Serial Monitor der Arduino IDE.

Der Controller sendet alle Minuten automatisch Temperaturberichte und sofortige Berichte über alle Ereignisse, wie z. B. das Ein- und Ausschalten eines angeschlossenen Geräts, die Aktivierung der Thermostatroutine usw.

Kontrollcodes

Es akzeptiert Kontrollcodes und sendet Bestätigungsnachrichten. Meine Befehlsstruktur basiert auf zweistelligen Zahlen wie ‚XY‘ – wobei;

„X“ ist der Gerätecode und „Y“ ist der Opcode

30, 31, 32:Beleuchtung aus / an / logischen Zustand umkehren

40, 41, 42:Lüften Aus / Ein / logischen Zustand umdrehen

50, 51, 52:einmaliges Heizprogramm Aus / Ein / logischen Zustand umkehren

10 – 24 Zahlen werden als Solltemperatur für die Thermostatfunktion akzeptiert

‘r’ – Bericht über den Betriebszustand der kontrollierten Geräte

‘w’ – deaktiviert das Ereignis „Fensteralarm“ manuell, wenn Sie nicht auf seine automatische Beendigung warten möchten

„A, a… H, h“ – Buchstaben werden so akzeptiert, wie sie die GUI-App gesendet hätte

Fahrenheit-Version

Mir wurden alle Korrekturvariablen, Referenz- und Verhältniswerte umgerechnet, damit das System seine Berechnungs- und Arbeitsbesonderheiten beibehielt.

Nur wenige Modifikationen. Die neuen Gerätecodes der Fahrenheit-Version:

1 - Beleuchtung (10:aus, 11:an, 12:Flip-Zustand)

2 - Lüften

3 - Heizung

50 - 76 Zahlen sind Zieltemperaturwerte

Die Fortsetzung

UPDATE:ein vollständiges Hausautomationssystem mit interner Bluetooth-Verbindung und Sprachsteuerung!

DallasTemperature, elapsedMillis, OneWire, SoftwareSerial, olikraus/u8glib

Wenn Sie unterschiedliche Tastenwiderstände verwenden oder die A0-Messwerte überprüfen müssen, schlage ich vor, dies zu überprüfen:

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
Der Programmcode erklärt sich selbst, nützlich für Anfänger. Gut kommentiert, beschreibt alle wichtigen Schritte; was, warum und wie. Aufgeteilt in Module nach Funktionen, daher übersichtlich.
// Celsius version v1.1// Programmcode einer intelligenten Arduino Smarthome Thermostatlösung, // basierend auf Arduino Nano (oder höher) Board, DS18B20 Thermosensor, HC-05 Bluetooth-Adapter, I2C 128X64 zweifarbiges OLED-Display.// Das System kann über Tasten und Android-Smartphone über Bluetooth gesteuert werden.//// Es steuert den HEATER Gasboiler, den Badezimmer-Lüfter und die Küchen-BELEUCHTUNG - schaltbar mit Relais .// Die Heizung hat zwei Arbeitswege. 1:Zeitgesteuerter Modus für einmaliges Heizen (15 Minuten), 2:Thermostatmodus (höhere Priorität). Die eingestellte Solltemperatur // im EEPROM gespeichert. Das Programm erkennt Hardwarefehler und Fensteröffnungen - in diesen Fällen stoppt die Heizung und/oder startet nicht.//// Entworfen und programmiert von Gyula Osi.// Alle Rechte vorbehalten.// --------- -------------------------------------------------- -------------------------------------------------- -----------// ---- I2C-Bus anzeigen, SDA(TX) -> A4, SCL(RX) -> A5#include "U8glib.h"U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); // Konstruktorbyte-Rahmen anzeigen =0; // Logo-Zeiger starten// ---- Ports und zugehörige Deklarationenconst Byte Summer =9; // Summer zu D9int btnVal; // speichert analoge Werte von buttonsconst byte relayA =11; // airingbool aState =0;bool aStateByCmd; // wenn "Fensteralarm" weg ist, geht die Lüftungssteuerung zurück zum ursprünglichen Zustandconst Byte RelayL =13; // Lightingbool lState =0; const byte relayH =10; // Heizungskonstante Byte ledH =6; // PWM-Ports ermöglichen die Anpassung des Ausgangspegels zum Ändern der Helligkeitconst Byte ledA =5; const byte ledL =3;const byte bright[3] ={0, 10, 100};byte brightHeat =bright[2];#define ledInterval 1000 // Heizer-LED-Blinkintervallunsigned long prev =0;// ---- Strings für Anzeige- und Serienberichte #define STATE_ITEMS 3 // Gerätezustandsanzeige-Strings für Ausgänge// i -> 0 1 2const String state_str[STATE_ITEMS] ={"on.", "off.", "auto."}; String-Heizungszustand; 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] ={"Heizung ist", "Lüftung ist", "Beleuchtung ist", "Fenster Alert!", "Hardware Error!", "Hit a Key>>", "oder send a Code!", "Target tempr =", "Temperature =", " * ", " -"};// -- -- Funktionen zur Temperaturmessung und Heizung#include  elapsedMillis timer0; // 8-Bit-PWM-Timer, verwendet von der Funktion elapsedMillis()#define sftyTmrInterval 15 * 60000 // Einmaliges Heizen (15 Min.) Zeitgesteuertes Modusintervall [ms]bool sftyTmrEnded; // Boolescher Start, der Timer0 ist beendet#include byte tTarget; // angepasstes Ziel temprconst int addr =0; // die aktuelle Adresse der tTarget-Variablen im EEPROM memorybool hState =0; // Heizung Boolean statebool hThermostat =0; // Thermostat Boolescher Zustand#include "OneWire.h" #include "DallasTemperature.h"#define DS18B20 2 // Einrichten des OneWire-Busses auf D2OneWire temprWire(DS18B20); // DS18B20 so einrichten, dass es an den OneWire-BusDallasTemperatursensoren (&temprWire) arbeitet; float tempr; // Messwertfloat temprPrev; // Messwertkopie für Trendanalysebool windowAlrt =0; // angegebener Temperaturgrad dropbool measError =0; // gemessener tempr-Wert liegt außerhalb des als normalconst angegebenen Bereichs long temprInterval =60000; // zyklisches Tempr-Messintervall [ms] unsigned long temprTmrPrev =0; // die verstrichene Zeit wird die vorherige sein, wenn temprMeas() aufgerufenfloat heatCorrVal; // deklariert den Grad der Überhitzung und Rückkühlung, siehe tempMeas() Funktion // ---- Konfiguration der seriellen Kommunikation auf virtuellem RXD/TXD#include  // SW serielle RX &TX Pins für HC-05const int RX1 =8;konst int TX1 =4;SoftwareSerial sUART(RX1,TX1); Zeichen RX[2]; // empfangene serielle Databool speichern errMsgSentBySys =0; bool startup =1; // Doppelte BT-Berichte beim Start vermeiden const 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, 0xFF, 0xFF, 0x3F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF , 0x7F, 0x00, 0xFC, 0xFF, 0x7F, 0xF0, 0x3F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFC, 0xFF, 0x7F 0x8F,FF, 0, 0xFF0 , 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 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, 0x00, 0xFE,FFx 0x, 0xFx 0x, 0xFE,FFx , 0x18, 0xC0, 0x8F, 0xFF, 0x1F, 0x1F, 0x0C, 0x3E, 0x1E, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0x31, 0xFE, 0x7F, 0xFC, 0x8F, 0xFF, 0x1x,E , 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0x31, 0xFE, 0x7F, 0xFC, 0x0F, 0x0E, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0xFC, 0x00, 0xF8, 0x1F, 0x7C , 0x0F, 0x0E, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0xFC, 0x00, 0xF8, 0x1F, 0x7C, 0x30, 0xFE, 0x7F, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0xE, 0x1F, 0x , 0xF8, 0x1F, 0x7C, 0xF0, 0x00, 0x7E, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0x,F , 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 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, 0xF, 0xF, 0x7C, 0xF, 0x 0x7E, 0x00, 0x3C, 0x80, 0x07, 0xF0, 0x00, 0xF8, 0x7F, 0x00, 0x3C, 0x00, 0x1E, 0xC0, 0x3F, 0x00, 0x7E, 0x00, 0x3C, 0x80F 0x07, 0x, 0x07, 0x 0x00, 0x3C, 0x00, 0x1E, 0xC0, 0xFF, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x, 0xFF, 0x 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x 0x, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x 0x, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 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, 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, 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, 0 0x00, 0x00, 0x00, 0x00, 0x7E, 0x06, 0xE6, 0x3F, 0x06, 0xC6, 0x7F, 0xFE, 0xE7, 0x3F, 0x7E, 0xFE, 0xC7, 0x7F, 0x00, 0x00, 0x30, 066,0x 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x30, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x 0x00, 0x00, 0x30, 0x1E, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x30, 0x3E, 0x66, 0x60, 0x0, 066 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, 0xC,F, 0, 0xC,F 0x00, 0x00, 0x3C, 0xDE, 0xE7, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x1D, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x3C, 0x1E, 0xE7, 0xE61 0x70, 0xE0, 0x31, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x3C, 0x1E, 0xE6, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x61, 0x3C, 0x, 0x, 0x,00 0x3C, 0x1E, 0xE6, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x61, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x7F, 0x1E, 0xE6, 0x3F, 0xFC, 0x 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, 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, 0x , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x , 0x00, 0x00, 0x00,};void setup () { sUART.begin (9600); pinMode (RelaisH, AUSGANG); RelaisHandlerH(4); // den Arbeitszustand abrufen pinMode (ledH, OUTPUT); pinMode (RelaisA, AUSGANG); RelaisHandlerA(4); pinMode (ledA, AUSGANG); pinMode (RelaisL, AUSGANG); RelaisHandlerL(4); pinMode (ledL, AUSGANG); pinMode (Summer, AUSGANG); sensoren.begin(); // DS18B20 starten temprMeas(); // warte nicht auf den meas.timer, rufe die Funktion einmal beim Start auf tTarget =EEPROM.read(addr); // den zuvor gespeicherten tTarget-Wert von der aktuellen Adresse des EEPROM beim Startup-Start lesen =0; if (!measError) { sTX(8); // Aufruf für sofortigen Bericht über Arbeitszustände nach dem Start } else { sTX(2); }}void loop () { temprTimer (); ledHandler(); btnReadings(); sRX(); safetyTmr(); u8g.firstPage(); // scr-Schleife tun { draw(); } while(u8g.nextPage()); wenn (Rahmen ==0) { Verzögerung (3000); Rahmen =1; clrScr(); }}void btnReadings() { // --------- Btn Readings btnVal =analogRead (A0); // Analogwert von A0 lesen if (btnVal>=510 &&btnVal <=516) {// btn Beleuchtungsverzögerung (100); // BTN-Entprellung Buzz(3, 1); RelaisHandlerL(2); // die richtige Funktion mit dem logischen Zustands-Flip-Opcode als Parameter aufrufen} else if (btnVal>=849 &&btnVal <=855){ // btn Airing if (windowAlrt ==1) { // wenn sich das System im Window Alert-Modus befindet, deaktivieren Sie es windowAlrt =0; Summen (4, 3); RelaisHandlerA(3); aufrechtzuerhalten. Else {// Else schalte die Verzögerung des Belüftungsventilators ein / aus (100); Summen (3, 1); RelaisHandlerA(2); aufrechtzuerhalten. aufrechtzuerhalten. Sonst if (btnVal>=927 &&btnVal <=933) {// btn Einmaliges Heizen (15 Minuten) Zeitgesteuerte Modusverzögerung (100); Summen (3, 1); RelaisHandlerH(2); aufrechtzuerhalten. Sonst if (btnVal>=767 &&btnVal <=777) {// btn verringern tTarget delay (100); tTargetHandler(0); aufrechtzuerhalten. Sonst if (btnVal>=687 &&btnVal <=697) {// btn erhöhen tTarget delay (100); tTargetHandler(1); aufrechtzuerhalten. Sonst if (btnVal>=856 &&btnVal <=862) {// inc &dec btns gleichzeitig tTarget =14; // <====Anfangswert - diese Tasten beim allerersten Einschalten drücken! }}void sRX() { // ------------- Serielle Daten empfangen while (sUART.available()> 0) {// wenn Daten zum Lesen verfügbar sind (Byte i =0; i <2; i ++) { RX [i] =sUART.read (); } } int iRX[2]; für (Byte i =0; i <2; i++) { iRX[i] =RX[i] – '0'; } switch (RX[0]) { // ------------ SINGLE ALPHABETICAL Steuercodes akzeptieren Fall 'A':relayHandlerH(1); // 1 =bei Pause; Fall 'a':relayHandlerH(0); // 0 =Pause aus; // Die empfangenen seriellen Daten können ein einzelner alphabetischer Buchstabe aus der Android-App "Arduino case 'B':// Bluetooth Control Device" sein. Wenn ein richtiger alphabetischer RelayHandlerA(1); // Zeichen kommt an, der Programmcode wartet nicht auf das zweite, break; // ruft aber die entsprechende Funktion mit einem richtigen Operationscode auf. case 'b':// Fälle von kombinierten numerischen Daten sind unten zu sehen. RelaisHandlerA(0); brechen; Fall 'C':relayHandlerL(1); brechen; Fall 'c':relayHandlerL(0); brechen; Fall 'D':Fall 'd':tTarget =21; tTargetEEPROM(); Summen (3, 1); brechen; Fall 'E':Fall 'e':tTarget =19; tTargetEEPROM(); Summen (3, 1); brechen; Fall 'F':Fall 'f':tTarget =14; tTargetEEPROM(); Summen (3, 1); brechen; case 'R':// Aufruf für einen Übersichtsbericht über kontrollierte Geräte case 'r':sTX(8); brechen; case 'W':// Deaktivieren des Fensteralarmstatus case 'w':windowAlrt =0; Summen (4, 3); RelaisHandlerA(3); brechen; } // ----------------------- COMBINED NUMERIC Steuercodes akzeptieren // In diesem Fall kommt ein zweistelliger numerischer Steuercode im char-Format an, // von einer seriellen Android-Bluetooth-App zum Beispiel. Nach einer Umwandlung von char in integer // (nur wenn das erste Zeichen '1' oder '2' ist) folgt ein Merge-Prozess, // und das System von Bedingungen und Anweisungen trifft eine Entscheidung und führt sie aus. // Entsprechende Zahlencodes sind:// // ---------------- Zieltemperatur:// 10 - 24 Werte werden als Zieltemperatur für die Thermostatfunktion akzeptiert. // // ---------------- Gerätesteuerungscodes:// Erste =Gerätecode, Zweite =Bedienercode // 30, 31, 32 schaltet die Beleuchtung ein:30=aus, 31=ein // 32=logischer Zustand umdrehen (ein -> aus / aus -> an) // 40, 41, 42 macht das gleiche mit dem Lüftungsventilator // 50, 51, 52 handhabt die einmalige Erwärmung (15 min) zeitgesteuertes Heizprogramm wie oben // // ---------------- Klassifizierte Bedienercodes:// X3, X4 sind klassifiziert, werden nur für Funktionsaufrufe durch innere Programmsequenzen verwendet, wenn ( RX[0] =='3') { relayHandlerL(iRX[1]); aufrechtzuerhalten. Wenn (RX[0] =='4') { RelayHandlerA (iRX[1]); aufrechtzuerhalten. Wenn (RX[0] =='5') { RelayHandlerH(iRX[1]); } if ((iRX[0] * 10 + iRX[1] <=24) &&(iRX[0] * 10 + iRX[1]>=10)) { // nur numerische Werte zwischen 10 &24 akzeptieren tTarget =iRX[0] * 10 + iRX[1]; // zwei Integer zusammenführen und tTarget setzen tTargetEEPROM(); // Rufen Sie nach dem Set die EEPROM-Handlerfunktion auf und summieren Sie (3, 1); // schreibe den tTarget-Wert in das entsprechende Byte des EEPROM} if (RX[0] =='0') { // teste auf (Byte i =1; i <5; i++) { Buzz(5, 2); } } for (byte i =0; i <2; i++) { // alle Nachrichtenempfänger und Konvertierungsvariablen leeren RX[i] ='Z'; aufrechtzuerhalten. if ((measError) &&((lOperator ==1) || (lOperator ==2))) { sTX(4); Rückkehr; } if ((lOperator ==2) || (lOperator ==0) &&(lState) || (lOperator ==1) &&(!lState)) { lState =!lState; digitalWrite (RelaisL, lState); Summen (2, 1); } if (lOperator>=0) { // Füllen Sie das Arbeitszustandszeichen mit der richtigen Zustandsanzeigezeichenfolge aus if (lState) { lightingState =state_str[0]; aufrechtzuerhalten. Else { LightingState =state_str[1]; } if (!start) { sTX(7); } }}void relayHandlerA(byte aOperator) { // Airing-Handler-Sequenz if ((measError) &&((aOperator ==1) || (aOperator ==2))) { // Operatoren sind:0=off, 1=an, 2 =Zustand umkehren, sTX(4); // 3=Aufruf durch temprMeas()-Funktion, 4=Lüftungszustands-Char var füllen/auffüllen. Rückkehr; } aState =digitalRead (RelaisA); if (!windowAlrt) { if ((aOperator ==2) || (aState) &&(aOperator ==0) || (!aState) &&(aOperator ==1)) { aState =!aState; digitalWrite (RelaisA, aState); aStateByCmd =digitalRead (RelaisA); Summen (2, 1); } } if (aOperator ==3) { // von der Funktion temprMeas() aufgerufen, 'windowAlrt' beendet oder gestartet if ((!aState) &&(windowAlrt) || (aState) &&(!windowAlrt) &&(!aStateByCmd )) { DigitalWrite (RelaisA, FensterAlrt); } } aState =digitalRead (RelaisA); if (aOperator>=0) { if (aState) { if (windowAlrt) { airingState =state_str[2]; aufrechtzuerhalten. Sonst { airingState =state_str[0]; } } else { airingState =state_str[1]; } } if (!start) { sTX(6); aufrechtzuerhalten der Heizungszustand char var. if ((measError) &&((hOperator ==1) || (hOperator ==2))) { sTX(4); Rückkehr; } if ((!hThermostat) &&(!windowAlrt) &&(!measError)) { // Ein-/Ausschalten des Zeitmodus für einmaliges Heizen (15 Minuten) if ((hOperator ==2) || (hOperator ==1 ) &&(!hState) || (!hOperator) &&(hState)) { Buzz(2, 1); hState =!hState; sftyTmrEnded =0; Timer0 =0; digitalWrite (RelaisH, hState); } } if (windowAlrt) { sTX(3); } if (hOperator ==3) { // diese Funktion wird von der Funktion temprMeas() aufgerufen (op 3) // um windowAlrt &measError boolesche Werte zu untersuchen if ((windowAlrt) &&(hState)) { // ein Fenster ist offen und die Heizung läuft digitalWrite (RelaisH, 0); Summen(5, 3); } if ((!windowAlrt) &&(!measError)) { if ((hThermostat) || (!hThermostat) &&(hState) &&(sftyTmrEnded)) { digitalWrite(relayH, hThermostat); // den Befehl der Thermostat-Routine fortführen } } } hState =digitalRead (relayH); if (hOperator>=0) { if (hState) { if (hThermostat) {heaterState =state_str[2]; aufrechtzuerhalten. Else {heaterState =state_str[0]; } } else {heaterState =state_str[1]; } if ((((!windowAlrt) &&(hOperator !=3)) || (hState)) &&(!startup)) { sTX(5); } }}void safetyTmr () { // Timer für den einmaligen Heizmodus (15 min zeitgesteuert) if ((hState) &&(!sftyTmrEnded) &&(timer0> sftyTmrInterval) &&(!hThermostat)) { sftyTmrEnded =1; RelaisHandlerH(0); für (Byte i =1; i <5; i++) {Buzz(i, 2); } }}void temprTimer() { // Zyklischer Timer für temprMeas() unsigned long temprTmrCurr =millis(); if (temprInterval <=temprTmrCurr - temprTmrPrev) { temprTmrPrev =temprTmrCurr; temprMeas(); } }void temprMeas() { // ----------- Temperaturmessung &Vergleichssequenz temprPrev =tempr; // Wert für den nächsten Vergleich speichern sensor.requestTemperatures(); // Sensorwerte aktualisieren tempr =Sensoren.getTempCByIndex (0); // Temperatur lesen if ((tempr>=40) || (tempr <=0)) { // Extremwerte:if (!errMsgSentBySys) { // -127, -196.60 sind HW-Fehler, +85 ist typisch SW Fehler, aber sTX(4); // kann Feuer oder ein zerbrochenes Fenster sein } errMsgSentBySys =1; hThermostat =0; if (hState) { RelayHandlerH(0); aufrechtzuerhalten. Wenn (aState) { RelayHandlerA(0); } if (lState) { RelayHandlerL(0); } Messfehler =1; für (Byte i =1; i <10; i++) { Buzz (4, 1); Verzögerung (50); } } else { temprPrev =tempr; Messfehler =0; errMsgSentBySys =0; } if (!measError) { // ------------ Start der Temperaturanalysesequenz if (tempr <=17) { // Häufiges, kurzzeitiges Schalten des Heizgaskessels würde abbrechen seine Lebensdauer, das heatCorrVal =0,5; // Der heatCorrVal-Wert hilft, dies zu vermeiden. Gibt den Grad der Überhitzung und Rückkühlung an. } // Niedrigere Temperatur erfordert mehr heatCorrVal, da die Wände kälter sind und besser absorbieren if ((tempr> 17) &&(tempr <19)) { // Wärme aus der frisch erwärmten Luft, so dass der oben beschriebene Effekt effektiver. heatCorrVal =0,4; aufrechtzuerhalten. Wenn (tempr>=19) {heatCorrVal =0,3; } if (tTarget - tempr>=heatCorrVal) {// Subtrahiere den gemessenen Wert vom Ziel, wenn die Differenz gleich oder größer als heatCorrVal sftyTmrEnded =1 ist; // Deaktivieren Sie das zeitgesteuerte Programm für einmaliges Heizen (15 Minuten), wenn es läuft hThermostat =1; // Schalten Sie das Thermostat-Summen ein (1, 1); } if ((tTarget - tempr <=-1 * heatCorrVal) &&(hThermostat)) { hThermostat =0; } if ((temprPrev - tempr>=0.2) &&(!windowAlrt) &&(tempr <=20)) {// in einem Messzyklus und in der Heizperiode das TemperaturfensterAlrt =1; // fällt, wird ausgewertet, wenn ein Fenster geöffnet ist sftyTmrEnded =1; für (Byte i =1; i <5; i++) { Buzz (4, 1); Verzögerung (50); } RelayHandlerA(3); // Aufruf der Ausstrahlungsfunktion (opcode =3), um die Luft aufzufrischen} if ((temprPrev - tempr <=-0.12) &&(windowAlrt)) { // the tempr. Fallen ist vorbei, die Luft wurde wärmer windowAlrt =0; // aufgrund der Wärmekapazität der Umgebung, Summen (4, 3); // also zurück in den normalen Modus wechseln relayHandlerA (3); } RelayHandlerH(3); // die Funktion prüft den Aufrufer param(3) &windowAlrt &measError boolesche Werte 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]); brechen; case 1:sUART.print(funct_str[8]); // Tempr. sUART.print(tempr); sUART.print(char(176)); sUART.println("C"); brechen; case 2:sUART.print(funct_str[7]); // TTemp sUART.print(tTarget); sUART.print(char(176)); sUART.println("C"); brechen; case 3:sUART.print(funct_str[3]); // Window Alert sUART.print(funct_str[9]); sUART.print(tempr); sUART.print(char(176)); sUART.println("C"); brechen; case 4:sUART.println(funct_str[4]); // Error report break; case 5:sUART.print(funct_str[0]); // Working state of devices sUART.println(heaterState); brechen; case 6:sUART.print(funct_str[1]); sUART.println(airingState); brechen; case 7:sUART.print(funct_str[2]); sUART.println(lightingState); brechen; case 8:// Overview report sTX(0); relayHandlerH(4); relayHandlerA(4); relayHandlerL(4); sTX(2); if (measError) { sTX(4); } brechen; }}
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 (Summer, AUSGANG); sensoren.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); brechen; case 'C':relayHandlerL(1); brechen; case 'c':relayHandlerL(0); brechen; case 'D':case 'd':tTarget =21; tTargetEEPROM(); buzz(3, 1); brechen; case 'E':case 'e':tTarget =19; tTargetEEPROM(); buzz(3, 1); brechen; case 'F':case 'f':tTarget =14; tTargetEEPROM(); buzz(3, 1); brechen; case 'R':// call for an overview report about controlled devices case 'r':sTX(8); brechen; case 'W':// disable Window Alert state case 'w':windowAlrt =0; buzz(4, 3); relayHandlerA(3); brechen; } // ----------------------- 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); Rückkehr; } 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. Rückkehr; } 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); Rückkehr; } 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); Verzögerung (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); Verzögerung (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]); brechen; case 1:sUART.print(funct_str[8]); // Tempr. sUART.print(tempr); //sUART.print(char(176)); sUART.println("F"); brechen; case 2:sUART.print(funct_str[7]); // TTemp sUART.print(tTarget); //sUART.print(char(176)); sUART.println("F"); brechen; case 3:sUART.print(funct_str[3]); // Window Alert sUART.print(funct_str[9]); sUART.print(tempr); //sUART.print(char(176)); sUART.println("F"); brechen; case 4:sUART.println(funct_str[4]); // Error report break; case 5:sUART.print(funct_str[0]); // Working state of devices sUART.println(heaterState); brechen; case 6:sUART.print(funct_str[1]); sUART.println(airingState); brechen; case 7:sUART.print(funct_str[2]); sUART.println(lightingState); brechen; case 8:// Overview report sTX(0); relayHandlerH(4); relayHandlerA(4); relayHandlerL(4); sTX(2); if (measError) { sTX(4); } brechen; }}

Schaltpläne

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

Herstellungsprozess

  1. Zutrittskontrolle mit QR, RFID und Temperaturüberprüfung
  2. Universelle Fernbedienung mit Arduino, 1Sheeld und Android
  3. Münzprüfer mit Arduino steuern
  4. Automatisches Pflanzenbewässerungssystem mit Arduino
  5. Arduino mit Bluetooth zur Steuerung einer LED!
  6. Smarte Schuhe (automatische Schnürung und Stromerzeugung)
  7. Arduino Nano:Steuerung von 2 Schrittmotoren mit Joystick
  8. Steuerung des Servomotors mit Arduino und MPU6050
  9. Sprachgesteuerte Bluetooth-Geräte mit OK Google
  10. Autosteuerung mit Arduino Uno und Bluetooth