Перезагрузка ардуино, возможно проблема кода

Я новичок не пинайтк сильно. Код писал полностью сам, готов принятт критику.
Проблема, ардуина перезагружается как то рандомно, не могу понять пока почему, но есть теория что стоит рядом с четырехканальным реле и из за наводок…, но может пробоеиа с кодом.
Ткните носом на ошибки кода, может я перемудрил. А так код вроде рабочий))
Также прошу знатоков скзаать на счет меню, энкодер туговато отзывается когда поворачиваешь и меняешь значения.

#include <GyverEncoder.h>         // библиотека энкодера
#include <DHT.h>                  // библиотека датчика температуры и влажности
#include <Wire.h>                 //Подключения библиотеке для работы I2C
#include <LiquidCrystal_I2C.h>    // Подключения библиотеке LCD
#include <microDS3231.h>          // Подключения библиотеке датчика реального времени
#define CLK 6                     // Установка пина энкодера
#define DT 7                      // Установка пина энкодера
#define SW 8                      // Установка пина энкодера
#define DHTPIN 2                  // вывод, к которому подключается датчик температуры и влажности
#define DHTTYPE DHT22             // модель датчика
#define Light 3                   // Пин освещения
#define Hidro 4                   // Пин увлажнителя
#define Fan 5                     // Пин вентиляции
Encoder enc1(CLK, DT, SW, TYPE2); // Установка типа энкодера и количества кнопок
MicroDS3231 rtc;                  // установка датчика реального времени
LiquidCrystal_I2C lcd(0x27,16,2); // установка дисплея (0x27 адрес, 16 символов, 2 строки)
DHT dht(DHTPIN, DHTTYPE);         // создаём объект dht с которым будем работать
float maxTemp = 30;               // Включения вентиляции
float minTemp = 27;               // Выключения вентиляции
int minH = 60;                    // Включения увлажнителя
int maxH = 70;                    // Выключения увлажнителя
int maxT = 22;                    // Вермя выключения освещения
int minT = 8;                     // Время включения освещения
float T;                          // Средний показатель температуры за 15 секунд (5 измерений)
float t1;                         // 1 показание температуры
float t2;                         // 2 показание температуры
float t3;                         // 3 показание температуры
float t4;                         // 4 показание температуры
float t5;                         // 5 показание температуры
int tt = 1;                       // Переменная номера измерений температуры
float H;                          // Средний показатель влажности за 15 секунд (5 измерений)
float h1;                         // 1 показание влажности
float h2;                         // 2 показание влажности
float h3;                         // 3 показание влажности
float h4;                         // 4 показание влажности
float h5;                         // 5 показание влажности
int hh = 1;                       // Переменная номера измерений влажности
int days = 0;                     // Переменная дней

int i = 0, j = 0, k = 0, p = 0;   // Переменные для работы с меню, подсветкой LCD, флаг вентиляции для вытяжки

unsigned long time_dht22;         // Опрос датчика влажности и температуры
unsigned long time_lcd;           // Обновления LCD в меню HOME
unsigned long last_mod;           // Обновления LCD в настройках
unsigned long backlightLCD;       // Время подсветки LCD
unsigned long time_dht22_sredne;  // Подсчет средних результатов за 15 секунд
unsigned long good_time;          // Переменная секундамера
unsigned long good = 0;           // Переменная секунд
unsigned long last_mod_home;      // Переменная отвечающая за возврат в меню HOME через 30 секунд

