Тестирование стабильности работы ENC28J60 c Ардуино Нано (Atmega 328p) в различных условиях

чНекоторое время назад я запустил на кухне счетчик электричества, на основе готовых модулей — «Ардуино», часов RTC и т. п.. Для сетевой передачи я выбрал, наверное, самый дешевый из модулей для такой задачи — на основе имс производства microship — ENC28J60. К слову, говорят, что есть и более стабильные решения на WizNet 5100 и более новой 5500, но их цена намного больше. У последнего модуля она раз в десять выше, так к слову. Поэтому для создания прототипов дешевых устройств приходиться тестировать ENC28J60.

enc_28_j60

К сожалению со стабильностью работы у сборки Ардуино + ENC28J60 рабтающей в составе счетчика возникают проблемы. Иногда данные не доходят до веб-сервера. Принимающий скрипт конечно усредняет поступающие данные про потребление электрики, но хотелось бы достичь большей стабильности работы.

Вот пример, 8-мь часов не передавались почасовые данные, скрипт усреднил график. За день такое может и устроит, но при анализе почасовых данных — не очень.

e-data

Для того чтобы понять, что происходит, и возможно сделать другую версию устройства или модификацию программы я решил собрать макет тестирующего устройства для ENC28J60 по следующей схеме:

enc28j60

Вначале я ошибочно предполагал, что удастся задействовать вывод сброса микросхемы/модуля (reset). Но ничего из этого не вышло, так как программа просто зависала -переставала передавать отладочные данные на последовательном порту. И не понятно совершенно по какой причине. Пробовал я и разные длительности сброса —  0.1 cек, 1 сек. Причем сбрасывать в setup(), то есть один раз — проходит отлично. А повторно — не получается.

enc28j60-testing--001

Отпаял разъем — без него мне удобней было МГТФ-ом макетировать

Все безрезультатно  — зависает, точнее перестает функционировать основной цикл.  Также я пробовал задействовать SPI сброс с помощью вызова метода библиотеки ethercard. doBIST().

28j60_callback

Также первоначально была попытка запустить макет с «Ардуино Нано«, но возможностей встроенного стабилизатора напряжения в 3,3 вольт оказалось недостаточно (на выходе питания 3.3V было 2,2В), и сама плата просто не работала — не определялась по USB/COM (ch340g), Поэтому тесты проводились с «Ардуино Уно«.

После сборки макета, я запустил его с этой вот прошивкой — t_28j60, которая передает тестовый get-запрос каждые 60-ть секунд на внутренний веб-сервер (Apache/Synology).  Там создал вот такой скрипт, записывающий текущее время в новую запись таблицы mysql ($mdb->query() эквивалентно mysql_query) —

//init
if ( $_GET["val"] ==1 )
$mdb->query("TRUNCATE TABLE " . ibt("enc28j60") . ";");

