Web-server на ENC28J60
- Войдите на сайт для отправки комментариев
Сб, 19/03/2016 - 02:51
Добрый день
Может найдется добрый человек который объяснит почему первый код работает, а второй, точно такойже с добавленным 3 реле - нет
ПС. Пытался использовать код на основе (и оригинальный) Дмитрия Осипова, но там вообще засада - пишет всегда 401 Unauthorized
Первый работающий
[code] /* * arduWebRelays.ino * * Created: 07/09/2013 15:55:00 * Author: Guillaume Carriere - guillaume.carriere@gmail.com * */ #include <EtherCard.h> static byte mymac[] = { 0x00,0x01,0x01,0x01,0x01,0x01 }; static byte myip[] = { 192,168,1,23 }; #define BUFFER_SIZE 500 byte Ethernet::buffer[BUFFER_SIZE]; BufferFiller bfill; #define CS_PIN 10 #define RELAIS_1 8 #define RELAIS_2 9 bool relais1Status = false; bool relais2Status = false; const char http_OK[] PROGMEM = "HTTP/1.0 200 OK\r\n" "Content-Type: text/html\r\n" "Pragma: no-cache\r\n\r\n"; const char http_Found[] PROGMEM = "HTTP/1.0 302 Found\r\n" "Location: /\r\n\r\n"; const char http_Unauthorized[] PROGMEM = "HTTP/1.0 401 Unauthorized\r\n" "Content-Type: text/html\r\n\r\n" "<h1>401 Unauthorized</h1>"; void homePage() { bfill.emit_p(PSTR("$F" "<title>Arduino Relais Webserver</title>" "Relais 1: <a href=\"?relais1=$F\">$F</a><br />" "Relais 2: <a href=\"?relais2=$F\">$F</a>"), http_OK, relais1Status?PSTR("off"):PSTR("on"), relais1Status?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>"), relais2Status?PSTR("off"):PSTR("on"), relais2Status?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>")); } void setup() { Serial.begin(115200); pinMode(RELAIS_1, OUTPUT); pinMode(RELAIS_2, OUTPUT); if (ether.begin(BUFFER_SIZE, mymac, CS_PIN) == 0) Serial.println("Cannot initialise ethernet."); else Serial.println("Ethernet initialised."); ether.staticSetup(myip); Serial.println("Setting up DHCP"); //if (!ether.dhcpSetup()) Serial.println( "DHCP failed"); ether.printIp("My IP: ", ether.myip); //ether.printIp("Netmask: ", ether.mymask); ether.printIp("GW IP: ", ether.gwip); ether.printIp("DNS IP: ", ether.dnsip); } void loop() { digitalWrite(RELAIS_1, relais1Status); digitalWrite(RELAIS_2, relais2Status); delay(1); // necessary for my system word len = ether.packetReceive(); // check for ethernet packet word pos = ether.packetLoop(len); // check for tcp packet if (pos) { bfill = ether.tcpOffset(); char *data = (char *) Ethernet::buffer + pos; if (strncmp("GET /", data, 5) != 0) { // Unsupported HTTP request // 304 or 501 response would be more appropriate bfill.emit_p(http_Unauthorized); } else { Serial.print("----"); Serial.print(data); Serial.println("----"); data += 5; if (data[0] == ' ') { // Return home page homePage(); } else if (strncmp("?relais1=on ", data, 12) == 0) { relais1Status = true; bfill.emit_p(http_Found); } else if (strncmp("?relais2=on ", data, 12) == 0) { relais2Status = true; bfill.emit_p(http_Found); } else if (strncmp("?relais1=off ", data, 13) == 0) { relais1Status = false; bfill.emit_p(http_Found); } else if (strncmp("?relais2=off ", data, 13) == 0) { relais2Status = false; bfill.emit_p(http_Found); } else { // Page not found bfill.emit_p(http_Unauthorized); } } ether.httpServerReply(bfill.position()); // send http response } } [/code]
Второй не работающий
/* * arduWebRelays.ino * * Created: 07/09/2013 15:55:00 * Author: Guillaume Carriere - guillaume.carriere@gmail.com * */ #include <EtherCard.h> static byte mymac[] = { 0x00,0x01,0x01,0x01,0x01,0x01 }; static byte myip[] = { 192,168,1,23 }; #define BUFFER_SIZE 500 byte Ethernet::buffer[BUFFER_SIZE]; BufferFiller bfill; #define CS_PIN 10 #define RELAIS_1 8 #define RELAIS_2 9 #define RELAIS_3 7 bool relais1Status = false; bool relais2Status = false; bool relais3Status = false; const char http_OK[] PROGMEM = "HTTP/1.0 200 OK\r\n" "Content-Type: text/html\r\n" "Pragma: no-cache\r\n\r\n"; const char http_Found[] PROGMEM = "HTTP/1.0 302 Found\r\n" "Location: /\r\n\r\n"; const char http_Unauthorized[] PROGMEM = "HTTP/1.0 401 Unauthorized\r\n" "Content-Type: text/html\r\n\r\n" "<h1>401 Unauthorized</h1>"; void homePage() { bfill.emit_p(PSTR("$F" "<title>Arduino Relais Webserver</title>" "Relais 1: <a href=\"?relais1=$F\">$F</a><br />" "Relais 2: <a href=\"?relais2=$F\">$F</a><br />" "Relais 3: <a href=\"?relais3=$F\">$F</a>"), http_OK, relais1Status?PSTR("off"):PSTR("on"), relais1Status?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>"), relais2Status?PSTR("off"):PSTR("on"), relais2Status?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>"), relais3Status?PSTR("off"):PSTR("on"), relais3Status?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>")); } void setup() { Serial.begin(115200); pinMode(RELAIS_1, OUTPUT); pinMode(RELAIS_2, OUTPUT); pinMode(RELAIS_3, OUTPUT); if (ether.begin(BUFFER_SIZE, mymac, CS_PIN) == 0) Serial.println("Cannot initialise ethernet."); else Serial.println("Ethernet initialised."); ether.staticSetup(myip); Serial.println("Setting up DHCP"); //if (!ether.dhcpSetup()) Serial.println( "DHCP failed"); ether.printIp("My IP: ", ether.myip); //ether.printIp("Netmask: ", ether.mymask); ether.printIp("GW IP: ", ether.gwip); ether.printIp("DNS IP: ", ether.dnsip); } void loop() { digitalWrite(RELAIS_1, relais1Status); digitalWrite(RELAIS_2, relais2Status); digitalWrite(RELAIS_3, relais3Status); delay(1); // necessary for my system word len = ether.packetReceive(); // check for ethernet packet word pos = ether.packetLoop(len); // check for tcp packet if (pos) { bfill = ether.tcpOffset(); char *data = (char *) Ethernet::buffer + pos; if (strncmp("GET /", data, 5) != 0) { // Unsupported HTTP request // 304 or 501 response would be more appropriate bfill.emit_p(http_Unauthorized); } else { Serial.print("----"); Serial.print(data); Serial.println("----"); data += 5; if (data[0] == ' ') { // Return home page homePage(); } else if (strncmp("?relais1=on ", data, 12) == 0) { relais1Status = true; bfill.emit_p(http_Found); } else if (strncmp("?relais2=on ", data, 12) == 0) { relais2Status = true; bfill.emit_p(http_Found); } else if (strncmp("?relais3=on ", data, 12) == 0) { relais3Status = true; bfill.emit_p(http_Found); } else if (strncmp("?relais1=off ", data, 13) == 0) { relais1Status = false; bfill.emit_p(http_Found); } else if (strncmp("?relais2=off ", data, 13) == 0) { relais2Status = false; bfill.emit_p(http_Found); } else if (strncmp("?relais3=off ", data, 13) == 0) { relais3Status = false; bfill.emit_p(http_Found); } else { // Page not found bfill.emit_p(http_Unauthorized); } } ether.httpServerReply(bfill.position()); // send http response } }
Ни что за ошибка, ни на чем запускаете...
Если дело происходит на ATmega328 то скорее всего оперативки вам не хватает. Но это так... просто на зарезервированный буфер и количество текстовых строк глянул...
Ни что за ошибка, ни на чем запускаете...
Если дело происходит на ATmega328 то скорее всего оперативки вам не хватает. Но это так... просто на зарезервированный буфер и количество текстовых строк глянул...
спасибо, что не прошли мимо
запускаю на MiniPro и ENC28j60. ошибка на странице -401 Unauthorized. при загрузке вроде не ругается
пишет в 2-х релейном
Скетч использует 10 720 байт (34%) памяти устройства. Всего доступно 30 720 байт.
Глобальные переменные используют 1 087 байт (53%) динамической памяти, оставляя 961 байт для локальных переменных. Максимум: 2 048 байт.
в 3-х релейном случае
Скетч использует 10 966 байт (35%) памяти устройства. Всего доступно 30 720 байт.
Глобальные переменные используют 1 114 байт (54%) динамической памяти, оставляя 934 байт для локальных переменных. Максимум: 2 048 байт.
пои обращении к странице в монитор порта выводит в 2-х релейном скетче
----GET / HTTP/1.1
Host: 192.168.1.23
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
Cache-Control: max-age=0
----
в 3-х релейном
----GET / HTTP/1.1
Host: 192.168.1.23
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
Cache-Control: max-age=0
----
и выдает ошибку на вебстранице
вопрос с большинством строк снимаем - PROGMEM и PSTR проглядел
но тем не менее, то что вам рисует после компиляции, и сколько библиотека потом заюзает динамически это две разных вещи. Попробуйте буфер уменьшить (вам же по сути только первая строка запроса нужна, остальное можно просто проустить) или тектовые части укоротить (в разборе запросов) - они в память программ не убраны (соответственно, в коде странички тоже). Судя по всему все же ошибка с переполнением памяти "куча" на "стек" залазит.
а еще маленький вопрос. просто изменив размер буфера до 200-300 я мог упороть ардуину?
после этих манипуляций перестали загружаться скетчи
пишет вот такое
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x46
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x46
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x46
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x46
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x46
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x46
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x46
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x46
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x46
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x46
Проблема загрузки в плату. Помощь по загрузке: http://www.arduino.cc/en/Guide/Troubleshooting#upload .
Этим точно нет :) Контакты проверяйте, порт через который шьете. И главное, а через что шьете? Ethernet модуль отключили при прошивке?
Вопросы:
1. Он, во втором случае, при ПЕРВОМ обращении к веб-серверу отображает homepage (в браузере), или сразу нет?
2. Нужно вывести в ком-порт пакет ДО проверки на заголовок "GET /". Сделайте это сейчас и давайте посмотрим на пакет.
Есть подозрение, что буфер в 500 не велик, а мал. Но нужно посмотреть на принятый пакет.
Вопросы:
1. Он, во втором случае, при ПЕРВОМ обращении к веб-серверу отображает homepage (в браузере), или сразу нет?
2. Нужно вывести в ком-порт пакет ДО проверки на заголовок "GET /". Сделайте это сейчас и давайте посмотрим на пакет.
Есть подозрение, что буфер в 500 не велик, а мал. Но нужно посмотреть на принятый пакет.
жаль не успел пока вы были здесь
по вопросу 1 - да, в браузере сразу выдается страница с ошибкой 401, ничего другого не отображается
по вопосу 2. если я правильно вас понял, то сделал следующее
после этого при обновлении страницы пишет в компорт следующее
396
54
----GET / HTTP/1.1
Host: 192.168.1.23
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
Cache-Control: max-age=0
----
60
54
буфер увеличил до 1000
Этим точно нет :) Контакты проверяйте, порт через который шьете. И главное, а через что шьете? Ethernet модуль отключили при прошивке?
самое смешное что часа 2 постояло и все прошло.
при это между нормальной работой и появлением ошибки ничего не произошло (ни программно ни физически) кроме изменения размера буфера.
шил через AVR ISP. модуль не отключаю, он норммально шьется, видимо правильно ресет подсоединил :)
А не смотрели, может он греется (это намек почему могло не прошиваться)?
По поводу буфера - вы же и так его выводите, и видите что в него попало. Увеличивая - вы резервируете больше адресов, но по факту используете ровно столько столько в буфер и записалось (ну с учетом сдвига на начало tcp). Так что резать его надо в пределах необходимого. Возился с этим модулем года 2-3 назад, буфер что-то в районе 100-200 байт делал - и то работало. Отрезайте код проверки запроса кусками, там и увидите, на каком моменте память закончилась.
Кстати, модуль очень глючный. Может сейчас что улучшилось, но тогда я забил на него. Купил w5100 и забыл о 28j60 как о страшном сне :)
давайте смотреть откуда приходит 401: поставьте разные (да хоть "1" и "2") выводы в ком-порт рядом с обоими вариантами, где формируется ответ 401.
То есть при проверке на GET и в последнем else. Надо понять откуда он взялся.
давайте смотреть откуда приходит 401: поставьте разные (да хоть "1" и "2") выводы в ком-порт рядом с обоими вариантами, где формируется ответ 401.
То есть при проверке на GET и в последнем else. Надо понять откуда он взялся.
Проблема в том, что если не хватает оперативки, то проблема может вылазить как угодно и когда угодно. Надо взять рабочий скетч, и постепенно его расширять. Вы же тоже смотрели код? Явных огрехов там нет. Ну либо мы оба их проглядели :)
Кстати, модуль очень глючный. Может сейчас что улучшилось, но тогда я забил на него. Купил w5100 и забыл о 28j60 как о страшном сне :)
5100 более чем в три раза дороже, а так - да - Мега и 5100 лучше, чем про-мини и 28j60, никто и не спорит.
Я пытаюсь найти место, где не хватает оперативки и кто ее ест.
Я имею подозрение на саму библиотеку. Сидел пару часов, "втыкал" в нее. Вроде все гуманно - "прогмем" кругом и только буфер ввода-вывода в общей памяти.
Я видел в своей жизни ахрененно кривые сетевые драйвера, которые потом переписывал, правда это был линух на АРМе. Но там был конкретно "индусский" код, даже с коментами на ломаном индо-английском ;). Може пакет криво в бубеф записывается или новый пакет накладывается в каких-то случаях на старый. Смотреть надо. Начнем с тихой "printf" диагностики, в том смысле, что будем пихать тестовые выводы в разные места. Еще тема - написать сервер "с нуля" вот только модуль кужно заказать, я об этом уже думаю.
давайте смотреть откуда приходит 401: поставьте разные (да хоть "1" и "2") выводы в ком-порт рядом с обоими вариантами, где формируется ответ 401.
То есть при проверке на GET и в последнем else. Надо понять откуда он взялся.
Проблема в том, что если не хватает оперативки, то проблема может вылазить как угодно и когда угодно. Надо взять рабочий скетч, и постепенно его расширять. Вы же тоже смотрели код? Явных огрехов там нет. Ну либо мы оба их проглядели :)
так я так и попытался сделать, взял работающий 2-хрелейный и дописал по аналогии еще одно реле
подобавлял выводы. надеюсь это прояснит ъхоть чтото
и вот что выводит в ком при обращении
Ethernet initialised.
Setting up DHCP
DHCP failed
My IP: 192.168.1.23
GW IP: 0.0.0.0
DNS IP: 0.0.0.0
1 len: 370
1 pos: 54
1 data: GET / HTTP/1.1
Host: 192.168.1.23
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
++++++++
3 len: 370
3 pos: 54
++++++++
----GET / HTTP/1.1
Host: 192.168.1.23
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
----
1 len: 60
1 pos: 54
1 data:
++++++++
2 len: 60
2 pos: 54
2 data:
++++++++
Последний мой пост в эту тему. Я уже не знаю как вам сказать, что надо ити от работающего скетча, а не добавлять(усугублять) неработающий. Почитайте здесь - очень доходчиво
И да, ити от рабочего, это значит ити по шагам, и анализировать на каком шаге и из-за чего возникла проблема
Последний мой пост в эту тему. Я уже не знаю как вам сказать, что надо ити от работающего скетча, а не добавлять(усугублять) неработающий. Почитайте здесь - очень доходчиво
И да, ити от рабочего, это значит ити по шагам, и анализировать на каком шаге и из-за чего возникла проблема
я наверное и правда вас не понимаю. 2-х релейный скетч - работающий, 3-х, который я сделал из 2-хрелейного - не работающий. вы имеете ввиду что надо выводы в компорт делать в 2-х релейном скетче и там смотреть?
У библиотеки EtherCard есть проблемы с корректностью контроля переполнения буфера. То есть проблема не в количестве свободной оперативки а в том что если ответ (вебстраница) больше чем буфер то вебсраница может затереть данные в оперативке сразу за буфером. Естественно с самыми неожиданными последствиями. Кстати не забывайте что в буфере находится не только тело страницы но и tcp header. Исходя из того что единственное отличие между рабочим и не рабочим скетчем как раз в размере страницы, то эта проблема самая вероятная.
сектор приз на барабане!!!
а вы ведь правы, просто закомменитровал вывод на страницу 2-го реле и все заработало
поборол это закомментировав тайтл страницы
Спасибо огромное все кто помогал
еще один совсем не относящийся к теме вопрос.
в приведнном коде реализована "кнопка с фиксацией". а как мне ее переделать на "кнопку без фиксации"?
У библиотеки EtherCard есть проблемы с корректностью контроля переполнения буфера. То есть проблема не в количестве свободной оперативки а в том что если ответ (вебстраница) больше чем буфер то вебсраница может затереть данные в оперативке сразу за буфером. Естественно с самыми неожиданными последствиями. Кстати не забывайте что в буфере находится не только тело страницы но и tcp header. Исходя из того что единственное отличие между рабочим и не рабочим скетчем как раз в размере страницы, то эта проблема самая вероятная.
Примерно так я и думал. Рано спать ушел. Поздравляю с решением!