После выхода новой Arduino Ethernet Shield 05 прошло довольно много времени, но недавно мне случилось снова обратиться к этой теме, изучая возможности платы Freeduino EthernetSD Shield:
Отправная точка для ее создания сходна с Freeduino One - попытка собрать ограниченную партию для собственных нужд из доступной комплектации. Но попутно выяснилось много маленьких, но интересных фактов.
Например - каким образом новая плата оказалась совместима с Mega?
Напомню историю проблемы: в Arduino обмен с Ethernet-чипом W5100 происходит по шине SPI, и сначала сигналы на Arduino Ethernet Shield были разведены прямо от колодки цифровых входов 11,12 и 13, к которым и был привязан аппаратный SPI на ATmega168/328. Но после триумфального выхода Arduino Mega все вдруг с опозданием спохватились, что аппаратный SPI "переехал" на 50,51 и 52 - и это стало причиной несовместимости MEGA не только с EthernetShield, но и вообще со всеми шилдами, использовавшими аппаратный SPI.
Именно в результате этого недоразумения SPI теперь принято разводить с колодки ICSP, которая, к огромному счастью, сохранила свое позиционное расположение во всех оригинальных платах Arduino. Заглянем на обратную сторону EthernetSD шилда:
Таким образом, SPI-сигналы MISO, MOSI и SCK будут всегда правильными:
- в обычных (не-MEGA) платах будут использоваться digital 11,12,13;
- в Mega и Mega2560 - 50,51,52.
Единственный сигнал, которого нет на вилке ICSP - это SS (Slave Select). Низким уровнем он выбирает ведомое устройство на шине SPI, с которым будет общаться ведущее (в нашем случае - ATmega):
- для выбора Ethernet используется digital 10;
- для выбора SD-карты используется digital 4.
Соответственно, использовать digital 10 и 4 в схемах с EthernetSD Shield для какого-то другого применения - нельзя.
Ради интереса можете сравнить решение по доступу к SD с вариантом от libellium, котрое я разбирал в статье MicroSD Shield (в основе - тот же резистивный делитель для согласования уровней сигналов). В старой версии Ethernet Shield разъем SD никогда не напаивался (лишь гордо блестели залуженные площадки из-под маски, напоминая о былых ошибках и вселяя ложную надежду в сердца тех, кто рассчитывал напаять разъем и получить какие-то дополнительные функции) - то ли из-за отсутствия согласования сигналов по уровню 3,3В, а может - из-за отсутствия программной поддержки. Да и сигналы эти были разведены на другие пины. Но теперь SD и Ethernet физически разделяют одну шину SPI, одинаково используя преимущества аппаратной поддержки в ATmega.
Отсюда, кстати, вытекает второй нюанс: в случае необходимости работать и с SD-картой, и с Ethernet, между ними придется попеременно переключаться. В принципе, это вполне возможно, особенно в режиме TCP - если данные все-таки потеряются по приему, TCP перезапросит пропущенный фрагмент и автоматически уменьшит окно. Ну, по крайней мере, мне в это хочется верить ;)
На оригинальной схеме Arduino Ethernet Shield 05 сигналы детекта карты и защиты от записи почему-то оказались не разведены на разъем microSD, но сохранены для полноразмерного SD-разъема (они даже имеют подтяжки 10К к Vcc). Я некоторое время колебался - но в итоге оставил эту странность в покое ради полной совместимости. Ведь представьте себе - установка/изъятие SD-карты влечет изменение уровня на analog0 и автоматически приводит к невозможности его использования для других целей.
Авторы по прежнему сохраняют разорванную перемычку INT, которая может соединить выход прерывания W5100 c digital2 и использовать для ввода/вывода механизм прерываний. Однако, поддержка прерываний с W5100 так до сих пор и не реализована: библиотека работает традиционным для Arduino методом пулинга (постоянного опроса состояния буфера из скетча).
Схема сброса с дополнительным супервизором и триггером Шмидта в придачу сразу сняла все непонятные глюки, которые у меня наблюдались с первой версией платы. Жить стало проще и веселее (с) ;)
Заслуживает нескольких слов и программная поддержка, над которой сообщество также изрядно потрудилось.
Когда-то я мучительно плодил классы для работы с UDP, в конечном итоге добиваясь возможности синхронизации времени по протоколу NTP. Но прогресс не стоит на месте и теперь UDP включен в библиотеку вEthernet в составе ArduinoIDE 0022, ничего изобретать не надо. Кроме того, энтузиастами написана поддержка следующих возможностей:
- EthernetDHCP, позволяет получать IP-адрес динамически, поддерживается блокирующий и неблокирующий режим вызова функций; есть возможность обновления lease (и перехода на другой IP, если его поменяют "на лету"). Более, чем достаточно!
- EthernerDNS, позволяет преобразовывать символические имена в реальные IP-адреса. Необходимо только знать IP-адрес своего DNS-сервера - например, взять из DHCP lease (см. выше);
- EthernetBonjour, поддержка протокола Bonjour/Zeroconf, реализующего MulticastDNS и DNS Service Discovery - при помощи него вы можете донести до остальных пользователей информацию о том, какие сервисы запущены на вашем Arduino (поклонники Apple быстрее остальных поймут, о чем речь ;)
- WebDuino, библиотека с каркасом для построения веб-серверов на основе Arduino - включает в себя парсинг URL и прочие полезные функции. Почему-то напомнила CGI.pm ;)
- RadiusClient, библиотека для поддержки авторизации по протоколу Radius (видимо, Diametr должен быть на подходе ;)
- UdpNtpClient, пример из стандартной библиотеки, запрашивающий по NTP время и расшифровывающий ответ в виде ЧЧ:ММ:СС. Что я могу сказать... весьма грубо усеченный, но рабочий вариант.
Недавно мне задали вопрос: "Насколько сложно программировать для EthernetSD Shield?" В качестве демонстрации ответа, приведу решение задачи, которую один мой знакомый сформулировал так: "у меня есть компьютер с портом RS232, надо дать к нему доступ через Internet". При этом от предложений на основе PC+Linux он отказался в пользу Arduino+Ethernet Shield. Учтите, выставлять в public internet сервер Telnet - чистое безумие не совсем безопасно! Так что используйте на свой страх и риск:
// Copyright (C) 2011 Ilya Danilov // http://mk90.blogspot.com // // TelnetServer is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation, either version 3 of // the License, or (at your option) any later version. // // TelnetServer is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // Illustrates how to make simple Telnet Server based on Ethernet Shield. #if defined(ARDUINO) && ARDUINO > 18 #include <SPI.h> #endif #include <Ethernet.h> #include <EthernetDHCP.h> #include <SD.h> byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEC }; #define MAXPASSLEN 16 #define READ_TIMEOUT_IN_MS 60000L char enteredPassword[MAXPASSLEN]; char cardPassword[MAXPASSLEN]; Server server(23); // Just a utility function to nicely format an IP address. const char* ip_to_str(const uint8_t* ipAddr) { static char buf[16]; sprintf(buf, "%d.%d.%d.%d\0", ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3]); return buf; } void setup() { pinMode(10, OUTPUT); pinMode(4, OUTPUT); digitalWrite(10, HIGH); digitalWrite(4, HIGH); SD.begin(4); digitalWrite(4, HIGH); Serial.begin(9600); Serial.println("Attempting to obtain a DHCP lease..."); EthernetDHCP.begin(mac); const byte* ipAddr = EthernetDHCP.ipAddress(); const byte* gatewayAddr = EthernetDHCP.gatewayIpAddress(); const byte* dnsAddr = EthernetDHCP.dnsIpAddress(); Serial.println("A DHCP lease has been obtained."); Serial.print("My IP address is "); Serial.println(ip_to_str(ipAddr)); Serial.print("Gateway IP address is "); Serial.println(ip_to_str(gatewayAddr)); Serial.print("DNS IP address is "); Serial.println(ip_to_str(dnsAddr)); server.begin(); } boolean authenticateClient(Client &client) { int i=0, k=0; unsigned long timeoutTime; delay(500); client.flush(); // kill telnet handshake junk memset(enteredPassword,0,sizeof(enteredPassword)); for (i=0;i<3;i++) { client.println("Password:"); k = 0; timeoutTime = millis() + READ_TIMEOUT_IN_MS; while ( (k<MAXPASSLEN) && client.connected() && (millis() < timeoutTime) ) { char ch = client.read(); if (ch != -1) { if (ch == '\r') continue; if (ch == '\n') break; enteredPassword[k++] = ch; } else delay(10); } if (millis() >= timeoutTime) return false; if (!client.connected()) return false; // read password from SD if (enteredPassword[0]) { if (SD.exists("passwd")) { memset(cardPassword,0,sizeof(cardPassword)); k = 0; File f = SD.open("passwd"); while (f.available() && k<MAXPASSLEN ) { char ch = f.read(); if (ch == '\r') continue; if (ch == '\n') break; cardPassword[k++] = ch; } f.close(); digitalWrite(4, HIGH); // compare if (!strcmp(cardPassword,enteredPassword)) return true; else { client.println("Password mistmatch, try again!"); } } else { client.println("Password file not found\n"); } } } return false; } void loop() { boolean authenticated = false; //EthernetDHCP.maintain(); // listen for incoming clients Client client = server.available(); if (client) { while (client.connected()) { if (!authenticated) { if (!authenticateClient(client)) { client.println("Authorization failed."); client.stop(); break; } else authenticated = true; } else { //auth passed if (client.available()) { char c = client.read(); Serial.print(c); } if (Serial.available() >0 ) { char c = Serial.read(); client.print(c); } } } } }
После старта Arduino получает адрес динамически и выводит его через Serial-порт, чтобы было понятно, на какой IP ломиться telnet-клиентом. По входящему соединению выдается запрос "Password:", полученная в ответ комбинация символов сравнивается с содержимым простого текстового файла passwd, который располагается в корне SD-карты (внутри файла просто пароль, не путать с /etc/passwd :).
И как водится во всех сказках, на ввод правильного пароля дается три попытки ;)
Если выкинуть авторизацию, скетч займет один экран. Сложно? Не думаю, хотя для серьезных задач потребуется изучение нюансов. В итоге: после компиляции скетч занял 23К в памяти, переключение между SD-картой и Ethernet работает нормально.
И как водится во всех сказках, на ввод правильного пароля дается три попытки ;)
Если выкинуть авторизацию, скетч займет один экран. Сложно? Не думаю, хотя для серьезных задач потребуется изучение нюансов. В итоге: после компиляции скетч занял 23К в памяти, переключение между SD-картой и Ethernet работает нормально.
Как всегда, часть плат пока еще доступна здесь.
пример интересный, но ваш знакомый все-таки очень странный человек - плата ардуино + шилд примерно 2000-2200р
ОтветитьУдалитьпри этом например такой роутер ( http://wiki.openwrt.org/toh/tp-link/tl-wr741nd ) стоит 660р
прекрасно перешивается на openwrt, имеет внутри нераспаянный порт консоли и ssh "из коробки"
один из вариантов применения (в паре с ардуино)
http://www.instructables.com/id/Home-automation-server-with-router/#step1
Человек ищет решение, но не всегда знает о всех путях его осуществления. Это как в perl - "есть много способов сделать это".
ОтветитьУдалитьНо, тем не менее - это правда, т.е. запрос про именно такое решение мне озвучивали. Ах, знали бы Вы, что мне вообще озвучивали! ;)
Кстати интересно а какую реально скорость может обеспечить такой Ethernet шилд?
ОтветитьУдалитьПонятно что SPI будет тормозом и 100Мбит/c даже близко не получится, но все же сколько можно из нее реально вытащить?
Забавно, но и я этим вопросом задавался (по работе). Минимальный период SCLK - 70 нс, значит байт передается не быстрее 560 нс и т.д., если я ничего не путаю - полмегабайта в секунду (на пределе возможностей).
ОтветитьУдалитьЧтобы увеличить скорость, надо использовать параллельный интерфейс W5100, который в этом шилде не используется.
Планирую приобрести шилд для Mega, как по внешнему виду быть уверенным, что они будут совместимы? Должен быть распаян SD и присутствовать мама-SPI?
ОтветитьУдалитьПриобретать, скорее всего, буду на ebay.
SD может быть и не распаян, а вот мама-SPI на тыльной стороне - да, должна быть.
ОтветитьУдалитьПравильно ли я понимаю, что для Mega надо использовать
ОтветитьУдалитьpinMode(53, OUTPUT) ?
Кстати, есть ли где-то возможность автоматического определения "платформы" Т.е. где-то в библиотеке определять 10 или 53 используется в конкретном случае, что что бы не править каждый раз код перед заливкой на разные платы?
Нет, неправильно понимаете. Просто всегда используйте 10, потому что выбор SD висит именно на нем, а не на аппаратном SS.
ОтветитьУдалитьСегодняшняя моя истоия: http://mircobot.blogspot.com/2011/11/micro-sd-ethernet-shield-05.html
ОтветитьУдалитьНаводящий вопрос: на шилде написано "mk90.ru" или "mk90.blogspot.com"?
ОтветитьУдалитьНа шилде написано mega compatible :)
ОтветитьУдалитьmade in china, мама-SPI присутствует.
Тогда извиняюсь - подумал, что речь про мой шилд или про оригинальный Arduino-вский. Видимо, китайцы даже схему правильно скопировать не могут :( Но на будущее - спасибо, буду знать - что и такое бывает ;)
ОтветитьУдалитьПри появлении MEGA проблема четко обозначилась для EthernetShield из-за "переезда" пинов, отвечающих за аппаратный SPI. Тогда и было решено брать их надо исключительно с вилки ISCP6. Сигнал SS на ней отсутствует, но для устройства-мастера его аппаратная поддержка уж точно не критична, поэтому его можно взять с любого general-пина.
А у Вас точно не работает скетч из статьи? Все никак не могу поверить :(
Классический SD-скетч заработал, когда я вписал pinMode(53, OUTPUT);
ОтветитьУдалитьДаже в комментариях там написано:
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin
// (10 on most Arduino boards, 53 on the Mega) must be left as an output
// or the SD library functions will not work.
Ваш скетч у меня заработал (работу с SD я выбросил для упрощения).
Причем пришлось оставить:
oid setup() {
pinMode(10, OUTPUT);
pinMode(4, OUTPUT);
digitalWrite(10, HIGH);
digitalWrite(4, HIGH);
// SD.begin(4);
digitalWrite(4, HIGH);
delay(500);
Если последний digitalWrite(4, HIGH); убрать, то не происходит подключение к dhcp серверу 8).
Гм. Тогда зря я ругал кетайцев ;)
ОтветитьУдалитьНи как не могу разобраться что сделать что бы у меня одновременно заработало SD и Ethernet.
ОтветитьУдалитьКакой должен быть алгоритм? После работы с sd вызывать digitalWrite(4, HIGH); ?
Так Вы же говорите, что скетч из статьи работает? Там и SD, и Ethernet используются, попеременно.
ОтветитьУдалитьЯ написал, что убрал из вашего скетча SD. Нельзя ли где-то пообщаться в более удобном месте. Каждый раз капчу вводить надоело, да и код не удобно будет в комметах читать.
ОтветитьУдалитьЯ только за, предлагаю в форуме.
ОтветитьУдалитьГотово: http://mk90.ru/forum/viewtopic.php?f=4&t=19
ОтветитьУдалитьПомогите с этим шилдом.
ОтветитьУдалитьВсе в него заливается, мигает посекундно сверху пару диодов(+ зеленый слева на коннекторе витой пары).
Например Определить свой IP внутри DHCP, ничего не выдает.
На роутере ,свиче, лампочка коннекта не горит.
Думал кабель - вставляю его в комп с этим кабелем - работают.
Может что-то не правильно сделал?
Я перепробовал несколько различных библиотек пока что-то наконец-то заработало. Так же пришлось периодически менять состояние 4 и 10 пинов. Об этом написано выше. Причем на Mega 2560 это работает, а UNO стабильно вешается через какое-то время. Причину не исследовал.
УдалитьА обращаться в нашу поддержку пробовали? Можно сразу через форум.
УдалитьМой личный совет - попробуйте для начала что-то простое: со статическим ip, при непосредственном соединении с компом. Скажем, из стандартных примеров - WebServer. Отключите от Arduino все схемы, кроме самого EtherSD шилда. И SD-карту тоже извлеките, если она вдруг вставлена. С Arduino 1.0.1 должно работать, без всяких шаманств - в итоге должно получиться зайти на ардуинку браузером по порту 80.
Ну а потом, убедившись, что все нормально завелось, можно переходить и к более сложным комбинациям...
Проблема в том, что на работе, интернет-клубе через обычные счичи все примеры по Етернет-шилде работают ,а дома DIR-615, не ребоатает.
УдалитьДаже лампочки не светятся о том, что на ЛАН подлючен провод. На Ардуино мигает зеленая а на роутере - ноль эмоций.
Не знаю даже как подружить. Ведь дома хочу работать с Ардуино, а не на работе, когда занят.
имеем:
ОтветитьУдалить1)arduino mega 2560 R3
2)ethernet shield
Система win7, arduino ide = arduino-1.5.4-r2-windows.
При подключении одной ардуины - видится порт с ней, скетчи заливаются.
Если навесить ethernet shield - теряется порт или видится, но вкл/отключив подключение дуины к компу кабелем USB - порта нет.
Или при заливке вываливается ошибка:
КОД: ВЫДЕЛИТЬ ВСЁ
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_getsync(): timeout communicating with programmer
что делать?
странность в том,что без шилда, ок все, с ним - косяк.
Чаще всего в такую ситуацию можно попасть, устроив на шилде короткое замыкание (замкнув GND и VCC, или же дав по нему чрезмерное потребление). Еще может быть "сюрприз", если ethernet shield довольно стар и не совместим с Mega.
Удалитьспасибо)
Удалитьтут еще ситуация такая: если с шилдом, то ардуинка видна в устройствах на комп., но не видна в arduino ide, без шилда и там и там и работает)
прозвонить с шилдом GND и VCC?
китайцам отписался, предлагают выпаять 2 элемента возле кнопки на шилде)
что-то боязно)))
А если попробовать разобраться, что это за элементы и зачем их выпаивать? Схемы, конечно же, нет?
Удалить