/*Программа написана Федоровым Александром HOME LABORATORY ©
https://fedoroffalexander.wixsite.com/smart,
Написано для Антона Кузнецова. Июнь 2022.
Программа написана на основе свободно распространяемых в Интернет
библиотек и кода. Распространяется свободно для частного и коммерческого
испоьзования. Код не гарантирует надежной работы устройств управления.
Ответственность за использование этого кода лежит на его пользователе.
*/
/*Раскоментировать для Энкодера
#define pin_CLK 16
#define pin_DT 17
#define pin_Btn 32
*/
#include "Wire.h"
#include <LiquidCrystal_I2C.h>
#include "time.h"
#include <TaskScheduler.h> //https://github.com/arkhipenko/TaskScheduler
#include "RTClib.h"
#include <Preferences.h> //http://developer.alexanderklimov.ru/arduino/esp32/preferences.php
#include <SD.h> //https://www.mischianti.org/2021/03/28/how-to-use-sd-card-with-esp32-2/
#include "SdFat.h"
/*Раскоментировать для Энкодера #include "GyverEncoder.h"
unsigned long CurrentTime, LastTime;
enum eEncoderState {eNone, eLeft, eRight, eButton};
uint8_t EncoderA, EncoderB, EncoderAPrev;
int8_t counter;
bool ButtonPrev;
*/
#define SPI_SPEED SD_SCK_MHZ(4)
#define CS_PIN 5
#define UP 1
#define DOWN 2
#define ENTER 3
#define ERASESCREEN true
#define NOERASESCREEN false
#define OffUpDown 3
#define VERT_PIN 2 //дойстик
#define SEL_PIN 15 //дойстик
#define IN_MOTOR_STOP 27
#define IN_MOTOR_UP 13
#define IN_MOTOR_DOWN 33
#define OUT_MOTOR_STOP 26
#define OUT_MOTOR_UP 25
#define OUT_MOTOR_DOWN 12
//**********РАЗОБРАТЬ
#define IN_AMPER 35 //Аналог. Ток с сдатчика VP
#define OUT_PUSH 5 //Режим подъема
#define IN_HEGH 34 //высота подъема. 1 тик в минуту
int activScreen = 0;
int menuPositionMain = 1; int menuPositionMain2 = 1; int menuPositionManual = 0;
int menuPositionSettings = 0; int menuPositionDigitalSettings = 0;
int selectColor = 0;
String ManualOnOff = "OFF"; String ManualUPOnOff = "OFF";
String AutoOnOff = "OFF";
bool ClickManualUPOnOff = false; bool ClickManualDOWNOnOff = false;
bool ClickSettingsOnOff = false;
String ManualDOWNOnOff = "OFF"; bool ClickAutoOnOff = false;
bool edit = false;
int counter=0;
String Time = ""; String Date = "";
float power = 2.00; //Потребляемая мощность
String dimensionPower = ""; //Единицы измерения мощности
int vp = 0; //Управляющие сигналы с датчиков ограничения движения 0/1
int pr = 2; //Управляющие сигналы с датчиков ограничения движения 0/1
int heigh; //Высота подъема/спуска
String VP; String PR; String H;
int upMax=0; int downMax=10; //Максимальные точки подъема\спуска
int depthUpMax, depthDownMax; //Глубина подъема\спуска
float depth; //Текущая глубина
int _cycle = 0;
int cycle = 3; //Количество подъемов\спусков
int pauseCycle = 2; //пауза между циклами
int dd=11; int mm=22; int gg=33; int hh=44; int mnt=55; //Время дата
volatile unsigned long redrowSkreen = 0;
int positionDigital = 1;
int positionCursor = 2;
int tenPosition, hundredPosition, onePosition;
int positionMin=13; int positionMax=18;
int positionCycl=15; int positionPause=19;
int positionDD=6; int positionMM=12; int positionG=19;
int positionHH=6; int position_MM=12;
float AcsValue=0.0,Samples=0.0,AvgAcs=0.0,AcsValueF=0.0;
bool cycleOK=false;
LiquidCrystal_I2C lcd(0x27, 20, 4);
RTC_DS1307 rtc;
DateTime now;
SdFat sd;
File root;
Preferences preferences;
//https://cplusplus.com/reference/ctime/tm/
//Ссылка на структуру системного времени. Обязательно нужно выставлять вручную
//Или если использовать Wi Fi, автоматическая синхронизация с NTP при старте один раз
//struct tm timeinfo;
Scheduler userScheduler; //Управление задачами по таймеру
//Раз в минуту вызываем getTime(). Получаем системное время
void getTime(); //Декларируем функцию обработки
void drowScreen(); //Декларируем функцию разрешения перерисовки экрана
void printDirectory(File dir, int numTabs); //Декларируем функцию чтения директории SD
void saveSettings();
void readSettings();
Task taskTime( TASK_SECOND * 60 , TASK_FOREVER, &getTime );
Task taskDrow( TASK_SECOND * 1 , TASK_FOREVER, &drowScreen ); //TASK_MILLISECOND
/*Раскоментировать для энкодер
eEncoderState GetEncoderState() {
// Считываем состояние энкодера
eEncoderState Result = eNone;
CurrentTime = millis();
if (CurrentTime - LastTime >= 5) {
// Считываем не чаще 1 раза в 5 мс для уменьшения ложных срабатываний
LastTime = CurrentTime;
if (digitalRead(pin_Btn) == LOW )
{
if (ButtonPrev) {
Result = eButton; // Нажата кнопка
Serial.println("ENTER");
_switch = eButton;
ButtonPrev = 0;
}
}
else
{
ButtonPrev = 1;
EncoderA = digitalRead(pin_DT);
EncoderB = digitalRead(pin_CLK);
if ((!EncoderA) && (EncoderAPrev)) // Сигнал A изменился с 1 на 0
{
if (EncoderB) {
Result = eRight; // B=1 => энкодер вращается по часовой
_switch = eRight
Serial.println("DOWN");
}
else {
Result = eLeft; // B=0 => энкодер вращается против часовой
Serial.println("UP");
_switch = eLeft;
}
}
EncoderAPrev = EncoderA; // запомним текущее состояние
}
}
return Result;
}
*/
void getTime() {
//Не забыть установить RTC
now = rtc.now();
hh=now.hour(); mnt=now.minute(); dd=now.day(); mm=now.month(); gg=now.year();
Time = String(hh)+":"+String(mnt);
Date = String(dd)+"/"+String(mm)+"/"+String(gg);
}
void drowScreen() {
redrowSkreen++;
//Serial.print(".");
}
void helloScreen(bool erase) {
if(erase) lcd.clear();
lcd.setCursor(5, 1); lcd.print("ELEVATOR");
lcd.setCursor(2, 2); lcd.print("Project V 0.0.0");
activScreen = 0;
}
void mainScreen(bool erase, int UpDown) {
//Очистить если true
if(erase) {
lcd.clear();
menuPositionMain = 1;
}
if(UpDown == UP) menuPositionMain--;
if(UpDown == DOWN) menuPositionMain++;
lcd.setCursor(5, 0); lcd.print("MAIN MENU 1");
lcd.setCursor(2, 1); lcd.print("MANUAL");
lcd.setCursor(2, 2); lcd.print("HALF-AUTO");
lcd.setCursor(2, 3); lcd.print("AUTO");
lcd.setCursor(17, 3); lcd.print(AutoOnOff);
if(UpDown == DOWN) {
lcd.setCursor(0, menuPositionMain-1);
lcd.print(" ");
if(menuPositionMain > 3) {
activScreen = 2;
mainScreen2(ERASESCREEN, OffUpDown);
return;
}
}
if(UpDown == UP) {
lcd.setCursor(0, menuPositionMain+1);
lcd.print(" ");
if(menuPositionMain < 1) {
activScreen = 2;
mainScreen2(ERASESCREEN, OffUpDown);
return;
}
}
lcd.setCursor(0, menuPositionMain);
lcd.print(char(126)); //lcd.print(">");
activScreen = 1;
}
void mainScreen2(bool erase, int UpDown) {
//Очистить если true
if(erase) {
lcd.clear();
menuPositionMain2 = 1;
}
if(UpDown == UP) menuPositionMain2--;
if(UpDown == DOWN) menuPositionMain2++;
lcd.setCursor(5, 0); lcd.print("MAIN MENU 2");
lcd.setCursor(2, 1); lcd.print("PUSH");
lcd.setCursor(2, 2); lcd.print("SETTINGS");
//"DOWN"
if(UpDown == DOWN) {
lcd.setCursor(0, menuPositionMain2-1);
lcd.print(" ");
if(menuPositionMain2 > 2) {
activScreen = 1;
mainScreen(ERASESCREEN, OffUpDown);
return;
}
}
if(UpDown == UP) {
lcd.setCursor(0, menuPositionMain2+1);
lcd.print(" ");
if(menuPositionMain2 < 1) {
activScreen = 1;
mainScreen(ERASESCREEN, OffUpDown);
return;
}
}
lcd.setCursor(0, menuPositionMain2);
lcd.print(char(126)); //lcd.print(">");
activScreen = 2;
}
void manualScreen(bool erase, int UpDown) {
//Очистить если true
if(erase) {
lcd.clear();
menuPositionManual = 0;
}
if(UpDown == UP) menuPositionManual--;
if(UpDown == DOWN) menuPositionManual++;
lcd.setCursor(2, 0); lcd.print("UP");
lcd.setCursor(6, 0); lcd.print(ManualUPOnOff);
lcd.setCursor(10, 0); lcd.print(Date);
lcd.setCursor(2, 1); lcd.print("DOWN");
lcd.setCursor(11, 1); lcd.print(Time);
lcd.setCursor(7, 1); lcd.print(ManualDOWNOnOff);
lcd.setCursor(0, 2); lcd.print(VP);
lcd.setCursor(5, 2); lcd.print(PR);
lcd.setCursor(10, 2); lcd.print(H);
lcd.setCursor(0, 3); lcd.print(dimensionPower);
if(UpDown == DOWN) {
lcd.setCursor(0, menuPositionManual-1);
lcd.print(" ");
if(menuPositionManual > 1) {
activScreen = 1;
mainScreen(ERASESCREEN, OffUpDown);
return;
}
}
if(UpDown == UP) {
lcd.setCursor(0, menuPositionManual+1);
lcd.print(" ");
if(menuPositionManual < 0) {
activScreen = 1;
mainScreen(ERASESCREEN, OffUpDown);
return;
}
}
lcd.setCursor(0, menuPositionManual);
lcd.print(char(126)); //lcd.print(">");
activScreen = 3;
}
void settingsScreen(bool erase, int UpDown) {
//Очистить если true
if(erase) {
lcd.clear();
menuPositionSettings = 0;
}
if(UpDown == UP) menuPositionSettings--;
if(UpDown == DOWN) menuPositionSettings++;
lcd.setCursor(2, 0); lcd.print("MinMax="); lcd.setCursor(10, 0); lcd.print(String(upMax));
lcd.setCursor(14, 0); lcd.print("/");
lcd.setCursor(15, 0); lcd.print(String(downMax));
lcd.setCursor(2, 1); lcd.print("CyclPause="); lcd.setCursor(13, 1);lcd.print(String(cycle));
lcd.setCursor(16, 1); lcd.print("/");
lcd.setCursor(17, 1); lcd.print(String(pauseCycle));
lcd.setCursor(2, 2); lcd.print("DD= "); lcd.setCursor(5, 2); lcd.print(String(dd));
lcd.setCursor(8, 2); lcd.print("MM= "); lcd.setCursor(11, 2); lcd.print(String(mm));
lcd.setCursor(14, 2); lcd.print("G="); lcd.setCursor(16, 2); lcd.print(String(gg));
lcd.setCursor(2, 3); lcd.print("HH= "); lcd.setCursor(5, 3); lcd.print(String(hh));
lcd.setCursor(8, 3); lcd.print("MM="); lcd.setCursor(11, 3); lcd.print(String(mnt));
//"DOWN"
if(UpDown == DOWN) {
lcd.setCursor(0, menuPositionSettings-1);
lcd.print(" ");
if(menuPositionSettings > 3) {
activScreen = 2;
mainScreen2(ERASESCREEN, OffUpDown);
return;
}
}
if(UpDown == UP) {
lcd.setCursor(0, menuPositionSettings+1);
lcd.print(" ");
if(menuPositionSettings < 0) {
activScreen = 2;
mainScreen2(ERASESCREEN, OffUpDown);
return;
}
}
lcd.setCursor(0, menuPositionSettings);
lcd.print(char(126)); //lcd.print(">");
activScreen = 4;
}
//Обработка кода "кнопки"
void reciveBtnCode() {
// Enter-0 up-4095 down-0
//************Закоментарить до фразы "ЗАКОМЕНТИРОВАТЬ" ЭТО ДЛЯ РАБОТЫ ДЖОЙСТИКА В ЭМУЛЯТОРЕ
int _case = 0; int _switch = 0;
_case = analogRead(VERT_PIN);
if ( _case == 4095) { _switch = UP; Serial.printf("UP %d\n",_case); }
if ( _case == 0) { _switch = DOWN; Serial.printf("DOWN %d\n",_case); }
_case = digitalRead(SEL_PIN);
if ( _case == 0 ) { _switch = ENTER; Serial.printf("ENTER %d\n",_case); }
//************************************************************"ЗАКОМЕНТИРОВАТЬ"
if ( _switch == 0 ) return; // Закоментировать для Энкодер
switch ( _switch ) {
case UP:
// UP**************
if(edit == false) {
if(activScreen == 1) { mainScreen(NOERASESCREEN, UP); break; }
if(activScreen == 2) { mainScreen2(NOERASESCREEN, UP); break; }
if(activScreen == 3) { manualScreen(NOERASESCREEN, UP); break; }
if(activScreen == 4) { settingsScreen(NOERASESCREEN, UP); break; }
}
if(edit == true) {
if(activScreen == 4) {
if(menuPositionSettings == 0) {
if(menuPositionDigitalSettings==1) { ++upMax; lcd.noBlink();
if(upMax > 9999) upMax = 0;
lcd.setCursor(10, 0); lcd.print(" ");
settingsScreen(NOERASESCREEN, OffUpDown); lcd.setCursor(10, 0); lcd.blink(); break;
}
if(menuPositionDigitalSettings==2) { ++downMax; lcd.noBlink();
if(downMax > 9999) downMax = 0;
lcd.setCursor(15, 0); lcd.print(" ");
settingsScreen(NOERASESCREEN, OffUpDown); lcd.setCursor(15, 0); lcd.blink(); break;
}
}
if(menuPositionSettings == 1) {
if(menuPositionDigitalSettings==1) { ++cycle; lcd.noBlink();
if(cycle > 9999) cycle = 0;
lcd.setCursor(13, 1); lcd.print(" ");
settingsScreen(NOERASESCREEN, OffUpDown);
lcd.setCursor(13, 1); lcd.blink(); break;
}
if(menuPositionDigitalSettings==2) { ++pauseCycle; lcd.noBlink();
if(pauseCycle > 9999) pauseCycle = 0;
lcd.setCursor(17, 1); lcd.print(" ");
settingsScreen(NOERASESCREEN, OffUpDown);
lcd.setCursor(17, 1); lcd.blink(); break;
}
}
if(menuPositionSettings == 2) {
if(menuPositionDigitalSettings==1) { ++dd; lcd.noBlink();
if(dd > 31) dd = 1;
lcd.setCursor(5, 2); lcd.print(" ");
settingsScreen(NOERASESCREEN, OffUpDown);
lcd.setCursor(5, 2); lcd.blink(); break;
}
if(menuPositionDigitalSettings==2) { ++mm; lcd.noBlink();
if(mm > 12) mm = 1;
lcd.setCursor(11, 2); lcd.print(" ");
settingsScreen(NOERASESCREEN, OffUpDown);
lcd.setCursor(11, 2); lcd.blink(); break;
}
if(menuPositionDigitalSettings==3) { ++gg; lcd.noBlink();
lcd.setCursor(16, 2); lcd.print(" ");
settingsScreen(NOERASESCREEN, OffUpDown);
lcd.setCursor(16, 2); lcd.blink(); break;
}
}
//Не забыть переустановить время в RTC
if(menuPositionSettings == 3) {
if(menuPositionDigitalSettings==1) { ++hh; lcd.noBlink();
if(hh > 24) hh = 1;
lcd.setCursor(5, 3); lcd.print(" ");
settingsScreen(NOERASESCREEN, OffUpDown); lcd.setCursor(5, 3); lcd.blink(); break;
}
if(menuPositionDigitalSettings==2) { ++mnt; lcd.noBlink();
if(mnt > 59) mnt = 0;
lcd.setCursor(11, 3); lcd.print(" ");
settingsScreen(NOERASESCREEN, OffUpDown); lcd.setCursor(11, 3); lcd.blink(); break;
}
}
}
}
break;
case ENTER:
//"PLAY" ВЫБОР
//MAIN экран******************************************************
//****************************************************************
if(activScreen == 1) {
if(menuPositionMain == 1) { manualScreen(ERASESCREEN, OffUpDown); break; }
//Включить/выключить кнопку ON/OFF
if(menuPositionMain == 3) {
ClickAutoOnOff = !ClickAutoOnOff;
if(ClickAutoOnOff == true) { AutoOnOff = "ON "; mainScreen(NOERASESCREEN, OffUpDown);
activScreen = 3; manualScreen(ERASESCREEN, OffUpDown); cycleOK = !cycleOK; break; }
if(ClickAutoOnOff == false) { AutoOnOff = "OFF"; cycleOK = !cycleOK; mainScreen(NOERASESCREEN, OffUpDown); break; }
// mainScreen(NOERASESCREEN, OffUpDown);
//break;
}
}
//Экран MAIN2**********************************************
if(activScreen == 2) {
if(menuPositionMain2 == 2) { settingsScreen(ERASESCREEN, OffUpDown); break; }
}
//*****************************************************************
//Экран MANUAL UP **********************************************
//**************************************************************
if(activScreen == 3) {
if(menuPositionManual == 0) {
ClickManualUPOnOff = !ClickManualUPOnOff;
if(ClickManualUPOnOff == true) {
ManualUPOnOff = "ON "; ManualDOWNOnOff = "OFF";
digitalWrite(OUT_MOTOR_UP,HIGH); digitalWrite(OUT_MOTOR_DOWN,LOW);
manualScreen(NOERASESCREEN, OffUpDown);
ClickManualDOWNOnOff = !ClickManualDOWNOnOff; break;
}
if(ClickManualUPOnOff == false) {
ManualUPOnOff = "OFF";
digitalWrite(OUT_MOTOR_UP,LOW);
manualScreen(NOERASESCREEN, OffUpDown); break;
}
}
if(menuPositionManual == 1) {
ClickManualDOWNOnOff = !ClickManualDOWNOnOff;
if(ClickManualDOWNOnOff == true) {
ManualDOWNOnOff = "ON "; ManualUPOnOff = "OFF";
digitalWrite(OUT_MOTOR_DOWN,HIGH); digitalWrite(OUT_MOTOR_UP,LOW);
manualScreen(NOERASESCREEN, OffUpDown);
ClickManualUPOnOff = !ClickManualUPOnOff; break;
}
if(ClickManualDOWNOnOff == false) {
ManualDOWNOnOff = "OFF";
digitalWrite(OUT_MOTOR_DOWN,LOW);
manualScreen(NOERASESCREEN, OffUpDown); break;
}
}
break;
}
//Экран SETTINGS**************************************************
if(activScreen == 4) {
delay(100);
//Маркер строчек Экрана SETTINGS menuPositionDigitalSettings
if(menuPositionSettings == 0) {
if(menuPositionDigitalSettings == 0) edit = !edit;
menuPositionDigitalSettings++;
//Serial.println(menuPositionDigitalSettings);
if(edit == true) {
if(menuPositionDigitalSettings==1) { lcd.noBlink(); lcd.setCursor(10, 0); lcd.blink(); break; }
if(menuPositionDigitalSettings==2) { lcd.noBlink(); lcd.setCursor(15, 0); lcd.blink(); break; }
if(menuPositionDigitalSettings > 2) { edit = !edit; /*menuPositionDigitalSettings=0; lcd.noBlink(); break;*/ }
}
if(edit == false) { menuPositionDigitalSettings=0; lcd.noBlink(); saveSettings(); break; }
}
if(menuPositionSettings == 1) {
if(menuPositionDigitalSettings == 0) edit = !edit;
menuPositionDigitalSettings++;
//Serial.println(menuPositionDigitalSettings);
if(edit == true) {
if(menuPositionDigitalSettings==1) { lcd.noBlink(); lcd.setCursor(13, 1); lcd.blink(); break; }
if(menuPositionDigitalSettings==2) { lcd.noBlink(); lcd.setCursor(17, 1); lcd.blink(); break; }
if(menuPositionDigitalSettings > 2) { edit = !edit; /*menuPositionDigitalSettings=0; lcd.noBlink(); break;*/ }
}
if(edit == false) { menuPositionDigitalSettings=0; lcd.noBlink(); saveSettings(); break; }
}
if(menuPositionSettings == 2) {
if(menuPositionDigitalSettings == 0) edit = !edit;
menuPositionDigitalSettings++;
//Serial.println(menuPositionDigitalSettings);
if(edit == true) {
if(menuPositionDigitalSettings==1) { lcd.noBlink(); lcd.setCursor(5, 2); lcd.blink(); break; }
if(menuPositionDigitalSettings==2) { lcd.noBlink(); lcd.setCursor(11, 2); lcd.blink(); break; }
if(menuPositionDigitalSettings==3) { lcd.noBlink(); lcd.setCursor(16, 2); lcd.blink(); break; }
if(menuPositionDigitalSettings > 3) edit = !edit;
}
if(edit == false) { menuPositionDigitalSettings=0; lcd.noBlink(); saveSettings(); break; }
}
if(menuPositionSettings == 3) {
if(menuPositionDigitalSettings == 0) edit = !edit;
menuPositionDigitalSettings++;
//Serial.println(menuPositionDigitalSettings);
if(edit == true) {
if(menuPositionDigitalSettings==1) { lcd.noBlink(); lcd.setCursor(5, 3); lcd.blink(); break; }
if(menuPositionDigitalSettings==2) { lcd.noBlink(); lcd.setCursor(11, 3); lcd.blink(); break; }
if(menuPositionDigitalSettings > 2) { edit = !edit; /*menuPositionDigitalSettings=0; lcd.noBlink(); break;*/ }
}
if(edit == false) { menuPositionDigitalSettings=0; lcd.noBlink(); saveSettings(); break; }
}
}
break;
case DOWN:
//"MINUS" DOWN
if(edit == false) {
if(activScreen == 1) { mainScreen(NOERASESCREEN, DOWN); break;}
if(activScreen == 2) { mainScreen2(NOERASESCREEN, DOWN); break;}
if(activScreen == 3) { manualScreen(NOERASESCREEN, DOWN); break;}
if(activScreen == 4) { settingsScreen(NOERASESCREEN, DOWN); break;}
}
if(edit == true) {
if(activScreen == 4) {
if(menuPositionSettings == 0) {
if(menuPositionDigitalSettings==1) { --upMax; lcd.noBlink();
if(upMax > 9999) upMax = 0;
lcd.setCursor(10, 0); lcd.print(" ");
settingsScreen(NOERASESCREEN, OffUpDown); lcd.setCursor(10, 0); lcd.blink(); break;
}
if(menuPositionDigitalSettings==2) { --downMax; lcd.noBlink();
if(downMax > 9999) downMax = 0;
lcd.setCursor(15, 0); lcd.print(" ");
settingsScreen(NOERASESCREEN, OffUpDown); lcd.setCursor(15, 0); lcd.blink(); break;
}
}
if(menuPositionSettings == 1) {
if(menuPositionDigitalSettings==1) { --cycle; lcd.noBlink();
if(cycle < 0) cycle = 9999;
lcd.setCursor(13, 1); lcd.print(" ");
settingsScreen(NOERASESCREEN, OffUpDown);
lcd.setCursor(13, 1); lcd.blink(); break;
}
if(menuPositionDigitalSettings==2) { --pauseCycle; lcd.noBlink();
if(pauseCycle < 0 ) pauseCycle = 9999;
lcd.setCursor(17, 1); lcd.print(" ");
settingsScreen(NOERASESCREEN, OffUpDown);
lcd.setCursor(17, 1); lcd.blink(); break;
}
}
if(menuPositionSettings == 2) {
if(menuPositionDigitalSettings==1) { --dd; lcd.noBlink();
if(dd < 1) dd = 31;
lcd.setCursor(5, 2); lcd.print(" ");
settingsScreen(NOERASESCREEN, OffUpDown);
lcd.setCursor(5, 2); lcd.blink(); break;
}
if(menuPositionDigitalSettings==2) { --mm; lcd.noBlink();
if(mm <1) mm = 12;
lcd.setCursor(11, 2); lcd.print(" ");
settingsScreen(NOERASESCREEN, OffUpDown);
lcd.setCursor(11, 2); lcd.blink(); break;
}
if(menuPositionDigitalSettings==3) { --gg; lcd.noBlink();
lcd.setCursor(16, 2); lcd.print(" ");
settingsScreen(NOERASESCREEN, OffUpDown);
lcd.setCursor(16, 2); lcd.blink(); break;
}
}
//Не забыть переустановить время в RTC
if(menuPositionSettings == 3) {
if(menuPositionDigitalSettings==1) { --hh; lcd.noBlink();
if(hh < 1) hh = 24;
lcd.setCursor(5, 3); lcd.print(" ");
settingsScreen(NOERASESCREEN, OffUpDown); lcd.setCursor(5, 3); lcd.blink(); break;
}
if(menuPositionDigitalSettings==2) { --mnt; lcd.noBlink();
if(mnt <0 ) mnt = 59;
lcd.setCursor(11, 3); lcd.print(" ");
settingsScreen(NOERASESCREEN, OffUpDown); lcd.setCursor(11, 3); lcd.blink(); break;
}
}
}
}
break;
}
}
//******************************************************************************
//Рабочее пространство для разработчика. В код МЕНЮ лазить не надо!!!
//Все переменные автоматически отобразятся в МЕНЮ
//float upMax, downMax; //Максимальные точки подъема\спуска
//int vp, pr; //Управляющие сигналы с датчиков ограничения движения 0/1
//float heigh; //Высота подъема/спуска
//String VP; String PR; String H;
//float depthUpMax, depthDownMax; //Глубина подъема\спуска
//float power; //Потребляемая мощность
//String dimensionPower = "kWh"; //Единицы измерения мощности
//int cycle = 10; //Количество подъемов\спусков
void developer() {
//Прием данных с пинов********************
AcsValue = analogRead(IN_AMPER); //Read current sensor values
AcsValue = (2.5 - (AcsValue * (3.3 / 1024.0)) )/0.185;
dimensionPower = String(AcsValue)+"A ";
//*****************************************
//Двигатель ВВЕРХ
if( digitalRead(IN_MOTOR_UP) == HIGH ) {
digitalWrite(OUT_MOTOR_UP,HIGH);
digitalWrite(OUT_MOTOR_DOWN,LOW);
//menuPositionManual = 0;
ClickManualUPOnOff != ClickManualUPOnOff; //щелкнуть выключатель
ManualUPOnOff = "ON "; ManualDOWNOnOff = "OFF"; //Нарисовать выключатели
if(activScreen == 3) manualScreen(NOERASESCREEN, OffUpDown);
return;
}
//Двигатель ВНИЗ
if( digitalRead(IN_MOTOR_DOWN) == HIGH ) {
digitalWrite(OUT_MOTOR_DOWN,HIGH);
digitalWrite(OUT_MOTOR_UP,LOW);
//menuPositionManual = 1;
ClickManualDOWNOnOff != ClickManualDOWNOnOff; //щелкнуть выключатель
ManualDOWNOnOff = "ON "; ManualUPOnOff = "OFF"; //Нарисовать выключатели
if(activScreen == 3) manualScreen(NOERASESCREEN, OffUpDown);
return;
}
//Сигналы с Верхнего-Нижнего датчиков и кнопки Стоп*****************
if( digitalRead(IN_MOTOR_STOP) == HIGH ) {
digitalWrite(OUT_MOTOR_STOP,HIGH);
digitalWrite(OUT_MOTOR_UP,LOW);
digitalWrite(OUT_MOTOR_DOWN,LOW);
delay(500);
digitalWrite(OUT_MOTOR_STOP,LOW);
if ( ManualUPOnOff == "ON ") {
ClickManualUPOnOff != ClickManualUPOnOff; //щелкнуть выключатель
ManualUPOnOff = "OFF"; //Нарисовать выключатели
VP = "VP-"+String("1");
PR = "PR-"+String("0");
H = "H-"+String(heigh)+"M ";
if(activScreen == 3) manualScreen(NOERASESCREEN, OffUpDown);
return;
}
if ( ManualDOWNOnOff == "ON ") {
ClickManualDOWNOnOff != ClickManualDOWNOnOff; //щелкнуть выключатель
ManualDOWNOnOff = "OFF"; //Нарисовать выключатели
PR = "PR-"+String("1");
VP = "VP-"+String("0");
H = "H-"+String(heigh)+"M ";
if(activScreen == 3) manualScreen(NOERASESCREEN, OffUpDown);
return;
}
}
//*****************************************************************
//Serial.println(AutoOnOff);
if(AutoOnOff == "ON ") {
//Число циклов cycle не завершено !cycleOK
if(cycleOK == true) {
//Двигаемся ВНИЗ
if(ManualUPOnOff == "OFF" and heigh < downMax-1) {
ManualDOWNOnOff = "ON ";
/*Serial.println("_DOWN");*/
heigh++;
manualScreen(NOERASESCREEN, OffUpDown);
}
else { ManualDOWNOnOff = "OFF"; /*AutoOnOff = "OFF";
activScreen=1; mainScreen(ERASESCREEN, OffUpDown);*/
}
//нижнее положение достигнуто или счетчик heigh
//Двигаемся ВВЕРХ
if(ManualDOWNOnOff == "OFF" and heigh > upMax) {
ManualUPOnOff = "ON ";
//Serial.println("_UP");
heigh--;
manualScreen(NOERASESCREEN, OffUpDown);
}
//верхнее положение достигнуто или счетчик heigh
else ManualDOWNOnOff = "ON ";
if(heigh <= 1) { _cycle++; Serial.println(_cycle); }
//Посчитать. ЦИКЛы закончились. Все выключить.
if(_cycle >= cycle) {
Serial.println("PAUSE");
taskDrow.enable();
_cycle=0;
cycleOK = !cycleOK;
ManualUPOnOff = "OFF"; ManualDOWNOnOff = "OFF";
//AutoOnOff = "OFF";
manualScreen(NOERASESCREEN, OffUpDown);
}
}
//Число циклов завершено cycleOK. Пауза. Включить AUTO в секундах
/*if( redrowSkreen >= pauseCycle) {
Serial.println(redrowSkreen);
redrowSkreen = 0;
cycleOK = !cycleOK;
AutoOnOff = "ON ";
taskDrow.disable();
}*/
//manualScreen(NOERASESCREEN, OffUpDown);
}
//***************************************************************
if( ManualUPOnOff == "ON " or ManualDOWNOnOff == "ON " ) {
//Формирование строк из данных при обработки логики ON/OFF. Показывать/остановить показ
//Здесь обработка логики включения\выключения пинов
if(digitalRead(IN_HEGH)) {
if(ManualUPOnOff == "ON ") heigh--;
if(ManualDOWNOnOff == "ON ") heigh++;
}
//Проверить. Уперлись в датчик или перекрутили по счетчику
if(heigh <= upMax or heigh >= downMax or digitalRead(IN_MOTOR_STOP) == HIGH) {
digitalWrite(OUT_MOTOR_DOWN,LOW);
digitalWrite(OUT_MOTOR_UP,LOW);
ClickManualUPOnOff != ClickManualUPOnOff; //щелкнуть выключатель
ManualUPOnOff = "OFF"; ManualDOWNOnOff = "OFF"; //Нарисовать выключатели
AutoOnOff = "OFF"; //выключить если включено AUTO
if(heigh >= downMax) {
digitalWrite(OUT_MOTOR_UP,HIGH);
heigh--;
//delay(1000); //Время на отъезд от датчика
digitalWrite(OUT_MOTOR_UP,LOW);
}
if(heigh <= upMax) {
digitalWrite(OUT_MOTOR_DOWN,HIGH);
heigh++;
//delay(1000); //Время на отъезд от датчика
digitalWrite(OUT_MOTOR_DOWN,LOW);
}
}
dimensionPower = String(AcsValue)+"A ";
H = "H-"+String(heigh)+"M ";
VP = "VP-"+String("0");
PR = "PR-"+String("0");
if(activScreen == 3) manualScreen(NOERASESCREEN, OffUpDown);
return;
}
}
//******************************************************************************
void setup() {
Serial.begin(115200);
lcd.init(); // This is the I2C LCD object initialization.
lcd.backlight();
//https://microcontrollerslab.com/save-data-esp32-flash-permanently-preferences-library/
preferences.begin("memory", false); //Инициализация записи в EEPROM
//preferences.clear();
//Если ключа нет сохраняем предустановленные параметры
if(preferences.getUInt("upMax", 0) == 0) saveSettings();
else
readSettings();
//SD карта. Подключение файловой системы
/*if (!sd.begin(CS_PIN, SPI_SPEED)) {
if (sd.card()->errorCode()) {
Serial.println("SD initialization failed.");
} else if (sd.vol()->fatType() == 0) {
Serial.println("Can't find a valid FAT16/FAT32 partition.");
} else {
Serial.println("Can't determine error type");
}
return;
}
Serial.println("Files on card:");
Serial.println(" Size Name");
sd.ls(LS_R | LS_SIZE);*/
//******************************************************
//Файл Config
Serial.print("Initializing SD card... ");
if (!SD.begin(CS_PIN)) {
Serial.println("Card initialization failed!");
while (true);
}
Serial.println("initialization done.");
//Serial.println("Files in the card:");
//root = SD.open("/");
//SD.remove("/Config.txt");
//root.close();
/*
root = SD.open("/Config.txt", FILE_WRITE); //Файл не существует. Создать и записать параметры
//Проверка на готовом файле
root.println(5); root.println(6);
root.println(10); root.println(90);
if(!root) {
root.println(upMax); root.println(downMax);
root.println(cycle); root.println(pauseCycle);
//Проверка на вновь созданном файле
//root.println(5); root.println(6);
//root.println(10); root.println(90);
Serial.println("Creat Config.txt file");
root.close();
}
else
Serial.println("File Config.txt read...");
root = SD.open("/Config.txt", FILE_READ);
if(root) {
String str = root.readStringUntil('\n'); upMax = str.toInt(); str="";
str = root.readStringUntil('\n'); cycle = str.toInt(); str="";
str = root.readStringUntil('\n'); pauseCycle = str.toInt();
Serial.printf("%d %d %d %d\n",upMax,downMax,cycle,pauseCycle);
Serial.println("Files on card:");
Serial.println(" Size Name");
root.close();
}
else
Serial.println("No file");
root = SD.open("/");
printDirectory(root, 0);
Serial.println("");
root.close();
*/
//******************************************************
if (! rtc.begin()) Serial.println("Couldn't find RTC");
pinMode(VERT_PIN, INPUT); // Enter(0)-2048 up-4095 down-0
pinMode(SEL_PIN, INPUT_PULLUP); //1-кнопка отпущена 0-нажата
pinMode(IN_HEGH, INPUT); //высота подема. 1 тик 1 метр
//digitalWrite(IN_HEGH,LOW);
pinMode(IN_MOTOR_STOP, INPUT); digitalWrite(IN_MOTOR_STOP,LOW);
pinMode(IN_MOTOR_UP, INPUT); digitalWrite(IN_MOTOR_UP,LOW);
pinMode(IN_MOTOR_DOWN, INPUT); digitalWrite(IN_MOTOR_DOWN, LOW);
pinMode(OUT_MOTOR_STOP, OUTPUT); digitalWrite(OUT_MOTOR_STOP,LOW);
pinMode(OUT_MOTOR_UP, OUTPUT); digitalWrite(OUT_MOTOR_UP,LOW);
pinMode(OUT_MOTOR_DOWN, OUTPUT); digitalWrite(OUT_MOTOR_DOWN,LOW);
helloScreen(ERASESCREEN);
delay(1000);
//getLocalTime(&timeinfo);
//hh=timeinfo.tm_hour; mnt=timeinfo.tm_min;
now = rtc.now();
dd=now.day(); mm=now.month(); gg=now.year();
hh=now.hour(); mnt=now.minute();
Time = String(hh)+":"+String(mnt);
Date = String(dd)+"/"+String(mm)+"/"+String(gg);
userScheduler.init();
userScheduler.addTask( taskTime );
userScheduler.addTask( taskDrow );
//mainScreen(ERASESCREEN, OffUpDown);
//Поднять элеватор наверх. Мотор UP
heigh = 10; //Для теста. Высота подъема/спуска
digitalWrite(OUT_MOTOR_UP,HIGH);
ClickManualUPOnOff != ClickManualUPOnOff; //щелкнуть выключатель
ManualUPOnOff = "ON "; ManualDOWNOnOff = "OFF"; //Нарисовать выключатели
manualScreen(ERASESCREEN, OffUpDown); //нарисовать экран
//Выключить по счетчику высоты и/или дачику vp (пин 27)
while(heigh >= upMax and digitalRead(IN_MOTOR_STOP) == LOW) {
if(digitalRead(IN_HEGH) == HIGH) --heigh;
H = "H-"+String(heigh)+"M ";
vp = digitalRead(IN_MOTOR_STOP); //на один пин заведены СТОП, VP, PR
VP = "VP-"+String(vp);
PR = "PR-"+String("0");
//https://www.engineersgarage.com/acs712-current-sensor-with-arduino/
AcsValue = analogRead(IN_AMPER); //Read current sensor values
AcsValue = (2.5 - (AcsValue * (3.3 / 1024.0)) )/0.185;
dimensionPower = String(AcsValue)+"A ";
manualScreen(NOERASESCREEN, OffUpDown); //нарисовать экран
}
digitalWrite(OUT_MOTOR_UP,LOW); //STOP мотор вверх
//Serial.println(heigh);
//Проверить. Уперлись в верхний датчик или перекрутили вверх по счетчику
if(heigh <= 0 or digitalRead(IN_MOTOR_STOP) == HIGH) {
digitalWrite(OUT_MOTOR_DOWN,HIGH); //Включить мотор DOWN
//delay(1000); //Время на отъезд от верхнего датчика
ClickManualUPOnOff != ClickManualUPOnOff; //щелкнуть выключатель
ManualUPOnOff = "OFF"; ManualDOWNOnOff = "ON "; //Нарисовать выключатели
if(digitalRead(IN_HEGH) == HIGH) heigh++ ; //pin34
vp = digitalRead(IN_MOTOR_STOP); //на один пин27 заведены СТОП, VP, PR
if(vp == 1) heigh = 0; //уперлись в верхний датчик. Сброс счетчика высоты
VP = "VP-"+String(vp); //36
PR = "PR-"+String("0"); //39
H = "H-"+String(heigh)+"M ";
digitalWrite(OUT_MOTOR_DOWN,LOW);
manualScreen(NOERASESCREEN, OffUpDown); //нарисовать экран
}
//Еще раз все выключили
digitalWrite(OUT_MOTOR_DOWN,LOW);
digitalWrite(OUT_MOTOR_UP,LOW);
ClickManualUPOnOff != ClickManualUPOnOff; //щелкнуть выключатель
ManualUPOnOff = "OFF"; ManualDOWNOnOff = "OFF"; //Нарисовать выключатели
manualScreen(NOERASESCREEN, OffUpDown); //нарисовать экран
taskTime.enable();
//taskDrow.enable();
//taskDrow.disable();
}
void loop() {
//redrowSkreen = false;
//DateTime now = rtc.now();
//unsigned long m1 = millis();
//Serial.println(digitalRead(IN_HEGH));
reciveBtnCode(); //Закоментировать для Энкодер
//eEncoderState GetEncoderState(); //раскоментировать для Эенкодер
//if(millis() - m1 != 0) Serial.printf("Btn %d millis\n", millis() - m1);
//Не трогать, обновления экранов
//redrowSkreen = true;
//Serial.println(redrowSkreen);
/*if ( edit == false and redrowSkreen == true ) {
//redrowSkreen = false;
//unsigned long m = millis();
if(activScreen == 3) manualScreen(NOERASESCREEN, OffUpDown);
if(activScreen == 4) settingsScreen(NOERASESCREEN, OffUpDown);
//if(millis() - m != 0)
// Serial.printf("Screen %d millis\n", millis() - m);
//redrowSkreen != redrowSkreen;
}*/
developer();
userScheduler.execute();
delay(100); // this speeds up the simulation
}
void printDirectory(File dir, int numTabs) {
while (true) {
File entry = dir.openNextFile();
if (! entry) {
// no more files
break;
}
for (uint8_t i = 0; i < numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
printDirectory(entry, numTabs + 1);
} else {
// files have sizes, directories do not
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
entry.close();
}
}
void saveSettings() {
preferences.begin("memory", false);
preferences.putUInt("upMax", upMax);
preferences.putUInt("downMax", downMax);
preferences.putUInt("cycle", cycle);
preferences.putUInt("pauseCycle", pauseCycle);
preferences.end();
Serial.printf("Save Memory %d %d %d %d\n",upMax,downMax,cycle,pauseCycle);
}
void readSettings() {
preferences.begin("memory", false);
upMax=preferences.getUInt("upMax", upMax);
downMax=preferences.getUInt("downMax", downMax);
cycle=preferences.getUInt("cycle", cycle);
pauseCycle=preferences.getUInt("pauseCycle", pauseCycle);
preferences.end();
Serial.printf("Read Memory %d %d %d %d\n",upMax,downMax,cycle,pauseCycle);
}