산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

Bluetooth를 통한 스마트 온도 조절기, 환기 및 조명 제어

구성품 및 소모품

Arduino Nano R3
× 1
HC-05 블루투스 모듈
× 1
Maxim 통합 DS18B20 프로그래밍 가능 분해능 1선식 디지털 온도계
× 1
oled 1306 I2C 바이컬러
× 1
ControlEverything.com I2C용 4채널 릴레이 컨트롤러
× 1

앱 및 온라인 서비스

Android용 Morich 직렬 블루투스 터미널
Android용 Arduino Bluetooth 제어 장치

이 프로젝트 정보

소개

블루투스를 이용한 간단하지만 유용한 DIY Arduino 온도 조절기 프로젝트

지능형 온도 조절 루틴은 히터 가스 보일러를 제어하고 시스템은 릴레이로 주방 조명과 욕실 환풍기를 전환합니다. 버튼과 Android 기기 또는 Bluetooth를 통해 컴퓨터로 제어할 수 있습니다. 섭씨화씨 버전도 가능합니다! 모든 부품은 수작업입니다.

Arduino Nano(또는 그 이상) 보드에서 개발되었으며 Dallas DS18B20 온도 센서, HC-05/06 Bluetooth 어댑터, I2C 128X64 2색 OLED 디스플레이를 사용합니다. 다른 LCD/OLED 디스플레이를 선택할 수 있으며 u8glib는 많은 유형을 지원합니다.

동영상

이 비디오는 모든 중요한 작업 방법을 보여주고 처음부터 프로젝트를 구축하는 방법에 대한 아이디어를 제공합니다.

히터 작동 방식

1:1회 가열(15분) 시간 모드, 봄/가을 저녁에 유용합니다.

2: 온도 조절기 모드(높은 우선 순위) , EEPROM 메모리에 저장된 조정된 목표 온도

보일러 절약 알고리즘

빈번한 단기 전환은 히터 가스 보일러의 수명을 단축시킬 수 있습니다. 이를 방지하기 위해 프로그램은 수정 값을 사용합니다. 이 값은 과열 및 냉각 정도를 선언합니다. 벽이 더 차가워지고 새로 데워진 공기의 따뜻함을 더 잘 흡수하기 때문에 온도가 낮을수록 더 큰 보정 값이 필요하므로 위에서 설명한 효과가 더 강해집니다.

열린 창 감지

프로그램은 창문이 열려 있는지 감지하여 1분 동안 온도가 최소 -0, 2°C(-0, 36F)로 떨어집니다. 히터가 멈추거나 시작되지 않고 환기 팬이 켜집니다. 공기를 상쾌하게 도와줍니다. 환경의 열용량으로 인해 공기가 +0, 12°C(+0, 216F) 이상 따뜻해지면 시스템이 다시 일반 모드로 전환되고 '창 경고' 이벤트가 해제됩니다.

오류 감지

0°C(32F) 미만 또는 40°C(104F) 이상의 측정 온도는 오작동 또는 기타 문제(오류, 깨진 유리창, 화재 등)로 평가되고 모든 장치가 종료됩니다.

블루투스 통신

Android GUI 앱에는 8개의 버튼이 있으며, 'B'와 'b'는 방송을 켜고('A'), 'B'는 'C'를 켜고, 'A'를 켜거나('a') 끄기 위해('a') 대문자와 소문자를 보냅니다. ' 및 'c' 조명…

내 프로젝트의 또 다른 장점은 괴짜 친구 Bluetooth 직렬 터미널 사용입니다. 직렬 터미널을 사용하여 Bluetooth를 통해 시스템과 채팅하기만 하면 됩니다. 예를 들어 Arduino IDE의 직렬 모니터와 같이 Android 앱일 수도 있지만 일반 PC에서도 가능합니다.

컨트롤러는 자동으로 1분마다 온도 보고서를 전송하고 연결된 장치가 켜짐/꺼짐, 온도 조절 장치 루틴 활성화 등과 같은 모든 이벤트에 대한 즉각적인 보고서를 보냅니다.

