Привет. С одним хостом проблем нет. Код (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, пытался вынести его за пределы - не получилось (
Интересно, бьюсь с этой проблемой уже несколько дней. Судя по указанию 10го пина - у тебя тоже arduino nano + ethernet shield на enc28j60
Интересно, но я в скетче не вижу проверки на доступность хоста. Когда я через монитор порта смотрю, что на arduino происходит то вижу что пинг строка ether.printIp("Pinging: ", ether.hisip); срабатывает и когда у меня сеть подключена и когда ее нет. Счетчики count и all. тоже сами по себе работают. А светодиод отрабатывает по условиям if (count>5) if (all>2), правдя я не совсем понял зачем они вообще нужны были? Хотелось бы все-таки понять возможно ли реализовать проверку по icmp на enc28j60 или нужно брать w5100. я в arduino новичок, так что строго за глупые вопросы не судите.
Нет, строка Код (C++): if ((ether.packetLoopIcmpCheckReply(ether.hisip))==0){ Именно посылает icmp запрос. w5100 как я понял имеет свои библиотеки, там есть чип работы с tcp А у 28j60 -это простая железка, обработка всего tcp идет программно.
я когда смотрю исполнение этого скетча через "Монитор порта" вижу что это условие выполняется и когда пинг есть и когда пинга нет. Т.е. проверки по пингу по этому условия не происходит Код (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); }
Я привожу свой, он работает. Несомненно модуль 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); }
Большое спасибо, насколько я понимаю это именно то, что мне нужно, если будет пару минут, прошу вникните в суть моего проекта и подскажите, что поправить в вашем коде под мои задачи? Есть IP 192.168.0.80 к примеру, если пинг этого адреса пропал и в течении 10 секунд не возвращается, выключить питание (реле), подождать 10 секунд и включить питание, подождать 1 минуту, запустить мониторинг заново... и так в цикле бесконечно, пока есть питание на модулях. Как это реализовать? Я так понимаю нужна Arduino Nano + Lan module + реле модуль, нагрузка на выключателе около 1А, реле держит до 10А, а как написать скетч такого мониторинга? Заранее буду весьма благодарен, если подскажите? Из железок, предполагаю Arduino Nano + ENC28J60 SPI модуль + Реле модуль + блок питания 5В 2А.
+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 потом идёт замыкание определенного пина) З.Ы.Временно реализовал через жопу (пингует не ардуинка, а комп ардуинку, работает, но хочется по нормальному...)
Мне очень интересно как сделать обращение к нескольким разным хостам минуя проблему с переменной hisip. Расскажи как сделал. Я уже несколько дней бьюсь с этой проблемой...