Зависает Arduino Nano через ≈ 8-12 часов.

Chicony72
Offline
Зарегистрирован: 29.09.2021

Доброго времени суток! Возникла необходимость собрать приточно-вытяжную вентиляцию, ну и до кучи прикрутить датчик движения для управления светом. Систему "климат-контроля" собрал из : arduino nano, 4-х канального релейного модуля, датчика DHT-11 и PIR датчика (типа НС-SR501). Собрал систему написал скетч вроде работает, но через 8-12 часов после запуска "зависает" (светятся светодиоды: power и L(13 PIN), TX не моргает). Если перезагрузить по питанию, то работает опять 8-12 часов. Не могу понять почему зависает. Это мой первый код на millis(), думаю что мог где создать абсурдное условие которое приводит к зависанию. Код:

#include "DHT.h"

#define DHTPIN 12
#define PIN_PIR 7
#define PIN_LED 4
#define PIN_RELAY1 2
#define PIN_RELAY2 3
#define PIN_BUTT 8

#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

static uint32_t myTimer1, myTimer2, myTimer3, myTimer4, period;
static byte mode = 0;
boolean butt_flag = 0;
boolean butt;
boolean relay_flag = 0;

void setup() {
  pinMode(6, OUTPUT);digitalWrite(6, LOW);
  pinMode(8, OUTPUT);
  pinMode (PIN_BUTT, INPUT_PULLUP);
  pinMode(PIN_PIR, INPUT);
  pinMode(PIN_LED, OUTPUT);
  pinMode(PIN_RELAY1, OUTPUT);digitalWrite(PIN_RELAY1, HIGH);
  pinMode(PIN_RELAY2, OUTPUT);digitalWrite(PIN_RELAY2, HIGH);
  pinMode(11, OUTPUT);digitalWrite(11, HIGH);
  dht.begin();
  Serial.begin(9600);
}
void loop() {

  // каждую секунду
  if (millis() - myTimer3 >= 1000) {
    myTimer3 = millis(); // сбросить таймер
    toggleLED();
  }
  if (millis() - myTimer2 >= 1000) {
    myTimer2 = millis(); // сбросить таймер
    humid();
  }

 if (millis() - myTimer4 >= 1000) {
    myTimer4 = millis(); // сбросить таймер
    butt = !digitalRead(PIN_BUTT);
  if(butt == 1 && butt_flag == 0) {
    butt_flag = 1;
    relay_flag = !relay_flag;
    
  }
  if (butt == 0 && butt_flag == 1) {
    butt_flag = 0;
  }
  Serial.println(F("Relay: "));
  Serial.println(relay_flag);}
  digitalWrite(13, relay_flag);
  }
  

void toggleLED() {
  int pirVal = digitalRead(PIN_PIR);
   Serial.println("Motion:");
   Serial.println(pirVal);
   Serial.println("Mode:");
   Serial.println(mode);
  //Если обнаружили движение
  if (pirVal == 0)
  {
    digitalWrite(PIN_LED, HIGH);
  }
  else
  {
    digitalWrite(PIN_LED, LOW);
  }
}
void humid() {
   float h = dht.readHumidity();
Serial.println(F("Humidity: "));
  Serial.println(h);
  digitalWrite(6, HIGH);
  if (h >= 65 || relay_flag == 1){
    if (millis()-myTimer1 >= period){
      myTimer1 = millis();
      if (++mode >= 5) mode = 0;
      switch (mode) {
        case 0: digitalWrite(PIN_RELAY1, HIGH); period = 500; break;
        case 1: digitalWrite(PIN_RELAY1, LOW); period = 90000; break;
        case 2: digitalWrite(PIN_RELAY1, HIGH); period = 500; break;
        case 3: digitalWrite(PIN_RELAY2, LOW); period = 90000; break;
        case 4: digitalWrite(PIN_RELAY2, HIGH); period = 500; break;
      }
}
 }else if(h < 65 || relay_flag == 1){
  digitalWrite(PIN_RELAY1, HIGH);
  digitalWrite(PIN_RELAY2, HIGH);
  mode = 0;
 }
 }

Логика работы: при повышении влажности более 65% попеременно включаются реле1 (вытяжка) и реле2 (приточка) до тех пор пока не будет ниже 65%, и второе условие если нажать кнопку то реле переключаются до повторного нажатия. Параллельно этому отслеживается движение и по нему включается реле3 (лампа).

Спасибо за внимание!

P.S. Питание от адаптера на пин 5+.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

WatchDog включи и забей на свой говнокод.

Alex_Ferrum
Offline
Зарегистрирован: 04.05.2015

Возможно помимо программной части, зависание возникает из-за помех по питанию, у вас там несколько реле, возможно вы включаете и выключает двигатель. Решение именно в данном случае - повесить около пинов питания контроллера батарею из керамики микрофарад на 100 и поставить запирающий диод, чтобы не допустить просадок напряжения питания контроллера.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

керамика на 100 микрофарад! За троллинг зачёт!!!

b707
Offline
Зарегистрирован: 26.05.2017

Chicony72 скорее всего наводки от реле, в коде явных проблем не вижу.

Комбинируйте советы #1 и #2: добавить конденсаторы по питанию на 10-100 мкФ, керамику 104-105 на каждый вход, на каждое реле по диоду в обратной полярности.

Ну и ватчдог обязательно.

Alex_Ferrum
Offline
Зарегистрирован: 04.05.2015

ua6em пишет:

керамика на 100 микрофарад! За троллинг зачёт!!!


Да это не троллинг, я из таких конденсаторов:
https://www.chipdip.ru/product0/9000591944
паял батареи 7х7, итого 7х7х10мкф=490 микрофарад.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Может и не троллинг, но от помех от двигателя сомнительная польза. Скорее всего человек имел ввиду нанофарады. 

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Если советы выше про конденсаторы не помогут, можно ещё попробовать отключать части схемы, как программно, так и электрически.

Скажем, отключить библиотеку , вместо датчика выключатель с резисторами на пин.  Вкл-  влажность больше 65% Выкл- меньше.

Так же и электрически, отключить  реле, оставить светодиоды...Проверить работу программы, без периферии

Само - собой проверить источники питания, оптопара на управление реле очень желательна

Смысл в том, чтобы определить , где именно косяк

ata3d
Offline
Зарегистрирован: 24.05.2017

У меня было что то похожее, через пару дней зависало, оказалось что датчик влажности и температуры AMC2315 при длинных периодах считывания зависал, уменьшил период считывания и все работает. Датчик куплен в Китае, один из самых дорогих в нижнем сегменте, скорее всего клон.

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

Alex_Ferrum пишет:
и поставить запирающий диод, чтобы не допустить просадок напряжения питания контроллера.

ладно с кондером бог с ним, а вот  про диод можно поподробней, просто кусочек схемы?

ddr2
Offline
Зарегистрирован: 27.12.2020
Питание от адаптера на пин 5+.

Есть адаптеры с такими помехами, что 8 часов для Nano неплохой результат.

Вобщем нужно:

1) Найти адаптер с низкими помехами.
2) поставить фильтр на вход. 
3) Включить Watchdog.