25 февраля 2015 в 10:51

WEB Server на базе ENC28j60 + Arduino — проще не бывает

image

Всем привет.
Как многие слышат, что нужно создать WEB сервер – сразу становится не по себе, всячески пытаются отойти от этой темы применив другие варианты управления и мониторинга своих устройств. Но ведь интернет и сеть есть уже почти в каждом устройстве. Так чем Ваш творение хуже?
Так что Если Вам интересно – идем дальше.


Не так страшен Волк, как его рисуют. Среди Нас много специалистов, но и много новичков. Учится никогда не поздно, я сам многому учусь, и многое познаю в практике. Надеюсь, эта статья поможет начинающим или освежит память начавшим.
За основу взят популярный модуль с контроллером ENC28j60.

image

А также я взял Arduino UNO(также можно Nano или Pro Mini). Все они работают на ATmega328.
В этой статье я покажу основы создания WEB сервера на самых простых библиотеках.
В данном случае:
#include «etherShield.h»
#include «ETHER_28J60.h»
Они просты для понимания – но и возможностей тоже меньше. Для обычного мониторинга и управления нагрузками – более чем достаточно.
Давайте рассмотрим, что нам нужно для этого.

image

Для начала идет инициализация библиотек.
Далее я указал пины для подключения модуля с контроллером ENC28j60. Так же Нам необходимо указать параметры нашего сетевого устройства. Для этого указываем MAC адрес –помните он не должен совпасть с MAC адресом Ваших сетевых устройств. Так же и IP Адрес – должен быть индивидуальным – но находиться в Вашей подсети.
К примеру, у Вас роутер(192,168,0,1), Ваш ПК(192,168,0,5) то Ваше устройство может быть(192,168,0,100).
К примеру, у Вас роутер(192,168,4,1), Ваш ПК(192,168,4,10) то Ваше устройство может быть(192,168,4,100).
Далее нужно указать порт. По умолчанию 80 – так как Веб браузеры по умолчанию опрашивают именно его(смотрите тест изменения порта в видео ниже).
Далее ETHER_28J60 ethernet; — указываем на имя объекта для обращения(ethernet), ниже в программе мы будем обращаться по этому имени.
Далее Нам необходима инициализация сетевого контроллера – применяем все установки адресов и портов.

Ну тут думаю самое сложное и не интересное закончилось …

Далее в основном цикле программы мы должны поставить условие которое будет проверять, есть ли запрос по нашему IP адресу?.. Если есть то отправить строчки нашей странички, а браузер уже придаст ей привычный нам вид. Давайте посмотрим пример:

image

Выделенная строка создает крупный тест на страничке, его легко редактировать и таких строчек можно добавлять по необходимости(но все упирается в количество Flash памяти контроллера).
Команда ethernet.respond(); отправляет все наши строчки сайта на браузер с которого сделали запрос на сайт(в данном случае 192.168.0.100).
Но если Вы заметили то названия у этого сайта нет(просто IP адрес).Не волнуйтесь, это поправимо, если добавить одну строчку:

image

Вот… теперь уже лучше.
Далее добавляя, строчки мы будем добавлять объекты на страничке которые помогут нам отображать информацию или управлять нею.
Начнем с ссылки, при нажатии на которую, мы отправим на контроллер запрос с тестом (который нужен будет нам позже для обработки).

image

Красной стрелкой название кнопки, а синей мы указываем на текст в запросе при нажатии на ссылку. Значит, если Мы нажмем на ссылку «Стоп» то отправим запрос на наш сервер: «192.168.0.100/stop» — где «stop» будет текст запроса.
Далее рассмотрим такой же вариант только с кнопкой:

image

Добавились атрибуты необходимые для отображения браузером кнопки. При нажатии, на которую, уже отправится запрос с тестом «start». Думаю здесь все понятно.
Для любителей красоты можно добавить параметры и создать интересную кнопку:

image

Для следующего варианта нам понадобятся переменные, добавим их в начале скетча:

image

Сейчас отобразим на Нашей страничке таблицу:

image

Для обозначения объекта таблица используется атрибут table. Далее я красным подчеркнул ( tr ) внешние границы таблицы и синим — внутренние рамочки. Обратите внимание что они попарно, а в центре пары Ваше значение или переменная(к примеру ves1 или ves2). Так же вы можете заметить что пара создает жирный текст а обычный текст. В конце объект таблица завершается /table.
Думаю с отображением объектов на странице достаточно для создания не сложных WEB страниц(более подробно и наглядно вы можете увидеть ниже в видео уроках для начинающих).
Но как же обработать запрос – для этого немного модифицируем наше условие с самого начала, добавив при этом переменную для строки. Так же создадим для примера два условия обработки запросов: 1-е это пустой запрос (192.168.0.100); 2-е это запрос с текстом «start»(192.168.0.100/start)