void setup() {
  rtc.setTime(COMPILE_TIME);      // Установка веремни на часах == веремя компиляции скетча
  pinMode (Light, OUTPUT);        // Обозначения пина как выхода
  digitalWrite(Light, 0);         // Установка отключения реле по умолчанию
  pinMode (Hidro, OUTPUT);        // Обозначения пина как выхода
  digitalWrite(Hidro, 0);         // Установка отключения реле по умолчанию
  pinMode (Fan, OUTPUT);          // Обозначения пина как выхода
  digitalWrite(Fan, 0);           // Установка отключения реле по умолчанию

  enc1.setType(TYPE2);            // тип энкодера
  enc1.setFastTimeout(20);
 
  lcd.init();                      // Инициализация LCD
  lcd.backlight();                 // Включение подсветки LCD
  dht.begin();                     // Инициализация датчика влажности
 
  //Serial.begin(9600);            // Инициализация открытия порта для отладки программы
 
 
  // проверка наличия модуля на линии i2c
  // вызов rtc.begin() не обязателен для работы
 if (!rtc.begin()) {
 Serial.println("DS3231 not found");
 for(;;);
  }
 
}

void loop() {
 
  if (millis() - good_time > 1000){ // Секундный таймер на последнем экране
    good++;
    good_time = millis();
  }
  if (good >= 2592000){ // Дневной таймер на последнем экране
   good = 0;
   days++;
  }
  if (days > 30){ // Дневной таймер сброс каждые 30 дней
   days = 0;
  }
  enc1.tick();
  if (enc1.isTurn()) {     // если был совершён поворот (индикатор поворота в любую сторону)
    // ваш код
  }
  if (k == 0 && millis() - backlightLCD > 30000){ // при истечениее 30 секунд выключение подсветки дисплея
      lcd.noBacklight();
      k = 1;
    }    
  if (k == 1){ // при долгом нажатии включение подсветки дисплея на 30 секунд
    if (enc1.isHolded()){
      lcd.backlight();;
      k = 0;
      backlightLCD = millis();
    }
  }

  // Меню построенное на условиях и переменных
 
  if (i == 1 && j == 0){
    lcd.clear();
    j  = 1;
    last_mod_home = millis();
  }
  if (i == 1 && j == 1 && millis() - last_mod > 100){
    lcd.setCursor(2,0);
    lcd.print("Temperature");
    lcd.setCursor(0,1);
    lcd.print("OFF Fan");
    if (enc1.isRight()) minTemp = minTemp - 0.2;        // если был поворот направо, увеличиваем на 1
    if (enc1.isLeft()) minTemp = minTemp + 0.2;
    lcd.setCursor(10,1);
    lcd.print(minTemp, 2);
    lcd.setCursor(14,1);
    lcd.print("*C");
    //Serial.println("LCD MIN TEMP 100 mlsecond");
    //Serial.println(minTemp);
    last_mod = millis();
  }
  if (i == 2 && j == 1){
    lcd.clear();
    j = 2;
    last_mod_home = millis();  
  }
  if (i == 2 && j == 2 && millis() - last_mod > 100){
    lcd.setCursor(2,0);
    lcd.print("Temperature");
    lcd.setCursor(0,1);
    lcd.print("ON Fan ");
    if (enc1.isRight()) maxTemp = maxTemp - 0.2;        // если был поворот направо, увеличиваем на 1
    if (enc1.isLeft()) maxTemp = maxTemp + 0.2;
    lcd.setCursor(10,1);
    lcd.print(maxTemp, 2);
    lcd.setCursor(14,1);
    lcd.print("*C");
    //Serial.println("LCD MAX TEMP 100 mlsecond");
    //Serial.println(maxTemp);
    last_mod = millis();
  }
   if (i == 3 && j == 2){
    lcd.clear();
    j = 3;
    last_mod_home = millis();  
  }
  if (i == 3 && j == 3 && millis() - last_mod > 100){
    lcd.setCursor(5,0);
    lcd.print("Hidro");
    lcd.setCursor(0,1);
    lcd.print("ON  ");
    if (enc1.isRight()) minH = minH - 1;        // если был поворот направо, уменьшает на 1
    if (enc1.isLeft()) minH = minH + 1;         // если был поворот налево, увеличиваем на 1
    lcd.setCursor(13,1);
    lcd.print(minH);
    lcd.setCursor(15,1);
    lcd.print("%");
    //Serial.println("LCD MIN HIDRO 100 mlsecond");
    //Serial.println(minH);
    last_mod = millis();
  }
  if (i == 4 && j == 3){
    lcd.clear();
    j = 4;
    last_mod_home = millis();
  }
  if (i == 4 && j == 4 && millis() - last_mod > 100){
    lcd.setCursor(5,0);
    lcd.print("Hidro");
    lcd.setCursor(0,1);
    lcd.print("OFF  ");
    if (enc1.isRight()) maxH = maxH - 1;        // если был поворот направо, увеличиваем на 1
    if (enc1.isLeft()) maxH = maxH + 1;
    lcd.setCursor(13,1);
    lcd.print(maxH);
    lcd.setCursor(15,1);
    lcd.print("%");
    //Serial.println("LCD MAX HIDRO 100 mlsecond");
    //Serial.println(minH);
    last_mod = millis();
  }
  if (i == 5 && j == 4){
    lcd.clear();
    j = 5;
    last_mod_home = millis();  
  }
  if (i == 5 && j == 5 && millis() - last_mod > 100){
    lcd.setCursor(5,0);
    lcd.print("Light");
    lcd.setCursor(0,1);
    lcd.print("ON");
    if (enc1.isRight()) minT = minT - 1;        // если был поворот направо, увеличиваем на 1
    if (enc1.isLeft()) minT = minT + 1;
    lcd.setCursor(11,1);
    lcd.print(minT);
    lcd.setCursor(13,1);
    lcd.print(":00");
    //Serial.println("LCD ON LIGHT 100 mlsecond");
    //Serial.println(minT);
    last_mod = millis();
  }
  if (i == 6 && j == 5){
    lcd.clear();
    j = 6;
    last_mod_home = millis();
  }
  if (i == 6 && j == 6 && millis() - last_mod > 100){
    lcd.setCursor(5,0);
    lcd.print("Light");
    lcd.setCursor(0,1);
    lcd.print("OFF");
    if (enc1.isRight()) maxT = maxT - 1;        // если был поворот направо, увеличиваем на 1
    if (enc1.isLeft()) maxT = maxT + 1;
    lcd.setCursor(11,1);
    lcd.print(maxT);
    lcd.setCursor(13,1);
    lcd.print(":00");
    //Serial.println("LCD OFF LIGHT 100 mlsecond");
    //Serial.println(maxT);
    last_mod = millis();
  }
    if (i == 7 && j == 6){
    lcd.clear();
    j = 7;
    last_mod_home = millis();
  }
    if (i == 7 && j == 7){
    lcd.setCursor(0,0);
    lcd.print("*");
    lcd.setCursor(1,0);
    lcd.print(minTemp, 1);
    lcd.setCursor(5,0);
    lcd.print("*C");
    lcd.setCursor(9,0);
    lcd.print("*");
    lcd.setCursor(10,0);
    lcd.print(maxTemp, 1);
    lcd.setCursor(14,0);
    lcd.print("*C");

    lcd.setCursor(0,1);
    lcd.print("*");
    lcd.setCursor(1,1);
    lcd.print(minH);
    lcd.setCursor(3,1);
    lcd.print("%");
    lcd.setCursor(6,1);
    lcd.print(minT);
    lcd.setCursor(8,1);
    lcd.print("-");
    lcd.setCursor(9,1);
    lcd.print(maxT);
    lcd.setCursor(12,1);
    lcd.print("*");
    lcd.setCursor(13,1);
    lcd.print(maxH);
    lcd.setCursor(15,1);
    lcd.print("%");;
    j = 8;
  }
  if (i == 8 && j == 8){
    lcd.clear();
    j = 9;
    last_mod_home = millis();
  }
  if (i == 8 && j == 9){
    lcd.setCursor(0,0);
    lcd.print("Time:");
    lcd.setCursor(6,0);
    lcd.print(good);
    lcd.setCursor(0,1);
    lcd.print("Day:");
    lcd.setCursor(6,1);
    lcd.print(days);
  }
  if (i == 9 && j == 9){
    lcd.clear();
    j = 0;
    i = 0;
  }
  if (i != 0 && millis() - last_mod_home > 30000) {
    lcd.clear();
    j = 0;
    i = 0;
  }

  // КОНЕЦ МЕНЮ

 
  if (enc1.isClick()) i++;         // отпускание кнопки (+ дебаунс)
 
  //if (enc1.isRight() && i == 1) minTemp = minTemp - 0.2;        // если был поворот направо, увеличиваем на 1
  //if (enc1.isLeft() && i == 1) minTemp = minTemp + 0.2;         // если был поворот налево, уменьшаем на 1
  //if (enc1.isRight() && i == 2) maxTemp = maxTemp - 0.2;        // если был поворот направо, увеличиваем на 1
  //if (enc1.isLeft() && i == 2) maxTemp = maxTemp + 0.2;         // если был поворот налево, уменьшаем на 1
  //if (enc1.isRightH()) Serial.println("Right holded"); // если было удержание + поворот
  //if (enc1.isLeftH()) Serial.println("Left holded");
  //if (enc1.isPress())  ;         // нажатие на кнопку (+ дебаунс)
  //if (enc1.isRelease()) Serial.println("Release");     // то же самое, что isClick
  //if (enc1.isHolded()) Serial.println("Holded");       // если была удержана и энк не поворачивался
  //if (enc1.isHold()) Serial.println("Hold");         // возвращает состояние кнопки

  //if (millis() - time_dht22 > 3000)
  //{
 // H = dht.readHumidity();
 // T = dht.readTemperature();
 // Serial.print("H: ");
  //Serial.print(H);
  //Serial.print(" %\t");
  //Serial.print("T: ");
  //Serial.print(T);
  //Serial.print(" *C ");
  //Serial.println("3 seconds");
  //time_dht22 = millis();
  //}
 
  //ВЫВОД СРЕДНЕГО - Опрос каждые 3 секунды и вывод среднего за 15 секунд!
    if (millis() - time_dht22 > 3000 && tt == 1) {
    t1 = dht.readTemperature();
    h1 = dht.readHumidity();
    time_dht22 = millis();
    //Serial.println("tt1");
    tt++;
    }
    if (millis() - time_dht22 > 3000 && tt == 2) {
    t2 = dht.readTemperature();
    h2 = dht.readHumidity();
    time_dht22 = millis();
    //Serial.println("tt2");
    tt++;
    }
    if (millis() - time_dht22 > 3000 && tt == 3) {
    t3 = dht.readTemperature();
    h3 = dht.readHumidity();
    time_dht22 = millis();
    //Serial.println("tt3");
    tt++;
    }
    if (millis() - time_dht22 > 3000 && tt == 4) {
    t4 = dht.readTemperature();
    h4 = dht.readHumidity();
    time_dht22 = millis();
    //Serial.println("tt4");
    tt++;
    }
    if (millis() - time_dht22 > 3000 && tt == 5) {
    t5 = dht.readTemperature();
    h5 = dht.readHumidity();
    time_dht22 = millis();
    //Serial.println("tt5");
    tt = 1;
    }
    if (millis() - time_dht22_sredne > 2500){
    T = (t1 + t2 + t3 + t4 + t5) / 5; // средняя температора за 15 секкунд (5 измерений)
    H = (h1 + h2 + h3 + h4 + h5) / 5; // средняя влажность за 15 секунд (5 измерений)
    //Serial.print(T);
    //Serial.println(" Srednee za 15 seconds");
    //Serial.print(H);
    //Serial.println(" Srednee za 15 seconds");
    time_dht22_sredne = millis();
    }


 
  if (i == 0 && millis() - time_lcd > 200) // Вывод LCD дисплей HOME
  {
  lcd.setCursor(0,0);
  lcd.print(rtc.getTimeString());
 
  lcd.setCursor(0,1);
  lcd.print("T: ");
  lcd.setCursor(2,1);
  lcd.print(T, 1);

  if (digitalRead(Light) == 1){
    //Serial.println("Light On");
    lcd.setCursor(12,0);
    lcd.print("L");
  } else {
    lcd.setCursor(12,0);
    lcd.print("-");
  }
  if (digitalRead(Hidro) == 1){
    lcd.setCursor(13,0);
    lcd.print("H");
  } else {
    lcd.setCursor(13,0);
    lcd.print("-");
  }

  if (digitalRead(Fan) == 1){
    lcd.setCursor(14,0);
    lcd.print("F");
  } else {
    lcd.setCursor(14,0);
    lcd.print("-");
  }
 
  lcd.setCursor(15,0);
  lcd.print("-");
 
  lcd.setCursor(10,1);
  lcd.print("H: ");
  lcd.setCursor(12,1);
  lcd.print(H, 1);
  time_lcd = millis();
  //Serial.println(" LCD 200 mlsekond");
  }

  if (T >= maxTemp && digitalRead(Fan) == 0 && p == 0){ // Включение вентиляции с проверкой переменной для увлажнителя
    digitalWrite(Fan, 1);
  }
  if (T <= minTemp && digitalRead(Fan) == 1){ // Выключение вентиляции
    digitalWrite(Fan, 0);
  }

 if (H >= maxH && digitalRead(Hidro) == 1){ // Включение увлажнителя и закрытие переменной для вентиляции
    digitalWrite(Hidro, 0);
    p = 0;
  }
  if (H <= minH && digitalRead(Hidro) == 0){ // Выключение вентиляции и включение увлажнителя
    digitalWrite(Fan, 0);
    p = 1;
    digitalWrite(Hidro, 1);
   
  }
  if (rtc.getHours() >= minT && rtc.getHours() < maxT && digitalRead(Light) == 0) { // Включение света в диапазоне
    digitalWrite(Light, 1);
    //Serial.println(" ON LIGHT");
    //Serial.println(minT);
    //Serial.println(maxT);
    //Serial.println(rtc.getHours());
  }
  if (rtc.getHours() >= minT && rtc.getHours() >= maxT && digitalRead(Light) == 1) { // Выключение света в верхнем диапазоне
    digitalWrite(Light, 0);
    //Serial.println(" OFF LIGHT 2");
    //Serial.println(minT);
    //Serial.println(maxT);
    //Serial.println(rtc.getHours());
  }
  if (rtc.getHours() < minT && rtc.getHours() <= maxT && digitalRead(Light) == 1) { // Включение света в нижнем диапазоне
    digitalWrite(Light, 0);
    //Serial.println(" OFF LIGHT 3");
    //Serial.println(minT);
    //Serial.println(maxT);
    //Serial.println(rtc.getHours());
  }
}

