здравствуйте, у меня проблема с работой, я связал мегу и w5100, блинк находится у меня на сервере, проблема в том что в какое-то время он работает хорошо, но когда начинаю менять настройки через приложение, то блинк выходит из сети и останавливает мега, пока не перезапущу все, не работает.
I think we need to see your code, and understand which widgets you have in the app and which pins these widgets are connected to.
Pete.
#define pin_SW_SDA 22
#define pin_SW_SCL 23
#define BLYNK_PRINT Serial
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#include <iarduino_RTC.h>
#include <SPI.h>
#include <Ethernet.h>
#include <BlynkSimpleEthernet.h>
LiquidCrystal_I2C lcd(0x3F, 20, 4);
iarduino_RTC watch(RTC_DS3231);
BlynkTimer timer;
// Настройки
#define W5100_CS 10
#define auth "89b98dd34c114df4b0e693567453a346"
#define channel_count 5 // Кол-во каналов
#define pump_count 2 // Кол-во насосов
byte pump_pin[pump_count] = {26, 27}; // Пины насосов
byte pump_valve_pin[pump_count][channel_count] = {{30, 31, 32, 33}, {34}}; // Привязка пинов клапанов к насосам {{Первый насос (26)}, {Второй насос (27)}}
// Blynk
byte status_display[channel_count] = {V0, V1, V2, V3, V4}; // "Value Display" (Вывод состояния канала)
byte watering_select[channel_count] = {V5, V6, V7, V8, V9}; // "Numeric Input" (Выбор полива для редактирования)
byte time_select[channel_count] = {V10, V11, V12, V13, V14}; // "Time Input" (Установка времени выбранного полива)
byte on_off[channel_count] = {V15, V16, V17, V18, V19}; // "Button" (Включение/отключение выбранного полива)
byte manual_time_select[channel_count] = {V20, V21, V22, V23, V24}; // "Time Input" (Установка времени ручного полива)
byte manual_on_off[channel_count] = {V25, V26, V27, V28, V29}; // "Button" (Включение/отключение ручного полива)
WidgetTerminal terminal[channel_count] = {V30, V31, V32, V33, V34}; // "Terminal" (Вывод списка поливов)
String notify_text[channel_count] = {
"Канал 1: полив завершен",
"Канал 2: полив завершен",
"Канал 3: полив завершен",
"Канал 4: полив завершен",
"Канал 5: полив завершен"
};
// Blynk
// Кнопки
#define page_selection 38 // Кнопка смены страницы (состояние, канал 1, канал 2)
#define page_page_selection 39 // Кнопка смены страницы внутри страницы (страницы состояния, ручного полива и времени)
#define item_selection 40 // Кнопка смены строки со значениями (номера каналов и поливов)
#define value_selection 41 // Кнопка выбора значения (часы, минуты, дни)
#define value_up 42 // Кнопка увеличения значения
#define value_down 43 // Кнопка уменьшения значения
#define universal 44 // Общая кнопка (описание ниже)
/*
страница состояния - показывает оставшееся до полива время
страница ручного полива - включает полив на выбранном канале
страница времени поливов - включает/отключает выбранный полив
страница дней поливов - включает/отключает выбранный день
*/
// Кнопки
#define default_time_set 0 // Установка времени поливов по умолчанию (прошить так, после изменить на 0 и перепрошить)
//#define valve_delay 1 // Пауза между открытием клапана и включением насоса при начале полива (сек.)
// Настройки
struct time_struct {
byte h;
byte m;
byte s;
byte day;
};
struct watering_time_struct {
byte time_h;
byte time_m;
byte duration_m;
byte duration_s;
bool on_off;
};
struct next_watering_struct {
long time;
long duration;
byte day;
byte left;
};
struct watering_on_struct {
long time;
long duration;
};
struct watering_time_left_struct {
byte h;
byte m;
byte s;
};
struct duration_time_left_struct {
byte m;
byte s;
};
time_struct time;
watering_time_struct watering_time[channel_count][20];
next_watering_struct next_watering[channel_count];
watering_time_left_struct watering_time_left[channel_count];
duration_time_left_struct duration_time_left[channel_count];
duration_time_left_struct manual_watering[channel_count];
duration_time_left_struct manual_watering_left[channel_count];
byte rus_l[8] = {0b00100, 0b01010, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b00000};
byte rus_ia[8] = {0b11111, 0b10001, 0b10001, 0b11111, 0b00101, 0b01001, 0b10001, 0b00000};
byte rus_d[8] = {0b01110, 0b01010, 0b01010, 0b01010, 0b01010, 0b11111, 0b10001, 0b00000};
byte rus_i[8] = {0b10001, 0b10001, 0b10011, 0b10101, 0b11001, 0b10001, 0b10001, 0b00000};
byte rus_p[8] = {0b11111, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b00000};
byte rus_ch[8] = {0b10001, 0b10001, 0b10001, 0b11111, 0b00001, 0b00001, 0b00001, 0b00000};
byte rus_b[8] = {0b11111, 0b10000, 0b10000, 0b11111, 0b10001, 0b10001, 0b11111, 0b00000};
byte rus_u[8] = {0b10001, 0b10001, 0b10001, 0b01010, 0b00100, 0b01000, 0b10000, 0b00000};
byte full[8] = {0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};
byte on[8] = {0b00000, 0b00100, 0b00100, 0b10101, 0b10101, 0b10001, 0b01110, 0b00000};
byte underline[8] = {0b11111, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000};
byte e[8] = {0b00011, 0b00010, 0b00011, 0b00010, 0b00011, 0b00000, 0b00000, 0b00000};
byte page;
byte page_page;
byte watering_on_count[channel_count];
byte watering_day_count[channel_count];
byte value_selected;
byte item_selected;
byte channel;
byte watering_num[channel_count];
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
byte first_notify;
bool page_selection_flag;
bool page_page_selection_flag;
bool item_selection_flag;
bool value_selection_flag;
bool value_up_flag;
bool value_down_flag;
bool universal_flag;
bool set_char_flag;
bool manual_watering_state[channel_count];
bool watering_mode[channel_count];
bool show_left;
bool lcd_clear_flag[channel_count];
bool blink_state;
bool days[channel_count][7];
bool pump_valve_state[pump_count][channel_count];
bool page_selection_time_flag;
bool no_watering[channel_count];
bool blynk_connect_failed;
bool notify_flag[channel_count];
bool first_notify_flag;
bool e_lcd_clear_flag;
bool last_action_flag;
unsigned long blink_time;
unsigned long manual_watering_time[channel_count];
//unsigned long valve_delay_time[channel_count];
unsigned long watering_start_time[channel_count];
unsigned long page_selection_time;
unsigned long time_last[channel_count];
unsigned long notify_time;
unsigned long last_action_time;
String selected_day_str[channel_count];
void setup() {
lcd.begin();
lcd.backlight();
watch.begin();
Ethernet.begin(mac, 10000);
Blynk.config("мой сервер" 8080);
Blynk.connect(10000);
Serial.begin(9600);
timer.setInterval(300000, blynk_reconnect);
for (int i = 0; i < pump_count; i++) {
pinMode(pump_pin[i], OUTPUT);
for (int j = 0; j < channel_count; j++) {
pinMode(pump_valve_pin[i][j], OUTPUT);
}
}
pinMode(page_selection, INPUT_PULLUP);
pinMode(page_page_selection, INPUT_PULLUP);
pinMode(item_selection, INPUT_PULLUP);
pinMode(value_selection, INPUT_PULLUP);
pinMode(value_up, INPUT_PULLUP);
pinMode(value_down, INPUT_PULLUP);
pinMode(universal, INPUT_PULLUP);
//watch.settime(0, 53, 18, 20, 6, 20, 6); // Прошить так, после этого закомментировать эту строку и прошить ещё раз (описание ниже)
/*
Секунды, минуты, часы, день, номер месяца, год (две последние цифры), день недели:
0 - воскресенье
1 - понедельник
2 - вторник
3 - среда
4 - четверг
5 - пятница
6 - суббота
*/
#if default_time_set
for (int i = 0; i < channel_count; i++) {
for (int j = 0; j < 20; j++) {
EEPROM.update((j * 5) + (i * 100), j + 1);
EEPROM.update((j * 5) + (i * 100) + 1, 0);
EEPROM.update((j * 5) + (i * 100) + 2, 30);
EEPROM.update((j * 5) + (i * 100) + 3, 0);
EEPROM.update((j * 5) + (i * 100) + 4, 0);
}
for (int j = 0; j < 7; j++) {
EEPROM.update((channel_count * 100) + (i * 7) + j, 0);
}
EEPROM.update((channel_count * 100) + (channel_count * 7) + (i * 2), 1);
EEPROM.update((channel_count * 100) + (channel_count * 7) + (i * 2) + 1, 0);
}
#endif
for (int i = 0; i < channel_count; i++) {
for (int j = 0; j < 20; j++) {
watering_time[i][j].time_h = EEPROM.read((j * 5) + (i * 100));
watering_time[i][j].time_m = EEPROM.read((j * 5) + (i * 100) + 1);
watering_time[i][j].duration_m = EEPROM.read((j * 5) + (i * 100) + 2);
watering_time[i][j].duration_s = EEPROM.read((j * 5) + (i * 100) + 3);
watering_time[i][j].on_off = EEPROM.read((j * 5) + (i * 100) + 4);
}
for (int j = 0; j < 7; j++) {
days[i][j] = EEPROM.read((channel_count * 100) + (i * 7) + j);
}
manual_watering[i].m = EEPROM.read((channel_count * 100) + (channel_count * 7) + (i * 2));
manual_watering[i].s = EEPROM.read((channel_count * 100) + (channel_count * 7) + (i * 2) + 1);
if (Blynk.connected()) {
show_watering_time(i);
Blynk.virtualWrite(manual_time_select[i], (int(manual_watering[i].m) * 60) + manual_watering[i].s, 0, "Europe/Moscow");
Blynk.virtualWrite(manual_on_off[i], LOW);
}
get_selected_day(i);
}
Serial.println(watch.gettime("d-m-Y, H:i:s, D"));
}
void loop() {
watch.gettime();
time.h = watch.Hours;
time.m = watch.minutes;
time.s = watch.seconds;
time.day = watch.weekday;
get_next_watering();
if (!digitalRead(page_selection) && !page_selection_time_flag) {
page_selection_flag = true;
if (millis() - page_selection_time >= 1000) {
page = 0;
page_page = 0;
value_selected = 0;
item_selected = 0;
set_char_flag = false;
blink_state = false;
page_selection_flag = false;
page_selection_time_flag = true;
lcd.clear();
}
}
else if (digitalRead(page_selection) && page_selection_flag) {
page_selection_flag = false;
page < (channel_count * 2) + 1 ? page++ : page = 0;
if (page > 1 && page < channel_count + 2) {
channel = page - 2;
}
else if (page > channel_count + 1 && page < (channel_count * 2) + 2) {
channel = page - (channel_count + 2);
}
page_page = 0;
value_selected = 0;
item_selected = 0;
set_char_flag = false;
blink_state = false;
blink_time = millis();
page_selection_time = millis();
last_action_time = millis();
last_action_flag = false;
lcd.clear();
}
else if (digitalRead(page_selection)) {
page_selection_time = millis();
page_selection_time_flag = false;
}
if (page == 0) {
if (!set_char_flag) {
set_char_flag = true;
set_char(rus_p, rus_ch, rus_b, rus_u, rus_l, rus_i, e);
}
if (!digitalRead(page_page_selection) && !page_page_selection_flag) {
page_page_selection_flag = true;
if (channel_count > 3) {
if (channel_count % 3) {
page_page < ceil(channel_count / 3) ? page_page++ : page_page = 0;
}
else
{
page_page < ceil(channel_count / 3) - 1 ? page_page++ : page_page = 0;
}
}
lcd.clear();
}
else if (digitalRead(page_page_selection) && page_page_selection_flag) {
page_page_selection_flag = false;
}
String day_name;
switch (time.day) {
case 0: day_name = "BC"; break;
case 1: day_name = "\1H"; break;
case 2: day_name = "BT"; break;
case 3: day_name = "CP"; break;
case 4: day_name = "\2T"; break;
case 5: day_name = "\1T"; break;
case 6: day_name = "C\3"; break;
}
lcd.setCursor(1, 0);
lcd.print("COCT (");
lcd.print(time.h < 10 ? "0" + String(time.h) + ":" : String(time.h) + ":");
lcd.print(time.m < 10 ? "0" + String(time.m) + ":" : String(time.m) + ":");
lcd.print(time.s < 10 ? "0" + String(time.s) : String(time.s));
lcd.print(" " + day_name + ")");
if(blynk_connect_failed){
if(!e_lcd_clear_flag){
e_lcd_clear_flag = true;
lcd.clear();
}
}
else
{
lcd.print("\7");
e_lcd_clear_flag = false;
}
for (int i = 0; i < 3; i++) {
byte num = i + (page_page * 3);
if (num < channel_count) {
if (manual_watering_state[num]) {
lcd.setCursor(0, i + 1);
lcd.print(String(num + 1) + ")");
lcd.print("P\4\2 \1O\5\6B ");
lcd.print(manual_watering_left[num].m < 10 ? "0" + String(manual_watering_left[num].m) + "m:" : String(manual_watering_left[num].m) + "m:");
lcd.print(manual_watering_left[num].s < 10 ? "0" + String(manual_watering_left[num].s) + "s" : String(manual_watering_left[num].s) + "s");
}
else
{
if (watering_mode[num]) {
lcd.setCursor(0, i + 1);
lcd.print(String(num + 1) + ")");
lcd.print("\1O\5\6B ");
lcd.print(duration_time_left[num].m < 10 ? "0" + String(duration_time_left[num].m) + "m:" : String(duration_time_left[num].m) + "m:");
lcd.print(duration_time_left[num].s < 10 ? "0" + String(duration_time_left[num].s) + "s" : String(duration_time_left[num].s) + "s");
}
else
{
if (watering_on_count[num] > 0 && watering_day_count[num] > 0) {
if (!digitalRead(universal) && !universal_flag) {
universal_flag = true;
show_left = !show_left;
lcd.clear();
}
else if (digitalRead(universal) && universal_flag) {
universal_flag = false;
}
if (show_left) {
lcd.setCursor(0, i + 1);
lcd.print(String(num + 1) + ")");
lcd.print(watering_time_left[num].h < 10 ? "0" + String(watering_time_left[num].h) + "h:" : String(watering_time_left[num].h) + "h:");
lcd.print(watering_time_left[num].m < 10 ? "0" + String(watering_time_left[num].m) + "m:" : String(watering_time_left[num].m) + "m:");
lcd.print(watering_time_left[num].s < 10 ? "0" + String(watering_time_left[num].s) + "s" : String(watering_time_left[num].s) + "s");
}
else
{
byte next_watering_time_h = floor(next_watering[num].time / 3600);
byte next_watering_time_m = (next_watering[num].time % 3600) / 60;
byte next_watering_duration_m = (next_watering[num].duration % 3600) / 60;
byte next_watering_duration_s = next_watering[num].duration % 60;
lcd.setCursor(0, i + 1);
lcd.print(String(num + 1) + ")");
if (next_watering[num].left > 0) {
switch (next_watering[num].day) {
case 0: day_name = "BC"; break;
case 1: day_name = "\1H"; break;
case 2: day_name = "BT"; break;
case 3: day_name = "CP"; break;
case 4: day_name = "\2T"; break;
case 5: day_name = "\1T"; break;
case 6: day_name = "C\3"; break;
}
lcd.print(day_name + " ");
lcd_clear_flag[num] = false;
}
lcd.print(next_watering_time_h < 10 ? "0" + String(next_watering_time_h) + "h:" : String(next_watering_time_h) + "h:");
lcd.print(next_watering_time_m < 10 ? "0" + String(next_watering_time_m) + "m " : String(next_watering_time_m) + "m ");
lcd.print(next_watering_duration_m < 10 ? "0" + String(next_watering_duration_m) + "m:" : String(next_watering_duration_m) + "m:");
lcd.print(next_watering_duration_s < 10 ? "0" + String(next_watering_duration_s) + "s" : String(next_watering_duration_s) + "s");
if (next_watering[num].left == 0) {
if (!lcd_clear_flag[num]) {
lcd_clear_flag[num] = true;
lcd.clear();
}
}
}
}
else
{
lcd.setCursor(0, i + 1);
lcd.print(String(num + 1) + ")");
lcd.print("HET \1O\5\6BOB");
}
}
}
}
}
}
else if (page == 1) {
if (!set_char_flag) {
set_char_flag = true;
set_char(rus_u, rus_ch, rus_p, rus_l, rus_i, full, on);
}
if (!digitalRead(page_page_selection) && !page_page_selection_flag) {
page_page_selection_flag = true;
if (channel_count > 3) {
if (channel_count % 3) {
page_page < ceil(channel_count / 3) ? page_page++ : page_page = 0;
}
else
{
page_page < ceil(channel_count / 3) - 1 ? page_page++ : page_page = 0;
}
}
value_selected = 0;
item_selected = 0;
blink_state = false;
blink_time = millis();
last_action_time = millis();
last_action_flag = false;
lcd.clear();
}
else if (digitalRead(page_page_selection) && page_page_selection_flag) {
page_page_selection_flag = false;
}
if (!digitalRead(item_selection) && !item_selection_flag) {
item_selection_flag = true;
if (channel_count > 1) {
if ((page_page + 1) * 3 < channel_count) {
item_selected < 2 ? item_selected++ : item_selected = 0;
}
else
{
item_selected < (page_page + 1) * 3 - channel_count ? item_selected++ : item_selected = 0;
}
}
value_selected = 0;
blink_state = false;
blink_time = millis();
last_action_time = millis();
last_action_flag = false;
}
else if (digitalRead(item_selection) && item_selection_flag) {
item_selection_flag = false;
}
if (!digitalRead(value_selection) && !value_selection_flag) {
value_selection_flag = true;
value_selected < 1 ? value_selected++ : value_selected = 0;
blink_state = false;
blink_time = millis();
last_action_time = millis();
last_action_flag = false;
}
else if (digitalRead(value_selection) && value_selection_flag) {
value_selection_flag = false;
}
if (millis() - blink_time >= 500) {
blink_state = !blink_state;
blink_time = millis();
}
lcd.setCursor(5, 0);
lcd.print("P\1\2 \3O\4\5B");
for (int i = 0; i < 3; i++) {
byte num = i + (page_page * 3);
if (num < channel_count) {
if (blink_state) {
switch (value_selected) {
case 0:
lcd.setCursor(num + 1 < 10 ? 2 : 3, item_selected + 1);
lcd.print("\6\6");
break;
case 1:
lcd.setCursor(num + 1 < 10 ? 6 : 7, item_selected + 1);
lcd.print("\6\6");
break;
}
}
else
{
lcd.setCursor(0, i + 1);
lcd.print(String(num + 1) + ")");
lcd.print(manual_watering[num].m < 10 ? "0" + String(manual_watering[num].m) + "m:" : String(manual_watering[num].m) + "m:");
lcd.print(manual_watering[num].s < 10 ? "0" + String(manual_watering[num].s) + "s" : String(manual_watering[num].s) + "s");
if (manual_watering_state[num]) {
lcd.setCursor(19, i + 1);
lcd.print("\7");
}
}
}
}
byte item_selected_index = page_page * 2 + page_page + item_selected;
if (!digitalRead(universal) && !universal_flag) {
universal_flag = true;
manual_watering_state[item_selected_index] = !manual_watering_state[item_selected_index];
manual_watering_time[item_selected_index] = millis() / 1000;
//valve_delay_time[item_selected_index] = millis() / 1000;
if (Blynk.connected()) Blynk.virtualWrite(manual_on_off[item_selected_index], manual_watering_state[item_selected_index]);
blink_state = false;
blink_time = millis();
last_action_time = millis();
last_action_flag = false;
lcd.clear();
}
else if (digitalRead(universal) && universal_flag) {
universal_flag = false;
}
switch (value_selected) {
case 0:
value_change(manual_watering[item_selected_index].m, 1, 59, (channel_count * 100) + (channel_count * 7) + (item_selected_index * 2), channel, true);
break;
case 1:
value_change(manual_watering[item_selected_index].s, 0, 59, (channel_count * 100) + (channel_count * 7) + (item_selected_index * 2) + 1, channel, true);
break;
}
}
else if (page > 1 && page < channel_count + 2) {
if (!set_char_flag) {
set_char_flag = true;
set_char(rus_l, rus_ia, full, on, 0, 0, 0);
}
if (!digitalRead(page_page_selection) && !page_page_selection_flag) {
page_page_selection_flag = true;
page_page < 6 ? page_page++ : page_page = 0;
value_selected = 0;
item_selected = 0;
blink_state = false;
blink_time = millis();
last_action_time = millis();
last_action_flag = false;
lcd.clear();
}
else if (digitalRead(page_page_selection) && page_page_selection_flag) {
page_page_selection_flag = false;
}
if (!digitalRead(item_selection) && !item_selection_flag) {
item_selection_flag = true;
if ((page_page + 1) * 3 < 20) {
item_selected < 2 ? item_selected++ : item_selected = 0;
}
else
{
item_selected < (page_page + 1) * 3 - 20 ? item_selected++ : item_selected = 0;
}
value_selected = 0;
blink_state = false;
blink_time = millis();
last_action_time = millis();
last_action_flag = false;
}
else if (digitalRead(item_selection) && item_selection_flag) {
item_selection_flag = false;
}
if (!digitalRead(value_selection) && !value_selection_flag) {
value_selection_flag = true;
value_selected < 3 ? value_selected++ : value_selected = 0;
blink_state = false;
blink_time = millis();
last_action_time = millis();
last_action_flag = false;
}
else if (digitalRead(value_selection) && value_selection_flag) {
value_selection_flag = false;
}
if (millis() - blink_time >= 500) {
blink_state = !blink_state;
blink_time = millis();
}
lcd.setCursor(2, 0);
lcd.print("KAHA\1 " + String(channel + 1) + " (BPEM\2)");
for (int i = 0; i < 3; i++) {
byte num = i + (page_page * 3);
if (num < 20) {
if (blink_state) {
switch (value_selected) {
case 0:
lcd.setCursor(num + 1 < 10 ? 2 : 3, item_selected + 1);
lcd.print("\3\3");
break;
case 1:
lcd.setCursor(num + 1 < 10 ? 6 : 7, item_selected + 1);
lcd.print("\3\3");
break;
case 2:
lcd.setCursor(num + 1 < 10 ? 10 : 11, item_selected + 1);
lcd.print("\3\3");
break;
case 3:
lcd.setCursor(num + 1 < 10 ? 14 : 15, item_selected + 1);
lcd.print("\3\3");
break;
}
}
else
{
lcd.setCursor(0, i + 1);
lcd.print(String(num + 1) + ")");
lcd.print(watering_time[channel][num].time_h < 10 ? "0" + String(watering_time[channel][num].time_h) + "h:" : String(watering_time[channel][num].time_h) + "h:");
lcd.print(watering_time[channel][num].time_m < 10 ? "0" + String(watering_time[channel][num].time_m) + "m " : String(watering_time[channel][num].time_m) + "m ");
lcd.print(watering_time[channel][num].duration_m < 10 ? "0" + String(watering_time[channel][num].duration_m) + "m:" : String(watering_time[channel][num].duration_m) + "m:");
lcd.print(watering_time[channel][num].duration_s < 10 ? "0" + String(watering_time[channel][num].duration_s) + "s" : String(watering_time[channel][num].duration_s) + "s");
if (watering_time[channel][num].on_off) {
lcd.setCursor(19, i + 1);
lcd.print("\4");
}
}
}
}
byte item_selected_index = page_page * 2 + page_page + item_selected;
if (!digitalRead(universal) && !universal_flag) {
universal_flag = true;
watering_time[channel][item_selected_index].on_off = !watering_time[channel][item_selected_index].on_off;
EEPROM.update((item_selected_index * 5) + (channel * 100) + 4, watering_time[channel][item_selected_index].on_off);
show_watering_time(channel);
blink_state = false;
blink_time = millis();
last_action_time = millis();
last_action_flag = false;
lcd.clear();
}
else if (digitalRead(universal) && universal_flag) {
universal_flag = false;
}
switch (value_selected) {
case 0:
value_change(watering_time[channel][item_selected_index].time_h, 0, 23, (item_selected_index * 5) + (channel * 100), channel, false);
break;
case 1:
value_change(watering_time[channel][item_selected_index].time_m, 0, 59, (item_selected_index * 5) + (channel * 100) + 1, channel, false);
break;
case 2:
value_change(watering_time[channel][item_selected_index].duration_m, 1, 59, (item_selected_index * 5) + (channel * 100) + 2, channel, false);
break;
case 3:
value_change(watering_time[channel][item_selected_index].duration_s, 0, 59, (item_selected_index * 5) + (channel * 100) + 3, channel, false);
break;
}
}
else if (page > channel_count + 1 && page < (channel_count * 2) + 2) {
if (!set_char_flag) {
set_char_flag = true;
set_char(rus_l, rus_d, rus_i, rus_p, rus_b, full, underline);
}
if (!digitalRead(value_selection) && !value_selection_flag) {
value_selection_flag = true;
value_selected < 6 ? value_selected++ : value_selected = 0;
last_action_time = millis();
last_action_flag = false;
lcd.clear();
}
else if (digitalRead(value_selection) && value_selection_flag) {
value_selection_flag = false;
}
if (!digitalRead(universal) && !universal_flag) {
universal_flag = true;
days[channel][value_selected] = !days[channel][value_selected];
EEPROM.update((channel_count * 100) + (channel * 7) + value_selected, days[channel][value_selected]);
get_selected_day(channel);
blink_state = false;
blink_time = millis();
last_action_time = millis();
last_action_flag = false;
}
else if (digitalRead(universal) && universal_flag) {
universal_flag = false;
}
if (millis() - blink_time >= 500) {
blink_state = !blink_state;
blink_time = millis();
}
String day_name[7] = {"\4H ", "BT ", "CP ", "4T ", "\4T ", "C\5 ", "BC"};
byte coordinates[7] = {0, 3, 6, 9, 12, 15, 18};
lcd.setCursor(3, 0);
lcd.print("KAHA\1 " + String(channel + 1) + " (\2H\3)");
for (int day = 0; day < 7; day++) {
if (days[channel][day]) {
lcd.setCursor(coordinates[day], 2);
blink_state ? lcd.print("\6\6") : lcd.print(day_name[day]);
}
else
{
lcd.setCursor(coordinates[day], 2);
lcd.print(day_name[day]);
}
}
lcd.setCursor(coordinates[value_selected], 3);
lcd.print("\7\7");
}
for (int watering_time_ch = 0; watering_time_ch < channel_count; watering_time_ch++) {
if (manual_watering_state[watering_time_ch]) {
if (millis() / 1000 - manual_watering_time[watering_time_ch] >= (int(manual_watering[watering_time_ch].m) * 60) + manual_watering[watering_time_ch].s) {
manual_watering_state[watering_time_ch] = false;
lcd.clear();
}
else
{
manual_watering_left[watering_time_ch].m = floor(((int(manual_watering[watering_time_ch].m) * 60) + manual_watering[watering_time_ch].s - (millis() / 1000 - manual_watering_time[watering_time_ch])) / 60);
manual_watering_left[watering_time_ch].s = ((int(manual_watering[watering_time_ch].m) * 60) + manual_watering[watering_time_ch].s - (millis() / 1000 - manual_watering_time[watering_time_ch])) % 60;
byte index = 0;
for (int i = 0; i < pump_count; i++) {
for (int j = 0; j < channel_count; j++) {
if (pump_valve_pin[i][j] != 0) {
index++;
}
if (watering_time_ch == index - 1) {
digitalWrite(pump_valve_pin[i][j], HIGH);
pump_valve_state[i][j] = true;
}
}
}
if (Blynk.connected()) {
if (manual_watering_left[watering_time_ch].s != time_last[watering_time_ch]) {
Blynk.virtualWrite(status_display[watering_time_ch], "ручной полив - " + (manual_watering_left[watering_time_ch].m < 10 ? "0" + String(manual_watering_left[watering_time_ch].m) + "m:" : String(manual_watering_left[watering_time_ch].m) + "m:") + (manual_watering_left[watering_time_ch].s < 10 ? "0" + String(manual_watering_left[watering_time_ch].s) + "s" : String(manual_watering_left[watering_time_ch].s) + "s"));
time_last[watering_time_ch] = manual_watering_left[watering_time_ch].s;
}
}
}
no_watering[watering_time_ch] = false;
}
else
{
if (watering_on_count[watering_time_ch] > 0 && watering_day_count[watering_time_ch] > 0) {
if (watering_mode[watering_time_ch]) {
if (millis() / 1000 - watering_start_time[watering_time_ch] >= next_watering[watering_time_ch].duration) {
watering_mode[watering_time_ch] = false;
notify_flag[watering_time_ch] = true;
lcd.clear();
}
else
{
duration_time_left[watering_time_ch].m = floor((next_watering[watering_time_ch].duration - (millis() / 1000 - watering_start_time[watering_time_ch])) / 60);
duration_time_left[watering_time_ch].s = (next_watering[watering_time_ch].duration - (millis() / 1000 - watering_start_time[watering_time_ch])) % 60;
}
byte index = 0;
for (int i = 0; i < pump_count; i++) {
for (int j = 0; j < channel_count; j++) {
if (pump_valve_pin[i][j] != 0) {
index++;
}
if (watering_time_ch == index - 1) {
digitalWrite(pump_valve_pin[i][j], HIGH);
pump_valve_state[i][j] = true;
}
}
}
if (Blynk.connected()) {
if (duration_time_left[watering_time_ch].s != time_last[watering_time_ch]) {
Blynk.virtualWrite(status_display[watering_time_ch], "полив - " + (duration_time_left[watering_time_ch].m < 10 ? "0" + String(duration_time_left[watering_time_ch].m) + "m:" : String(duration_time_left[watering_time_ch].m) + "m:") + (duration_time_left[watering_time_ch].s < 10 ? "0" + String(duration_time_left[watering_time_ch].s) + "s" : String(duration_time_left[watering_time_ch].s) + "s"));
time_last[watering_time_ch] = duration_time_left[watering_time_ch].s;
}
}
}
else
{
long left_time = 0;
if (next_watering[watering_time_ch].left == 0) {
left_time = next_watering[watering_time_ch].time - ((long(time.h) * 3600) + (int(time.m) * 60) + time.s);
}
else
{
left_time = (next_watering[watering_time_ch].left * 86400) - (((long(time.h) * 3600) + (int(time.m) * 60) + time.s) - next_watering[watering_time_ch].time);
}
watering_time_left[watering_time_ch].h = floor(left_time / 3600);
watering_time_left[watering_time_ch].m = (left_time % 3600) / 60;
watering_time_left[watering_time_ch].s = left_time % 60;
if (left_time == 0) {
watering_mode[watering_time_ch] = true;
watering_start_time[watering_time_ch] = millis() / 1000;
//valve_delay_time[watering_time_ch] = millis() / 1000;
lcd.clear();
}
byte index = 0;
for (int i = 0; i < pump_count; i++) {
for (int j = 0; j < channel_count; j++) {
if (pump_valve_pin[i][j] != 0) {
index++;
}
if (watering_time_ch == index - 1) {
digitalWrite(pump_valve_pin[i][j], LOW);
pump_valve_state[i][j] = false;
}
}
}
if (Blynk.connected()) {
if (watering_time_left[watering_time_ch].s != time_last[watering_time_ch]) {
Blynk.virtualWrite(status_display[watering_time_ch], "ожидание - " + (watering_time_left[watering_time_ch].h < 10 ? "0" + String(watering_time_left[watering_time_ch].h) + "h:" : String(watering_time_left[watering_time_ch].h) + "h:") + (watering_time_left[watering_time_ch].m < 10 ? "0" + String(watering_time_left[watering_time_ch].m) + "m:" : String(watering_time_left[watering_time_ch].m) + "m:") + (watering_time_left[watering_time_ch].s < 10 ? "0" + String(watering_time_left[watering_time_ch].s) + "s" : String(watering_time_left[watering_time_ch].s) + "s"));
time_last[watering_time_ch] = watering_time_left[watering_time_ch].s;
}
}
}
no_watering[watering_time_ch] = false;
}
else
{
byte index = 0;
for (int i = 0; i < pump_count; i++) {
for (int j = 0; j < channel_count; j++) {
if (pump_valve_pin[i][j] != 0) {
index++;
}
if (watering_time_ch == index - 1) {
digitalWrite(pump_valve_pin[i][j], LOW);
pump_valve_state[i][j] = false;
}
}
}
if (Blynk.connected()) {
if (!no_watering[watering_time_ch]) {
Blynk.virtualWrite(status_display[watering_time_ch], "нет поливов");
no_watering[watering_time_ch] = true;
}
}
}
}
if (Blynk.connected()) {
if (notify_flag[watering_time_ch] && !first_notify_flag) {
first_notify_flag = true;
first_notify = watering_time_ch;
}
if (millis() / 1000 - notify_time > 5 && notify_flag[first_notify]) {
Blynk.notify(notify_text[first_notify]);
notify_flag[first_notify] = false;
first_notify_flag = false;
notify_time = millis() / 1000;
}
}
}
byte channel_on[pump_count] = {};
for (int i = 0; i < pump_count; i++) {
for (int j = 0; j < channel_count; j++) {
if (pump_valve_state[i][j]) {
channel_on[i]++;
}
}
if (channel_on[i] > 0) {
digitalWrite(pump_pin[i], HIGH);
}
else
{
digitalWrite(pump_pin[i], LOW);
}
}
if (Blynk.connected()) {
Blynk.run();
blynk_connect_failed = false;
}
else
{
blynk_connect_failed = true;
}
if(millis() - last_action_time > 30000 && !last_action_flag && page != 0){
last_action_flag = true;
page = 0;
page_page = 0;
value_selected = 0;
item_selected = 0;
set_char_flag = false;
blink_state = false;
lcd.clear();
}
timer.run();
}
void set_char(byte char_1[], byte char_2[], byte char_3[], byte char_4[], byte char_5[], byte char_6[], byte char_7[]) {
lcd.createChar(1, char_1);
lcd.createChar(2, char_2);
lcd.createChar(3, char_3);
lcd.createChar(4, char_4);
lcd.createChar(5, char_5);
lcd.createChar(6, char_6);
lcd.createChar(7, char_7);
}
void value_change(byte &value, byte value_min, byte value_max, int eeprom_cell, byte ch, bool manual) {
if (!digitalRead(value_up)) {
value < value_max ? value++ : value = value_min;
value_up_flag = true;
delay(100);
}
else if (digitalRead(value_up) && value_up_flag) {
value_up_flag = false;
if (Blynk.connected()){
if (manual) {
Blynk.virtualWrite(manual_time_select[ch], (int(manual_watering[ch].m) * 60) + manual_watering[ch].s, 0, "Europe/Moscow");
}
else
{
show_watering_time(ch);
}
}
last_action_time = millis();
last_action_flag = false;
}
if (!digitalRead(value_down)) {
value > value_min ? value-- : value = value_max;
value_down_flag = true;
delay(100);
}
else if (digitalRead(value_down) && value_down_flag) {
value_down_flag = false;
if (Blynk.connected()){
if (manual) {
Blynk.virtualWrite(manual_time_select[ch], (int(manual_watering[ch].m) * 60) + manual_watering[ch].s, 0, "Europe/Moscow");
}
else
{
show_watering_time(ch);
}
}
last_action_time = millis();
last_action_flag = false;
}
EEPROM.update(eeprom_cell, value);
}
void get_next_watering() {
for (int watering_time_ch = 0; watering_time_ch < channel_count; watering_time_ch++) {
watering_on_count[watering_time_ch] = 0;
watering_day_count[watering_time_ch] = 0;
for (int watering_time_index = 0; watering_time_index < 20; watering_time_index++) {
if (watering_time[watering_time_ch][watering_time_index].on_off) {
watering_on_count[watering_time_ch]++;
}
}
watering_on_struct watering_on[watering_on_count[watering_time_ch]];
if (watering_on_count[watering_time_ch] > 0) {
byte index = 0;
for (int watering_time_index = 0; watering_time_index < 20; watering_time_index++) {
if (watering_time[watering_time_ch][watering_time_index].on_off) {
watering_on[index].time = (long(watering_time[watering_time_ch][watering_time_index].time_h) * 3600) + (int(watering_time[watering_time_ch][watering_time_index].time_m) * 60);
watering_on[index].duration = (int(watering_time[watering_time_ch][watering_time_index].duration_m) * 60) + watering_time[watering_time_ch][watering_time_index].duration_s;
index++;
}
}
qsort(watering_on, watering_on_count[watering_time_ch], sizeof(watering_on[0]), compare);
}
for (int day_index = 0; day_index < 7; day_index++) {
if (days[watering_time_ch][day_index]) {
watering_day_count[watering_time_ch]++;
}
}
byte watering_days[watering_day_count[watering_time_ch]];
if (watering_day_count[watering_time_ch] > 0) {
byte index = 0;
for (int day_index = 0; day_index < 7; day_index++) {
if (days[watering_time_ch][day_index]) {
watering_days[index] = day_index + 1;
index++;
}
}
}
if (watering_on_count[watering_time_ch] > 0 && watering_day_count[watering_time_ch] > 0 && !watering_mode[watering_time_ch]) {
if (days[watering_time_ch][time.day == 0 ? 6 : time.day - 1]) {
bool next_watering_time_flag = false;
for (int watering_on_time_index = 0; watering_on_time_index < watering_on_count[watering_time_ch]; watering_on_time_index++) {
if (watering_on[watering_on_time_index].time >= (long(time.h) * 3600) + (int(time.m) * 60) + time.s) {
next_watering[watering_time_ch].time = watering_on[watering_on_time_index].time;
next_watering[watering_time_ch].duration = watering_on[watering_on_time_index].duration;
next_watering[watering_time_ch].day = time.day;
next_watering[watering_time_ch].left = 0;
next_watering_time_flag = true;
break;
}
}
if (!next_watering_time_flag) {
next_watering[watering_time_ch].time = watering_on[0].time;
next_watering[watering_time_ch].duration = watering_on[0].duration;
for (int watering_days_index = 0; watering_days_index < watering_day_count[watering_time_ch]; watering_days_index++) {
if (watering_days[watering_days_index] == (time.day == 0 ? 7 : time.day)) {
if (watering_days_index + 1 < watering_day_count[watering_time_ch]) {
next_watering[watering_time_ch].day = watering_days[watering_days_index + 1] == 7 ? 0 : watering_days[watering_days_index + 1];
next_watering[watering_time_ch].left = watering_days[watering_days_index + 1] - (time.day == 0 ? 7 : time.day);
}
else
{
next_watering[watering_time_ch].day = watering_days[0] == 7 ? 0 : watering_days[0];
next_watering[watering_time_ch].left = (7 - (time.day == 0 ? 7 : time.day)) + watering_days[0];
}
}
}
}
}
else
{
next_watering[watering_time_ch].time = watering_on[0].time;
next_watering[watering_time_ch].duration = watering_on[0].duration;
if (watering_day_count[watering_time_ch] > 1) {
bool first_day = false;
for (int watering_days_index = 0; watering_days_index < watering_day_count[watering_time_ch]; watering_days_index++) {
if (watering_days[watering_days_index] < (time.day == 0 ? 7 : time.day) && watering_days[watering_days_index + 1] > (time.day == 0 ? 7 : time.day) && watering_days_index + 1 < watering_day_count[watering_time_ch]) {
next_watering[watering_time_ch].day = watering_days[watering_days_index + 1] == 7 ? 0 : watering_days[watering_days_index + 1];
next_watering[watering_time_ch].left = watering_days[watering_days_index + 1] - (time.day == 0 ? 7 : time.day);
first_day = false;
break;
}
else
{
first_day = true;
}
}
if (first_day) {
next_watering[watering_time_ch].day = watering_days[0] == 7 ? 0 : watering_days[0];
if (watering_days[0] > (time.day == 0 ? 7 : time.day)) {
next_watering[watering_time_ch].left = watering_days[0] - (time.day == 0 ? 7 : time.day);
}
else
{
next_watering[watering_time_ch].left = (7 - (time.day == 0 ? 7 : time.day)) + watering_days[0];
}
}
}
else
{
next_watering[watering_time_ch].day = watering_days[0] == 7 ? 0 : watering_days[0];
if (watering_days[0] > (time.day == 0 ? 7 : time.day)) {
next_watering[watering_time_ch].left = watering_days[0] - (time.day == 0 ? 7 : time.day);
}
else
{
next_watering[watering_time_ch].left = (7 - (time.day == 0 ? 7 : time.day)) + watering_days[0];
}
}
}
}
}
}
int compare(const void* first, const void* second) {
const watering_on_struct* a = (const watering_on_struct*)first;
const watering_on_struct* b = (const watering_on_struct*)second;
if (a->time < b->time) return -1;
return a->time == b->time ? 0 : 1;
}
BLYNK_WRITE_DEFAULT() {
int pin = request.pin;
for (int i = 0; i < channel_count; i++) {
if (pin == watering_select[i]) {
watering_num[i] = param.asInt() - 1;
long start_time = (long(watering_time[i][watering_num[i]].time_h) * 3600) + (int(watering_time[i][watering_num[i]].time_m) * 60);
long stop_time = (int(watering_time[i][watering_num[i]].duration_m) * 60) + watering_time[i][watering_num[i]].duration_s;
Blynk.virtualWrite(time_select[i], start_time, stop_time, "Europe/Moscow", selected_day_str[i]);
Blynk.virtualWrite(on_off[i], watering_time[i][watering_num[i]].on_off);
}
else if (pin == time_select[i]) {
TimeInputParam time_data(param);
watering_time[i][watering_num[i]].time_h = time_data.getStartHour();
watering_time[i][watering_num[i]].time_m = time_data.getStartMinute();
watering_time[i][watering_num[i]].duration_m = time_data.getStopMinute();
watering_time[i][watering_num[i]].duration_s = time_data.getStopSecond();
EEPROM.update((watering_num[i] * 5) + (i * 100), watering_time[i][watering_num[i]].time_h);
EEPROM.update((watering_num[i] * 5) + (i * 100) + 1, watering_time[i][watering_num[i]].time_m);
EEPROM.update((watering_num[i] * 5) + (i * 100) + 2, watering_time[i][watering_num[i]].duration_m);
EEPROM.update((watering_num[i] * 5) + (i * 100) + 3, watering_time[i][watering_num[i]].duration_s);
for (int j = 0; j < 7; j++) {
days[i][j] = time_data.isWeekdaySelected(j + 1);
EEPROM.update((channel_count * 100) + (i * 7) + j, days[i][j]);
}
show_watering_time(i);
get_selected_day(i);
}
else if (pin == on_off[i]) {
watering_time[i][watering_num[i]].on_off = param.asInt();
EEPROM.update((watering_num[i] * 5) + (i * 100) + 4, watering_time[i][watering_num[i]].on_off);
show_watering_time(i);
}
else if (pin == manual_time_select[i]) {
TimeInputParam time_data(param);
manual_watering[i].m = time_data.getStartMinute();
manual_watering[i].s = time_data.getStartSecond();
EEPROM.update((channel_count * 100) + (channel_count * 7) + (i * 2), manual_watering[i].m);
EEPROM.update((channel_count * 100) + (channel_count * 7) + (i * 2) + 1, manual_watering[i].s);
}
else if (pin == manual_on_off[i]) {
manual_watering_state[i] = !manual_watering_state[i];
manual_watering_time[i] = millis() / 1000;
}
}
}
void show_watering_time(byte ch) {
terminal[ch].clear();
String data;
for (int i = 0; i < 20; i++) {
i < 9 ? data += String(i + 1) + ") " : data += String(i + 1) + ") ";
watering_time[ch][i].time_h < 10 ? data += "0" + String(watering_time[ch][i].time_h) + "h:" : data += String(watering_time[ch][i].time_h) + "h:";
watering_time[ch][i].time_m < 10 ? data += "0" + String(watering_time[ch][i].time_m) + "m -> " : data += String(watering_time[ch][i].time_m) + "m -> ";
watering_time[ch][i].duration_m < 10 ? data += "0" + String(watering_time[ch][i].duration_m) + "m:" : data += String(watering_time[ch][i].duration_m) + "m:";
watering_time[ch][i].duration_s < 10 ? data += "0" + String(watering_time[ch][i].duration_s) + "s " : data += String(watering_time[ch][i].duration_s) + "s ";
watering_time[ch][i].on_off ? data += "ON\n" : data += "OFF\n";
}
terminal[ch].print(data);
terminal[ch].flush();
}
void get_selected_day(byte ch) {
int selected_day = 0;
int selected_num = 0;
for (int i = 0; i < 7; i++) {
if (days[ch][i]) {
selected_day++;
}
}
for (int i = 0; i < 7; i++) {
if (days[ch][i]) {
selected_num++;
selected_num < selected_day ? selected_day_str[ch] += String(i + 1) + String(",") : selected_day_str[ch] += String(i + 1);
}
}
}
void blynk_reconnect() {
if (blynk_connect_failed) {
bool fail = false;
for(int i = 0; i < channel_count; i++){
if(manual_watering_state[i] && watering_mode[i]){
fail = true;
}
else
{
if(watering_on_count[i] > 0 && watering_day_count[i] > 0){
if(watering_time_left[i].h == 0 && watering_time_left[i].m == 0){
fail = true;
}
}
}
}
if(!fail){
Ethernet.begin(mac, 10000);
if (Blynk.connect(10000)) {
for (int i = 0; i < channel_count; i++) {
show_watering_time(i);
}
}
}
}
}
The problem is your void loop.
Please read this to understand why it is a problem and what you need to do to solve the problem…
Pete.
Вам надо разгрузить код в LOOP и повесить все на таймеры. В библиотеке Blynk таймер уже есть можно повесить до 16 штук (если мне память не изменяет). Мой LOOP выглядит так и никаких проблем со связью я не наблюдаю.
void loop()
{
Blynk.run();
timer.run();
Serial.println(DataTime());
}
P.S. Не смотря на то что, весь код программы значительно больше и сложнее…
но виснет только когда меняю какое-то значение, если не трогать ничего то работает. как только начинаю в блинке что-то менять сразу виснет и мега и блинк
Вы код в теле LOOP переделали, как вам писали? ЭТО ВАЖНО! Это написано в инструкции!
Дайте контроллеру нормально “общаться” с шилдом W5100… (Кстати 5100 не лучший шилд, W5500 меньше греется и стабильнее). Но проблема не в 5100.
Сходу по коду явных ошибок не увидел. Советы:
- Нужно оставлять комментарии по коду (это хороший тон и он помогает нарыть ошибки вам самим), сидеть и ковырять чужой код на огромное количество вложений/ветвлений if/for сложно.
- Освойте таймеры https://docs.blynk.cc/#blynk-firmware-blynktimer (читатйте внимательно что здесь написано), вам легче будет и нам.
- Разбейте код на процедуры и функции.
P.S. Я вообще перевел все файлы help на русский, но к сайту ребята приаттачили только описание виджетов из мобильной версии, а потом что-то все затихло.