Доброго времени суток дамы и господа! Вы моя наверное последняя инстанция, не знаю куда дальше рыть, так как не понимаю в какую сторону. И так, имеется: солнечная на панель, аккумулятор наверное от трактора (12в, 190А/ч), UPS от компа, переделанный как инвертор на 600 вт, ну и ардуино с модулями. В итоге планировалось получить некое устройство в коробочке из губки для обуви, которое бы находилось у меня в гараже и имело следующий функционал:
- измерения напряжения аккумулятора и отключение всей нагрузки кроме ардуино при падении уровня заряда батареи ниже критического;
- ватметр (некий электросчетчик, чисто для меня чтобы знать сколько потратил «чистого» электричества);
- 3 задаваемого таймера на включение и выключение инвертора (включение насоса бассейна летом и новогодней иллюминации зимой)
- датчик bme280 для отображения сведений о температуре и влажности на дисплее и для отправки сведений на esp8266 с последующим предоставлением сведений в телеграмм канале.
Данные ватметра и таймеры записываются в EEprom c целью защиты от утери при зависании и перезагрузок.
Управление непосредственно на устройстве осуществляется с помощью 3х сенсорных кнопок используя долгое нажатие, клик и удержание, так же с помощью телеграмм канала, только для меня (сверка по id пользователя) предоставляются дополнительные кнопки на принудительное включение и выключение инвертора. Для остальных пользователей только выводится информация с датчика BME280.
И вроде схема работает, но по отдельности. Так к примеру, при подключении бме280 и дисплея я могу видеть на дисплее данные из бме280, при подключении ватметра и дисплея я могу видеть данные ватметра, но все вместе работать отказывается. При включении дисплей черный или с артефактами, перезагрузка не помогает. Почему так происходит не понимаю, так как ватметр подключается не по I2C и перехлест адресов не может быть в принципе.
Зная свои руки было решено заказать готовую плату на широко известном китайском предприятии. Пришла схема собрал, но видно от того что рядом с сенсорными кнопками у меня находятся резисторы, сенсорные кнопки при подключении начинают устраивать дискотеку (при срабатывании на модуле сенсорной кнопки загорается светодиод, так вот они на кнопках начинают часто и в перебой мигать без видимой последовательности при подаче питания на плату). Действительно ли резисторы так влияют на сенсорные кнопки? Если не так, то может кто поймет в чем проблема и подскажет как исправить? Если дело в резисторах, то знает ли кто как можно прикрепить обычную ардуиновскую кнопку с алишки надежно и более или менее симпатично?
Схема:
Распиновка площадки на схеме: 1) +5V; 2) gnd; 3) Tx ардуины; 4) Rx ардуины; 5) 3,3В для питания esp; 6) пин снятия данных с шунта; 7) SDA; 8) SCL; 9) пин вкл/выкл инвертора; 10) пин защиты аккумулятора от переразряда; 11) GND; 12) +12V.
Пин 7 и 8 используется для подключения датчика bme280 так как он выносится за пределы помещения для снятия уличных данных.
Получившаяся плата:
ну и на всякий случай выкладываю скетч проекта ардуины:
- измерения напряжения аккумулятора и отключение всей нагрузки кроме ардуино при падении уровня заряда батареи ниже критического;
- ватметр (некий электросчетчик, чисто для меня чтобы знать сколько потратил «чистого» электричества);
- 3 задаваемого таймера на включение и выключение инвертора (включение насоса бассейна летом и новогодней иллюминации зимой)
- датчик bme280 для отображения сведений о температуре и влажности на дисплее и для отправки сведений на esp8266 с последующим предоставлением сведений в телеграмм канале.
Данные ватметра и таймеры записываются в EEprom c целью защиты от утери при зависании и перезагрузок.
Управление непосредственно на устройстве осуществляется с помощью 3х сенсорных кнопок используя долгое нажатие, клик и удержание, так же с помощью телеграмм канала, только для меня (сверка по id пользователя) предоставляются дополнительные кнопки на принудительное включение и выключение инвертора. Для остальных пользователей только выводится информация с датчика BME280.
И вроде схема работает, но по отдельности. Так к примеру, при подключении бме280 и дисплея я могу видеть на дисплее данные из бме280, при подключении ватметра и дисплея я могу видеть данные ватметра, но все вместе работать отказывается. При включении дисплей черный или с артефактами, перезагрузка не помогает. Почему так происходит не понимаю, так как ватметр подключается не по I2C и перехлест адресов не может быть в принципе.
Зная свои руки было решено заказать готовую плату на широко известном китайском предприятии. Пришла схема собрал, но видно от того что рядом с сенсорными кнопками у меня находятся резисторы, сенсорные кнопки при подключении начинают устраивать дискотеку (при срабатывании на модуле сенсорной кнопки загорается светодиод, так вот они на кнопках начинают часто и в перебой мигать без видимой последовательности при подаче питания на плату). Действительно ли резисторы так влияют на сенсорные кнопки? Если не так, то может кто поймет в чем проблема и подскажет как исправить? Если дело в резисторах, то знает ли кто как можно прикрепить обычную ардуиновскую кнопку с алишки надежно и более или менее симпатично?
Схема:
Распиновка площадки на схеме: 1) +5V; 2) gnd; 3) Tx ардуины; 4) Rx ардуины; 5) 3,3В для питания esp; 6) пин снятия данных с шунта; 7) SDA; 8) SCL; 9) пин вкл/выкл инвертора; 10) пин защиты аккумулятора от переразряда; 11) GND; 12) +12V.
Пин 7 и 8 используется для подключения датчика bme280 так как он выносится за пределы помещения для снятия уличных данных.
Получившаяся плата:
ну и на всякий случай выкладываю скетч проекта ардуины:
C++:
#include <EEPROM.h>
#include <microDS3231.h>
MicroDS3231 rtc;
#define OLED_SOFT_BUFFER_64 // Буфер на стороне МК
#include <GyverOLED.h> // Библиотека дисплея
#include <GyverBME280.h> // библиотека датчика BME280
#include <GyverButton.h> // библиотека кнопок
#include <GyverUART.h>
GyverOLED<SSD1306_128x64, OLED_BUFFER> oled;
GyverBME280 bme;
GButton up(4, LOW_PULL); // Кнопки
GButton down(5, LOW_PULL);
GButton ok(3, LOW_PULL);
#define ITEMS 3 // Общее кол во пунктов (больше 8 - нужно несколько страниц)
#define Check220 6 // пин включения инвертора 220В
#define Health 7 // пин сохранения жизни аккумулятора панели и переключение при низком заряде на сеть 220В
#define PARSE_AMOUNT 4 // число значений в массиве, который хотим получить
#define INPUT_AMOUNT 80 // максимальное количество символов в пакете, который идёт в сериал
#define Volt A0 // пин измерения напряжения сети
#define Amp A1 // пин измерения падения напряжения, для измерения ампеража потребления
const char week_1[] PROGMEM = "Пн"; const char week_2[] PROGMEM = "Вт"; const char week_3[] PROGMEM = "Ср"; const char week_4[] PROGMEM = "Чт"; const char week_5[] PROGMEM = "Пт"; const char week_6[] PROGMEM = "Сб"; const char week_0[] PROGMEM = "Вс";
const char* const week[] PROGMEM = {week_1, week_2, week_3, week_4, week_5, week_6, week_0};
const char mesyac_1[] PROGMEM = "января"; const char mesyac_2[] PROGMEM = "февраля"; const char mesyac_3[] PROGMEM = "марта"; const char mesyac_4[] PROGMEM = "апреля"; const char mesyac_5[] PROGMEM = "мая"; const char mesyac_6[] PROGMEM = "июня";
const char mesyac_7[] PROGMEM = "июля"; const char mesyac_8[] PROGMEM = "августа"; const char mesyac_9[] PROGMEM = "сентября"; const char mesyac_10[] PROGMEM = "октября"; const char mesyac_11[] PROGMEM = "ноября"; const char mesyac_12[] PROGMEM = "декабря";
const char* const mesyac[] PROGMEM = {mesyac_1, mesyac_2, mesyac_3, mesyac_4, mesyac_5, mesyac_6, mesyac_7, mesyac_8, mesyac_9, mesyac_10, mesyac_11, mesyac_12};
bool flagTimer[] = {0, 0, 0}; //флаг был ли включен будильник
uint8_t timerminuk[] = {0, 0, 0}; //конец работы таймера (минуты)
uint8_t timerchask[] = {0, 0, 0}; //конец работы таймера (час)
uint8_t timerchasn[] = {0, 0, 0}; //начало работы таймера (час)
uint8_t timerminun[] = {0, 0, 0}; //начало работы таймера (минуты)
uint8_t addr = 0; // начальный адрес считывания с EEPROM
bool vkl = 0; //флаг включен таймер или нет
bool faccum = 0; //флаг сработала ли безопастность отключение источников от батарей
uint8_t cont = 255; // начальная яркость экрана
bool contr = 0; // флаг включено ли меню настройки яркости
uint32_t bmeup = 0; // опрос датчика bme раз в 2 секунды
uint32_t Wh = 0; // время для счетчика ватт*час
float Watt = 0; // переменная хранящая ватт*час
float temp; //переменная хранящая значение температуры
int Humidity; //переменная хранящая значение влажности
uint16_t davlen; //переменная хранящая значение атмосферного давления
bool disp = 0; //режим отображения дисплея
int16_t savedate = 0;
bool n=1; // может быть не нужна
void setup() {
uart.begin(9600);
bme.setMode(FORCED_MODE); //БМЕ будет работать в спящем режиме и просыпаться по запросу
bme.begin(); // Инциализация БМЕ
oled.init(); // Инциализация дисплея
oled.setContrast(cont); // Макс. яркость
pinMode(Check220, OUTPUT); // подключается паралельно к кнопке инвертора для вкл/выкл его по таймеру
pinMode(Health, OUTPUT); // подключается реле 220 аакума и сети по умолчанию открыт питание от аккума
digitalWrite(Check220, n);
digitalWrite(Health, HIGH);
bme.oneMeasurement(); // Просим датчик проснуться и сделать одно преобразование
while (bme.isMeasuring());
temp = bme.readTemperature();
Humidity = int(bme.readHumidity());
davlen = int(pressureToMmHg((bme.readPressure())));
ok.setTickMode(AUTO); //
up.setTickMode(AUTO); // кнопки опрашиваются автоматически
down.setTickMode(AUTO); //
ok.setTimeout(500);
recovery ();
savedate = rtc.getDate();
}
void loop() {
if (ok.isHolded()) { //вход в меню при удержании кнопки ок
menu();
}
if (up.isClick() || down.isClick()) {
disp = !disp;
}
if (down.isHolded()) { //потом удалить для проверки срабатывания безопастности
n=!n;
digitalWrite(Check220, n);
}
ammetr();
printTime(); //вывод инфы на дисплей
provBudil(); //проверка исполнения таймеров
saveAccum(); //проверка сохранения жизни аккумулятора панели и переключение при низком заряде на сеть 220В
peredacha (); //отправка данных на esp
}
void printTime() { // вывод главное экрана с временем и значениями
switch (disp) {
case 0: {
if (millis() - bmeup >= 2000) {
bme.oneMeasurement(); // Просим датчик проснуться и сделать одно преобразование
while (bme.isMeasuring());
temp = bme.readTemperature();
Humidity = int(bme.readHumidity());
davlen = int(pressureToMmHg((bme.readPressure())));
bmeup = millis();
}
DateTime now = rtc.getTime();
bool ftimer[3]; EEPROM.get(12, ftimer);
oled.clear(); // Очищаем буфер
oled.home();
oled.setScale(2);
if (now.hour < 10) oled.print(F("0"));
oled.print(now.hour);
oled.print(F(":"));
if (now.minute < 10) oled.print(F("0"));
oled.print(now.minute);
oled.print(F(":"));
if (now.second < 10) oled.print(F("0"));
oled.print(now.second);
printFromPGM(&week[now.day - 1]);
oled.println();
oled.setScale(1);
oled.print(F(" "));
oled.print(now.date);
oled.print(F(" "));
printFromPGM(&mesyac[now.month - 1]); //oled.print(now.month);
oled.print(F(" "));
oled.print(now.year);
oled.println(F("г."));
oled.setCursor(0, 4);
oled.print(F("Темп = "));
oled.print(temp, 1);
oled.println(F("*C"));
oled.print(F("Влажность = "));
oled.print(Humidity);
oled.println(F("%"));
oled.print(F("Давлен = "));
oled.print(davlen);
oled.println(F("mmHg"));
oled.print(F("сменить вид нажми +-"));
if (contr) {
oled.setCursor(0, 3);
oled.print(F("Яркость: "));
oled.invertText(true);
oled.print(cont / 10);
oled.invertText(false);
}
for (byte i = 0; i < 3; i++) {
if (flagTimer[i]) {
oled.setCursor(110, 3); oled.invertText(true); oled.print(F(" T ")); oled.invertText(false);
}
}
if(!n) {
oled.setCursor(85, 3); oled.invertText(true); oled.print(F(" Ин ")); oled.invertText(false);
}
oled.update();
if(faccum) {
oled.setCursor(70, 3); oled.invertText(true); oled.print(F(" ! ")); oled.invertText(false);
}
oled.update();
break;
}
case 1: {
oled.clear(); // Очищаем буфер
oled.home();
oled.setScale(1);
oled.print(F("Напряжение: ")); //напряжение сети
oled.print(analogRead(Volt) * 0.01464, 1);
oled.println(F("V"));
oled.print(F("потреб = "));
if (Watt > 1000) {
oled.print (Watt / 1000, 3);
oled.println(F(" kВт"));
}
else {
oled.print (Watt, 2);
oled.println(F(" Вт"));
}
oled.print(F("сила тока= "));
oled.print((analogRead(Amp) * 0.05922));
oled.println(F(" А"));
oled.print(F("сменить вид нажми +-"));
oled.update();
break;
}
}
}
void printFromPGM(int charMap) { //чтение данных из массивов progmem и вывод на экран
char buffer[24]; // буфер для хранения строки
uint16_t ptr = pgm_read_word(charMap); // получаем адрес из таблицы ссылок
uint8_t i = 0; // переменная - индекс массива буфера
do {
buffer[i] = (char)(pgm_read_byte(ptr++)); // прочитать символ из PGM в ячейку буфера, подвинуть указатель
} while (buffer[i++] != NULL); // повторять пока прочитанный символ не нулевой, подвинуть индекс буфера
oled.print(buffer);
} // печатаем готовую строку
void menu() { //меню настроек устройства
while (1) { //меню настроек при удержании кнопки ок
static int8_t pointer = 0; // Переменная указатель
/* Кнопки */
if (up.isClick() or up.isHold()) { // Если кнопку нажали или удерживают
pointer = constrain(pointer - 1, 0, ITEMS - 1); // Двигаем указатель в пределах дисплея
}
if (down.isClick() or down.isHold()) {
pointer = constrain(pointer + 1, 0, ITEMS - 1);
}
if (ok.isClick()) { // Нажатие на ОК - переход в пункт меню
switch (pointer) { // По номеру указателей располагаем вложенные функции (можно вложенные меню)
case 0: Budilnic(); break; // По нажатию на ОК при наведении на 0й пункт вызвать функцию
case 1: setVremya(); break;
case 2: Yarkoct(); break;
}
}
/* меню */
oled.clear(); // Очищаем буфер
oled.home(); // Курсор в левый верхний угол
oled.println (F(" SET таймер 220В"));
oled.println (F(" SET дата и время"));
oled.println (F(" Яркость экрана"));
printPointer(pointer); // Вывод указателя
oled.update(); // Выводим кадр на дисплей
provBudil(); //проверка исполнения таймеров
saveAccum(); //проверка сохранения жизни аккумулятора панели и переключение при низком заряде на сеть 220В
peredacha ();
ammetr();
if (ok.isHolded()) return;
}
}
void printPointer(uint8_t pointer) { //отображеие курсора в меню
oled.setCursor(0, pointer);
oled.print(">");
}
void setVremya (void) { //раздел меню Set дата и время, установка текущей даты и времени
DateTime now = rtc.getTime();
int8_t sec = now.second; int8_t minu = now.minute; int8_t chas = now.hour; int8_t den = now.date; int8_t mes = now.month; int16_t god = now.year;
int8_t fmesto = 0; bool save = 0;
while (1) {
provBudil(); //проверка исполнения таймеров
saveAccum(); //проверка сохранения жизни аккумулятора панели и переключение при низком заряде на сеть 220В
peredacha ();
ammetr();
if (ok.isHolded()) { //при удержании кнопки ок выход с сохранением если настройка времени в сохраняется или без сохранения
if (save) {
rtc.setTime(sec, minu, chas, den, mes, god);
return;
} else {
return;
}
}
if (ok.isClick()) { // при клике ок меняется что будет изменяться
fmesto++;
}
if (fmesto >= 6) { //при клике ок на последнем настраиваемом пункте возвращается на первый
fmesto = 0;
}
if (up.isClick() or up.isHold()) { // клик или удержание кнопки вверх увеличивает значение с проверкой предотвращающей неправильные значения
switch (fmesto) {
case 0: {
chas++;
if (chas >= 24) {
chas = 0;
};
break;
}
case 1: {
minu++;
if (minu >= 60) {
minu = 0;
};
break;
}
case 2: {
den++;
if (den >= provdate(mes, god) + 1) {
den = 1;
};
break;
}
case 3: {
mes++;
if (mes >= 13) {
mes = 1;
};
break;
}
case 4: {
god++;
if (god >= 2101) {
god = 2020;
};
break;
}
case 5: {
save = !save;
break;
}
}
}
if (down.isClick() or down.isHold()) { // клик или удержание кнопки вниз уменьшает значение значение с проверкой предотвращающей неправильные значения
switch (fmesto) {
case 0: {
if (chas == 0) {
chas = 23;
} else {
chas--;
} break;
}
case 1: {
if (minu == 0) {
minu = 59;
} else {
minu--;
} break;
}
case 2: {
if (den == 1) {
den = provdate(mes, god);
} else {
den--;
} break;
}
case 3: {
if (mes == 1) {
mes = 12;
} else {
mes--;
} break;
}
case 5: {
save = !save;
break;
}
}
}
oled.clear(); // далее до конца функции код вывода инфы на дисплей
oled.home();
oled.println(F(" установка времени"));
oled.setCursor (7, 2);
if (fmesto == 0) oled.invertText(true);
if (chas < 10) oled.print(F("0"));
oled.print(chas);
oled.invertText(false);
oled.print(F(":"));
if (fmesto == 1) oled.invertText(true);
if (minu < 10) oled.print(F("0"));
oled.print(minu);
oled.invertText(false);
oled.print(F(":0"));
oled.print(sec);
oled.setCursor (2, 4);
if (fmesto == 2) oled.invertText(true);
oled.print(den);
oled.invertText(false);
oled.print(F(" "));
if (fmesto == 3) oled.invertText(true);
printFromPGM(&mesyac[mes - 1]);
oled.invertText(false);
oled.print(F(" "));
if (fmesto == 4) oled.invertText(true);
oled.print(god);
oled.invertText(false);
oled.print(F("г."));
if (fmesto == 5) oled.invertText(true);
if (save) {
oled.setCursor(5, 6);
oled.print(F("Сохранить"));
} else {
oled.setCursor(4, 6);
oled.print(F("не сохранять"));
}
oled.invertText(false);
oled.update();
}
}
int provdate(int mes, int god) { //проверка в каком месяце сколько дней
byte den;
switch (mes) {
case 1: {
den = 31;
break;
}
case 2: {
if (god % 4 == 0) {
den = 29;
} else {
den = 28;
} break;
}
case 3: {
den = 31;
break;
}
case 4: {
den = 30;
break;
}
case 5: {
den = 31;
break;
}
case 6: {
den = 30;
break;
}
case 7: {
den = 31;
break;
}
case 8: {
den = 31;
break;
}
case 9: {
den = 30;
break;
}
case 10: {
den = 31;
break;
}
case 11: {
den = 30;
break;
}
case 12: {
den = 31;
break;
}
}
return den;
}
void Budilnic() { //раздел меню SET таймер 220В, установка таймеров на включение и выключение 220В
int8_t minu[] = {timerminun[0], timerminun[1], timerminun[2]}; int8_t chas[] = {timerchasn[0], timerchasn[1], timerchasn[2]}; //проставляем текущее время во время включения таймера
int8_t timinu[] = {timerminuk[0], timerminuk[1], timerminuk[2]}; int8_t tichas[] = {timerchask[0], timerchask[1], timerchask[2]}; //инициализируем временной интервал таймера (сколько работать)
int8_t fmesto = 0; bool save[] = {0, 0, 0}; int8_t timnomer = 0; bool fTimer[] = {flagTimer[0], flagTimer[1], flagTimer[2]};
while (1) {
provBudil(); //проверка исполнения таймеров
saveAccum(); //проверка сохранения жизни аккумулятора панели и переключение при низком заряде на сеть 220В
peredacha ();
ammetr();
if (ok.isHolded()) {
for (byte i = 0; i < 3; i++) { // сохранение и выход на меню вверх
flagTimer[i] = fTimer[i];
timerminuk[i] = timinu[i];
timerchask[i] = tichas[i];
timerchasn[i] = chas[i];
timerminun[i] = minu[i];
}
EEPROM.put(addr, timerminuk); addr += sizeof(timerminuk);
EEPROM.put(addr, timerchask); addr += sizeof(timerchask);
EEPROM.put(addr, timerchasn); addr += sizeof(timerchasn);
EEPROM.put(addr, timerminun); addr += sizeof(timerminun);
EEPROM.put(addr, flagTimer); addr = 0; return;
}
if (ok.isClick()) {
fmesto++;
}
if (fmesto >= 7) {
fmesto = 0;
}
if (up.isClick() or up.isHold()) {
switch (fmesto) {
case 0: {
timnomer++;
if (timnomer >= 3) {
timnomer = 0;
};
break;
}
case 1: {
fTimer[timnomer] = !fTimer[timnomer];
break;
}
case 2: {
chas[timnomer]++;
if (chas[timnomer] >= 24) {
chas[timnomer] = 0;
};
break;
}
case 3: {
minu[timnomer]++;
if (minu[timnomer] >= 60) {
minu[timnomer] = 0;
};
break;
}
case 4: {
tichas[timnomer]++;
if (tichas[timnomer] >= 24) {
tichas[timnomer] = 0;
};
break;
}
case 5: {
timinu[timnomer]++;
if (timinu[timnomer] >= 60) {
timinu[timnomer] = 0;
};
break;
}
case 6: {
save[timnomer] = !save[timnomer];
break;
}
}
}
if (down.isClick() or down.isHold()) {
switch (fmesto) {
case 0: {
if (timnomer == 0) {
timnomer = 2;
} else {
timnomer--;
} break;
}
case 1: {
fTimer[timnomer] = !fTimer[timnomer];
break;
}
case 2: {
if (chas[timnomer] == 0) {
chas[timnomer] = 23;
} else {
chas[timnomer]--;
} break;
}
case 3: {
if (minu[timnomer] == 0) {
minu[timnomer] = 59;
} else {
minu[timnomer]--;
} break;
}
case 4: {
if (tichas[timnomer] == 0) {
tichas[timnomer] = 23;
} else {
tichas[timnomer]--;
} break;
}
case 5: {
if (timinu[timnomer] == 0) {
timinu[timnomer] = 59;
} else {
timinu[timnomer]--;
} break;
}
case 6: {
save[timnomer] = !save[timnomer];
break;
}
}
}
oled.clear(); // очистить
oled.home();
oled.println(F(" установка"));
oled.println(F(" электротаймера"));
oled.print(F("таймер N. "));
if (fmesto == 0) oled.invertText(true);
oled.println(timnomer + 1);
oled.invertText(false);
oled.print(F("Таймер: "));
if (fmesto == 1) oled.invertText(true);
if (fTimer[timnomer]) {
oled.println("ВКЛ!");
}
else {
oled.println("ВЫКЛ");
}
oled.invertText(false);
oled.print(F("Вкл. в: "));
if (fmesto == 2) oled.invertText(true);
if (chas[timnomer] < 10) oled.print(F("0"));
oled.print(chas[timnomer]);
oled.invertText(false);
oled.print(F("ч."));
if (fmesto == 3) oled.invertText(true);
if (minu[timnomer] < 10) oled.print(F("0"));
oled.print(minu[timnomer]);
oled.invertText(false);
oled.println(F("м."));
oled.print(F("Выкл. в: "));
if (fmesto == 4) oled.invertText(true);
if (tichas[timnomer] < 10) oled.print(F("0"));
oled.print(tichas[timnomer]);
oled.invertText(false);
oled.print(F("ч."));
if (fmesto == 5) oled.invertText(true);
if (timinu[timnomer] < 10) oled.print(F("0"));
oled.print(timinu[timnomer]);
oled.invertText(false);
oled.println(F("м."));
if (fmesto == 6) oled.invertText(true);
if (save[timnomer]) {
oled.setCursor(5, 7);
oled.print(F("Сохранить"));
} else {
oled.setCursor(4, 7);
oled.print(F("не сохранять"));
}
oled.invertText(false);
oled.update();
}
}
void provBudil() { //проверка не наступило ли время включенных таймеров и исполнение их
DateTime now = rtc.getTime();
int8_t minu = now.minute; int8_t chas = now.hour;
EEPROM.get(addr, timerminuk); addr += sizeof(timerminuk);
EEPROM.get(addr, timerchask); addr += sizeof(timerchask);
EEPROM.get(addr, timerchasn); addr += sizeof(timerchasn);
EEPROM.get(addr, timerminun); addr += sizeof(timerminun);
EEPROM.get(addr, flagTimer); addr = 0;
for (byte i = 0; i < 3; i++) {
if (flagTimer[i] && chas == timerchasn[i] && minu == timerminun[i] && !vkl) {
n=0;
digitalWrite(Check220, n);
vkl = !vkl;
}
if (flagTimer[i] && chas == timerchask[i] && minu == timerminuk[i] && vkl) {
n=1;
digitalWrite(Check220, n);
vkl = !vkl;
}
}
}
void Yarkoct() { //изменение яркости экрана
contr = 1;
while (1) {
oled.setContrast(cont);
printTime();
provBudil(); //проверка исполнения таймеров
saveAccum(); //проверка сохранения жизни аккумулятора панели и переключение при низком заряде на сеть 220В
peredacha ();
ammetr();
if (ok.isHolded()) {
contr = 0;
return;
}
if (up.isClick() or up.isHold()) {
if (cont > 245) {
cont = 255;
}
else cont += 10;
}
if (down.isClick() or down.isHold()) {
if (cont < 10) {}
else cont -= 10;
}
}
}
void peredacha () { //передача данных в ESP8266
int dataArray[1];
String dacha;
int bigwatt=0;
int minwatt=0;
if (uart.parsePacket((int*)dataArray)) {
switch (dataArray[0]) {
case 0: { //0 инвертор включен потому что открывает ключ земля
n=0;
digitalWrite(Check220, n);
break;
}
case 1: { //1 инвертор выключен на пине питание
n=1;
digitalWrite(Check220, n);
break;
}
}
if (Watt>32767){
bigwatt= Watt/32767;
minwatt=Watt-(long)(32767*bigwatt);
}
else {minwatt=(int)Watt;}
String dacha = "$"+ String(int(temp* 10)) + " " + String(int(Humidity)) + " " + String(int(davlen)) + " " + String(int(analogRead(Volt) * 0.01464*10))+" "+ String(int(analogRead(Amp) * 0.05922 * 100)) + " " +String(int(minwatt)) + " " + String(int(bigwatt))+ " "+ String(n) + " "+String(faccum)+";";
saveznach ();
uart.print(dacha); //вернуть на просто принт
}
}
void saveAccum() { //проверка сохранения жизни аккумулятора панели и переключение при низком заряде на сеть 220В
if ((analogRead(Volt) * 0.01464) < 11 && !faccum) {
digitalWrite(Health, LOW);
faccum = !faccum;
}
if ((analogRead(Volt) * 0.01464) > 12.5 && faccum) {
digitalWrite(Health, HIGH);
faccum = !faccum;
}
}
void ammetr() { //расчет ватт * час
Watt = Watt + (((analogRead(Volt) * 0.01464) * (analogRead(Amp) * 0.05922)) * (millis() - Wh) / 3600000);
Wh = millis();
saveznach ();
}
void saveznach () { //сохраняет в EEPROM значение ватт*час и количество запросов при смене даты
float vremwatt;
uint32_t schetzapr;
if (rtc.getDate() != savedate) {
EEPROM.get(15, vremwatt);
if (vremwatt > Watt) {
Watt = vremwatt + Watt;
EEPROM.put(15, Watt);
}
else {
EEPROM.put(15, Watt);
}
}
}
void recovery () { //проверка целостности данных EEPROM
uint8_t recovery[] = {0, 0, 0}; // если в EEPROM некорректные данные переменная для сохранения в EEPROM значений по умолчанию
bool recflagTimer[] = {0, 0, 0}; // если в EEPROM некорректные данные переменная для сохранения в EEPROM значений по умолчанию (флаги)
float watik = 0;
EEPROM.get(addr, timerminuk);
for (byte i = 0; i < 3; i++) {
if (timerminuk[i] < 0 || timerminuk[i] > 59) {
EEPROM.put(addr, recovery);
}
}
addr += sizeof(timerminuk);
EEPROM.get(addr, timerchask);
for (byte i = 0; i < 3; i++) {
if (timerchask[i] < 0 || timerchask[i] > 23) {
EEPROM.put(addr, recovery);
}
}
addr += sizeof(timerchask);
EEPROM.get(addr, timerchasn);
for (byte i = 0; i < 3; i++) {
if (timerchasn[i] < 0 || timerchasn[i] > 23) {
EEPROM.put(addr, recovery);
}
}
addr += sizeof(timerchasn);
EEPROM.get(addr, timerminun);
for (byte i = 0; i < 3; i++) {
if (timerminun[i] < 0 || timerminun[i] > 59) {
EEPROM.put(addr, recovery);
}
}
addr += sizeof(timerminun);
EEPROM.get(addr, flagTimer);
for (byte i = 0; i < 3; i++) {
if (flagTimer[i] < 0 || flagTimer[i] > 1) {
EEPROM.put(addr, recflagTimer);
}
}
addr += sizeof(flagTimer);
EEPROM.get(addr, watik);
if (watik < 0) {
EEPROM.put(addr, 0);
}
addr += sizeof(watik);
addr = 0;
}