Перезагрузка роутера при зависании UNO+ECN28J60+реле
- Войдите на сайт для отправки комментариев
Чт, 30/06/2016 - 23:33
Есть скетч написан под shield W5100, подскажите не могу поправить под ethercard (ECN28J60) И Возможно ли это?
#include <Arduino.h> #include <SPI.h> #include <Ethernet.h> #include <EthernetUdp.h> #include <stdint.h> #define pinRelay 7 // Сюда включим реле #define timeIntervalToNextAttempt 60000 // Интервал обычной проверки NTP 1 минута #define timeIntervalIfFirstAttemptFall 60000 // Интервал повторной проверки после перезагрузки 1 минута #define timeIntervalIfSecondAttemptFall 120000 // Интервал если перезагрузка не помогла 2 минуты. #define timeZone 2 // Временная зона, где мы живем byte mac[] = { 0x90, 0xA2, 0xDA, 0x0F, 0x79, 0xF0 }; // MAC address для шилда. //IPAddress ip = ( 192, 168, 1, 177 ); unsigned int localPort = 8888; // local port для прослушки UDP пакетов IPAddress timeServer(132, 163, 4, 101); // сервер NTP time-a.timefreq.bldrdoc.gov IPAddress timeServer02(128, 138, 140, 44); // сервер NTP utcnist.colorado.edu IPAddress timeServer03(216, 228, 192, 69); // сервер NTP nist-time-server.eoni.com const int NTP_PACKET_SIZE= 48; // NTP time stamp - первые 48 байтов пакета byte packetBuffer[ NTP_PACKET_SIZE]; // Буфер для входящих и исходящих пакетов EthernetUDP Udp; // Создаем UDP const unsigned long seventyYears = 2208988800UL;// Время Unix началось 1 января 1970 года. В секундах это 2208988800 unsigned long timeWhenCheckNTP ; // Время, когда пора проверить NTP сервер. // unsigned long timeWhenGotNTP; String timeNowIs = ""; // Здесь храним запись текущего времени; uint8_t attemptCounter = 0; // Считаем попытки достучаться до вервера; bool isNeedToReboot = false; // Надо ли перегружать роутер? // Объявляем функции: unsigned long sendNTPpacket(IPAddress& address); // Функция отправки запроса NTP void fUDPReadAndGotTime(void); // Функция разбора ответа NTP void setup() { pinMode(pinRelay, OUTPUT); digitalWrite(pinRelay, LOW); Serial.begin(9600); //while (!Serial) {; } Ethernet.begin(mac, ip); while (ether.begin(sizeof Ethernet::buffer, mymac,10) == 0) { // start Ethernet and UDP Serial.println("Failed to configure Ethernet using DHCP"); delay(1000); } Udp.begin(localPort); delay(5000); sendNTPpacket(timeServer); fUDPReadAndGotTime(); timeWhenCheckNTP = millis() + timeIntervalToNextAttempt; } void loop() { /***************************** Проверяем NTP, три сервера **************************/ if (millis()> timeWhenCheckNTP) { sendNTPpacket(timeServer); // Отправляем запрос delay (1000); if (Udp.parsePacket()) { // Если есть ответ fUDPReadAndGotTime(); // Читаем время attemptCounter = 0; // Обнуляем счетчик перезагрузок } else { sendNTPpacket(timeServer02); delay(1000); if (Udp.parsePacket()) { fUDPReadAndGotTime(); attemptCounter = 0; } else { sendNTPpacket(timeServer03); delay(1000); if (Udp.parsePacket()) { fUDPReadAndGotTime(); attemptCounter = 0; } else { // Если ни один из серверов не ответил isNeedToReboot = true; // Установка флага перезагрузки attemptCounter +=1; // Увеличение счетчика перезагрузок } } } /***************************** Определяем время следующей перезагрузки **************************/ if (attemptCounter == 0) { // Если все хорошо то следующая проверка через 10 минутЖ; timeWhenCheckNTP = millis() + timeIntervalToNextAttempt; } if (attemptCounter == 1) { // Если перегрузились - проверяем через пять минут timeWhenCheckNTP = millis() + timeIntervalIfFirstAttemptFall; } if (attemptCounter > 1) { // Если перегрузка не помогла - перегружаемся каждый час timeWhenCheckNTP = millis() + timeIntervalIfSecondAttemptFall; } /******************************* Перегружаем, если надо ****************************************/ if(attemptCounter < 50) { // Перегружаемся не более двух суток if (isNeedToReboot) { // Если флаг перезагрузки установлен isNeedToReboot = false; // Сбрасываем его Serial.println("Relay!! Relay!! Relay!!"); // Оповещаем в сериал-порт digitalWrite(pinRelay, HIGH); // Включаем реле delay(30000); // Ждем 30 секунд digitalWrite(pinRelay, LOW); // Отключаем реле } } } } /********************************** Отправка пактета на сервер NTP ***************************/ unsigned long sendNTPpacket(IPAddress& address) { memset(packetBuffer, 0, NTP_PACKET_SIZE); // set all bytes in the buffer to 0 // Initialize values needed to form NTP request // (see URL above for details on the packets) packetBuffer[0] = 0b11100011; // LI, Version, Mode packetBuffer[1] = 0; // Stratum, or type of clock packetBuffer[2] = 6; // Polling Interval packetBuffer[3] = 0xEC; // Peer Clock Precision // 8 bytes of zero for Root Delay & Root Dispersion packetBuffer[12] = 49; packetBuffer[13] = 0x4E; packetBuffer[14] = 49; packetBuffer[15] = 52; // all NTP fields have been given values, now // you can send a packet requesting a timestamp: Udp.beginPacket(address, 123); //NTP requests are to port 123 Udp.write(packetBuffer,NTP_PACKET_SIZE); Udp.endPacket(); } /******************************** Анализ пактета от NTP **************************************/ void fUDPReadAndGotTime(void) { Udp.read(packetBuffer,NTP_PACKET_SIZE); // read the packet into the buffer unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); //the timestamp starts at byte 40 of the received packet and is four bytes, unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); // or two words, long. First, esxtract the two words: unsigned long secsSince1900 = highWord << 16 | lowWord; // combine the four bytes (two words) into a long integer Serial.print("Seconds since Jan 1 1900 = " ); // this is NTP time (seconds since Jan 1 1900) Serial.println(secsSince1900); Serial.print("Unix time = "); // now convert NTP time into everyday time: unsigned long epoch = secsSince1900 - seventyYears + (timeZone*3600); // subtract seventy years + Time Zone correction: Serial.println(epoch); // print Unix time: Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT) Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day) timeNowIs = (String) ((epoch % 86400L) / 3600); Serial.print(':'); timeNowIs += ":"; if ( ((epoch % 3600) / 60) < 10 ) { // In the first 10 minutes of each hour, we'll want a leading '0' Serial.print('0'); timeNowIs += "0"; } Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute) timeNowIs += (String) ((epoch % 3600) / 60); Serial.print(':'); timeNowIs += ":"; if ( (epoch % 60) < 10 ) { // In the first 10 seconds of each minute, we'll want a leading '0' Serial.print('0'); timeNowIs += "0"; } Serial.println(epoch %60); // print the second timeNowIs += (String) (epoch %60); Serial.println(timeNowIs); }
Возможно, использовать библиотеку
https://github.com/ntruchsess/arduino_uip
да возможно, но не знаю как переписать скетч под данную библиотеку :(
Ем, все просто. заменить в начале
на
И дожно поехать.
О спасибо. Думал весь скетч нужно пересобирать под другую библиотеку...
исправил начал компиляцию, вылетело с 3мя ошибками
ошибка первая
Только что проверил, все компилится
Незабываем сюта указат свой адрес своей подсети
IPAddress ip = ( 192, 168, 1, 177 );
залил скетч, интерфейс не пингуеться, не знаю может не должен проверяем работу включаем смотрю в монитор порта
постоянно дёргает релле, видимо сети не видит
у меня первая подсеть, по этому адрес оставил 192,168,1,177
может быть дело в 10 пине?
while (ether.begin(sizeof Ethernet::buffer, mymac,10)
как его в этом коде прописать? если не он то что может быть...
строку 48 закоментировать после ее вставить
Так хоть увидим, что подключился
модуль работает, адрес получает, уже хорошо.
пробегаем по серверах:
да забыл сказать я изначально подменил не рабочий сервер на рабочий ничего не изменилось
изменил
sendNTPpacket(timeServer);
Так, надо исключить нерабочий сервер, у нас тут 3 сервера.
Нужно немного переписать код с 63-90 строки, на проверку 2 серверов, или
IPAddress timeServer(132, 163, 4, 101); заменить на рабочий сервер.
Пока идеи кончились.
Проблема работы или сетевого интерфейса или библиотеки <UIPUdp.h>, как бы их проверить?
сеть адрес получает, но ходит ли трафик? почему пинги не ходят? библиотека не поддерживает?
Сегодня бужет на руках модуль, постараюсь проверить.
оо было бы отлично. спасибо)
тоже давно хотел замутить подобное устройство. но программить я почти 0.
тут ещё вопрос насколько стабильно будет работать модуль ECN28J60, ну это только с практики увидим.
Немгого добавли задержки, а также в случаи проверки ждем 10 мин.
Полчилось как-то так:
Лог:
Даже при задержке в 10 минут, при повторной проверке, перегружает, при задержке в 1 минуту вообще ничего не проверяет сразу перегружает.
Я не понимаю почему он дёргает реле когда реально есть интернет, может проблема с питанием модуля, попробую запитать его отдельно, может поможет ...
Там все просто, если не получаем от ответ 3 серверов перегружаем. Ответы приходят через раз... вот и дергает реле. Завтра помозгую чтобы раз 10-15 дела проверку, в слчаи недудачи толькто тогда уходил на реле, а так было 3 сек, ответов нет реле, и так по кругу...
ага я думал он проверят 1 нет ответа, проверяет 2 нет ответа, проверяет 3 есть ответ окей...
а он проверил 1й нет ответа дёргает реле ?
не может же 3 сервера не дать ответ?
может он не успевает дождаться ответа, и дёргает релюху, а в те времена когда успевает получить ответ тогда не перегружается наверное нужно ещё увеличить делей завтра попробую ...
Там по очереди перебираем 3 сервера, если все 3 не дали ответ, тогда дёргаем релюшку. Зараз сделаю простою переборку, посмотрим как стабильно они отвечают
Вот что получилось:
Результат 100 проверок:
круто через раз, так понимаю не особо надёжный метод через сервера времени :(
или для надёжности по раз 5 проверять чтоб лишний раз не пегружать
Ну так и думаю реализовать, немного позже допишу код, зараз тестовой комп с ардуиной пока не доступен.
Так, модернизированый код, сильно не пинать:
Результат роботы
ООО шикарно по логу уже вижу что работает :))) Спасибо Виталий)))
Завтра погоняю ...
а у меня что то этот код не пашет :((( раз праверил потом всё релей релей (((
хм. странно, зараз еще протестирую. А вы загрузите код из 23 поста http://arduino.ru/forum/proekty/perezagruzka-routera-pri-zavisanii-unoecn28j60rele#comment-207642
Интересно посмотреть на статистику
нет грузил последний из 27го поста
из 23-го также себя ведёт кстати, 1 раз находит, дальше релюху клацает
Виталий а Вы отдельно езернет модуль запитали, или от ардуино ?
Все, вместе, уже больше часа работет...
Немного модернизировал код:
остальное все тоже.
работает стабильно.
Запитал от юсб, включаю монитор слышу что сразу реле клацнуло постояло 1.5 минуты опять релей релей клац клац ещё 1.5 клац клац
Думаю а ну дай запитаю от БП не подключая юсб, 9в 1а, думаю в полне подойдёт, включаю светодиоды загорелись, реле не клацнуло значит вообще аруино не завелась, в чём может быть проблема?
на роутере постотреть, іp ардуина получает?. У немя все от юсб от ноутубка, работает без сбоев.
только что проверил, ЮСБ + БП-12 в. Все работает
Кстати как затитан модуль 5в или 3,3?
у ментя вот такой:
http://ru.aliexpress.com/store/product/ENC28J60-LAN-Ethernet-Network-Mod...
Запитан +5в.
у меня вот такой запитан на 3,3в от ардуино, что впихнуть ему 5 не сгорит ?
http://ru.aliexpress.com/item/ENC28J60-LAN-Ethernet-Network-Board-Module-for-arduino-25MHZ-Crystal-AVR-51-LPC-STM32-3-3V/32615635511.html?spm=2114.13010608.0.57.8X4M6w
ведёт себя одинаково только от юсб, или юсб+бп, без юсб не могу понять почему но вообще не работает релюха при старте не клацает
да на роутере адрес получает, тот же что и в мониторе отображаеться значит всё ок.
сейчас подам ему 5в вместо 3.3 думаю не должён сгореть)
5 не желательно, нучше купить копеечный ams1117 3,3. Сам модуль прожарлив. Или что-то такого
http://ru.aliexpress.com/item/MB102-Breadboard-Power-Supply-Module-3-3V-...
ага не заметил разницы у вас уже стоит амс на модуле по этому на него можно подавать 5 в, да на мой нельзя было дым пошёл :(
и походу уно потянул, сама уно работает, но от бп уже не запускается ....
значит по идее скетч работает, если у вас запустился значит и у меня должен заработать, Большое спасибо за помощь.
закажу такой же модуль как у вас чтоб не питать его отдельно и проверю.
Лучше купите на W5100, он постабильней будет:
http://ru.aliexpress.com/store/product/Free-Shipping-1pcs-UNO-Shield-Eth...
Если смущают габариты, то можно такой:
http://ru.aliexpress.com/store/product/Free-shipping-1PCS-LOT-TOP-Mini-W...
А можно этот код переделать, что бы он пинговал не NTP серверы, а например, обычный компьютер в локальной сети?
Он не пингует, а делает NTP-запрос.