/*Навигация по меню
Во второй строке 0 - будильник включен, х - выключен.
Посмотреть время будильника - нажать D, еще раз нажать D - выйти в отображение текущего времени.
* - вход в меню.
Перемещение по меню A - вверх(и изменение значений), С - вниз(и изменение значений).
Если параметр не помещается на дисплее В - прокрутка параметра.
В - установить новое значение параметра.
# - выход из пунктов подменю и меню.
При вводе пароля 4 раскладки клавиатуры:
{'1', '2', '3', '4'},
{'5', '6', '7', '8'},
{'9', '0', 'A', 'B'},
{'*', '<', '#','>'}
{'C', 'D', 'E', 'F'},
{'G', 'H', 'I', 'J'},
{'K', 'L', 'M', 'N'},
{'*', '<', '#','>'}
{'O', 'P', 'Q', 'R'},
{'S', 'T', 'U', 'V'},
{'W', 'X', 'Y', 'Z'},
{'*', '<', '#','>'}
{' ', '-', '?', '!'},
{'@', '/', '(', ')'},
{'+', '=', '_', '%'},
{'*', '<', '#','>'}
Нижний ряд для редактирования:
* - смена раскладки клавиатуры на уровень ниже;
# - смена раскладки клавиатуры на уровень выше;
0 - удалить символ;
D - сохранить пароль.
*/
#include <LiquidCrystal_I2C.h>
#include "Keypad.h"
#include "Button.h"
#include "globalVar.h"
#include "sinchroTime.h"
#include "alarm.h"
#include "pirMotion.h"
#include "menu.h"
#include <EEPROM.h>
#define I2C_ADDR 0x27
#define LCD_COLUMNS 16
#define LCD_LINES 2
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
//RTC_DS1307 rtc;
const byte Rows= 4; // количество строк на клавиатуре
const byte Cols= 4; // количество столбцов на клавиатуре
// определяем массив символов соответствующий распределению кнопок на клавиатуре:
char keymap[Rows][Cols]=
{
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#','D'}
};
// соединения клавиатуры с выводами Arduino:
byte rPins[Rows]= {19, 18, 5, 17};
byte cPins[Cols]= {16, 4, 0, 2};
// создаем объект класса Keypad
Keypad kpd= Keypad(makeKeymap(keymap), rPins, cPins, Rows, Cols);
const char* ssid = "Wokwi-GUEST";
const char* password = "";
bool connectWiFi = 0;
DateTime now;
volatile bool httpRead = true;
const int mainLightSwitch_1 = 34;
const int mainLightSwitch_2 = 35;
const int mainLightRelay = 23;
const int nightLightingRelay = 15;
volatile bool mainLight = false;
volatile bool nightLight = false;
bool mainLighOn = true;
bool nightLightingOn = true;
const int buzer = 25;
const int additional_load = 26;
int mainLightStart = 25200;
int mainLightEnd = 82800;
int durationDaly = 10;
int nightLightingStart = 82800; //23 часа в сек
int nightLightingEnd = 25200;
int durationNighty = 10;
volatile bool show_menu_or_clock = true;
int AlarmDuration = 20;
int LoadDuration = 10;
bool render = true;
void menuNavigation();
volatile int Sheet = 0;
const int DEBOUNCE_TIME = 10;
const int pire = 32;
LcdMenu lmenu(lcd, kpd);
Button but1(mainLightSwitch_1, DEBOUNCE_TIME);
Button but2(mainLightSwitch_2, DEBOUNCE_TIME);
SinchroTime sinchTim (rtc);
PirMotion pirSensor(32, mainLightRelay, nightLightingRelay);
int init_addr = 0; // адрес первой ячейки и для ключа
byte init_key = 50;
void init_memory();
void setup()
{
pinMode( mainLightRelay, OUTPUT);
digitalWrite( mainLightRelay, LOW);
pinMode( nightLightingRelay, OUTPUT);
digitalWrite( nightLightingRelay, LOW);
pinMode (additional_load, OUTPUT);
pinMode(buzer,OUTPUT);
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
abort();
}
Serial.begin(115200);
lcd.init();
lcd.begin(16, 2);
lcd.backlight();
kpd.setHoldTime(200);
init_memory();
lmenu.MenuSetup();
}
void loop(){
if(!sinchTim.sinchron||connectWiFi){
sinchTim.sinchronic(ssid, password);
if(connectWiFi){
lcd.clear();
if(sinchTim.sinchron){
lcd.print("WiFi connected");
lcd.setCursor (0,1);
lcd.print("Pres any key");
kpd.waitForKey();
}
else{
lcd.print("Unable to connect");
lcd.setCursor (0,1);
lcd.print("Pres any key");
kpd.waitForKey();
}
}
if(!sinchTim.sinchron && (sinchTim.dayPassed==0)){
rtc.adjust(DateTime(2024, 1, 1, 0, 0, 0));
sinchTim.sinchron = true;
}
now = rtc.now();
sinchTim.dayPassed = now.day();
connectWiFi = false;
}
if((now.day() - sinchTim.dayPassed) > 1) {
sinchTim.sinchron = false;
Serial.print("sinchTim.dayPassed: ");
Serial.println(sinchTim.dayPassed);
}
if(show_menu_or_clock){
DateTime now = rtc.now(); // Read data from the RTC Chip
lcd.noBlink();
lcd.setCursor(1,0);
lcd.print(lmenu.tim.show_s(now.day(), now.month(), now.year(),1)+' ' + lmenu.tim.daysOfTheWeek[now.dayOfTheWeek()]);
lcd.setCursor (4,1);
if(lmenu.tim.alarm_flag == 1)
lcd.print(String(lmenu.tim.show_s(now.hour(),now.minute(),now.second(),0)+" o"));
else
lcd.print(String(lmenu.tim.show_s(now.hour(),now.minute(),now.second(),0)+" x"));
}
else if(render&&(Sheet==0)){
lmenu.DrawMenu();
render = false;
}
else if(render&&(Sheet==18)){
lmenu.DrawSheet18();
render = false;
}
menuNavigation();
if(but1.isPressed ()){
mainLight = !mainLight;
digitalWrite( mainLightRelay, mainLight);
}
if(but2.isPressed ()){
mainLight = !mainLight;
digitalWrite( mainLightRelay, mainLight);
}
pirSensor.pirActiv(now);
lmenu.tim.alarm(mainLightRelay, additional_load, AlarmDuration, LoadDuration);
}
void menuNavigation() {
switch (Sheet){
case 0:{
char key = kpd.getKey();
if (key == '*'){
if(show_menu_or_clock){
show_menu_or_clock = !show_menu_or_clock;
render = true;
}
}
else if(!show_menu_or_clock && key == '#'){
bool exit = lmenu.LeftPress();
if(exit){
show_menu_or_clock = 1;
lcd.clear();
}
else render = true;
}
if(!show_menu_or_clock && key == 'A'){
lmenu.UpPress();
render = true;
}
if(!show_menu_or_clock && key == 'C'){
lmenu.DownPress();
render = true;
}
if(!show_menu_or_clock && key == 'B'){
lmenu.RightPress();
render = true;
}
if(key == 'D'){
lcd.clear();
lcd.setCursor(3,0);
lcd.print("Alarm Clock");
lmenu.tim.formatPrint(lmenu.tim.ch, lmenu.tim.cmi, lmenu.tim.cs);
show_menu_or_clock = !show_menu_or_clock;
if(show_menu_or_clock) render = true;
else render = false;
}
if(kpd.getState()==HOLD){
noTone(buzer);
digitalWrite(mainLightRelay, LOW);
}
break;
}
case 18:{
char key = kpd.getKey();
if (key == '*'){
if(show_menu_or_clock){
show_menu_or_clock = !show_menu_or_clock;
render = true;
}
}
else if(!show_menu_or_clock && key == '#'){
bool exit = lmenu.LeftPress18();
if(exit) show_menu_or_clock = 1;
else render = true;
}
if(!show_menu_or_clock && key == 'A'){
lmenu.UpPress18();
render = true;
}
if(!show_menu_or_clock && key == 'C'){
lmenu.DownPress18();
render = true;
}
if(!show_menu_or_clock && key == 'B'){
lmenu.RightPress18();
render = true;
}
break;
}
}
}
void init_memory(){
EEPROM.begin(100);
if (EEPROM.read(init_addr) != init_key){ // первый запуск
int addr = init_addr;
EEPROM.write(addr, init_key); // записали ключ
addr = addr + 1;
EEPROM.put(addr, ssid);
addr = addr + 20;
EEPROM.put(addr, password);
addr = addr + 20;
EEPROM.put(addr, true);//ActivDay on/mainLighOn
addr = addr + 1;
EEPROM.put(addr, durationDaly);
addr = addr + 4;
EEPROM.put(addr, mainLightStart);
addr = addr + 4;
EEPROM.put(addr, mainLightEnd);
addr = addr + 4;
EEPROM.put(addr, true);//ActivNight on/nightLightingOn
addr = addr + 1;
EEPROM.put(addr, durationNighty);
addr = addr + 4;
EEPROM.put(addr, nightLightingStart);
addr = addr + 4;
EEPROM.put(addr, nightLightingEnd);
addr = addr + 4;
EEPROM.put(addr, false);//tim.alarm_flag//ActivAlarm
addr = addr + 1;
EEPROM.put(addr, 25200);//Время будильника
addr = addr + 4;
EEPROM.put(addr, AlarmDuration);
addr = addr + 4;
EEPROM.put(addr, LoadDuration);
EEPROM.commit();
}
}