Помогите реализовать "каскадное" включение реле.

Jackson_KHV
Offline
Зарегистрирован: 15.02.2016

Всем здравствовать!

Помогите, пожалуйста, написать код для каскадного включения реле. Суть вот в чем:

Имеем 4 реле - r1, r2, r3, r4. Сидят на пинах с А0 по А3, соответственно в коде с 14 по 17-й пин. Необходимо их включение (подачи управляемого напряжения) в следующем порядке:

1. Ожидаем 20 минут (настраивается от 10 мин до 40 мин с шагом 1 мин)

2. Включаем реле 1 на время t1 (настраивается от 0,5 сек до 5,0 сек с шагом 0,5 сек

3. Если после включения реле1 прошло время t1 - t2 (t2 фиксированное 1 сек), включаем реле 2 (то есть работают 2 реле (1 и 2))

4. По завершению времени t1 выключаем реле 1 , реле 2 остается включенным на время t1

5.Если после включения реле2 прошло время t1 - t2 , включаем реле 3 (то есть работают 2 реле (2 и 3)) 

6. и т.д.

Ниже приведена простенькая диаграмма включения реле.

Вот такой код для двух реле (нужно 4)

#define r1 = 14;        // Реле 1 А0 
#define r2 = 15;        // Реле 2 А1
#define r3 = 16;        // Реле 3 А2
#define r4 = 17;        // Реле 4 А3

int tint = 20;              // В минутах!! Настраивается с 10 мин 
                            //до 40 мин с шагом 1 мин.
int t1 = 2000;              // В миллисекундах, настраиваемое с 500 мсек 
                            //до 5000 мсек с шагом 500 мсек
int t2 = 1000;              // В миллисекундах фиксированное 1000 мсек                            
unsigned long t0 = 0;       // Вспомогательная переменная

void setup() {
  pinMode(r1, OUTPUT);
  pinMode(r2, OUTPUT);
  pinMode(r3, OUTPUT);
  pinMode(r4, OUTPUT);
  t0 = millis();
}

void loop () {
  if (millis() - t0 > tint * 60000) {
    
	while (millis() - t0 < t1) {
      ​digitalWrite (r1, HIGH)
      if (millis() - t0 >= t1 - t2) {
        digitalWrite (r2, HIGH);
      }
    }
    digitalWrite (r1, LOW);
    t0 = millis();

    while (millis() - t0 < t1) {
      ​digitalWrite (r2, HIGH)
      if (millis() - t0 >= t1 - t2) {
        digitalWrite (r3, HIGH);
      }
    }
    digitalWrite (r2, LOW);
    t0 = millis();

    while (millis() - t0 < t1) {
      ​digitalWrite (r3, HIGH)
      if (millis() - t0 >= t1 - t2) {
        digitalWrite (r4, HIGH);
      }
    }
    digitalWrite (r3, LOW);
    t0 = millis();

    while (millis() - t0 < t1) {
      ​digitalWrite (r4, HIGH)
    }
    digitalWrite (r4, LOW);
    t0 = millis();
  }
}

Да, я понимаю, что код рабочий, но выглядит уж очень топорно. Возможно ли улучшение его вида, что ли? Пробовал прикрутить цикл for.., но там беда с переменными..

В общем выручайте, братцы!

Jackson_KHV
Offline
Зарегистрирован: 15.02.2016

Немного ошибся.. Там код для 4-х реле. И в диаграмме неточности, но суть верная.

bwn
Offline
Зарегистрирован: 25.08.2014

А делеи отменили? Результат тот же, только компактнее.))))

Green
Offline
Зарегистрирован: 01.10.2015

bwn пишет:

А делеи отменили? Результат тот же, только компактнее.))))


А функции?)

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

Лучшее враг хорошего )))

Jackson_KHV
Offline
Зарегистрирован: 15.02.2016

bwn пишет:

А делеи отменили? Результат тот же, только компактнее.))))

Нет, не отменили. Но, к сожалению, есть необходимость изменения t1. Да и дилэй не по фэн-шую, говорят..

Jackson_KHV
Offline
Зарегистрирован: 15.02.2016

С этим не поспоришь.. Но всё же думаю тут можно оптимизировать код так, чтобы он стал компактнее. Хотя вот вопрос нужно ли, если итак работает?..

Jackson_KHV
Offline
Зарегистрирован: 15.02.2016

Green пишет:

bwn пишет:

А делеи отменили? Результат тот же, только компактнее.))))


А функции?)

Вот-вот.. Функции изменять нужно. 

Хм.. А если написать, 

delay(t1);

Работать будет?

bwn
Offline
Зарегистрирован: 25.08.2014

Jackson_KHV пишет:

