BT-выключатель. Помогите с кодом, зависает Адруина

Kest430
Offline
Зарегистрирован: 21.06.2016

Всем здрасьте.

На даче есть 4 прожектора, установленные вокруг дома. Раньше они "окучивались" китайский радио-выключателем с Алиэкспресса, но пережив одну зиму сдох. Решил сделать тоже самое на Ардуине (дальше буду допиливать функционал погодной станции)

 

Итак имею: Arduino Nano v.3, релейный модуль на 4 реле, bt-модуль hc-05, модуль расширения портов на PCF8574, два БП (1А и 2А), 5 кнопок и 6 светодиодов.

Arduino питается от БП на 1А (длина соединительных проводов ~10см), все остальное питается от второго БП на 2А. GNDестетсвенно соединены.

Релейный модуль подключен к Ардуино витой парой (~10 см) по паре на каждый канал реле, bt-модуль - витой парой ~ 8 метров (по паре на GND, +5, RX и TX), модуль расширения портов на PCF8574 - витой парой ~ 3 метра (по паре на GND, +5, SDA и SCL), диоды подключены к PCF8574, кнопки - витой парой ~ 3 метра к Ардуино с подтяжкой к GND

 

Проблема в том, что поработав от 30 минут до часа Ардуина вешается.

Вот код. Помогите разобраться почему

 

byte RELAY[4] = {9, 10, 11, 12};                                                    // пины к которым подключены Реле
byte LED[6]   = {0, 1, 2, 3, 6, 7};                                                 // пины PCF8574 0x3F к которым подключены LEDы

//___ все для работы с кнопками и LED'ами __________________________________________
#include <PCF8574.h>                                                                // Библиотека для PCF8574
#include <Wire.h>
PCF8574 LEDs;
#include <Button.h>                                                                 // титановый велосипед для тактовой кнопки by Клапауций
Button Keys;

void setup()
{
  Serial.begin(57600);

  //___ все для работы с реле ______________________________________________________
  for (byte i = 0; i < sizeof (RELAY - 1); i++)                                     // указываем пины, к которым подключены Relay как вывод и выкл их
  {
    pinMode (RELAY[i],  OUTPUT);                                                    // Инициализируем пин как выход
    digitalWrite (RELAY[i], HIGH);                                                  // Выключаем Реле
  }

  pinMode(13, OUTPUT);


  //___ все для работы с LED'ами через PCF8574 _____________________________________
  LEDs.begin(0x3F);                                                                 // Инициализируем PCF8574 по адресу 0x3F с именем LEDs
  for (byte i = 0; i < sizeof (LED); i++)                                           // указываем пины, к которым подключены LED как вывод и выкл их
  {
    LEDs.pinMode (LED[i],  OUTPUT);                                                 // Инициализируем пин как выход
    LEDs.digitalWrite (LED[i], HIGH);                                               // Выключаем LED
  }
  LEDs.digitalWrite (LED[4], LOW);

  //___ все для работы с кнопками __________________________________________________
  Keys.button (4, 5, 6, 7, 8);                                                      // Указываем пины, к которым подключены кнопки
  Keys.duration_bounce          (5);
  Keys.duration_click_Db      (250);
  Keys.duration_inactivity_Up(5000);
  Keys.duration_inactivity_Dn(1000);


}

void loop()
{
  Use_Keys();                                                                       // Использование кнопок
  Use_Bluetooth();                                                                  // Получение комманд по Bluetooth'У
}

////////////////////////////////////////////////////////////////////////////////////
//                    Использование кнопок                                        //
////////////////////////////////////////////////////////////////////////////////////
void Use_Keys()
{
  Keys.read();

  if (Keys.button[0].event_click_Up() == 1) DoIt (0);
  if (Keys.button[1].event_click_Up() == 1) DoIt (1);
  if (Keys.button[2].event_click_Up() == 1) DoIt (2);
  if (Keys.button[3].event_click_Up() == 1) DoIt (3);
  if (Keys.button[4].event_click_Up() == 1)
  {
    if (digitalRead (RELAY[0]) == HIGH && digitalRead (RELAY[1]) == HIGH && digitalRead (RELAY[2]) == HIGH && digitalRead (RELAY[3]) == HIGH)
    { // Если ВСЕ реле были выключены, то включаем ВСЕ
      for (byte i = 0; i < sizeof (RELAY - 1); i++)
      {
        digitalWrite (RELAY[i],  LOW);                                          // включи RELAY
        LEDs.digitalWrite (LED[i], LOW);                                        // включи LED
      }
      LEDs.digitalWrite(6, HIGH);                                               // Выключаем LED_Wait_1
      LEDs.digitalWrite(7, HIGH);                                               // Выключаем LED_Wait_2
    }
    else
    {
      if (digitalRead (RELAY[0]) == LOW || digitalRead (RELAY[1]) == LOW || digitalRead (RELAY[2]) == LOW || digitalRead (RELAY[3]) == LOW)
      { // если ХОТЯ БЫ ОДНО реле было включено, то выключаем ВСЕ
        for (byte i = 0; i < sizeof (RELAY - 1); i++)
        {
          digitalWrite (RELAY[i],  HIGH);                                          // выключи RELAY
          LEDs.digitalWrite (LED[i], HIGH);                                        // выключи LED
        }
        LEDs.digitalWrite(6, LOW);                                                 // Включаем LED_Wait_1
        LEDs.digitalWrite(7, LOW);                                                 // Включаем LED_Wait_2
      }
    }
  }
}