Дочитал до строки №40, выматерился и дальше читать не стал

Не удивительно!

А как так получается, что половина переменных имеет осмысленное название (maxTemp, например), а вторая - какая-то хрень (I, j, k, p …) ???

Дык, цельнотянутая технология - по кускам натаскано и чуть-чуть чего-то написано ))

1 лайк

Код писал сам, ничего не натаскано. Только с библиотек управление энкодером, и опрос датчиков!!

Тогда мой вопрос остаётся в силе:

Я новичок и этого не срывал, первое, второе писал код сам, попросил просто ткнуть носом чоо не так. Можно узнать почему не удивительнл что она перезагружается? Конкретика будет)?

Половина перкиенных писал с названиеэямт что бы не запутаться, другая половина типо, i, k, p. Взял их так как часто в уроках используют, а так они за место флагов грубо говоря кроме перкиенной i. Просто не придумал как по другому делать меню

А именно макс темп была и мин темп что бы самому не запутаться в коде. tt, t1, hh и h1 и тд написал что бы не запутаться в среднех значениях и в значениях получаемы с датчиков

Просто писал сам, то что взяты с примеров к библиотека опрос датчиков и управление энкедором, ну извиниье я хз как это по другому сделать))) остальное код писал все сам, так как даже не нашел подобных примеров того что мне надо было!!!