Да и дилэй не по фэн-шую, говорят..

Так ваши, зависшие циклы, от него ничем не отличаются.))))

-NMi-
Offline
Зарегистрирован: 20.08.2018

Развернуть весь цикл с квантом в одну секунду и оформить через иф или свич условия. И просто и ничо низависает.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

похоже что решение через автомат от ТС далековато.

-NMi-
Offline
Зарегистрирован: 20.08.2018

Кстати да, автомат там вообще красивый получится в виде одной функции. Вызывать по таймеру раз в секунду.

sadman41
Offline
Зарегистрирован: 19.10.2016

Секундный таймер Дед сегодня кому-то уже подарил.

Jackson_KHV
Offline
Зарегистрирован: 15.02.2016

-NMi- пишет:

Развернуть весь цикл с квантом в одну секунду и оформить через иф или свич условия. И просто и ничо низависает.

Благодарю! А можно поподробнее. Хотя бы в общих чертах.

 

Jackson_KHV
Offline
Зарегистрирован: 15.02.2016

-NMi- пишет:

Кстати да, автомат там вообще красивый получится в виде одной функции. Вызывать по таймеру раз в секунду.

Вот это мне и нужно! Всё свести к одной функции, но что то додуматься никак не могу. Просто ступор какой то ((

Jackson_KHV
Offline
Зарегистрирован: 15.02.2016

sadman41 пишет:

Секундный таймер Дед сегодня кому-то уже подарил.

А можно ссылку?

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

Jackson_KHV пишет:

sadman41 пишет:

Секундный таймер Дед сегодня кому-то уже подарил.

А можно ссылку?

Думаю, тебе пока не поможет, но на   https://github.com/DetSimen/Arduino_TimerList

Jackson_KHV
Offline
Зарегистрирован: 15.02.2016

DetSimen пишет:

Jackson_KHV пишет:

sadman41 пишет:

Секундный таймер Дед сегодня кому-то уже подарил.

А можно ссылку?

Думаю, тебе пока не поможет, но на   https://github.com/DetSimen/Arduino_TimerList

Благодарю! Именно оно, что и нужно было. Мы (с котом) уже разобрались и переделываем код.

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

с 1 таймером реле с А0 по А3 включаются последовательно на 2 секунды. Без сдвига.  Добавив второй таймер, можно включать их по очереди, со сдвигом, только я с утра не сабражаю ничо, может быть пожже.  А мошт и сам дагадаешь. 

/*
 Name:		RelayTest.ino
 Created:	03.03.2020 8:35:57
 Author:	DtS
*/
#include <Arduino.h>
#include <TimerList.h>

extern TTimerList TimerList;

const uint8_t MIN_RELAY_PIN = 14; // А0
const uint8_t MAX_RELAY_PIN = 17; // А3

const uint32_t t1_ms = 2000; // время включения реле 2 сек (2000 мс)

uint8_t CurrentRelay = MIN_RELAY_PIN;


THandle hT1Timer = INVALID_HANDLE;

void tmrT1Ends(void) {
	digitalWrite(CurrentRelay, LOW); // Выключается текущее реле
	CurrentRelay++;					 // Текущим становится следующее реле
	if (CurrentRelay > MAX_RELAY_PIN) CurrentRelay = MIN_RELAY_PIN; // или первое
	digitalWrite(CurrentRelay, HIGH); // включается текущее реле
	Serial.println(CurrentRelay);
}

// А если нада, чтоб реле сработали паочереди и остановились, тогда по другому

void tmrT1Ends_v2(void) {
	digitalWrite(CurrentRelay, LOW); // Выключается текущее реле
	CurrentRelay++;					 // Текущим становится следующее реле
	if (CurrentRelay <= MAX_RELAY_PIN)
		digitalWrite(CurrentRelay, HIGH); // включается текущее реле
	else
		TimerList.Stop(hT1Timer);  // или останавливается таймер
}


void setup() {
	Serial.begin(115200);
	delay(250);
	Serial.println("Application started.");

	digitalWrite(CurrentRelay, HIGH);          // включаем первое реле 
	hT1Timer = TimerList.Add(t1_ms, tmrT1Ends);// и взводим таймер на t1_ms миллисекунд
}

void loop() {
  
}

 

 

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Не хочу быть навязчивым, но возможно вам стоит попробовать PLC?

Дёшево и сердито, как раз для дилетантов типа меня:
http://arduino.ru/forum/obshchii/interesnoe-na-aliexpress-i-ebay-chast2?...

Jackson_KHV
Offline
Зарегистрирован: 15.02.2016

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

Ещё вопрос. Не совсем понятно как программируются эти реле? В каком то специальном софте?