////////////////////////////////////////////////////////////////////////////////////
//                    Получение комманд по Bluetooth'у                            //
////////////////////////////////////////////////////////////////////////////////////
void Use_Bluetooth()
{
  if (Serial.available() > 0)
  {
    switch (Serial.read())
    {
      case '1':                                                                     // Если прилетела '1'
        DoIt (0);
        break;
      case '2':                                                                     // Если прилетела '2'
        DoIt (1);
        break;
      case '3':                                                                     // Если прилетела '3'
        DoIt (2);
        break;
      case '4':                                                                     // Если прилетела '4'
        digitalWrite (PIN_RELAY_4, !digitalRead (PIN_RELAY_4));                     // Переключи РЕЛЕ_4
        //        LEDs.digitalWrite (3, digitalRead (PIN_RELAY_4));                           // включи/выключи LED_4
        //        Wait_LEDs();
        break;
      case '0':                                                                     // Если прилетел '0'
        if (digitalRead (RELAY[0]) == HIGH && digitalRead (RELAY[1]) == HIGH && digitalRead (RELAY[2]) == HIGH && digitalRead (RELAY[3]) == HIGH)
        { // Если ВСЕ реле были выключены, то включаем ВСЕ
          for (byte i = 0; i < sizeof (RELAY - 1); i++)
          {
            digitalWrite (RELAY[i],  LOW);                                          // включи RELAY
            LEDs.digitalWrite (LED[i], LOW);                                        // включи LED
          }
          LEDs.digitalWrite(6, HIGH);                                               // Выключаем LED_Wait_1
          //LEDs.digitalWrite(7, HIGH);                                               // Выключаем LED_Wait_2
        }
        else
        {
          if (digitalRead (RELAY[0]) == LOW || digitalRead (RELAY[1]) == LOW || digitalRead (RELAY[2]) == LOW || digitalRead (RELAY[3]) == LOW)
          { // если ХОТЯ БЫ ОДНО реле было включено, то выключаем ВСЕ
            for (byte i = 0; i < sizeof (RELAY - 1); i++)
            {
              digitalWrite (RELAY[i],  HIGH);                                          // выключи RELAY
              LEDs.digitalWrite (LED[i], HIGH);                                        // выключи LED
            }
            LEDs.digitalWrite(6, LOW);                                               // Включаем LED_Wait_1
            //LEDs.digitalWrite(7, LOW);                                               // Включаем LED_Wait_2
          }
        }
        break;
    }
  }
}



void DoIt (byte PIN)
{
  digitalWrite (RELAY[PIN], !digitalRead (RELAY[PIN]));                              // Переключи РЕЛЕ[pin]
  LEDs.digitalWrite (LED[PIN], digitalRead (RELAY[PIN]));                            // Включи/выключи LED[pin]
  // Если ВСЕ реле выключены, то включаем Wait_LED'ы
  if (digitalRead (RELAY[0]) == HIGH && digitalRead (RELAY[1]) == HIGH && digitalRead (RELAY[2]) == HIGH && digitalRead (RELAY[3]) == HIGH)
  {
    LEDs.digitalWrite(6, LOW);                                                       // Выключаем LED_Wait_1
    //    LEDs.digitalWrite(7, LOW);                                                     // Выключаем LED_Wait_2
  }
  // Если ХОТЯ БЫ ОДНО реле включено, то выключаем Wait_LED'ы
  if (digitalRead (RELAY[0]) == LOW || digitalRead (RELAY[1]) == LOW || digitalRead (RELAY[2]) == LOW || digitalRead (RELAY[3]) == LOW)
  {
    LEDs.digitalWrite(6, HIGH);                                                      // Включаем LED_Wait_1
    //    LEDs.digitalWrite(7, HIGH);                                                      // Включаем LED_Wait_2
  }
}

 

Kest430
Offline
Зарегистрирован: 21.06.2016

еще немного вводных:

