Неблокирующий скетч

c++

Пока что часть этого кода работает нормально, но реле 1 то включается, то выключается, а не остается выключенным.

Моя цель — включить реле 7, подождать 3 с, включить реле 8, подождать 10 с, включить реле 6, подождать 10 с, выключить реле 7, подождать 10 с, включить реле 5, подождать 3 с, включить реле 6. выкл, подождите 10 с, включите реле 5, подождите 3 с, выключите реле 6, подождите 10 с, включите реле 4, подождите 3 с, выключите реле 5, подождите 10 с, включите реле 3, подождите 3 с, выключите реле 4, подождите 10 с , включите реле 2, подождите 3 секунды, выключите реле 3, подождите 10 секунд, включите реле 1, подождите 10 секунд, выключите реле 1, подождите 3 секунды, выключите реле 8, без зацикливания, только одна последовательность.

Мне нужна помощь.

int RelayPompe = 2;
int RelayVanne7 = 3;
int RelayVanne6 = 4;
int RelayVanne5 = 5;
int RelayVanne4 = 6;
int RelayVanne3 = 7;
int RelayVanne2 = 8;
int RelayVanne1 = 9;

const unsigned long eventInterval1 = 10000;
const unsigned long eventInterval2 = 3000;
const unsigned long eventInterval3 = 15000;
const unsigned long eventInterval4 = 20000;
unsigned long previousTime1 = 0;
unsigned long previousTime2 = 0;
unsigned long previousTime3 = 0;
unsigned long previousTime4 = 0;

void setup() {
  Serial.begin(9600);
  pinMode(RelayPompe, OUTPUT);
  pinMode(RelayVanne1, OUTPUT);
  pinMode(RelayVanne2, OUTPUT);
  pinMode(RelayVanne3, OUTPUT);
  pinMode(RelayVanne4, OUTPUT);
  pinMode(RelayVanne5, OUTPUT);
  pinMode(RelayVanne6, OUTPUT);
  pinMode(RelayVanne7, OUTPUT);
  digitalWrite(RelayPompe, HIGH);
  digitalWrite(RelayVanne1, HIGH);
  digitalWrite(RelayVanne2, HIGH);
  digitalWrite(RelayVanne3, HIGH);
  digitalWrite(RelayVanne4, HIGH);
  digitalWrite(RelayVanne5, HIGH);
  digitalWrite(RelayVanne6, HIGH);
  digitalWrite(RelayVanne7, HIGH);
}

void loop() {
  unsigned long currentTime = millis();
  if (currentTime - previousTime1 >= eventInterval1) {
    digitalWrite(RelayPompe, LOW);
    previousTime1 = currentTime;
  }
  if (currentTime - previousTime2 >= eventInterval2) {
    digitalWrite(RelayVanne1, LOW);
    previousTime2 = currentTime;
  }
  if (currentTime - previousTime3 >= eventInterval3) {
    digitalWrite(RelayVanne2, LOW);
    previousTime3 = currentTime;
  }
  if (currentTime - previousTime4 >= eventInterval4) {
    digitalWrite(RelayVanne1, HIGH);
    previousTime4 = currentTime;
  }
}

, 👍-1

Обсуждение

какое реле 1?, @jsotola

пожалуйста, пересмотрите то, что вы написали ... кажется, есть некоторые ошибки, @jsotola

@jsotola «RelayPompe имеет номер 1 и подключен к контакту 2 платы Arduino», @Agili

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

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

все равно не могу разобраться., @Agili

вы сказали «подождите 10 секунд, включите реле 5, подождите 3 секунды, включите реле 6» дважды подряд, @jsotola

это система полива, мне нужно сначала включить реле 1, которое подключено к электромагнитному клапану 1, затем включить реле 8, которое подключено к водяному насосу, и оставить его включенным до конца последовательности, затем включить реле 2 - электромагнитный клапан 2 через 3 секунды выключить реле 1. затем через 10 с включите реле 3-электромагнитный клапан 3, затем через 3 с выключите реле 2 ... до реле 8-электромагнитный клапан 8, в конце выключите реле 8-водяной насос и завершите последовательность. кстати, 3s и 10 только для тестирования позже будут изменены на более длительный период, @Agili


