Использование millis вместо задержки перезагрузки реле

Я хочу перезагрузить реле (выключить, подождать 4 секунды и включить) он отлично работает, если я использую задержку (4000), но код блокируется во время задержки (4 секунды), и я не могу запустить реле 2. Как я могу использовать Millis вместо задержки, чтобы перезагрузить реле 1 и запустить реле 2 одновременно?

#include <SPI.h>
#include <Ethernet.h>
#include <Wire.h>
#include <EthernetUdp.h> //Загружаем UDP-библиотеку

// Ethernet
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; //Назначаем mac адрес
IPAddress ip(192, 168, 1, 178); // Назначаем IP-адрес
unsigned int localPort = 80; // Назначаем порт для разговора
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; // размер массива символов для хранения нашего пакета данных
String datReq; //Строка для наших данных
int packetSize; //Размер пакета
EthernetUDP Udp; // Создаем объект UDP // порт сервера
String readString;

bool relayState = false;
// определяем контакты реле
int relay_1 = 22;
int relay_2 = 24;

void setup() {
  Serial.begin(9600);
  Ethernet.begin(mac, ip);
  Udp.begin(localPort); //Инициализировать UDP
  delay(2000);

  //Исходное состояние реле
  pinMode(relay_1, OUTPUT); digitalWrite(relay_1, LOW); // реле 1 включено
  pinMode(relay_2, OUTPUT); digitalWrite(relay_2, HIGH);//реле 2 выключено


}

void loop() {

  packetSize = Udp.parsePacket(); //Чтение размера пакета
  if (packetSize > 0) { //если packageSize >0, значит кто-то отправил запрос
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE); //Чтение запроса данных
    String datReq(packetBuffer); // Преобразование массива символов packetBuffer в строку с именем datReq
    //Serial.println(datReq);

    if (datReq == "relay1reboot") { //перезагрузить реле
      digitalWrite(relay_1, HIGH);//реле выключено
      delay(4000); 
      digitalWrite(relay_1, LOW);//реле включено

      Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); //Инициализируем отправку пакета
      Udp.print("relay 1 reboot");
      Udp.endPacket(); //Конец пакета

    }
    if (datReq == "relay2on") {
      digitalWrite(relay_2, LOW);//реле 2 включено
      Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); //Инициализируем отправку пакета
      Udp.print("relay 2 on");
      Udp.endPacket(); //Конец пакета
    }
    if (datReq == "relay1on") {
      digitalWrite(relay_1, LOW);//реле 2 включено
      Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); //Инициализируем отправку пакета
      Udp.print("relay 1 on");
      Udp.endPacket(); //Конец пакета
    }
    // Используйте снимок, чтобы установить время отслеживания до следующего события
    //предыдущий Миллис = текущий Миллис;
  }
}

//}
memset(packetBuffer, 0, UDP_TX_PACKET_MAX_SIZE); //очищаем массив packetBuffer

}

, 👍0

Обсуждение

"перезагрузка" - это термин, относящийся к программируемым устройствам, таким как компьютеры... он не применяется к простому реле... имело бы смысл сказать "я хочу включить реле", @jsotola


1 ответ


2

Общий подход к удалению delay() заключается в замене его некоторым кодом. что:

  • обратите внимание, что некоторые действия (независимо от того, что следует за delay()) будут иметь будет выполнено в будущем

  • принимает к сведению текущее время.

Затем где-то еще в loop() вы проверяете, не произошло ли это «какое-то действие». нужно сделать прямо сейчас и, если это так, делает это.

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

bool relay1isRebooting = false;
unsigned long relay1rebootStarted;

void loop() {
  packetSize = Udp.parsePacket();
  if (packetSize > 0) { //мы получили пакет
    // ...
    if (datReq == "relay1reboot") {
      digitalWrite(relay_1, HIGH); // реле выключено
      relay1isRebooting = true;
      relay1rebootStarted = millis();
    }
    // ...
  }

  // Включите обратно реле 1, если необходимо.
  if (relay1isRebooting && millis() - relay1rebootStarted >= 4000) {
      digitalWrite(relay_1, LOW); //реле на
      relay1isRebooting = false;
      Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
      Udp.print("relay 1 reboot");
      Udp.endPacket();
  }
}

Обратите внимание, что тест на предмет того, следует ли включить реле 1 в обратном направлении on выполняется вне блока if (packetSize > 0). Также обратите внимание, что relay1rebootStarted имеет допустимое значение, только если relay1isRebooting истина.

,

для продвинутых кодеров: я обычно использую только переменную для миллисекунд. если он равен 0, таймер не работает. if (relay1rebootStarted && millis() - relay1rebootStarted >= RELAY_DELAY), @Juraj

@Juraj: мне не нравится такой подход. Ноль является законным возвращаемым значением для millis(), которое возвращается каждые 49,7 дней., @Edgar Bonet