Как закодировать 4 реле, чтобы они срабатывали с интервалами, а не последовательно?

Код:

//ДЛЯ АЭРОПОННОЙ СИСТЕМЫ С ДАТЧИКОМ КОМНАТНОЙ ТЕМПЕРАТУРЫ И ВЛАЖНОСТИ
//И 4 КАМЕРЫ ДЛЯ ВЫРАЩИВАНИЯ С РАЗНЫМ ВРЕМЕНЕМ ОПРЫСКИВАНИЯ

// УПРАВЛЕНИЕ РЕЛЕ
#define RELAY1_PIN 2
#define RELAY2_PIN 3
#define RELAY3_PIN 4
#define RELAY4_PIN 5

//Библиотеки
#include <DHT.h>;

//Константы
#define DHTPIN 6
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

//Переменные
int chk;
float hum;
float temp;

void setup()
{
    Serial.begin(9600);
    Serial.println("SENSOR RUNNING");
    dht.begin();

    pinMode(RELAY1_PIN, OUTPUT);
    pinMode(RELAY2_PIN, OUTPUT);
    pinMode(RELAY3_PIN, OUTPUT);
    pinMode(RELAY4_PIN, OUTPUT);
}

void loop()
{
    delay(2000);
    float h = dht.readHumidity();
    float t = dht.readTemperature();
    if (isnan(h) || isnan(t))
    {
        Serial.println("CONNECTION ERROR");
        return;
    }
    Serial.print("Humidity: ");
    Serial.print(h);
    Serial.print(" %\t");
    Serial.print("Temperature: ");
    Serial.print(t);
    Serial.print(" *C ");
    Serial.println(" ");
    delay(2*1000);
    {
        // ДЛЯ РЕЛЕ
        digitalWrite(RELAY1_PIN, HIGH);
        delay(2*1000); // ждать 2 секунды ON
        digitalWrite(RELAY2_PIN, HIGH);
        delay(3*1000); // ждем 3 секунды ON
        digitalWrite(RELAY3_PIN, HIGH);
        delay(4*1000); // ждем 4 секунды ON
        digitalWrite(RELAY4_PIN, HIGH);
        delay(5*1000); // ждем 5 секунд ON

        digitalWrite(RELAY1_PIN, LOW);
        digitalWrite(RELAY2_PIN, LOW);
        digitalWrite(RELAY3_PIN, LOW);
        digitalWrite(RELAY4_PIN, LOW);
        delay(5*60*1000); 
    }
}

Этот код не делает того, что я хочу. Как сделать их независимыми?

, 👍1

Обсуждение

Пожалуйста, разместите актуальный **вопрос**, а не код. Чего вы хотите добиться на самом деле? Я и многие другие не станем смотреть на ваш код, пока не узнаем, что нам нужно ответить. Если вы четко объясните свою проблему, а затем зададите конкретный вопрос, это, скорее всего, поможет., @morbo

Сделайте правильный отступ в коде. Как бы то ни было, он никак не скомпилируется, и, как вы должны видеть, следить за потоком исключительно сложно., @stevieb

подумайте о своем заголовке ... требование «не в последовательности» не имеет смысла ... что, если «в интервалах» окажется «в последовательности» ... вы хотите предотвратить активацию реле, если это произойдет?, @jsotola

Хотя вопрос **далеко** не ясен, похоже, ответ может заключаться в том, чтобы вы научились [Мигать без задержки](https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay)., @Edgar Bonet


1 ответ


Лучший ответ:

1

Вот код, который может вам помочь; не говоря о температуре и влажности:

// константы
// число или реле
const int relays = 4;

// выводы для реле
const int relayPins[] = {2, 3, 4, 5};

// время цикла реле
const unsigned long relayTimes[] = {
     5*60*1000, // 5 мин
     60*60*1000, // 1 час
     2*60*60*1000, // 2 часа
     12*60*60*1000 // 12 часов
  };

// реле длительности
const unsigned long relayOntimes[] = {
    1000, // 1 секунда
    10*1000, // 10 секунд
    60*1000, // 1 минута
    60*60*1000 // 1 час
  };

// время для реле
// сохраняем последний раз
unsigned long relayElapsed[] = {0, 0, 0, 0};

// состояние каждого реле
int relaystate[] = {0, 0, 0, 0};

// вспомогательная функция для обработки каждого реле
void relay_helper(unsigned long t, unsigned long &elapsed, int pin, int &state, unsigned long delta, unsigned long ontime)
{
  // в зависимости от состояния мы делаем разные вещи
  switch (state)
  {
  case 0: // состояние 0 выключено, подождите, пока не пройдет время
    if ((t-elapsed) > delta)
    {  // затем
       state = 1; // установить состояние на
       elapsed = t; // сбросить время
       digitalWrite(pin, HIGH); // включать
    }
    break;
  case 1: // состояние 1 включено, подождите, пока не пройдет время
    if ((t-elapsed) > ontime)
    {  // затем
       state = 0; // устанавливаем состояние выключено
       elapsed = t; // сбросить время
       digitalWrite(pin, LOW); // выключать
    }
    break;
  }
}

void setup()
{
  unsigned long start = millis();
  for(int i = 0; i < relays; i++) // для каждого вывода
  {
    pinMode(relayPins[i], OUTPUT); // установить его для вывода
    digitalWrite(relayPins[i], LOW); // и выключаем
    relayElapsed[i] = start;
  }
}

void loop()
{
  unsigned long tm = millis();
  for(int i = 0; i < relays; i++)
  {
    relay_helper(tm, relayElapsed[i], relayPins[i], relaystate[i], relayTimes[i], relayOnTimes[i]);
  }
  // делаем другие циклы
}

Основная идея заключается в том, что единственный способ делать что-то одновременно — это очень быстро делать что-то последовательно, мы не можем использовать delay(), потому что это цикл занятости, во время delay() больше ничего не может произойти, поэтому мы следите за временем и когда пора включать реле мы его включаем, а когда пора выключать выключаем.

Еще один вариант — написать класс для каждого ретранслятора:

class Relay
{
public:
  Relay(int pin, unsigned long delta, unsigned long ontime);
  ~Relay();

  process(unsigned long t);

private:
  unsigned long delta;
  unsigned long ontime;
  unsigned long last; // истекло
  int pin;      
};

Затем можно создать массив из них:

Relay[] relays = {
    Relay(2, 5*60000, 1000),
    Relay(3, 60*60000, 10000),
    Relay(4, 2*60*60000, 60000),
    Relay(5, 12*60*60000, 60*60000)
  };

поместите код из setup в конструктор, а код из помощника в процесс и, наконец, вызовите его в цикле в цикле.

Первый показанный способ — это то, как это можно было бы сделать без классов C++, а второй — с ними!

,