#include <Wire.h>
#include <U8g2lib.h>
#include <Arduino.h>
#include <DHT.h>
#include <EEPROM.h>
//#include <EEPROM.h>
// Create an instance for the SH1107 (I2C) in page buffer mode, rotated -90 degrees
U8G2_SH1107_128X128_1_HW_I2C u8g2(U8G2_R1); // Page buffer mode, no reset pin
//U8G2_SH1107_PIMORONI_128X128_1_HW_I2C u8g2(U8G2_R1);
#define kr_bitmap_height 10
// Bitmap for "건조" (Dry)
#define bitmap_GunJo_width 19 // Replace X with the width of your bitmap
const unsigned char bitmap_GunJo[] PROGMEM = {
0x80, 0x00, 0x00, 0x9e, 0xf8, 0x03, 0x90, 0x40, 0x00, 0xf8, 0xe0, 0x00, 0x8c, 0xb0, 0x01, 0x87,
0x58, 0x03, 0x80, 0x40, 0x00, 0x04, 0xfc, 0x07, 0x04, 0x00, 0x00, 0xfc, 0x00, 0x00
};
// Bitmap for "보관" (Storage)
#define bitmap_BoGuan_width 19
const unsigned char bitmap_BoGuan[] PROGMEM = {
0x00, 0x00, 0x02, 0x82, 0xfc, 0x02, 0x82, 0x80, 0x02, 0xfe, 0x90, 0x02, 0x82, 0x10, 0x06, 0xfe,
0xfc, 0x02, 0x10, 0x00, 0x02, 0xff, 0x11, 0x02, 0x00, 0x10, 0x00, 0x00, 0xf0, 0x03
};
// Bitmap for "설정" (Settings)
#define bitmap_SulJeong_width 19
const unsigned char bitmap_SulJeong[] PROGMEM = {
0x8c, 0xfc, 0x02, 0x8c, 0x30, 0x02, 0xec, 0xb0, 0x03, 0x9e, 0x78, 0x02, 0xb3, 0xcc, 0x02, 0x00,
0x00, 0x02, 0xfc, 0xe0, 0x01, 0xfc, 0x10, 0x02, 0x04, 0x10, 0x02, 0xfc, 0xe0, 0x01
};
// Bitmap for "언어" (Language)
#define bitmap_EonEo_width 19
const unsigned char bitmap_EonEo[] PROGMEM = {
0x9c, 0x00, 0x02, 0xb6, 0x30, 0x02, 0xa2, 0x48, 0x02, 0xe2, 0x48, 0x02, 0xb6, 0xc8, 0x03, 0x9c,
0x48, 0x02, 0x80, 0x48, 0x02, 0x04, 0x30, 0x02, 0x04, 0x00, 0x02, 0xfc, 0x00, 0x02
};
// Bitmap for "뒤로" (Back)
#define bitmap_Twiro_width 19
const unsigned char bitmap_Twiro[] PROGMEM = {
0xbe, 0x00, 0x00, 0x82, 0xf8, 0x03, 0x82, 0x00, 0x02, 0xbe, 0xf8, 0x03, 0x80, 0x08, 0x00, 0xff,
0xf8, 0x03, 0x88, 0x40, 0x00, 0x88, 0xfc, 0x07, 0x88, 0x00, 0x00, 0x88, 0x00, 0x00
};
// Bitmap for "초기화" (Default)
#define bitmap_ChoGiHwa_width 29
const unsigned char bitmap_ChoGiHwa[] PROGMEM = {
0x00, 0x00, 0x82, 0x08, 0x10, 0xfc, 0xf2, 0x0b, 0xfe, 0x80, 0x02, 0x08, 0x10, 0xc0, 0xe2, 0x09,
0x6c, 0x60, 0x32, 0x1b, 0xd6, 0x30, 0x32, 0x0b, 0x10, 0x18, 0xe2, 0x09, 0xff, 0x0d, 0x82, 0x08,
0x00, 0x00, 0xf2, 0x0b, 0x00, 0x00, 0x02, 0x08
};
struct TextBitmap {
const unsigned char* bitmap; // Pointer to the bitmap data
int width; // Width of the bitmap
int height; // Height of the bitmap
const char* englishText; // Corresponding English text
};
const TextBitmap HEAT = {bitmap_GunJo, bitmap_GunJo_width, 10, "DRY"};
const TextBitmap MONT = {bitmap_BoGuan, bitmap_BoGuan_width, 10, "KEEP"};
const TextBitmap SETT_TX = {bitmap_SulJeong, bitmap_SulJeong_width, 10, "SETTING"};
const TextBitmap LANG = {bitmap_EonEo, bitmap_EonEo_width, 10, "LANGUAGE"};
const TextBitmap DEFLT = {bitmap_ChoGiHwa, bitmap_ChoGiHwa_width, 10, "DEFAULT"};
const TextBitmap BACK = {bitmap_Twiro, bitmap_Twiro_width, 10, "BACK"};
struct MenuItem {
int menuItem; // The index of the menu item
int rowIndex; // The row index of the item
int x; // Starting x position
int y; // Starting y position
int width; // Width of the item
int height; // Height of the item
int value; // The current value of the item (e.g., MONITOR, LIM_HUMIDITY, etc.)
const char* unit; // Unit string (e.g., "C", "%", or empty for ON/OFF)
// Method to get the string representation of the value
const char* getValueString() const {
static char buffer[10]; // Static buffer to hold the string. Max size 10 characters
if (unit == "") {
// For ON/OFF, return "ON" or "OFF"
return value == 1 ? "ON" : "OFF";
} else {
// For numeric values, format the value with the unit
snprintf(buffer, sizeof(buffer), "%d%s", value, unit);
return buffer;
}
}
};
//MenuItem MI_HEATING = {/*menuItem*/0,/*rowIndex*/0,/*x*/64,/*y*/32,/*w*/32,/*h*/36,/*def val*/0,/*uint*/""};
MenuItem MI_MAX_TEMP = {/*menuItem*/1,/*rowIndex*/0,/*x*/64,/*y*/32,/*w*/32,/*h*/36,/*def val*/90,/*uint*/"C"};
MenuItem MI_TIMER = {/*menuItem*/2,/*rowIndex*/0,/*x*/97,/*y*/32,/*w*/32,/*h*/36,/*def val*/1,/*uint*/"h"};
MenuItem MI_MAX_HUMID = {/*menuItem*/3,/*rowIndex*/1,/*x*/64,/*y*/69,/*w*/31,/*h*/19,/*def val*/60,/*uint*/"%"};
MenuItem MI_MIN_TEMP = {/*menuItem*/4,/*rowIndex*/1,/*x*/64,/*y*/86,/*w*/31,/*h*/19,/*def val*/25,/*uint*/"C"};
MenuItem MI_MONITOR = {/*menuItem*/5,/*rowIndex*/1,/*x*/97,/*y*/69,/*w*/32,/*h*/36,/*def val*/0,/*uint*/""};
// NTC thermistor settings
#define THERMISTOR_PIN A6
#define BETA 3950 // Replace this with the correct value for your thermistor
#define R0 10000 // Replace this with the resistance at 25 degrees C for your thermistor
// DHT sensor settings
#define DHTPIN 1
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
// EEPROM addresses
#define EEPROM_INIT_FLAG_ADDR 0 // Address for the initialization flag
#define EEPROM_MAX_TEMP_ADDR 1
#define EEPROM_MIN_TEMP_ADDR 3
#define EEPROM_MAX_HUMIDITY_ADDR 5
#define EEPROM_HEAT_DURATION_ADDR 7
#define EEPROM_LANGUAGE_ADDR 9
// Default values
#define DEFAULT_MAX_TEMP 80
#define DEFAULT_MIN_TEMP 25
#define DEFAULT_MAX_HUMIDITY 60
#define DEFAULT_HEAT_DURATION 1 // Stored in hours
#define DEFAULT_LANGUAGE 0 //English
// Button pins
#define SELECT_PIN 2 // Pin for SELECT button
#define UP_PIN 3 // Pin for UP button
#define DOWN_PIN 4 // Pin for DOWN button
// Relay pin for PTC heater
#define RELAY_PIN 0
unsigned long lastInteractionTime = 0;
unsigned long lastSensorReadTime = 0;
const unsigned long timeoutDuration = 10000; // 10 seconds
const unsigned long SENSOR_READ_INTERVAL = 2000; // 2 seconds
// Navigation
enum Page { MAIN, SETT };
Page currentPage = MAIN;
int menuRow = 0; // Current label position.
int menuIndex = 0; // Current menu item position. -1: no position
int selectionMode = 0; // 0: inactive, 1: active
int language = 1; // 0: EN, 1: KR
float currentTemperature = 0;
float currentHumidity = 0;
bool setDefault = false;
// Variables for settings
unsigned long heatStartTime = 0;
int tempHysteresis = 5;
enum HeaterState { HEATING, MAINTAINING };
HeaterState heaterState = MAINTAINING;
// Example bitmap image (logo)
// Replace this with your own bitmap data
const unsigned char startup_logo [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xdf, 0xfb, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xc7, 0xe3, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xc1, 0x83, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc0, 0x03, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0xc0, 0x03, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0xc0, 0x03, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0xc0, 0x03, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01, 0xc0, 0x03, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0xc0, 0x03, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0xc0, 0x03, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x80, 0x03, 0xc0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x80, 0x0f, 0xf0, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x80, 0x3f, 0xf8, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xfe, 0x7e, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xc0, 0x0f, 0xf0, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xf0, 0x07, 0xc0, 0x0f, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xfc, 0x01, 0x80, 0x3f, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x80, 0x1f, 0x00, 0x00, 0xf8, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0xf8, 0x03, 0x00, 0x00, 0xc0, 0x1f, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x0e, 0xc7, 0x3f, 0xfc, 0x21, 0x00, 0x06, 0x3f, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x0e, 0xe7, 0x3f, 0xfe, 0x23, 0x00, 0x06, 0x73, 0x66, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x0e, 0xe7, 0x19, 0x8f, 0x27, 0x00, 0x0f, 0x63, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x0e, 0x77, 0x00, 0x07, 0x27, 0x00, 0x0f, 0x63, 0x06, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x0e, 0x77, 0x80, 0x03, 0x2e, 0x00, 0x09, 0x63, 0x0e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x0e, 0x77, 0xb0, 0x03, 0x2e, 0x80, 0x19, 0x3f, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x0e, 0x77, 0xb0, 0x03, 0x2e, 0x80, 0x10, 0x7f, 0x60, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x0e, 0x77, 0xb0, 0x07, 0x27, 0xc0, 0x30, 0x43, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x1e, 0xf7, 0x30, 0x87, 0x27, 0xc0, 0x30, 0xc3, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xfc, 0xe7, 0x3f, 0xff, 0x23, 0x40, 0x20, 0x43, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xfc, 0xc3, 0x3f, 0xfe, 0xe3, 0x6f, 0x60, 0x7f, 0x7f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xf0, 0x80, 0x1f, 0xf8, 0xe0, 0x3f, 0x40, 0x3f, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 displayLogo() {
u8g2.firstPage();
do {
u8g2.drawXBMP(/* x=*/0,/* y=*/ 0, /* height=*/128,/* width=*/ 128, startup_logo);
} while (u8g2.nextPage());
u8g2.clearBuffer();
delay(5000); // Wait for 5 seconds
}
void setup() {
// Initialize display
u8g2.begin();
// Display the logo for 5 seconds
displayLogo();
// Initialize buttons
pinMode(SELECT_PIN, INPUT_PULLUP);
pinMode(UP_PIN, INPUT_PULLUP);
pinMode(DOWN_PIN, INPUT_PULLUP);
pinMode(RELAY_PIN, OUTPUT);
dht.begin();
// Check if EEPROM has been initialized
if (EEPROM.read(EEPROM_INIT_FLAG_ADDR) != 0xAA) {
// EEPROM is not initialized, set default values
EEPROM.write(EEPROM_MAX_TEMP_ADDR, DEFAULT_MAX_TEMP);
EEPROM.write(EEPROM_MIN_TEMP_ADDR, DEFAULT_MIN_TEMP);
EEPROM.write(EEPROM_MAX_HUMIDITY_ADDR, DEFAULT_MAX_HUMIDITY);
EEPROM.write(EEPROM_HEAT_DURATION_ADDR, DEFAULT_HEAT_DURATION); // Stored as hours
EEPROM.write(EEPROM_LANGUAGE_ADDR, DEFAULT_LANGUAGE);
// Set the initialization flag
EEPROM.write(EEPROM_INIT_FLAG_ADDR, 0xAA); // Mark EEPROM as initialized
}
// Load values from EEPROM
MI_MAX_TEMP.value = EEPROM.read(EEPROM_MAX_TEMP_ADDR);
MI_MIN_TEMP.value = EEPROM.read(EEPROM_MIN_TEMP_ADDR);
MI_MAX_HUMID.value = EEPROM.read(EEPROM_MAX_HUMIDITY_ADDR);
MI_TIMER.value = EEPROM.read(EEPROM_HEAT_DURATION_ADDR); // Convert stored hours to seconds
language = EEPROM.read(EEPROM_LANGUAGE_ADDR);
// Draw initial screen
drawMenu();
}
void loop() {
// Check for timeout
if (selectionMode == 1 && millis() - lastInteractionTime > timeoutDuration) {
returnToMain();
}
// Read sensors at the defined interval
if (millis() - lastSensorReadTime > SENSOR_READ_INTERVAL) {
lastSensorReadTime = millis();
currentTemperature = readNTCTemperature();
currentHumidity = dht.readHumidity();
if (currentPage == MAIN) {
monitorEnvironment(currentTemperature, currentHumidity);
}
}
// Handle button presses based on current page
if (currentPage == MAIN) {
handleMainMenu();
} else if (currentPage == SETT) {
handleSettingsMenu();
}
// Redraw the screen
drawMenu();
}
float readNTCTemperature() {
int analogValue = analogRead(THERMISTOR_PIN);
float resistance = (1023.0 / analogValue - 1.0) * R0;
float celsius = 1.0 / (log(1023.0 / analogValue - 1.0) / BETA + 1.0 / 298.15) - 273.15;
return celsius;
}
void monitorEnvironment(float temperature, float humidity) {
if (MI_MONITOR.value == 0 ) {
heaterState = MAINTAINING;
heatStartTime = 0;
digitalWrite(RELAY_PIN, LOW);
return;
}
unsigned long currentTime = millis();
switch (heaterState) {
case HEATING:
// If the temperature has reached or exceeded the target temperature
if (temperature >= MI_MAX_TEMP.value && heatStartTime == 0) {
heatStartTime = millis(); // Start the timer once the target temperature is reached
}
// Continue maintaining the target temperature during the timer period
if (heatStartTime > 0) {
// Check if the timer has expired
if (currentTime - heatStartTime < MI_TIMER.value * 3600 * 1000) {
// Maintain target temperature
if (temperature < MI_MAX_TEMP.value - tempHysteresis) {
digitalWrite(RELAY_PIN, HIGH); // Turn on the heater to maintain target temperature
} else {
digitalWrite(RELAY_PIN, LOW); // Turn off heater if target temperature is maintained
}
} else {
// Timer expired, switch to maintaining minimum temperature
heaterState = MAINTAINING;
heatStartTime = 0; // Reset the timer for the next cycle
}
} else {
// If the target temperature has not yet been reached, keep heating
digitalWrite(RELAY_PIN, HIGH); // Continue heating
}
break;
case MAINTAINING:
// Check humidity first
if (humidity > MI_MAX_HUMID.value) {
heaterState = HEATING;
heatStartTime = 0; // Reset timer when switching back to heating
digitalWrite(RELAY_PIN, HIGH); // Turn on heater again to lower humidity
}
// Maintain minimum temperature with hysteresis
else if (temperature < MI_MIN_TEMP.value - tempHysteresis) {
digitalWrite(RELAY_PIN, HIGH); // Turn on heater to maintain minimum temperature
} else if (temperature >= MI_MIN_TEMP.value) {
digitalWrite(RELAY_PIN, LOW); // Turn off heater
}
break;
}
}
void handleMainMenu() {
if (digitalRead(SELECT_PIN) == LOW) {
lastInteractionTime = millis();
selectionMode = 1; // Activate selection mode
menuIndex++; // Move between items
if (menuIndex > 6) menuIndex = 1; // Loop through 6 items
menuRow = menuIndex / 3;
delay(200); // Debounce delay
}
if (selectionMode == 1) {
// Check if user is on 'SETT' and wants to open settings
if (menuRow == 2 && (digitalRead(UP_PIN) == LOW || digitalRead(DOWN_PIN) == LOW)) {
currentPage = SETT; // Switch to settings page
menuRow = 0; // Reset menuIndex for settings page
lastInteractionTime = millis();
delay(200); // Debounce delay
}
if (digitalRead(UP_PIN) == LOW) {
lastInteractionTime = millis();
changeValue(1); // Increase value
delay(200); // Debounce delay
}
if (digitalRead(DOWN_PIN) == LOW) {
lastInteractionTime = millis();
changeValue(-1); // Decrease value
delay(200); // Debounce delay
}
}
}
void handleSettingsMenu() {
if (digitalRead(SELECT_PIN) == LOW) {
lastInteractionTime = millis();
menuRow++; // Move between items in settings
if (menuRow > 2) menuRow = 0; // Loop through 3 items
delay(200); // Debounce delay
}
if (digitalRead(UP_PIN) == LOW || digitalRead(DOWN_PIN) == LOW) {
lastInteractionTime = millis();
if (menuRow == 0) {
// Language: change language
language = (language + 1) % 2; // Toggle between 0 and 1
EEPROM.write(EEPROM_LANGUAGE_ADDR, language);
} else if (menuRow == 1) {
// Default: reset values
resetToDefault();
} else if (menuRow == 2) {
// Back: return to main menu
returnToMain();
}
delay(200); // Debounce delay
}
}
void returnToMain() {
currentPage = MAIN;
selectionMode = 0;
menuIndex = 0;
setDefault= false;
menuRow = 0;
}
void resetToDefault() {
setDefault= true;
EEPROM.write(EEPROM_MAX_TEMP_ADDR, DEFAULT_MAX_TEMP);
EEPROM.write(EEPROM_MIN_TEMP_ADDR, DEFAULT_MIN_TEMP);
EEPROM.write(EEPROM_MAX_HUMIDITY_ADDR, DEFAULT_MAX_HUMIDITY);
EEPROM.write(EEPROM_HEAT_DURATION_ADDR, DEFAULT_HEAT_DURATION); // Stored as hours
// EEPROM.write(EEPROM_LANGUAGE_ADDR, DEFAULT_LANGUAGE);
// MI_HEATING.value = 0;
MI_MAX_TEMP.value = DEFAULT_MAX_TEMP;
MI_TIMER.value = DEFAULT_HEAT_DURATION;
// MI_MONITOR.value = 0;
MI_MAX_HUMID.value = DEFAULT_MAX_HUMIDITY;
MI_MIN_TEMP.value = DEFAULT_MIN_TEMP;
}
void changeValue(int direction) {
if (menuIndex == 1){
MI_MAX_TEMP.value = constrain(MI_MAX_TEMP.value + direction * 5, 0, 100); // Limit between 0 and 100
EEPROM.write(EEPROM_MAX_TEMP_ADDR, MI_MAX_TEMP.value);
}
if (menuIndex == 2){
MI_TIMER.value = constrain(MI_TIMER.value + direction, 1, 24); // Limit between 1 and 24
EEPROM.write(EEPROM_HEAT_DURATION_ADDR, MI_TIMER.value);
}
if (menuIndex == 3){
MI_MAX_HUMID.value = constrain(MI_MAX_HUMID.value + direction * 5, 0, 100); // Limit between 0 and 100
EEPROM.write(EEPROM_MAX_HUMIDITY_ADDR, MI_MAX_HUMID.value);
}
if (menuIndex == 4){
MI_MIN_TEMP.value = constrain(MI_MIN_TEMP.value + direction * 5, 0, 100); // Limit between 0 and 100
EEPROM.write(EEPROM_MIN_TEMP_ADDR, MI_MIN_TEMP.value);
}
if (menuIndex == 5){
MI_MONITOR.value = (MI_MONITOR.value + direction + 2) % 2;
}
}
void drawMenu() {
u8g2.firstPage(); // Start the first page
do {
if (currentPage == MAIN) {
drawMainMenu();
} else if (currentPage == SETT) {
drawSettingsMenu();
}
} while (u8g2.nextPage()); // Keep looping through pages until finished
}
void drawMainMenu() {
u8g2.setFont(u8g2_font_ncenB14_tf); // Smaller font
//u8g2.setFont(u8g2_font_9x15B_tf);
// Display temperature and humidity
u8g2.setCursor(13, 25);
u8g2.print(round(currentTemperature));
u8g2.print((char) 176);
u8g2.print("C");
u8g2.setCursor(76, 25);
u8g2.print(round(currentHumidity));
u8g2.print("%");
// Draw rows
draw_label_area(HEAT, 0, 32, 36);
drawItem(MI_MAX_TEMP);
drawItem(MI_TIMER);
draw_label_area(MONT, 1, 69, 36);
drawItem(MI_MONITOR);
drawItem(MI_MAX_HUMID);
drawItem(MI_MIN_TEMP);
draw_label_area(SETT_TX, 2, 106, 22);
}
void drawSettingsMenu() {
u8g2.setFont(u8g2_font_ncenB14_tf);
draw_label_area(LANG, 0, 0, 25);
u8g2.setCursor(95, 15);
//if(menuRow == 0) u8g2.setDrawColor(0);
u8g2.print(language == 0 ? "EN" : "KR");
draw_label_area(DEFLT, 1, 25, 25);
u8g2.setCursor(95, 40);
//if(menuRow == 1) u8g2.setDrawColor(0);
if(setDefault) u8g2.print("OK");
draw_label_area(BACK, 2, 50, 25);
}
void draw_label_area(const TextBitmap& text, int rowIndex, int y, int height) {
u8g2.setFont(u8g2_font_6x10_tf);
int textHeight = 10; // Height of the text for the u8g2_font_6x10_tf font
int centeredY = y + (height - textHeight) / 2;
u8g2.setDrawColor(1); // Normal white text for non-selected items
// Highlight the row if selected
if (selectionMode == 1 && menuRow == rowIndex) {
u8g2.drawCircle(8, centeredY + textHeight - 5, 3);
}
u8g2.drawFrame(0, y, 128, height);
if (language == 0) {
// English text
u8g2.setFont(u8g2_font_6x10_tf);
u8g2.setCursor(17, centeredY + textHeight - 1); // Adjusted to center vertically
u8g2.print(text.englishText);
} else {
// Korean bitmap
u8g2.drawXBMP(17, y + (height - text.height) / 2, text.width, text.height, text.bitmap);
u8g2.setFont(u8g2_font_6x10_tf);
}
u8g2.setDrawColor(1);
}
void drawItem(const MenuItem& item) {
// Determine if this item is selected
if (selectionMode == 1 && menuIndex == item.menuItem) {
u8g2.setDrawColor(1); // Set text to black
u8g2.drawBox(item.x, item.y, item.width, item.height); // Draw white background for the selected row
u8g2.setDrawColor(0); // Set text color to white (invert)
}
// else if (menuRow == item.rowIndex && menuIndex != -1) {
// u8g2.setDrawColor(0); // Set text to black
// }
else {
u8g2.setDrawColor(1); // Normal white text for non-selected items
}
const char* valueStr = item.getValueString();
if(valueStr == "ON" || valueStr == "OFF"){
//u8g2.setFont(u8g2_font_8x13B_tf);
u8g2.setFont(u8g2_font_8x13B_mf);
}else{
u8g2.setFont(u8g2_font_6x10_tf);
}
// Set the font and cursor for centered text
// Calculate centered x and y coordinates
int centeredX = item.x + (item.width - u8g2.getStrWidth(valueStr)) / 2;
int centeredY = item.y + (item.height - 10) / 2 + 10;
u8g2.setCursor(centeredX, centeredY - 1); // Centered horizontally and vertically
u8g2.print(valueStr);
}