Доброго времени всем участникам! Пожалуйста, подскажите скетч для вот такого проекта: Есть 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); } Спасибо!
Если честно, я бы выбросил ардуину вообще и модуль 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(); } }
Спасибо большое, я того же мнения, но камера у меня IP и вафля не всегда будет включена. Если не сложно, подскажите: Что поправить в скетче, приведен ниже, чтобы было вот так: есть 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; // Заводим таймер до следующей проверки }
Ковыряйте тут: https://mysku.ru/blog/aliexpress/53349.html Уходите от ENC28J60(очень кривой) - в проекте там используется W5500. И еще я бы софтовый wathdog на ардуине там включил. А код компилится? Для ENC28J60 и W5500 разные версии библиотек для работы по сети. Мне кажется приведенный пример как раз для W5500
Понял, вы оттуда код и взяли - меня тоже рубануло, там и в комментариях тоже самое - видимо мысли сходятся Код (C++): if (ErrorCont==8) { digitalWrite(POWERpin, LOW); delay(10000); digitalWrite(POWERpin, HIGH);} // Перезагружаем нагрузку Работать с ENC28J60 не будет. Там в статье все четко описано - ENC28J60 - низкоуровневый ehernet контроллер, дешевый но к нему надо писать всю обработку tcp, icmp самому.
Спасибо буду копать скетч ) И все же, как сделать логику: пингуем IP с периодом например в 1 минуту, затем, если нет пинга в течении 10 секунд, разрываем реле и ждем 10 секунд, затем включаем реле и ждем 1 минуту, затем запускаем мониторинг заново радуемся работе... И еще непонятно по поводу реле, есть вот такое реле goo.gl/25hxNe, оно НОРМАЛЬНО ЗАМКНУТО или НОРМАЛЬНО РАЗОМКНУТО? Мне нужно, чтобы было замкнуто, т.к. по сути мне нужно подавать питание на камеру, пока нет сбоя. Я не пойму, Ардуинка будет давать на него HIGH т.е. замыкать, пока не указано в скетче другого или это реле все время ЗАМКНУТО и Ардуино будет только размыкать его... Нигде на сайте нет подсказок от продавца, а ранее с такими я не работал.
Это реле с перекидным контактом. Т. е. контактная пара имеет три контакта; без напряжения - 2 контакт замкнут на 1, а после подачи напряжения - 2 контакт перекидывается с 1 на 3.
Спасибо, кстати ув. автор статьи, помог с кодом, за что ему большое спасибо! Код (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; // Заводим таймер до следующей проверки }