Ping IP + W5100 + реле

Тема в разделе "Arduino & Shields", создана пользователем AlexPebody, 15 июл 2017.

  1. AlexPebody

    AlexPebody Нуб

    Доброго времени всем участникам!

    Пожалуйста, подскажите скетч для вот такого проекта:

    Есть IP 192.168.0.80 к примеру, если пинг этого адреса пропал и в течении 10 секунд не возвращается, выключить питание (реле), подождать 10 секунд и включить питание, подождать 1 минуту, запустить мониторинг заново... и так в цикле бесконечно, пока есть питание на модулях.

    Как это реализовать? Я так понимаю нужна Arduino Nano + Lan module + реле модуль, нагрузка на выключателе около 1А, реле держит до 10А, а как написать скетч такого мониторинга? Заранее буду весьма благодарен, если подскажите?

    Из железок, предполагаю Arduino Nano + ENC28J60 SPI модуль + Реле модуль + блок питания 5В 2А.

    В написании скетчей полный 0, есть опыт работы в PHP и иже идущих языках программирования,
    поэтому некотрую логику скетча проследить могу. Если кому не сложно, начинаю изучать,
    подскжите скетч для моего проекта, камера замучала виснуть, хочу вот такую схемку сделать,
    чтобы сама перезапусказась, когда зависает (ремонт камеры - безсмысленно, цена Китай).

    Желательно работать с статическим IP, без DHCP, т.е. ручками прописать параметры LAN модуля.

    Заранее всем ОГРОМНОЕ спасибо и извиняюсь, если где то протупил!

    з.ы. Нашел вот такой скетч ув. pavel.1632 (с) прошу извинить за цитирование вашего когда, ссылки все дал, как и что изменить в коде под мою задачу?

    Код (C++):
    // Arduino demo sketch for testing the DHCP client code
    //
    // Original author: Andrew Lindsay
    // Major rewrite and API overhaul by jcw, 2011-06-07
    //
    // Copyright: GPL V2
    // See http://www.gnu.org/licenses/gpl.html

    #include <SimpleTimer.h>
    #include <EtherCard.h>
    #include <avr/wdt.h>

    char payload[] = "My UDP message";
    byte ipUDPSyslogAddress[4];

    String textToSend;

    static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
    unsigned int counterPingFailed = 0;
    unsigned int totalRelaySwith = 0;
    byte Ethernet::buffer[700];
    SimpleTimer timer1;

    //static byte srv1[4];

    void senduptime() {

        //char textToSend[] = "Uptime: " + (millis() / 1000) + "s";
        textToSend = "Uptime: " + String(millis() / 1000) + "s";
        SendToSerialAndUdp(textToSend);

    }

    void SendToSerialAndUdp(String input1) {
         Serial.println(input1);
    // с несколькими адресами так и не удалось заставить работать
    // ether.parseIp(ether.hisip, srv03);
    // ether.printIp("UDP: ", srv1);
    // Serial.println("SEND UDP");
    // ether.sendUdp(payload, sizeof(payload), 1234, srv1, 514);
    }

    void pingGoogle() {

      ether.printIp("Pinging: ", ether.hisip);
      if ((ether.packetLoopIcmpCheckReply(ether.hisip))==0){
        counterPingFailed=counterPingFailed+1;
        textToSend = "Pings: " + String(counterPingFailed) + "(of 15) Relay: " + String(totalRelaySwith) + " Uptime: " + String(millis() / 1000) + "s";;
        SendToSerialAndUdp(textToSend);
        }

         if (counterPingFailed > 15) {
         SendToSerialAndUdp("RELAY OFF");
         counterPingFailed = 0;
         totalRelaySwith=totalRelaySwith+1;
         digitalWrite(5, !digitalRead(5));
         digitalWrite(6, !digitalRead(6));
         delay (5000);
         SendToSerialAndUdp("RELAY ON");
         digitalWrite(5, !digitalRead(5));
         digitalWrite(6, !digitalRead(6));
         }
         ether.clientIcmpRequest(ether.hisip);
    }

    void testrelay()
    {
      digitalWrite(5, !digitalRead(5));
      digitalWrite(6, !digitalRead(6));
      }

    // called when a ping comes in (replies to it are automatic)
    static void gotPinged (byte* ptr) {
      ether.printIp(">>> ping from: ", ptr);
    }

    void watchdogUpdate() {
      wdt_reset();
      }

    void setup () {

      pinMode(5, OUTPUT);  
      pinMode(6, OUTPUT);
      digitalWrite(5, HIGH);
      digitalWrite(6, HIGH);
      Serial.begin(9600);
      Serial.println(F("\n[Started...]"));
      //delay(000); // Задержка, чтобы было время перепрошить устройство в случае bootloop
      wdt_enable (WDTO_8S); // Для тестов не рекомендуется устанавливать значение менее 8 сек.
      Serial.println(F("\n[testDHCP]"));
      Serial.print("MAC: ");
      for (byte i = 0; i < 6; ++i) {
        Serial.print(mymac[i], HEX);
        if (i < 5)
          Serial.print(':');
      }
      Serial.println();
      if (ether.begin(sizeof Ethernet::buffer, mymac,10) == 0)
        Serial.println(F("Failed to access Ethernet controller"));

      Serial.println(F("Setting up DHCP"));
      if (!ether.dhcpSetup())
        Serial.println(F("DHCP failed"));
      ether.printIp("My IP: ", ether.myip);
      ether.printIp("Netmask: ", ether.netmask);
      ether.printIp("GW IP: ", ether.gwip);
      ether.printIp("DNS IP: ", ether.dnsip);

      //timer = -9999999; // start timing out right away

      ether.parseIp(ether.hisip, "8.8.8.8");

      ether.printIp("SRV: ", ether.hisip);
      // call this to report others pinging us
      ether.registerPingCallback(gotPinged);
      timer1.setInterval(60000, pingGoogle);            //every 60sec
      timer1.setInterval(3600000, rebootWithWatchdog); //every hour if ping failed > 10
      timer1.setInterval(86400000, rebootWithWatchdog2); //every day
      timer1.setInterval(1000, watchdogUpdate);
    }

    void rebootWithWatchdog () {
      if (totalRelaySwith > 10) {
        Serial.println("Reboot with watchdog");
        delay(30000);
      }
    }

    void rebootWithWatchdog2() {
        Serial.println("Reboot with watchdog2");
        delay(30000);
    }

    void loop () {
      word len = ether.packetReceive(); // go receive new packets
      word pos = ether.packetLoop(len); // respond to incoming ping
      if (len > 0 && ether.packetLoopIcmpCheckReply(ether.hisip))
      {
          SendToSerialAndUdp("Ping SUCCESSFUL");
          counterPingFailed=0;
     
      }

      timer1.run();
      delay(1);
    }
    Спасибо!
     
    Последнее редактирование: 15 июл 2017
  2. AlexPebody

    AlexPebody Нуб

  3. pavel.1632

    pavel.1632 Нерд

    Если честно, я бы выбросил ардуину вообще и модуль ENC28J60 точно.
    Помыкавшись - я перешел на esp8266, там и реле есть и памяти больше (sonoff itead). Единственная разница - только в отсутствии порта ethernet и вместо него наличии wifi. И блок питания не нужен.

    Код (C++):
    #include <ESP8266Ping.h>
    String pingCheckIPAddressF;

    void pingCheck(void) {
        IPAddress convertedIP;
        convertedIP.fromString(pingCheckIPAddressF);
        bool ret = Ping.ping(convertedIP, 1);
        if (ret) {
          numberOfPingsFailed = 0;
          numberOfPingsSuccessful++;
        } else {
          numberOfPingsFailed++;
          numberOfPingsFailedTotal++;     // сколько ping не прошло всего
          blinkled(2);
        }
        if (numberOfPingsFailed > pingCheckNumberOfFaults && pingCheckNumberOfFaults > 0) {
          numberOfPingsFailed = 0;
          relay30secRestart();
        }
    }
     
    AlexPebody нравится это.
  4. AlexPebody

    AlexPebody Нуб

    Спасибо большое, я того же мнения, но камера у меня IP и вафля не всегда будет включена. :cool:

    Если не сложно, подскажите: Что поправить в скетче, приведен ниже, чтобы было вот так: есть IP 192.168.0.80 к примеру, если пинг этого адреса пропал и в течении 10 секунд не возвращается, выключить питание (реле), подождать 10 секунд и включить питание, подождать 1 минуту, запустить мониторинг заново.

    Код (C++):
    #include <SPI.h>      
    #include <Ethernet.h>
    #include <ICMPPing.h>
    #include <MsTimer2.h>

    #define RSTpin 9
    #define POWERpin 8

    int InactivityPeriod = 10*60; // Время между опросами ресурсов, 10 минут.

    byte mac[] = {0xC0, 0xFF, 0xEC, 0xAC, 0xA0, 0x01}; // mac-адрес. Должен не свопадать ни с одним из существующих в данной сети
    byte ip[] = {192,168,1,112}; // ip-адрес устройста.

    SOCKET pingSocket = 0;

    char buffer [256];
    ICMPPing ping(pingSocket, (uint16_t)random(0, 255));

    byte ErrorCont;
    int Inactivity;

    void TickEvery1s() // Эта процедура вызывается каждые полсекунды
    {
      if (Inactivity>0) Inactivity--;
    }

    void setup()
    {
      Inactivity=InactivityPeriod;
      pinMode(RSTpin, OUTPUT);
      digitalWrite(RSTpin, LOW); delay(20); digitalWrite(RSTpin, HIGH); delay(200);  // Перезагружаем плату
      pinMode(POWERpin, OUTPUT);
      digitalWrite(POWERpin, HIGH);  //Включаем нагрузку
      Ethernet.begin(mac, ip);
      MsTimer2::set(1000, TickEvery1s); // период вызова каждые 1000ms
      MsTimer2::start();

    }

    void loop()
    {
      while (Inactivity>0) {delay(1);}

      ErrorCont=0;
      for (byte i=0; i<=3; i++){
        ICMPEchoReply GoogleechoReply = ping(IPAddress (8,8,8,8), 2);
        if (GoogleechoReply.status != SUCCESS) {ErrorCont++;}
        delay(500);
        }
      for (byte i=0; i<=3; i++){
        ICMPEchoReply YandexechoReply = ping(IPAddress (77,88,8,8), 2);
        if (YandexechoReply.status != SUCCESS) {ErrorCont++;}
        delay(500);
        }

      if (ErrorCont==8) {
        digitalWrite(POWERpin, LOW); delay(10000); digitalWrite(POWERpin, HIGH);}  // Перезагружаем нагрузку
     
      Inactivity=InactivityPeriod;    // Заводим таймер до следующей проверки
    }
     
     
  5. pavel.1632

    pavel.1632 Нерд

    Ковыряйте тут:
    https://mysku.ru/blog/aliexpress/53349.html
    Уходите от ENC28J60(очень кривой) - в проекте там используется W5500.
    И еще я бы софтовый wathdog на ардуине там включил.

    А код компилится? Для ENC28J60 и W5500 разные версии библиотек для работы по сети.
    Мне кажется приведенный пример как раз для W5500
     
    AlexPebody нравится это.
  6. pavel.1632

    pavel.1632 Нерд

    Понял, вы оттуда код и взяли - меня тоже рубануло, там и в комментариях тоже самое - видимо мысли сходятся

    Код (C++):
    if (ErrorCont==8) {
        digitalWrite(POWERpin, LOW); delay(10000); digitalWrite(POWERpin, HIGH);}  // Перезагружаем нагрузку
     
    Работать с ENC28J60 не будет. Там в статье все четко описано - ENC28J60 - низкоуровневый ehernet контроллер, дешевый но к нему надо писать всю обработку tcp, icmp самому.
     
    AlexPebody нравится это.
  7. AlexPebody

    AlexPebody Нуб

    Спасибо буду копать скетч )

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

    пинга в течении 10 секунд, разрываем реле и ждем 10 секунд, затем включаем реле

    и ждем 1 минуту, затем запускаем мониторинг заново радуемся работе...

    И еще непонятно по поводу реле, есть вот такое реле goo.gl/25hxNe, оно НОРМАЛЬНО ЗАМКНУТО или НОРМАЛЬНО РАЗОМКНУТО? Мне нужно, чтобы было замкнуто, т.к. по сути мне нужно подавать питание на камеру, пока нет сбоя. Я не пойму, Ардуинка будет давать на него HIGH т.е. замыкать, пока не указано в скетче другого или это реле все время ЗАМКНУТО и Ардуино будет только размыкать его... Нигде на сайте нет подсказок от продавца, а ранее с такими я не работал.
     
    Последнее редактирование: 16 июл 2017
  8. fogary

    fogary Гик

    Это реле с перекидным контактом. Т. е. контактная пара имеет три контакта; без напряжения - 2 контакт замкнут на 1, а после подачи напряжения - 2 контакт перекидывается с 1 на 3.
     
    AlexPebody нравится это.
  9. AlexPebody

    AlexPebody Нуб

    Спасибо, кстати ув. автор статьи, помог с кодом, за что ему большое спасибо!
    Код (C++):
    #include <SPI.h>        
    #include <Ethernet.h>
    #include <ICMPPing.h>
    #include <MsTimer2.h>

    #define RSTpin 9
    #define POWERpin 8

    int InactivityPeriod = 1*60; // Время между опросами ресурсов, 10 минут.

    byte mac[] = {0xC0, 0xFF, 0xEC, 0xAC, 0xA0, 0x01}; // mac-адрес. Должен не свопадать ни с одним из существующих в данной сети
    byte ip[] = {192,168,0,112}; // ip-адрес устройста.

    SOCKET pingSocket = 0;

    char buffer [256];
    ICMPPing ping(pingSocket, (uint16_t)random(0, 255));

    byte ErrorCont;
    int Inactivity;

    void TickEvery1s() // Эта процедура вызывается каждые полсекунды
    {
      if (Inactivity>0) Inactivity--;
    }

    void setup()
    {
      Inactivity=InactivityPeriod;
      pinMode(RSTpin, OUTPUT);
      digitalWrite(RSTpin, LOW); delay(20); digitalWrite(RSTpin, HIGH); delay(200);  // Перезагружаем плату
      pinMode(POWERpin, OUTPUT);
      digitalWrite(POWERpin, HIGH);  //Включаем нагрузку
      Ethernet.begin(mac, ip);
      MsTimer2::set(1000, TickEvery1s); // период вызова каждые 1000ms
      MsTimer2::start();

    }

    void loop()
    {
      while (Inactivity>0) {delay(1);}
     
      ErrorCont=0;
      for (byte i=0; i<=5; i++){
        ICMPEchoReply CamEchoReply = ping(IPAddress (192,168,0,80), 2);
        if (CamEchoReply.status != SUCCESS) {ErrorCont++;}
        delay(500);
        }
     
      if (ErrorCont==6) {
        digitalWrite(POWERpin, LOW); delay(10000); digitalWrite(POWERpin, HIGH);}  // Перезагружаем нагрузку
       
      Inactivity=InactivityPeriod;    // Заводим таймер до следующей проверки
    }