image

В зависимости от поданного запроса на сервер, на браузере сайт будет отображаться согласно указанным строкам:

image

Вот так можно делать динамические станицы, которые будут меняться, и отображать различную информацию в зависимости от параметров переменных или запросов от ссылок и кнопок.

Более детально и наглядно можно увидеть все, выше упомянутое, в Видео уроках для начинающих:







Ссылки на скетчи с примерами(В первом примере библиотека):
www.facebook.com/download/1779869258903901/web_urok_01.rar
www.facebook.com/download/351288838383944/web_urok_02.rar
www.facebook.com/download/435653776600017/web_urok_03.rar

Старался изложить материал доступными словами не используя сложные термины.
Надеюсь, эта статья поможет многим начинающим создать свой web сервер. Для более продвинутых будут видео по другим библиотекам … более сложным.
@free_arduino
карма
0,0
рейтинг 0,0
Похожие публикации
Самое читаемое

Комментарии (48)

  • +8
    Спасибо за разжёвывание. Валяется в столе парочка таких модулей, но руки не доходили попробовать.

    Мелкая корректировка — вы нерационально расходуете память. Сейчас у вас весь HTML хранится в ней — пока код прост, это не вызовет проблем, но когда накрутите логики, придётся ужиматься.

    Решение простое — применяйте F():
    Serial.println(F("Эта строка-константа будет храниться не в SRAM, а в флэш-памяти"));
    • 0
      Не очень то и понял… а подробнее можно?
      • 0
        Ну автоматом закинет текст в Flash память и будет её таскать оттуда, а не держать в оперативке, которой не густо.
        • 0
          а где об это почитать можно? Есть много вопросов технических… что? как? куда? сколько?
          • 0
            Ну дык ссылку же привели, там всё написано.
      • 0
        У вас на последнем скриншоте вышло «Sketch size — 5 килобайт из 32 максимум», заметили?

        Если вы усложните страничку отображением пары индикаторов, нескольких кнопок и т.п. — вы мяукнуть не успеете, как размер скетча приблизится к пределу. Для кода, который должен выполняться по нажатию кнопочек (щёлканье релешками, мигание лампочками) может тупо не остаться места.

        Но если вы прочитаете руководство по ссылке, вы узнаете, что у Ардуины не одно место, где она может хранить длинные константы. Если уж начали писать HTML в коде, сразу начинайте убирать его в флеш-память, меньше придётся переписывать потом.
        • 0
          Я не спорю… простые примеры будут работать а более сложные не особо… но для них есть другие библиотеки, более продвинутые и сетевые контроллеры есть получше.
          А ссылочку Вашу на руководство я не вижу… :(
          • 0
            «Другие библиотеки» рискуют не вместиться, если от SRAM уже прилично отъедено — попросту не останется места для размещения их рабочих переменных.

            Ссылка — playground.arduino.cc/Learning/Memory — приведена в первом комментарии.
            • 0
              сори… не сразу понял что там ссылка… цветность монитора в мастерской хромает :)))
            • 0
              как мне вытянуть эту строку из флеш? и отправить её в сетевой… это пример на сколько я понял если я храню много переменных в массивах символов. А если в зависимости от условия мне добавляется та или иная строка из проги в масив(пример: слово — старт или стоп) то у меня будет хранится в массиве только одно слово которое согласно условию будет выбрано и отправлено в массив для ответа на сетевой запрос.
              Получается что слово «старт» и слово «стоп» первоначально будут хранится в Flash а согласно условию добавляются в масив?
            • 0
               if (param=="2"){
                    ethernet.print("<H1>Таблица с кнопкой</H1><br/>");                     // Не хранится в RAM?
                    ethernet.respond();     	
                 }
              


              Я так понимаю что пока не сработает условие то в RAM не попадает, а если сработало, то ethernet.print отправляет строку в массив(занимая часть RAM) и функцией ethernet.respond(); отправляет накопившиеся данные в массиве на браузер
        • 0
          >> У вас на последнем скриншоте вышло «Sketch size — 5 килобайт из 32 максимум», заметили?
          Так это и есть flash usage, разве нет?
          Если компилить из консоли средствами тулчайна, можно получить и предполагаемый RAM(SRAM) usage.
          Ну либо внутри скетча в нужных местах для дебага в serial текущую занятость оперативки выводить. Вот здесь в самом низу довольно простая функция описана.
          • 0
            позже попробую компельнуть в версии 1.5.2(1.4.0) уже есть расход RAM… проведу следственный эксперимент. :)
        • 0
          скетч-то как раз больше вряд ли станет, а вот оперативная освободится…
          • 0
            вы правы, я как-то привык к своей настройке IDE, которая выводит в лог расход SRAM. А у автора там выводится только размер скетча — он, действительно, не изменится.
    • +1
      Не знал что так можно, спасибо.
  • +1
    Баловался некоторое время назад с ENC28j60 — стабильность хромает из-за кривой реализации tcp/ip. Может, сейчас баги и пофиксили, но все же W5100 в разы лучше, хотя бы потому что для нее есть библа из «коробки» от ардуино.
    • 0
      Согласен… W5100 круче в разы… у нее аппаратный стек, и можно посылать кучу запросов одновременно, но цена соответственно выше… Думаю как для простенького варианта мониторинга или управления достаточно дешёвого 28j60. Хотя наверное актуальнее уже wi-fi модуль за 2-3$. Но для тех кому надо просто и доступно и не дорого думаю в самый раз.
      • 0
        Если уже не спотыкается и аптайм приличный, то сойдет ;)
        • 0
          на W5100 я делал сервер для управления садовым освещением с анализом датчиков движения, сайт на sd карте, моментальное отображение изменений одновременно на всех браузерах, и куча других приятных мелочей… На таком контроллере приятно что то создавать… кстати китайцы начали делать их компактными, но цена пока кусается.
    • 0
      Да, с 28J60 был опыт еще очень давно у меня, не особо удачный и осталось море неприятных впечатлений. WizNet, конечно, потом использовать было прельстиво.
      Если цена не кусает, я бы сразу смотрел на WizNet и забыл про 28J60.
      Espressif за 3 бакса сейчас очень актуален (особенно с учетом того, что весь веб-сервер и логику можно запилить прямо на нем), но, внезапно, иногда нужен ethernet и вот никак по другому (у меня как раз сейчас «наклевывается» проект, который я думал сделать с esp8266, но в техзадании строго — ethernet, что, в общем-то, в той ситуации у заказчиков пожалуй оправдано).
      • 0
        wi-fi esp8266 местами сыроват, хотя если взять с большим количеством gpio, то можно навешать все на него и написать в нем же прогу и все сведется к 2,7$… Как то делал обзор на него:

        • 0
          Сыроват, да. Но эти черти его пилят и пилят. И это хорошо. В некоторых своих мечтах я радуюсь полностью открытым исходникам либ его СДК. Может быть, через какое-то время так и произойдет.
          • 0
            В этом я согласен… Я запасся разными моделями wi-fi esp8266 и жду :))
            • 0
              Аналогично :)

              Я еще хочу, когда появится свободное время, запилить прошивку с поддержкой Pawn (типа как с поддержкой Lua, только лучше :).
              Думаю, это было-бы круто, так как сам Pawn — крут, стабилен, универсален и функционален. В некоторых проектах просто неоценимо выручает, и лучше скриптового языка для эмбеддерства, пожалуй, не найти.
              • 0
                не забудь поделиться ;-)
                • 0
                  Оф корса.
    • 0
      Столкнулся с очень неприятной ситуацией, W5100 не работает с дешевыми свичами, пробовал D-Link DES1005A, DES1005, DES1008,Surecom какой-то нифига, линк горит, кадры не ходят, а с Cisco catalyst 2960 работает без проблем, ну еще с парочкой серьезных свичей, кто-нибудь сталкивался?
  • 0
    на TP-LINK D-Link Asus Cisco работает у меня w5100. смотри проблема в опресовке… не каждый свитч автоматически «перекидывает жилки» с А на В.
    • 0
      Говорю же, линк поднимается, вот как это выглядит:
      www.youtube.com/watch?v=fzVjnMlayqI
      Библиотека с офф. сайта, даже не знаю на что грешить, думал мне такой шилд попался, попросил человека проверить, у него свой шилд и свой dlink, тоже не заработало.
      Когда работает в циске, никаких ошибок нет, runts, giants, crc, все в норме.
      • 0
        А не связано это с 10МБит а не 100 :))) была похожая история комп с Гигабиткой не хотел конектить пока вручную не выставил 10МБит… Попробуй к компу и кноуту напрямую…
  • 0
    Перезалейте, пожалуйста, картинки в png.
    то выглядит это именно так
    • 0
      Все равно не пойму что не так с jpeg :)
      • 0
        Тогда стоит протереть монитор)

        jpeg около каждого символа даёт тонны шума, который очень раздражает глаз.
  • 0
    Интересно, подобные туториалы, разумеется, видел, но выдавать html из скетча — это как-то не то. Куда девать оформление, CSS и тд?
    Можно туториал про хостинг «веб-морды» на SD карте или что-то похожее? А вообще, лично мое мнение — я бы написал веб-морду отдельно, например, на TP-LINK TL-MR3020, с базой показателей датчиков, нормальным оформлением, авторизацией, динамическим доменным именем и т.д, а arduino использовать по назначению — снимать показания и щелкать выключателями.

    Кстати, есть альтернативная библиотека ethernet для 28J60 github.com/ntruchsess/arduino_uip — никто не тестировал ее?
    • 0
      Для SD карты и тому подобного ардуино неплохо справляется… это следующие видео… только пока нарезка… позже публикации…
    • 0
      ethernet для 28J60 github.com/ntruchsess/arduino_uip
      я и забыл за такую библиотечку… протестирую отпишусь
    • 0
      вполне можно сделать подключение стиля CSS, который хранится на каком-нибудь сервере, и всех скриптов с картинками. а потом из скрипта аяксом посылать запросы на ардуино, и все.
      • 0
        Как раз тот способ, что я описал выше :) В качестве бонусов — база с графиками датчиков.
        Ну и плюс ко всему, аякс-запросы надо проксировать, а проксировать с сайта до ардуино или проксировать с сайта до соседнего адреса в ethernet — две большие разницы
        • 0
          а в чем проблема с аяксом? зачем проксирование? arduina должна иметь домен, порты проброшены…
          • 0
            Ну вообще, ajax издревле был однодоменным, кроссдомен прикручивается или через Flash или через фреймы или в jquery начиная с версии 1.5, все методы одинаково костыльные, не очень скоростные и не очень безопасные. Просто помимо белой странички есть еще куча всего воркуг этого веб-сервиса, скажем так, и реализовывать, например, ту же авторизацию, динамический домен, базы и тд — средствами Arduino не нужно и не очень удобно. Точнее, очень неудобно. Пусть занимается своим делом.
            • 0
              Есть CORS, который разрешает кроссдоменный ajax. В вашем случае достаточно отдавать соответствующие заголовки (preflight не нужен, скорее всего)
              • 0
                Так дело не в этом, если даже для какого-никакого оформления нужно задействовать внешний ресурс, а раз и так придется — неужели не проще и страницы рисовать и данные хранить сервисом, который на ардуино только гоняет опросы датчиков и запросы на переключения, например
  • 0
    Меня вполне jcw библиотека устраивает.

    Но! сам ENC28j60 периодически виснет.
    Поэтому:
    — Для инициализации/реинициализации используем пин сброса.
    — Отслеживаем программно работоспособность модуля.
    • 0
      А можете пример кода привести? Всяко полезная штука
      • 0
        Примеры в «примерах» — Github /jcw

        А отслеживать зависание, это уже кому, как удобно.
        Я просто по таймеру ухожу на прерывание и смотрю на флаги, которые
        должны сбрасываться если модуль работает. Что-то вроде вотчдога.

        Завис — хард-ресет модуля и инициализация по новой.

        Более продвинутый вариант — использовать таск-менеджер. И работать с модулем в своем «потоке».
        Тогда зависший модуль, не вешает основной цикл.
  • 0
    Любопытная статейка… И совершенно никакой пользы. Загрузить пример и немного его подправить — несложно. А вот разобраться, почему библиотека EtherShield не компилируется и ругается на ошибку, когда ей встречается слово «prog_char» — куда увлекательнее.
    Угробил пару дней на то, чтоб разобраться с этой ерундой. Понял, что время, которое я потратил, стоит дороже, чем разница в пару баксов между ENC28J60 и W5100.
    После активного гугления выяснил, что в исходниках библиотеки надо в объявлении функции uint16_t fill_tcp_data_p заменить const prog_char *progmem_s на const PROGMEM char *progmem_s, вот так:

    uint16_t fill_tcp_data_p(uint8_t *buf,uint16_t pos, const PROGMEM char *progmem_s)
    


    после этого, наконец-то, скетч скомпилировался (HelloWorld из примеров библиотеки ETHER_28J60), ардуина стала отвечать на пинг и показывать страничку «Hello World» в броузере.

    PS Arduino IDE 1.6.7.

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.