//insert
$mdb->query("

INSERT INTO
" . ibt("enc28j60") . "
SET
ts = now(),
val = ".$_GET["val"] ."

;" );

echo "Insert as record with id: " . mysql_insert_id($mdb->_link);

 

И оставил это дело на сутки. После чего проанализировал наличие в таблице данных записанных с промежутком более 60-т секунд, и на соответствие номеров записи и переданных «Ардуино». При этом передавалось все по кабелю в 1м, качественному (фабричный патчкорд). Скрипт проверки превышения передачи в 100 секунд. «Ардуино» передает каждые 60-т секунд, но веб-сервер может быть занят, поэтому такое вот значение:

 $arr_times = array();

 $res=$mdb->query("SELECT UNIX_TIMESTAMP(ts) uts FROM " . ibt("enc28j60")." ORDER BY ts DESC");
 $i=0;
 $err=0;
 $uts=0;
 while ( $o=mysql_fetch_object($res) )
 {
 $tsoprev=$o;
 if ( !$i++ )
 {
 $uts = $o->uts;
 continue;
 }

 if ( ($uts - $o->uts) > 100 )
 {
 echo date("Y-m-d H:i:s",$o->uts) . " - " . date("Y-m-d H:i:s",$uts) . " missed <br />\n"; 
 $err++;
 }

 $arr_times[($uts - $o->uts) ." s."] = 
 isset($arr_times[($uts - $o->uts) ." s."]) ? 
 $arr_times[($uts - $o->uts) ." s." ]+1 :
 1;

 $uts = $o->uts;


 }

 $rec = $mdb->query_obj("SELECT count(*) c FROM " . ibt("enc28j60"))->c;
 $maxid = $mdb->query_obj("SELECT val c FROM " . ibt("enc28j60"). " ORDER BY ts DESC LIMIT 1;")->c ;
 echo "Errors:$err, <br />Records:$rec, <br />Last record Id: $maxid<br />";

 echo "<br />Timimg:<pre>";
 arsort($arr_times);
 print_r($arr_times);

Через восемь часов скрипт выдал следующее:

Errors:0,
Records:507,
Last record Id: 507

Timimg:
Array
(
    [60 s.] => 290
    [61 s.] => 212
    [59 s.] => 4
)

Иначе говоря — ни одной ошибки.  На секунду дольше чем положено — 4  ре запроса. Это нормально так как сервер — немного нагруженный.

Фото оттестированного макета:

enc28j60-testing--003

Макет на Ардуино Уно, и лежащая без дела Ардуино Нано

А вот так оно не работает, тока встроенного в «Ардуино Нано» выпрямителя на 1117-3,3 не хватает:

enc28j60-testing--002

Скрипт тестирования с поминутными запросами. Обратите внимание что библиотека Ethercard модифицированная и прилагается — t_28j60_001

Дальнейшее тестирование было на почасовых «отсылках». Длинна пакета сделана более солидной, за счет переменной GET test=test…….test

Второй тест — был с достаточно длинным GET запросом, длинна его была 242 символа, а период следования 1 минута, макет все тот же Уно+платка с enc28j60, питание от USB. К сожалению очень длинный запрос, такой как допускает Ардуино Мега 256,  было не сделать с «Уно».

Через некоторое время получен следующий результат:

Errors:0, 
Records:681, 
Last record Id: 681

Timing:
Array
(
 [60 s.] => 380
 [61 s.] => 290
 [59 s.] => 10
)

То есть ошибок и при большей длине нет.
Прошивка для второго замера — вот t_28j60__002, кому интересно.

После этого остается только проверить работу модуля при менее устойчивом питании — от дешевого китайского блока питания. И посмотреть на результаты аналогичных тестов.

Для тестирования такого рода был приобретен блок питания, и корпус. Вот что вышло после сборки:

enc28j60-testing-2-001 enc28j60-testing-2-002

Надо немного пояснить что там делает 7805, это именно она стоит около блока питания. Оказалось, что встроенный стабилизатор (на 1117-5,0) не выдерживает питания enc28j60. Переставлять другой блок питания не хотелось, и подключил дополнительную 7805. Конденсаторы есть на платах, так что все ок.

После чего макет запустился без вопросов. Стабильность передачи практически не изменилась. За некоторое время

Errors:0, 
Records:156, 
Last record Id: 156

Timing:
Array
(
    [60 s.] => 82
    [61 s.] => 70
    [59 s.] => 3
)

Это уже результаты работы макета с менее стабильным питанием. GET-запрос длинный. Результаты прохождения практически не отличаются от предыдущего. Длина кабеля = 1.5 метра. Следующий тест будет с длинным кабелем.

Подключил длинным кабелем, вот тест за 13-ть часов работы — все нормально ни одного сбоя

Errors:0, 
Records:842, 
Last record Id: 842

Timing:
Array
(
    [60 s.] => 468
    [61 s.] => 366
    [59 s.] => 7
)

Выводы — тяжело делать, получается однозначно точно что сетевой кабель нормальный. Отличия от макета от устройства только в том, что «ресет» модуля не подключен был, и что питание в макете — пропущено через 7805 а не через внутренний выпрямитель платы «Ардуино». Также может повлиять на работу модуля то, что там рядом стоит измерительный трансформатор, надо будет от него либо избавляться совсем (но тут приехавший поломанный модуль peacefair — не облегчил задачу) либо по крайней мере экранировать, может он как-то влияет на сам разъем RJ45 — там также вроде встроены мелкие трансформаторы.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Тестирование стабильности работы ENC28J60 c Ардуино Нано (Atmega 328p) в различных условиях: 7 комментариев

  1. Уведомление: NTP запросы на Ардуино через enc28j60 | Хроники фрилансера

    • На изображении эскиза подключения хорошо видно, что она включена от 3.3 вольт. «Operating Voltage of 3.1V to 3.6V (3.3V typical)»

  2. Тоже делаю на enc28j60+Arduino+EtherCard. Задача — пинговать несколько адресов и вывести web-страничку, которая не поместится в один пакет. Не подскажете, как через этот чип отправить страничку, ну, скажем 3000 байт? Смотрел примеры, но просветления не наступило. И как отличить прилетевший пакет ответа от HTTP-запроса? Пока через поиск ‘GET’ думаю.

    • В примерах

      word len = ether.packetReceive(); // go receive new packets
      word pos = ether.packetLoop(len); // respond to incoming pings

      Ловим ответ ping:

      // report whenever a reply to our outgoing ping comes back
      if (len > 0 && ether.packetLoopIcmpCheckReply(ether.hisip)) {
      Serial.print(» «);
      Serial.print((micros() — timer) * 0.001, 3);
      Serial.println(» ms»);
      }

      ловим GET

      if (pos) {
      bfill = ether.tcpOffset();
      char* data = (char *) Ethernet::buffer + pos;
      #if SERIAL
      Serial.println(data);
      #endif
      // receive buf hasn’t been clobbered by reply yet
      if (strncmp(«GET / «, data, 6) == 0)
      homePage(bfill);

      —-

      Посмотрите в папке examples…

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *