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 сервер. Для более продвинутых будут видео по другим библиотекам … более сложным.
    Поделиться публикацией
    Похожие публикации
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 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
                        Столкнулся с очень неприятной ситуацией, 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.

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