제어 코드

제어 코드를 수락하고 확인 메시지를 보냅니다. 'XY'와 같은 두 자리 숫자를 기반으로 하는 내 명령 구조 – where;

'X'는 장치 코드이고 'Y'는 opcode입니다.

30, 31, 32:조명 끄기 / 켜기 / 논리 상태 반전

40, 41, 42:방송 끄기 / 켜기 / 논리 상태 반전

50, 51, 52:1회 히터 프로그램 끄기 / 켜기 / 논리 상태 반전

온도 조절기 기능의 목표 온도로 10 – 24개의 숫자가 허용됩니다.

'r' – 제어 장치의 작동 상태에 대한 보고

'w' – 자동 해제를 기다리지 않으려면 "창 경고" 이벤트를 수동으로 비활성화합니다.

'A, ... H, h' – GUI 앱이 보낸 문자로 허용됩니다.

화씨 버전

모든 수정 변수, 참조 및 비율 값을 변환하여 시스템이 계산 및 작업 특성을 유지했습니다.

약간의 수정만 가능합니다. 화씨 버전의 새 장치 코드:

1 - 조명(10:끄기, 11:켜기, 12:뒤집기 상태)

2 - 방영 중

3 - 히터

50 - 76 숫자는 목표 온도 값입니다.

속편

업데이트:내부 Bluetooth 링크 및 음성 제어 기능이 있는 완전한 홈 자동화 시스템!

DallasTemperature, elapsedMillis, OneWire, SoftwareSerial, olikraus/u8glib

다른 버튼 저항을 사용하거나 A0 판독값을 확인해야 하는 경우 다음을 확인하는 것이 좋습니다.

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

<섹션 클래스="섹션 컨테이너 섹션 축소 가능" id="코드">

코드