Просто непонятны глупые высказваания, напишите конкреьику что я накосячил в коде, почему не удивительно что она перезагружается, просто конкретику, фиг пойми, много переменных, хотя памяти на уно хватает, или много вычеслений и проц не справляется… Воду вилами мутить такое скбе занятие…
Дочитал до 40 строки и чуть не стошнило… Почему? Там даже все коменты на русском написал что бы понятно было что и к чему… Оборать можно, но конкретика все же куда более приятней (

Простите, я Вам что-то должен?

Вы просили указать на косяки, я указал на первый (дальше смотреть не стал). Указал как на очевидный ляп. Если Вы чего-то не поняли, будьте любезны спрашивать повежливее, а не требовать и качать права.
Умных высказываний по поводу таких ляпов не бывает. Слишком уж ляп глупый.

Потому, что использование в глобальном контексте однобуквенных имён переменных это прямой путь к:

  1. необъяснённым глюкам в работе программы;
  2. шлёпанью по рукам школьников;
  3. отказу в зачёте студентам без дополнительных поводов;
  4. увольнению разработчика или переводу его с разработки на разбор затыков бухгалтерш в 1С

Учение вообще, и ответы обучающего обучаемому в частности - редко бывают приятны. Уж так устроен этот мир.

1 лайк

Написать что использования переиных однобуквенных это ведет ошибкам программы это конкретика. А все остальное это вода.
Я готов к критике конкретной, а не все посыпалось меня тошнит.
Я далеко не школьник, не учусь на програмиста и тем более на инженера, мне просто надо сделать небольшой проект для себя. Для обоюдного понимания просто можно было написать что однобуквеннве переменные зло, правда не понимаю почему, видимо не хватает знаний мат части, но если бы хватало наверное тему бы не создавал!
Я вас услышал вечером отредактирую код после работы в не однобукаенные переменные, спасибо за конкретику.

Вставьте в код вывод в сериал отладочной информации и по логу смотрите где что происходит и последовательно сужайте область …

Если не понимаете, задавайте нормальные вежливые вопросы (т.к. я, например, не понимаю, чего Вы не понимаете). А будете тупо требовать конкретики (и, уж, тем более, учить меня как и что мне говорить), будете посланы на совершенно конкретный адрес.

А можно по подробнее? Это отладка именно для ардуино? Спасибо поисчу инфу в гугле

Оригинально ))

Нет, отладке подлежит любая программа.
Более того, отладка - процесс намного более трудоемкий, чем написание кода. В среднем - раз в десять. Но если код изначально написан небрежно, трудоемкость отладки увеличивается.
Как правило, когда человек потратит на отладку в 20-30 раз больше времени, чем он потратил на написание кода, он приходит к выводу, что старый исходник никуда не годится, его нужно отправить в мусорник и писать новый с нуля. Это будет гораздо быстрее, чем пытаться довести до ума изначально неудачный исходник.

А вообще, создание программы начинается далеко не с написания кода. Рекомендую:

  1. Проектирование - точное определение функциональности программы и ее структуры. Описание взаимодействия частей между собой.
  2. Подробная запись алгоритмов работы всех составных частей (по-русски).
  3. Перевод алгоритмов с русского на выбранный язык программирования (именно в результате этого этапа появляется код, а запись алгоритма по-русски превращается в комментарии к коду).
  4. Отладка (юнит-тест), в результате которой необходимо добиться, чтобы каждая из частей программы работала надлежащим образом). Сопровождается написанием большого по объему кода для тестирования, который потом не войдет в проект.
  5. Сборка программы из блоков - на этом этапе отлаживают взаимодействие блоков в программе.

Значит, не подойдёт, нужна именно для ардуино :frowning:

А чем для ардуино отличается от любой другой?