enc28J60 и пинг нескольких хостов

Тема в разделе "Arduino & Shields", создана пользователем sersahar, 9 янв 2016.

  1. sersahar

    sersahar Нерд

    Привет. С одним хостом проблем нет.
    Код (C++):

    #include <EtherCard.h>
    int outputPin = 6; // LED1 to pin 6
    int anotherOutputPin = 7; // LED2 to pin 7
    // ethernet interface mac address, must be unique on the LAN
    static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };

    byte Ethernet::buffer[700];
    static uint32_t timer;
    static uint32_t count;
    static uint32_t all;

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

    void setup () {
      pinMode(outputPin, OUTPUT);
      pinMode(anotherOutputPin, OUTPUT);
      digitalWrite(anotherOutputPin, HIGH);
      digitalWrite(outputPin, HIGH);
      count=0;
      all=0;
       Serial.begin(57600);
      Serial.println("\n[pings]");
      if (ether.begin(sizeof Ethernet::buffer, mymac,10) == 0)
        Serial.println( "Failed to access Ethernet controller");
      if (!ether.dhcpSetup())
        Serial.println("DHCP failed");
        ether.printIp("IP:  ", ether.myip);
      ether.printIp("GW:  ", ether.gwip);

      ether.parseIp(ether.hisip, "192.168.88.1");
    //#endif
      ether.printIp("SRV: ", ether.hisip);
       
      // call this to report others pinging us
      ether.registerPingCallback(gotPinged);
     
      timer = -9999999; // start timing out right away
      Serial.println();
    }

    void loop () {
      word len = ether.packetReceive(); // go receive new packets
      word pos = ether.packetLoop(len); // respond to incoming pings
       if (len > 0 && ether.packetLoopIcmpCheckReply(ether.hisip)) {
        Serial.print("  ");
        Serial.print((micros() - timer) * 0.001, 3);
        Serial.println(" ms");
        count=0;
        all=0;
    }

     
      // ping a remote server once every few seconds
      if (micros() - timer >= 5000000)
      {
        if ((ether.packetLoopIcmpCheckReply(ether.hisip))==0){
        count=count+1; }
        ether.printIp("Pinging: ", ether.hisip);
         Serial.println("Count ");
         Serial.println(count);
          Serial.println("all ");
         Serial.println(all);
         timer = micros();
         ether.clientIcmpRequest(ether.hisip);
      if (count>5)
        {
            digitalWrite(outputPin, LOW);    // turn the LED off by making the voltage LOW
            delay(20000);
            digitalWrite(outputPin, HIGH);   // turn the LED on (HIGH is the voltage level)
            count=0;  
            all=all+1;
         }
         if (all>2)
           digitalWrite(outputPin, LOW);
      }
    }
    А вот как пинговать несколько хостов проблема. Вижу, что параметр что пинговать задается в setup, пытался вынести его за пределы - не получилось (
     
  2. sersahar

    sersahar Нерд

    Победил сам. Если кому будет интересно - пишите
     
    AlexPebody нравится это.
  3. pavel.1632

    pavel.1632 Нерд

    Интересно, бьюсь с этой проблемой уже несколько дней.
    Судя по указанию 10го пина - у тебя тоже arduino nano + ethernet shield на enc28j60
     
  4. testik777

    testik777 Нуб

    Интересно, но я в скетче не вижу проверки на доступность хоста. Когда я через монитор порта смотрю, что на arduino происходит то вижу что пинг строка ether.printIp("Pinging: ", ether.hisip); срабатывает и когда у меня сеть подключена и когда ее нет. Счетчики count и all. тоже сами по себе работают. А светодиод отрабатывает по условиям if (count>5) if (all>2), правдя я не совсем понял зачем они вообще нужны были? Хотелось бы все-таки понять возможно ли реализовать проверку по icmp на enc28j60 или нужно брать w5100. я в arduino новичок, так что строго за глупые вопросы не судите.
     
  5. pavel.1632

    pavel.1632 Нерд

    Нет, строка

    Код (C++):
    if ((ether.packetLoopIcmpCheckReply(ether.hisip))==0){
    Именно посылает icmp запрос.
    w5100 как я понял имеет свои библиотеки, там есть чип работы с tcp
    А у 28j60 -это простая железка, обработка всего tcp идет программно.
     
  6. testik777

    testik777 Нуб

    я когда смотрю исполнение этого скетча через "Монитор порта" вижу что это условие выполняется и когда пинг есть и когда пинга нет. Т.е. проверки по пингу по этому условия не происходит
    Код (C++):
     if (micros() - timer >= 5000000)
      {
        if ((ether.packetLoopIcmpCheckReply(ether.hisip))==0){
        count=count+1;
        ether.printIp("Pinging: ", ether.hisip);
         Serial.println("Count ");
         Serial.println(count);
         timer = micros();
         ether.clientIcmpRequest(ether.hisip);
      if (count>2)
            digitalWrite(outputPin, HIGH);   // turn the LED on (HIGH is the voltage level)
        }
        else
         digitalWrite(outputPin, LOW);
      }
     
  7. pavel.1632

    pavel.1632 Нерд

    Я привожу свой, он работает.
    Несомненно модуль enc28j60 сложен - надо писать все обработки ICMP запросов и ответов софтово.
    У меня модуль показывал пинг через сутки там, где его не было.
    Решение - перезагружать по watchdog через стуки работы.
    АХТУНГ! Обычно watchdog в arduino nano не работает - надо перепрошивать boot!
    У меня на данной связке arduinoi nano + enc28j60 подключен роутер на даче, через модем 4g.
    Таймауты большие - около 15 минут - если за 15 минут ни одного icmp запроса не прошло,
    дергает выходы 5 и 6, на которых стоит реле - через него идет питание роутера.
    Пока глюков нет.

    И да - посыпаю голову пеплом - так и не удалось заставить работать больше чем с одним ip адресом.
    Очень хотелось, чтобы лог работы nano отправляла широковещательными пакетами udp или на 512 порт через udp - как syslog. Не удалось. Либо одно, либо второе.
    Код (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);
    }

     
     
    Последнее редактирование: 9 авг 2016
    AlexPebody нравится это.
  8. AlexPebody

    AlexPebody Нуб

    Большое спасибо, насколько я понимаю это именно то, что мне нужно, если будет пару минут, прошу вникните в суть моего проекта и подскажите, что поправить в вашем коде под мои задачи?

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

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

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

    DangerD Нуб

    +1 пингование одного адреса и замыкание реле не проблема, как реализовать перезагрузку сразу нескольких компов?
    Отослать icmp на несколько хостов не проблема
    Код (C++):
    ether.clientIcmpRequest(IP);
    для проверки ответа я так понимаю надо перебирать все ip
    Код (C++):
    if (len > 0 && ether.packetLoopIcmpCheckReply(IP)) {
    Забил несколько адресов в массив
    Код (C++):
    byte minersIP[2][4] = {
      { 192,168,1,201 },
      { 192,168,2,202 }

    };
    как теперь их теперь передавать в ether.clientIcmpRequest? Там оно как-то через переменную hisip всё завязано...
    Помогите куском кода с перебором нескольких IP (для каждого ip потом идёт замыкание определенного пина)


    З.Ы.Временно реализовал через жопу (пингует не ардуинка, а комп ардуинку, работает, но хочется по нормальному...)
     
  10. ArtyRotkin

    ArtyRotkin Нуб

    Мне очень интересно как сделать обращение к нескольким разным хостам минуя проблему с переменной hisip. Расскажи как сделал. Я уже несколько дней бьюсь с этой проблемой...