<울>
  • 온도 조절기 v11 - 섭씨 버전.ino
  • 온도 조절기 v11 - 화씨 버전.ino
  • 온도 조절기 v11 - 섭씨 버전.inoArduino
    프로그램 코드가 스스로 설명되어 초보자에게 유용합니다. 주석이 잘 되어 있고 모든 중요한 단계를 설명합니다. 무엇을, 왜, 어떻게. 기능별로 모듈로 나누어져 있어 개요가 보기 쉽습니다.
    // 섭씨 버전 v1.1// 지능형 Arduino 스마트홈 온도 조절 장치 솔루션의 프로그램 코드, // Arduino Nano(또는 그 이상) 보드 기반, DS18B20 온도 센서, HC-05 블루투스 어댑터, I2C 128X64 바이컬러 OLED 디스플레이.// 버튼과 블루투스를 통해 Android 스마트폰으로 시스템을 제어할 수 있습니다.//// HEATER 가스 보일러, 욕실 AIRING 환풍기 및 주방 조명을 처리합니다. 릴레이로 전환됩니다. .// 히터에는 두 가지 작동 방식이 있습니다. 1:1회 가열(15분) 시간 모드, 2:온도 조절기 모드(더 높은 우선 순위). 조정된 목표 온도 // EEPROM에 저장됨. 프로그램은 하드웨어 오류 및 창 열기를 감지합니다. 이 경우 히터가 중지되거나 시작되지 않습니다.//// Gyula Osi가 설계 및 프로그래밍했습니다.// 판권 소유// --------- -------------------------------------------------- -------------------------------------------------- -----------------------// ---- 디스플레이 I2C 버스, SDA(TX) -> A4, SCL(RX) -> A5#include "U8glib.h"U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); // 생성자 바이트 표시 프레임 =0; // 시작 로고 포인터// ---- 포트 및 관련 선언const byte buzzer =9; // D9int에 부저 btnVal; // 버튼의 아날로그 값을 저장합니다.const 바이트 relayA =11; // airingbool aState =0;bool aStateByCmd; // "창 경고"가 사라지면 방송 제어가 원래 stateconst byte로 돌아갑니다. relayL =13; // lightingbool lState =0; const 바이트 relayH =10; // 히터 구성 바이트 ledH =6; // PWM 포트는 밝기를 변경하는 데 사용되는 출력 레벨 조정을 허용합니다.const byte ledA =5; const byte ledL =3;const byte bright[3] ={0, 10, 100};byte brightHeat =bright[2];#define ledInterval 1000 // 히터 led 깜박임 간격 unsigned long prev =0;// ---- 디스플레이 및 직렬 보고서용 문자열 #define STATE_ITEMS 3 // 출력용 장치 상태 표시기 문자열// i -> 0 1 2const String state_str[STATE_ITEMS] ={"on.", "off.", "auto."}; 문자열 히터 상태; 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 =", " * ", " -"};// -- -- 온도 측정 및 히터 관련 기능#include  elapsedMillis timer0; // 8비트, PWM 타이머, elapsedMillis()#define sftyTmrInterval 15 * 60000 // 1회 가열(15분) 시간 모드 간격 [ms]bool sftyTmrEnded; // 부울 시작, timer0이 종료되었습니다.#include byte tTarget; // 조정된 타겟 temprconst int addr =0; // EEPROM memorybool에 있는 tTarget 변수의 현재 주소 hState =0; // 히터 부울 statebool hThermostat =0; // 온도 조절기 부울 상태#include "OneWire.h" #include "DallasTemperature.h#define DS18B20 2 // D2OneWire에 OneWire 버스 설정 temprWire(DS18B20); // OneWire 버스에서 작동하도록 DS18B20을 설정합니다.DallasTemperature sensor(&temprWire);float tempr; // 측정값 float temprPrev; // 경향 분석을 위한 측정값 복사bool windowAlrt =0; // 지정된 tempr 등급 dropbool measError =0; // 측정된 tempr 값이 normalconst로 지정된 범위를 벗어남 long temprInterval =60000; // 주기적 온도 측정 간격 [ms]unsigned long temprTmrPrev =0; // 경과된 시간은 temprMeas()가 호출될 때 이전 시간이 됩니다.float heatCorrVal; // 과열 및 냉각 백의 정도를 선언합니다. tempMeas() function// ---- 가상 RXD/TXD의 직렬 통신 구성#include  // HC-05const용 SW 직렬 RX 및 TX 핀 int RX1 =8; const int TX1 =4; 소프트웨어 직렬 sUART(RX1,TX1); 문자 RX[2]; // 수신된 직렬 데이터를 저장합니다.bool errMsgSentBySys =0; 부울 시작 =1; // 시작 시 중복 BT 보고 방지 유지const uint8_t frame1[] U8G_PROGMEM ={ // XBM 맵 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ,FF,0x0FF , 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, FF, 0xFF, 0xFF, , 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, FF, 0xFF, 0xFF, , 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFE, 0xFF , 0x7F, 0x00, 0xFC, 0xFF, 0x7F, 0xF0, 0x3F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x00,0x , 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF,0 , 0xF1, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0x1F, 0x7F, 0x8C , 0x3F, 0x1E, 0xFF, 0x00, 0xFE, 0x1F, 0xFF, 0xF1, 0x00, 0x18, 0xC0, 0x8F, 0xFF, 0x1F, 0x7F, 0x1F, 0x7F, 0x8C, 0x0x , 0x18, 0xC0, 0x8F, 0xFF, 0x1F, 0x1F, 0x0C, 0x3E, 0x1E, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0x31, 0xFE, 80x7 , 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0x31, 0xFE, 0x7F, 0xFC, 0x0F, 0x0E, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x0FC , 0x0F, 0x0E, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0xFC, 0x00, 0xF8, 0x1F, 0x7C, 0x1F, 0x7C, 0x30, 0xFE, 0x7F, 0x0F0, , 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의, 0 × 00, 0x3C, 0x00으로,에 0x1E, 0xc0과, 0x3F입니다, 0 × 00, 0x7E가, 0 × 00, 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 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, FF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, FF, 0xFF 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF 에프, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, FFx, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x06, 0xE6, 0x3F, 0x06, 0xC6, 0x7F, 0xFE, 0xE7, 0x3F, 0x7E, 0x3F, 0x0x 0x66, 0x00으로,는 0x60, 0x60으로,는 0x60, 0x30에,이 0x06, 0x60으로, 0 × 00, 0 × 00, 0 × 00, 0x30에,이 0x06, 0x66, 0x60으로,이 0x06, 0x66, 0x00으로,는 0x60, 0x60으로,는 0x60, 0x30에,이 0x06, 0x60으로, 0 × 00, × 00, 0 × 00, 0x30의,에 0x1E, 0x66, 0x60으로,이 0x06, 0x66, 0x00으로,는 0x60, 0x60으로,는 0x60, 0x30에,이 0x06, 0x60으로, 0 × 00, 0 × 00, 0 × 00,는 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, 0xC × 00, 0 × 00, 0x3C, 0xDE, 0xE7,이 0x61,에 0x1E, 0x07 값, 0x70, 0x70, 0xE0, 0x1D, 0x3C,에 0x1E, 0x00으로, 0x70, 0x00으로, 0 × 00, 0x3C,에 0x1E, 0xE7,이 0x61,에 0x1E, 0x07 값, 0x70, 0x70, 0xE0, 0x31로 회신, 0x3C,에 0x1E, 0x00으로, 0x70, 0x00으로, 0 × 00, 0x3C,에 0x1E, 0xE6,이 0x61,에 0x1E, 0x07 값, 0x70, 0x70, 0xE0,이 0x61, 0x3C,에 0x1E, 0x00으로, 0x70, 0x00으로, 0 × 00, 0x3C,에 0x1E, 0xE6,이 0x61,에 0x1E, 0x07 값, 0x70, 0x70, 0xE0,이 0x61, 0x3C,에 0x1E, 0x00으로, 0x70, 0x00으로, 0 × 00, 0x7F의,에 0x1E, 0xE6, 0x3F입니다, 0xFC, 0xE3, 0x3F입니다, 0x70, 0xE0, 이 0x61, 0x7E가, 0xFE로, 0xE7, 0x3F입니다, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00이 , 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00, 0 × 00이 , 0x00, 0x00, 0x00, }; 무효 설정() { sUART.begin(9600); 핀모드(릴레이H, 출력); 릴레이 핸들러H(4); // 작동 상태를 가져옵니다. pinMode(ledH, OUTPUT); 핀모드(릴레이A, 출력); 릴레이 핸들러A(4); 핀모드(LEDA, 출력); 핀모드(릴레이, 출력); 릴레이 핸들러L(4); 핀모드(LEDL, 출력); 핀모드(부저, 출력); sensor.begin(); // DS18B20 시작 temprMeas(); // meas.timer를 기다리지 않고 시작 시 함수를 한 번 호출합니다. tTarget =EEPROM.read(addr); // 시작 시 EEPROM의 현재 주소에서 이전에 저장된 tTarget 값을 읽습니다. startup =0; if (!measError) { sTX(8); // 시작 후 작업 상태에 대한 즉각적인 보고 호출 } else { sTX(2); }}무효 루프() { temprTimer(); ledHandler(); btnReadings(); sRX(); SafetyTmr(); u8g.firstPage(); // scr 루프 do { draw(); } 동안( u8g.nextPage() ); if (프레임 ==0) { 지연(3000); 프레임 =1; clrScr(); }}void btnReadings() { // --------- Btn 읽기 btnVal =analogRead(A0); // A0에서 아날로그 val 읽기 if (btnVal>=510 &&btnVal <=516) { // btn Lighting delay(100); // btn 디바운스 버즈(3, 1); 릴레이 핸들러L(2); // 논리 상태 플립 연산 코드를 매개변수로 사용하여 적절한 함수를 호출합니다. } else if (btnVal>=849 &&btnVal <=855){ // btn Airing if (windowAlrt ==1) { // 시스템이 창 경고 모드에 있는 경우, 비활성화 windowAlrt =0; 버즈(4, 3); 릴레이 핸들러A(3); } else { // else 송풍기 켜기/끄기 delay(100); 버즈(3, 1); 릴레이 핸들러A(2); } } else if (btnVal>=927 &&btnVal <=933){ // btn 1회 가열(15분) 시간 모드 지연(100); 버즈(3, 1); 릴레이 핸들러H(2); } else if (btnVal>=767 &&btnVal <=777) { // btn 감소 tTarget delay(100); tTargetHandler(0); } else if (btnVal>=687 &&btnVal <=697) { // btn 증가 tTarget delay(100); tTargetHandler(1); } else if (btnVal>=856 &&btnVal <=862) { // inc &dec btns를 동시에 tTarget =14; // <====초기 값 - 처음 전원을 켤 때 이 버튼을 누르십시오! }}void sRX() { // ------------- 직렬 데이터 수신 while (sUART.available()> 0) { // 데이터를 읽을 수 있는 경우 (byte i =0; 나는 <2; 나는 ++) { RX[i] =sUART.read(); } } int iRX[2]; for (바이트 i =0, i <2, i++) { iRX[i] =RX[i] - '0'; } switch (RX[0]) { // ------------ 단일 알파벳 제어 코드 승인 case 'A':relayHandlerH(1); // 1 =중단 시; 케이스 'a':relayHandlerH(0); // 0 =해제 중단; // 수신된 직렬 데이터는 "Arduino case 'B':// Bluetooth Control Device" Android 앱에서 하나의 알파벳 문자일 수 있습니다. 적절한 알파벳 순서의 relayHandlerA(1)인 경우; // 문자가 도착하면 프로그램 코드는 두 번째 문자를 기다리지 않습니다. break; // 그러나 적절한 연산 코드로 해당 함수를 호출합니다. case 'b':// 결합된 숫자 데이터의 경우는 아래에서 볼 수 있습니다. 릴레이 핸들러A(0); 부서지다; 케이스 'C':relayHandlerL(1); 부서지다; 케이스 'c':relayHandlerL(0); 부서지다; 케이스 'D':케이스 'd':tTarget =21; tTargetEEPROM(); 버즈(3, 1); 부서지다; 케이스 'E':케이스 'e':tTarget =19; tTargetEEPROM(); 버즈(3, 1); 부서지다; 케이스 'F':케이스 'f':tTarget =14; tTargetEEPROM(); 버즈(3, 1); 부서지다; case 'R':// 제어 장치에 대한 개요 보고서를 호출합니다. case 'r':sTX(8); 부서지다; case 'W':// 창 경고 상태를 비활성화합니다. case 'w':windowAlrt =0; 버즈(4, 3); 릴레이 핸들러A(3); 부서지다; } // ----------------------- COMBINED NUMERIC 제어 코드 허용 // 이 경우 두 자리 숫자 제어 코드가 char 형식으로 도착합니다. // 예를 들어 Android 블루투스 직렬 앱에서. 문자에서 정수로의 // 변환 후에(첫 번째 문자가 '1' 또는 '2'인 경우에만) 병합 프로세스가 따르고, // 조건 및 명령문의 시스템은 결정을 내리고 이를 실행합니다. // 적절한 숫자 코드는 다음과 같습니다. // // ---------------- 목표 온도:// 10 - 24 값은 온도 조절기 기능의 목표 온도로 허용됩니다. // // ---------------- 장치 제어 코드:// 첫 번째 =장치 코드, 두 번째 =연산자 코드 // 30, 31, 32는 조명을 켭니다. 30=끄기, 31=켜기 // 32=논리적 상태 반전(켜기 -> 끄기 / 끄기 -> 켜기) // 40, 41, 42는 환기하는 인공 호흡기에 대해 동일한 작업을 수행합니다. // 50, 51, 52는 일회성 난방(15 mins) 위의 시간 히터 프로그램 // // ---------------- 분류된 연산자 코드:// X3, X4는 분류되며, 내부 프로그램 시퀀스에 의한 함수 호출에만 사용됩니다. if ( 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)) { // 10과 24 사이의 숫자 값만 허용 tTarget =iRX[0] * 10 + iRX[1]; // 두 정수를 병합하고 tTarget을 설정합니다. tTargetEEPROM(); // 설정 후, EEPROM 핸들러 함수를 호출하고, buzz(3, 1); // tTarget 값을 EEPROM의 적절한 바이트에 씁니다. } if (RX[0] =='0') { // test for (byte i =1; i <5; i++) { buzz(5, 2); } } for (byte i =0; i <2; i++) { // 모든 메시지 수신자와 변환 변수를 비웁니다. RX[i] ='Z'; } }void relayHandlerL(byte lOperator) { // 조명 처리기 시퀀스 // 연산자는 다음과 같습니다. 0=off, 1=on, 2=상태 뒤집기, 4=조명 상태 채우기/다시 채우기 char var. if ((measError) &&((lOperator ==1) || (lOperator ==2))) { sTX(4); 반품; } if ((lOperator ==2) || (lOperator ==0) &&(lState) || (lOperator ==1) &&(!lState)) { lState =!lState; digitalWrite(릴레이L, lState); 버즈(2, 1); } if (lOperator>=0) { // 작업 상태 문자를 적절한 상태 표시기 문자열로 채웁니다. if (lState) { lightingState =state_str[0]; } else { 조명 상태 =state_str[1]; } if (! 시작) { sTX(7); } }}void relayHandlerA(byte aOperator) { // 에어링 핸들러 시퀀스 if ((measError) &&((aOperator ==1) || (aOperator ==2))) { // 연산자는 다음과 같습니다. 0=off, 1=켜기, 2=상태 반전, sTX(4); // 3=temprMeas() 함수에 의해 호출, 4=방송 상태 채우기/다시 채우기 char var. 반품; } 상태 =디지털 읽기(릴레이A); if (!windowAlrt) { if ((aOperator ==2) || (aState) &&(aOperator ==0) || (!aState) &&(aOperator ==1)) { aState =!aState; digitalWrite(릴레이A, 상태); aStateByCmd =디지털 읽기(릴레이A); 버즈(2, 1); } } if (aOperator ==3) { // temprMeas() 함수에 의해 호출, 'windowAlrt' 종료 또는 시작 if ((!aState) &&(windowAlrt) || (aState) &&(!windowAlrt) &&(!aStateByCmd )) { 디지털 쓰기(릴레이A, 창알트); } } 상태 =디지털 읽기(릴레이A); if (aOperator>=0) { if (aState) { if (windowAlrt) { airingState =state_str[2]; } else { 방송 상태 =state_str[0]; } } else { 방송 상태 =state_str[1]; } } if (!startup) { sTX(6); }} void relayHandlerH(byte hOperator) { // 히터 핸들러 시퀀스 // 연산자는 다음과 같습니다. 0=off, 1=on, 2=상태 뒤집기, // 3=temprMeas() 함수에 의해 호출됨, 4=fill/refill 히터 상태 char var. if ((measError) &&((hOperator ==1) || (hOperator ==2))) { sTX(4); 반품; } if ((!hThermostat) &&(!windowAlrt) &&(!measError)) { // 일회성 난방(15분) 시간 모드 켜기/끄기 if ((hOperator ==2) || (hOperator ==1 ) &&(!hState) || (!hOperator) &&(hState)) { 버즈(2, 1); hState =!hState; sftyTmrEnded =0; 타이머0 =0; digitalWrite(릴레이H, hState); } } if (windowAlrt) { sTX(3); } if (hOperator ==3) { // 이 함수는 temprMeas() 함수에 의해 호출됩니다(op 3) // windowAlrt &measError 부울을 검사하기 위해 if ((windowAlrt) &&(hState)) { // 윈도우는 열려 있고 히터가 실행 중입니다. digitalWrite(relayH, 0); 버즈(5, 3); } if ((!windowAlrt) &&(!measError)) { if ((hThermostat) || (!hThermostat) &&(hState) &&(sftyTmrEnded)) { digitalWrite(relayH, hThermostat); // 온도 조절기 루틴의 명령을 진행합니다. } } } hState =digitalRead(relayH); if (hOperator>=0) { if (hState) { if (hThermostat) { heaterState =state_str[2]; } else { 히터 상태 =state_str[0]; } } else { 히터 상태 =state_str[1]; } if (((!windowAlrt) &&(hOperator !=3)) || (hState)) &&(!startup)) { sTX(5); } }}void safetyTmr() { // 일회성 난방(15분 시간) 모드 타이머 if ((hState) &&(!sftyTmrEnded) &&(timer0> sftyTmrInterval) &&(!hThermostat)) { sftyTmrEnded =1; 릴레이 핸들러H(0); for (byte i =1; i <5; i++) {uzz(i, 2); } }}void temprTimer() { // temprMeas()용 순환 타이머 unsigned long temprTmrCurr =millis(); if (temprInterval <=temprTmrCurr - temprTmrPrev) { temprTmrPrev =temprTmrCurr; temprMeas(); } }void temprMeas() { // ----------- 온도 측정 및 비교 시퀀스 temprPrev =tempr; // 다음 비교를 위해 값을 저장합니다. sensor.requestTemperatures(); // 센서 판독값 업데이트 tempr =sensor.getTempCByIndex(0); // 온도 읽기 if ((tempr>=40) || (tempr <=0)) { // 극단 측정값:if (!errMsgSentBySys) { // -127, -196.60은 HW 오류, +85는 일반적으로 SW 오류이지만 sTX(4); // 화재 또는 깨진 창일 수 있습니다. } errMsgSentBySys =1; h온도 조절기 =0; if (hState) { relayHandlerH(0); } if (aState) { relayHandlerA(0); } if (lState) { relayHandlerL(0); } 측정 오류 =1; for (바이트 i =1; i <10; i++) { 버즈(4, 1); 지연(50); } } 그렇지 않으면 { 임시 이전 =임시; 측정 오류 =0; errMsgSentBySys =0; } if (!measError) { // ------------ 온도 분석 시퀀스 시작 if (tempr <=17) { // 히터 가스 보일러의 빈번한 단기 전환은 단락 수명, heatCorrVal =0.5; // heatCorrVal 값은 이를 방지하는 데 도움이 됩니다. 과열 및 냉각 정도를 선언합니다. } // 벽이 더 차갑고 더 잘 흡수되기 때문에 온도가 낮을수록 더 큰 heatCorrVal이 필요합니다. 더 효과적인. heatCorrVal =0.4; } if (tempr>=19) { heatCorrVal =0.3; } if (tTarget - tempr>=heatCorrVal) { // 차이가 heatCorrVal 이상인 경우 sftyTmrEnded =1; // 1회 가열(15분) 시간 프로그램이 실행 중인 경우 비활성화 hThermostat =1; // 온도 조절 장치를 켭니다. 버즈(1, 1); } if ((tTarget - tempr <=-1 * heatCorrVal) &&(hThermostat)) { hThermostat =0; } if ((temprPrev - tempr>=0.2) &&(!windowAlrt) &&(tempr <=20)) { // 측정 주기 및 난방 시즌에서 온도 windowAlrt =1; // 떨어뜨리면 창이 열려 있는 것으로 평가됩니다. sftyTmrEnded =1; for (바이트 i =1; i <5; i++) { 버즈(4, 1); 지연(50); } 릴레이 핸들러A(3); // airing 함수(opcode =3)를 호출하여 공기를 새로 고침 } if ((temprPrev - tempr <=-0.12) &&(windowAlrt)) { // tempr. 낙하가 끝나고 공기가 따뜻해졌습니다. windowAlrt =0; // 환경의 열용량으로 인해, 버즈(4, 3); // 그래서 일반 모드로 다시 전환합니다. relayHandlerA(3); } 릴레이 핸들러H(3); // 함수는 호출자 param(3) &windowAlrt &measError 부울을 검사합니다 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]); 부서지다; case 1:sUART.print(funct_str[8]); // Tempr. sUART.print(tempr); sUART.print(char(176)); sUART.println("C"); 부서지다; case 2:sUART.print(funct_str[7]); // TTemp sUART.print(tTarget); sUART.print(char(176)); sUART.println("C"); 부서지다; case 3:sUART.print(funct_str[3]); // Window Alert sUART.print(funct_str[9]); sUART.print(tempr); sUART.print(char(176)); sUART.println("C"); 부서지다; case 4:sUART.println(funct_str[4]); // Error report break; case 5:sUART.print(funct_str[0]); // Working state of devices sUART.println(heaterState); 부서지다; case 6:sUART.print(funct_str[1]); sUART.println(airingState); 부서지다; case 7:sUART.print(funct_str[2]); sUART.println(lightingState); 부서지다; case 8:// Overview report sTX(0); relayHandlerH(4); relayHandlerA(4); relayHandlerL(4); sTX(2); if (measError) { sTX(4); } 부서지다; }}
    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); sensor.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(); } 동안( 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); 부서지다; case 'C':relayHandlerL(1); 부서지다; case 'c':relayHandlerL(0); 부서지다; case 'D':case 'd':tTarget =21; tTargetEEPROM(); buzz(3, 1); 부서지다; case 'E':case 'e':tTarget =19; tTargetEEPROM(); buzz(3, 1); 부서지다; case 'F':case 'f':tTarget =14; tTargetEEPROM(); buzz(3, 1); 부서지다; case 'R':// call for an overview report about controlled devices case 'r':sTX(8); 부서지다; case 'W':// disable Window Alert state case 'w':windowAlrt =0; buzz(4, 3); relayHandlerA(3); 부서지다; } // ----------------------- 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); 반품; } 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. 반품; } 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); 반품; } 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); 지연(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); 지연(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]); 부서지다; case 1:sUART.print(funct_str[8]); // Tempr. sUART.print(tempr); //sUART.print(char(176)); sUART.println("F"); 부서지다; case 2:sUART.print(funct_str[7]); // TTemp sUART.print(tTarget); //sUART.print(char(176)); sUART.println("F"); 부서지다; case 3:sUART.print(funct_str[3]); // Window Alert sUART.print(funct_str[9]); sUART.print(tempr); //sUART.print(char(176)); sUART.println("F"); 부서지다; case 4:sUART.println(funct_str[4]); // Error report break; case 5:sUART.print(funct_str[0]); // Working state of devices sUART.println(heaterState); 부서지다; case 6:sUART.print(funct_str[1]); sUART.println(airingState); 부서지다; case 7:sUART.print(funct_str[2]); sUART.println(lightingState); 부서지다; case 8:// Overview report sTX(0); relayHandlerH(4); relayHandlerA(4); relayHandlerL(4); sTX(2); if (measError) { sTX(4); } 부서지다; }}

    회로도

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

    제조공정

    1. QR, RFID 및 온도 확인을 통한 출입 통제
    2. Arduino, 1Sheeld 및 Android를 사용한 범용 원격 제어
    3. Arduino로 코인 억셉터 제어
    4. Arduino를 사용한 자동 식물 관수 시스템
    5. Bluetooth가 탑재된 Arduino로 LED 제어!
    6. 스마트 신발(자동 끈 및 전기 생성)
    7. Arduino Nano:조이스틱으로 2개의 스테퍼 모터 제어
    8. Arduino 및 MPU6050으로 서보 모터 제어
    9. OK Google이 포함된 Bluetooth 음성 제어 기기
    10. Arduino Uno 및 Bluetooth로 차량 제어