Есть пульт, на котором расположены 5 кнопок и 6 диодов. Четыре кнопки (button[0], [1], [2] и [3]) и четыре LEDa (LED[0], [1], [2] и [3]) соответствуют релешкам RELAY[0], [1], [2] и [3]. Еще два LEDa (LED[4] и [5]) работают как "ночник". Если выключены все реле, то LEDы 4 и 5 включены, если включено хотя бы одно реле, то включен соответствующий ему LEDa, а LEDы 4 и 5 - выключены. Нажание кнопок 0, 1, 2 и 3 меняет состояние соответствующего реле и соответствующего LEDa. Нажатие кнопки 4 вЫключает ВСЕ реле если было включено ХОТЯ БЫ одно из них или включает все реле, если НИ одно из них не было включено.

Команды по блютусу работают так же.

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

Почти наверняка наводки по длинной витой паре.

Собственно, тут два пути. Можно лечить болезнь, а можно последствия.

Более правильно, конечно, болезнь - ставить фильтры на кабели и фильтровать помехи. Сложно и муторно.

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

 

ЗЫ - сорри, код не смотрел

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

1. Непонятно, что означает "(по паре на GND, +5, RX и TX)". Пара - это два провода, куда один, куда другой?

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

Kest430
Offline
Зарегистрирован: 21.06.2016
andriano пишет:
1. Непонятно, что означает "(по паре на GND, +5, RX и TX)". Пара - это два провода, куда один, куда другой?
"классическая" витая пара - это 8 проподников, свитых попарно. Так вот я использовал синюю пару в качестве проводника GND, коричневую - +5V, оранжевую - RX и зеленую - TX. Вот что я имел в виду.
 
andriano пишет:
и передачи сигнала на расстояние, исчисляемое метрами, обычно используют не напряжение, а токовую петлю.
Честно говоря вот тут я не понял
 
b707 пишет:
Почти наверняка наводки по длинной витой паре.
Собственно так и получилось. Вчера был на даче, отключил от Ардуины BT-модуль. После этого 1,5 дня все шарашило на ура. Буду переносить BT-модуль ближе к Ардуине и удлинять антену модулю, чтобы ловило с того места, откуда я хотел.
andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Kest430 пишет:

andriano пишет:
1. Непонятно, что означает "(по паре на GND, +5, RX и TX)". Пара - это два провода, куда один, куда другой?
"классическая" витая пара - это 8 проподников, свитых попарно. Так вот я использовал синюю пару в качестве проводника GND, коричневую - +5V, оранжевую - RX и зеленую - TX. Вот что я имел в виду.
Все равно не понял - как подключен каждый второй из проводников пары?
Скажем, если оранжевый - RX, то куда оранжевыо-белый? Я надеюсь, все-таки на землю? Но зачем тогда на землю еще и синий?
Цитата:
 
andriano пишет:
и передачи сигнала на расстояние, исчисляемое метрами, обычно используют не напряжение, а токовую петлю.
Честно говоря вот тут я не понял
 
А чего непонятного? Если не знаете, что такое "токовая петля" - гуглите.
Kest430
Offline
Зарегистрирован: 21.06.2016

andriano пишет:
Kest430 пишет:
andriano пишет:
1. Непонятно, что означает "(по паре на GND, +5, RX и TX)". Пара - это два провода, куда один, куда другой?
"классическая" витая пара - это 8 проподников, свитых попарно. Так вот я использовал синюю пару в качестве проводника GND, коричневую - +5V, оранжевую - RX и зеленую - TX. Вот что я имел в виду.
Все равно не понял - как подключен каждый второй из проводников пары?

Скажем, если оранжевый - RX, то куда оранжевыо-белый? Я надеюсь, все-таки на землю? Но зачем тогда на землю еще и синий?
"...я использовал синюю пару...", т.е. синий + бело-синий = GND, коричневый + б-коричневый = +5v, оранжевый + б-оранжевый = RX, зеленый + б-зеленый = TX.
 
andriano пишет:
и передачи сигнала на расстояние, исчисляемое метрами, обычно используют не напряжение, а токовую петлю.
Честно говоря вот тут я не понял[/quote]
А чего непонятного? Если не знаете, что такое "токовая петля" - гуглите.[/quote]я сначала написал коммент, а потом полез сразу гуглить.
andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Так какой тогда смысл в витой паре?

Обычно как раз один из проводов пары используется для каких-либо целей, а второй - для заземления. Тогда уровень помех существенно ниже.

Kest430
Offline
Зарегистрирован: 21.06.2016

andriano пишет:

Так какой тогда смысл в витой паре?

Обычно как раз один из проводов пары используется для каких-либо целей, а второй - для заземления. Тогда уровень помех существенно ниже.

теперь буду знать, СПАСИБО!