1 ответ


2

Для такого рода вещей я был бы склонен создать массив (возможно, структур), описывающий, что вы хотите, чтобы реле делали, а затем написать программу, которая проходит через этот массив, выполняя каждую "инструкцию" в последовательности. Таким образом, он отделяет то, что вы хотите сделать, от того, как вы хотите, чтобы это было сделано (если это имеет смысл).

Итак, вы можете создать простую структуру:

typedef struct {
    uint8_t relays;
    uint32_t postDelay;
} RelayState;

Затем вы можете создать массив, используя эту структуру для описания ваших состояний реле. Использование растрового изображения для ваших реле (бит 0 — это реле 1, бит 1 — это реле 2 и т. д.) означает, что вы можете упаковать все в одно целое число и описать реле в двоичной записи:

RelayState states[] = {
    { 0b01000000,  3000 }, // Реле 7 включено, подождите 3 секунды
    { 0b11000000, 10000 }, // Реле 8 включено, подождите 10 секунд
    { 0b11100000, 10000 }, // Реле 6 включено, подождите 10 секунд
    { 0b10100000, 10000 }, // Реле 7 выключено, подождите 10 секунд
    { 0b10110000,  3000 }, // Реле 5 включено, подождите 3 секунды
    // ... так далее ...
    { 0, 0 } // Маркер конца массива
};

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

Также может быть полезно создать массив контактов реле:

const uint8_t relayPins[8] = { 9, 8, 7, 6, 5, 4, 3, 2 };

Теперь вам просто нужно написать небольшую программу, которая должна иметь дело только с текущей записью в массиве - установить реле в соответствии с первой частью, затем задержать в соответствии со второй частью и перейти к следующей записи. Что-то вроде:

void setup() {
    // Установить выводы реле на выходы
    for (int i = 0; i < 8; i++) {
        pinMode(relayPins[i], OUTPUT);
    }

    // Устанавливаем начальное состояние из первой записи в массиве
    setRelays(states[0].relays);
}

void loop() {
    static uint32_t ts = millis(); // Память на время
    static uint8_t pos = 0; 

    if ((millis() - ts) >= states[pos].postDelay) { // Наше время истекло
        ts = millis(); // Записываем время
        pos++; // переход к следующей записи
        if ((states[pos].relays == 0) && (states[pos].postDelay == 0)) { // Маркер последнего входа
            pos = 0; // Начнем снова с начала
        }
        setRelays(states[pos].relays);
    }
}

// Небольшая вспомогательная функция для установки реле в соответствии с растровым изображением
void setRelays(uint8_t bm) {
    for (int i = 0; i < 8; i++) {
        digitalWrite(relayPins[i], bm & (1 << i));
    }
}

Примечание: этот код не тестировался, он просто написан "экспромтом" и может даже не компилироваться. Но в любом случае это должно дать вам общее представление о методологии.


Формат растровых изображений очень прост. Это просто двоичное представление числа, где каждый бит соответствует одному реле. Включите этот бит, и соответствующее реле включится.

  • Ретранслятор 1: 0b00000001
  • Ретранслятор 2: 0b00000010
  • Реле 3: 0b00000100

и т. д. Просто установите 1, чтобы реле было включено, и 0, чтобы реле было выключено в этот момент времени.

Итак, включение реле 1 – это 0b00000001, затем включение реле 4 – 0b00001001, а затем повторное выключение реле 1 – 0b00001000 (реле 4 все еще включено).

,

Я понял, мне нужно написать весь двоичный код для всех контактов, я попробую, @Agili

Пожалуйста, объясните мне, как добавить больше записей в массив: {0b01000000, 3000}, @Agili

что такое {0b01000000, 3000} и как добавить все реле?, @Agili

0bxxxxxxxx — это состояние каждого из 8 реле. 3000 - это сколько мс задержать., @Majenko

3000 - это задержка мс, но 0bxxxxxxxx, как добавить все 8 реле, которые управляют для ее создания?, @Agili

Решите, какие реле вы хотите включить, а какие выключить — реле 8 слева, а реле 1 справа. 1 для включения, 0 для выключения. Таким образом, включение реле 1, 5 и 7 будет 0b01010001., @Majenko