/*
IoT Manager mqtt device client https://play.google.com/store/apps/details?id=ru.esp8266.iotmanager
Based on Basic MQTT example with Authentication
PubSubClient library v 1.99.1 https://github.com/Imroy/pubsubclient
- connects to an MQTT server, providing userdescr and password
- publishes config to the topic "/IoTmanager/config/deviceID/"
- subscribes to the topic "/IoTmanager/hello" ("hello" messages from mobile device)
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
###### TO SELECT THE FONTS AND PINS YOU USE, SEE ABOVE ######
#########################################################################
Tested with
Arduino IDE 1.8.9
ESP32 board
PubSubClient library 2.7 https://github.com/knolleary/pubsubclient
ArduinoJson library 6.11.1 https://github.com/bblanchon/ArduinoJson
DS3231 Arduino Library 1.2.2 https://github.com/adafruit/RTClib
Adafruit BME280 Library 1.0.8 https://github.com/adafruit/Adafruit_BME280_Library
Adafruit Sensor 1.0.3 https://github.com/adafruit/Adafruit_Sensor
TFT_eSPI 1.4.11 https://github.com/Bodmer/TFT_eSPI https://www.arduinolibraries.info/libraries/tft_e-spi
NTPClient 3.1.0 исправленная автором https://github.com/taranais/NTPClient https://github.com/arduino-libraries/NTPClient
utf8rus() http://zelectro.cc/lcd_russian_symbols
Preferences.h отвечает за запись чтение информации из/в встроенную в контроллер ESP32 FLASH память
sketch version : Курятник v.0.0.0.9 на ESP32
IoT Manager : 1.4.6 and above
GPIO36 - Наличие Сети AC
GPIO39 - Напряжение Аккумулятора DC
GPIO34 - Энкодер A
GPIO35 - Энкодер B
GPIO32 - Энкодер Кнопка
GPIO33 - Buzzer
GPIO25 - RF 315/433МГц / DHT
GPIO26 - ШИМ
GPIO27 - Детектор нуля сети
GPIO14 - Sensor DS18b20
GPIO12 - Выход на тиристор
GPIO13 - T_CS / Touch
GPIO15 - CS_ILI9341
GPIO2 - DC_ILI9341
GPIO0 - Программатор
GPIO4 - 74H595 DS
GPIO16 - 74H595 SH_cp
GPIO17 - 74H595 ST_cp
GPIO5 - CS_SD-CARD
GPIO18 - SCK ILI9341 / SD-CARD / TOUCH
GPIO19 - MISO ILI9341 / SD-CARD / TOUCH
GPIO21 - SDA LCD1602_I2C_BME280_DD
GPIO3 - RXD
GPIO1 - TXD
GPIO22 - SCL LCD1602_I2C_BME280_DD
GPIO23 - MOSI ILI9341 / SD-CARD / TOUCH
*/
/* История версий
v.0.0.0.0 - Запуск Часы DS1307, LCD1602_I2C, ILI9341 в режиме отображение часов,
v.0.0.0.2 - Запущено расширание портов на 74HC595
v.0.0.0.3 - Запущено encoder
v.0.0.0.4 - Запущено NTP
v.0.0.0.5 - Исправление запуска устройства при отсутствии интернета и зависание при запросе NTP без интернета.
v.0.0.0.6 - Изменение структуры программы. ( Функции теперь расположены в отдельных файлах )
v.0.0.0.7 - Русифицирован интерфейс
v.0.0.0.8a - Поиск циклического перезапуска mDNS виноват
v.0.0.0.9
I2C device found at address 0x27 ! LCD1602_I2C
I2C device found at address 0x50 ! EEPROM
I2C device found at address 0x68 ! Часы DS1307 (DS3231)
I2C device found at address 0x76 ! BME280
*/
#ifdef ESP8266
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <EEPROM.h>
ESP8266WebServer server(80);
const char* host = "ESP8266";
#else
#include <WiFi.h> // WIFIMANAGER-ESP32 // OTA
#include <WiFiClient.h>
#include <WebServer.h> // WIFIMANAGER-ESP32 WebServer-esp32 https://github.com/zhouhan0126/WebServer-esp32
#include <ESPmDNS.h> // WIFIMANAGER-ESP32 // OTA DNSServer https://github.com/zhouhan0126/DNSServer---esp32
#include <driver/adc.h>
#include "esp32-hal-ledc.h"
#include <Preferences.h> // отвечает за запись чтение информации из/в встроенную в контроллер ESP32 FLASH память
WebServer server(80);
const char* host = "ESP32";
#endif
//#include <PubSubClient.h>
//#include <WiFiClientSecure.h> // ?
//#include <WiFiManager.h> // WIFIMANAGER-ESP32 ESP32 https://github.com/zhouhan0126/WIFIMANAGER-ESP32
#include <WiFiManager.h> // + ESP-12 https://github.com/tzapu/WiFiManager
//#include <ArduinoJson.h>
#include <ArduinoOTA.h> // OTA
//#include <DNSServer.h> // WIFIMANAGER-ESP32 ?
#include <WiFiUdp.h> // OTA
#include "SimpleTimer.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include "RTClib.h" // https://github.com/adafruit/RTClib https://rxtx.su/mikrokontrollery/arduino/biblioteki-dlya-arduino/biblioteka-rtclib/
#include "DHTesp.h" // https://github.com/beegee-tokyo/DHTesp
#include "BMx280I2C.h" // https://github.com/christandlg/BMx280MI https://bitbucket.org/christandlg/bmx280mi
#include <LiquidCrystal_I2C.h> // https://github.com/johnrickman/LiquidCrystal_I2C
//#include <Adafruit_Sensor.h> //
//#include <Adafruit_BMP280.h>
#include "SSD1306Wire.h" // https://github.com/ThingPulse/esp8266-oled-ssd1306
#include "OLEDDisplayUi.h"
#include "icons.h"
#include <SPI.h>
#include <TFT_eSPI.h> // Hardware-specific library
//#include <Update.h> // ? SPIFFS
#include "Encod_er.h" // http://mypractic.ru/urok-55-rabota-s-inkrementalnym-enkoderom-v-arduino-biblioteka-encod_er-h.html#comment-5255
#include <NTPClient.h>
#include <SD.h>
#include "JPEGDecoder.h" // Декодер Jpeg файлов
// Include the header files that contain the icons
#include "wifiicons.h"
#include "batticons.h"
#include "digitnumicons.h"
#include "Alert.h"
#include "Page_Login.h"
#include "Page_Update.h"
#include "Page_Setting.h"
//#include "Page_Admin.h"
//#include "Page_General.h"
//#include "Page_Script.js.h"
//#include "Page_Style.css.h"
//#include "Page_NetworkConfiguration.h"
// ------------------------- НАСТРОЙКИ --------------------
#define RESET_CLOCK 0 // сброс часов на время загрузки прошивки (для модуля с несъёмной батарейкой). Не забудь закоментить и прошить ещё раз!
#define FEATURE_TFT 1 // Выбор экрана ILI9341
#define FEATURE_LCD 1 // Выбор экрана LCD1602_I2C
//#define DS3231_I2C // Выбор наличие модуля аппаратных часов на DS3231
#define DS1307_I2C 1 // Выбор наличие модуля аппаратных часов на DS1307
#define SERIAL_DEBUG 1 // вывод в порт отладочной информации!
//#define SERIAL_DEBUG_TIME // вывод в порт отладочной информации о времени
#define NTP_TIME_SINC 1 // разрешение синхронизации времени с сервером времени при первом запуске
//#define NTP_TIME_VIEW // вывод на экран времени полученное с сервера времени
#define TFT_DEBUG 1 // вывод на экран отладочной информации!
//#define NTP_TFT_DEBUG // вывод на экран NTP отладочной информации!
#define FEATURE_PRINT_DATE 0 // вывод на экран расположение даты
#define FEATURE_PRINT_MONTH 1 // вывод на экран Месяц прописью
WiFiManager wifiManager;
TFT_eSPI tft = TFT_eSPI(); // Вызвать пользовательскую библиотеку
SimpleTimer timer;
#ifdef DS3231_I2C
RTC_DS3231 rtc;
#endif
#ifdef DS1307_I2C
RTC_DS1307 rtc;
#endif
DateTime now;
// Пин первоначальной настройки WiFi
int analogPin0 = 36; // номер порта к которому подключено наличие Сети AC
int analogPin1 = 39; // номер порта к которому подключено напряжение Аккумулятора DC
float vout1, vout2 = 0.0;
float R12 = 100000.0; // сопротивление R12 (100K)
float R13 = 26000.0; // сопротивление R13 (27K) DC_sens
float R14 = 100000.0; // сопротивление R14 (100K)
float R15 = 30000.0; // сопротивление R15 (30K) AC_sens
#define pin_CLK 34 // пин 34 подключаем к CLK энкодера
#define pin_DT 35 // пин 35 подключаем к DT энкодера
#define pin_SW 32 // пин 32 подключаем к SW энкодера
#define filtr_encoder 2 // 5 выборок фильтрации
int encoder_value = 0;
int counter_encoder = 0;
unsigned long encoderMillis = 0;
unsigned long ShiftMillis = 0;
unsigned long buttomMillis = 0;
Encod_er encoder(pin_CLK, pin_DT, filtr_encoder); // энкодер к выводам 35 и 34, 5 выборок фильтрации
int le, re = 0; // для теста удалить
#define Beep 33 // номер порта к которому подключено Тестовый светодиод
int minvalue = 0; // минимальное значение ADC
int maxvalue = 4095; // максимальное значение ADC
int vin1, vin2 = 0; // , vin3, vin4
int uin1, uin2, uin1raw, uin2raw = 0; // переменная для хранения считываемого значения
float voltage_value1, voltage_value2 = 0;
int battlevel1, battlevel2, channel = 0;
bool charge = 0;
bool ntp_update = 0;
bool time_sync = 0;
int8_t rssi = 0;
bool status_led = 0;
// Объявляем переменные для меню
long timeButtonPressed = 1500; // Долгое удержание кнопки после 1,5 секунд
volatile int state = 0; // Статус одного шага - от 0 до 4 в одну сторону, от 0 до -4 - в другую
// Переменные хранящие состояние действия до его выполнения
volatile bool flagCW = false; // Было ли вращение по часовой стрелке
volatile bool flagCCW = false; // Было ли вращение против часовой стрелки
volatile bool flagButton = false; // Было ли нажатие кнопки
volatile bool flagButtonLong = false; // Было ли долгое удержание кнопки
volatile long timeButtonDown = 0; // Переменная хранящая время нажатия кнопки
volatile bool isButtonDown = false; // Переменная хранящая время нажатия кнопки
volatile bool longPressReleased = false; // Переменная для фиксации срабатывания долгого нажатия
int actualIndex = 0;
//==========================================================================================================================
//==========================================================================================================================
//==========================================================================================================================
//==========================================================================================================================
struct Button {
const uint8_t PIN;
uint32_t numberKeyPresses;
bool pressed;
};
void print_status(void) {
print_Info_Net();
adc_read();
print_wifi_level();
print_batt_level();
// print_Temp_Hall_status();
}
void Display_Time_Now(void) {
// #ifdef DS1307_I2C
// DateTime now = rtc.now(); // Время полученное из DS1307
// #endif
// #ifdef DS3231_I2C
// DateTime now = rtc.now(); // Время полученное из DS3231
// #endif
#ifdef FEATURE_TFT
print_ili9341_clock_RTC();
#endif
#ifdef LCD1602_I2C
print_Lcd1602_ckock_RTC();
#endif
}
//void IRAM_ATTR isr() {
// button1.numberKeyPresses += 1;
// button1.pressed = true;
//}
//==========================================================================================================================
//==========================================================================================================================
//==========================================================================================================================
//==========================================================================================================================
void setup() {
timer.setInterval(1000L, Display_Time_Now);
// timer.setInterval(600000L, set_setDateTime);
actualIndex = getMenuIndexByID(0); // Main - актуальный элемент меню
init_Serial();
init_ILI9341();
init_set_ILI9341();
#ifdef SERIAL_DEBUG
Serial.println("Booting");
#endif
#ifdef TFT_DEBUG
tft.println("Booting"); // Загрузка
#endif
init_set_ADC();
init_pins_set_Shift();
pins_clr_Shift();
init_pins_set_Encoder();
init_set_Net();
// init_pins_set_Buttom();
#ifdef LCD1602_I2C
init_Lcd1602();
#endif
#ifdef DS1307_I2C
init_RTC();
#endif
#ifdef DS3231_I2C
init_RTC();
#endif
pinMode(Beep, OUTPUT);
int pin_SW_ = digitalRead(pin_SW); // Сдесь реакция на перемычку начальной установки конфигурации
if (pin_SW_ == 0) {
#ifdef SERIAL_DEBUG
Serial.println("Setup");
#endif
#ifdef TFT_DEBUG
tft.println("Setup");
#endif
if (!wifiManager.startConfigPortal("ESP_AP", "12345678")) {
Serial.println("Not connected");
delay(20000);
ESP.restart();
}
}
init_SD();
SD_Info();
Current_Net();
print_Info_Net();
init_timeClient();
#ifdef SERIAL_DEBUG
Serial.println("Init NTP service:");
#endif
set_setDateTime();
// attachInterrupt(pin_CLK, encode_rotary, CHANGE); // Настраиваем обработчик прерываний по изменению сигнала
// attachInterrupt(pin_SW, Button, CHANGE); // Настраиваем обработчик прерываний по изменению сигнала нажатия кнопки
// attachInterrupt(button1.PIN, isr, FALLING);
// Port defaults to 3232
// ArduinoOTA.setPort(3232);
// Hostname defaults to esp3232-[MAC]
// ArduinoOTA.setHostname("myesp32");
// No authentication by default
// ArduinoOTA.setPassword("admin");
// Password can be set with it's md5 value as well
// MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
// ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");
ArduinoOTA
.onStart([]()
{
String type;
if (ArduinoOTA.getCommand() == U_FLASH)
type = "sketch";
else // U_SPIFFS
type = "filesystem";
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
Serial.println("Start updating " + type);
})
.onEnd([]()
{
Serial.println("\nEnd");
})
.onProgress([](unsigned int progress, unsigned int total)
{
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
})
.onError([](ota_error_t error)
{
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});
ArduinoOTA.begin();
// /*use mdns for host name resolution*/
// if (!MDNS.begin(host)) // http://esp32.local
// {
// Serial.println("Web OTA error!"); // Error setting up MDNS responder!
// while (1)
// {
// delay(1000);
// }
// }
// tft.println("Web OTA included "); // mDNS responder started
// /*return index page which is stored in serverIndex */
server.on("/", HTTP_GET, []()
{
server.sendHeader("Connection", "close");
server.send(200, "text/html", loginIndex);
});
server.on("/serverIndex", HTTP_GET, []()
{
server.sendHeader("Connection", "close");
server.send(200, "text/html", serverIndex);
});
/*handling uploading firmware file */
server.on("/update", HTTP_POST, []()
{
server.sendHeader("Connection", "close");
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
ESP.restart();
}, []()
{
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START)
{
Serial.printf("Update: %s\n", upload.filename.c_str());
if (!Update.begin(UPDATE_SIZE_UNKNOWN)) // start with max available size
{
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_WRITE)
{
/* flashing firmware to ESP*/
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize)
{
Update.printError(Serial);
}
}
else if (upload.status == UPLOAD_FILE_END)
{
if (Update.end(true)) { //true to set the size to the current progress
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
}
else
{
Update.printError(Serial);
}
}
});
server.begin();
}
//==========================================================================================================================
//==========================================================================================================================
void loop() {
timer.run();
// Buttoncheck();
if (millis() >= (encoderMillis + 1)) { // проверяем каждые 5мс (200 Гц)
encoder.scanState();
re += encode_rotary();
Set_EXTPIN();
// test595();
encoderMillis = millis();
}
if (millis() >= (ShiftMillis + 1000)) { // проверяем каждые 1с (1 Гц)
print_status();
Blink();
// menuloop();
ShiftMillis = millis();
}
if (millis() - timeButtonDown > timeButtonPressed && isButtonDown) { // Время длительного удержания наступило
flagButtonLong = true;
}
ArduinoOTA.handle();
server.handleClient();
}