Байтовый обмен с arduino через ENC28j60

Nagaremono
Offline
Зарегистрирован: 12.08.2015

День добрый, есть система которая должна получать байтовые команды по ethernet и при необходимости в байтовом же формате передавать какой-то ответ, опять же по ethernet.

В качестве базового котнроллера Arduino UNO, в качестве ethernet shield вот такой контроллер на базе ENC28j60.

Начинал проект с W5100, там поставленная задача решалась просто, например вот так

EthernetClient client = server.available();
  if (client.available()>0)
  {
   serial_data=client.read();
   if (serial_data==3)
   server.write('1');

От чипа отказался, так как а) не мой; б) итоговый бутерброд не входит в корпус;  в) высокая цена.

Для чипа ENC28j60 использовал разные библиотеки в итоге заработала только EherCard, взятая с github, причем старая версия от 2014 года. С остальными библиотеками столкнусля с ошибками на стадии компиляции примеров (среда arduino ide 1.6.5 с оф сайта) причина их не понятна, но не в этом суть.

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

Почти все примеры имеют отношение к общению через веб. У меня задача другая, открываю какой-либо порт и из приложения кидаю команды, представляющие собой числа в hex объемом 1 байт, arduino их принимает, что-то делает и если надо отвечает через этот же порт в приложение каким-то числом в такой же форме

Подскажите варианты как это можно реализовать

Заранее спасибо!

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Nagaremono пишет:

Почти все примеры имеют отношение к общению через веб. У меня задача другая, открываю какой-либо порт и из приложения кидаю команды, представляющие собой числа в hex объемом 1 байт, arduino их принимает, что-то делает и если надо отвечает через этот же порт в приложение каким-то числом в такой же форме

Вы хотите работать в обход всех протоколов, или просто неправильно выразились?

Венитесь к w5100.

http://www.ebay.com/itm/TOP-Mini-W5100-LAN-Ethernet-Shield-Network-Module-board-for-Arduino-Best-/400745078775?hash=item5d4e449ff7

Он, кстати, как раз более высокоуровневый, чем ENC

Nagaremono
Offline
Зарегистрирован: 12.08.2015

Ну да, получается в обход протоколов.

Возможно вернусь, но сейчас стоит вопрос о работе именно с этим модулем. Даже из принципа хочется его завести))

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Nagaremono пишет:

Ну да, получается в обход протоколов.

Возможно вернусь, но сейчас стоит вопрос о работе именно с этим модулем. Даже из принципа хочется его завести))

Подозреваю, что вы все-таки запутались в терминах. Иначе - "Ну-ну" (с)

 

По ENC у Осипова разжевано.
https://www.youtube.com/watch?v=PPB2Xvubt4s
https://www.youtube.com/watch?v=RgJnYsTmM5A

и пр.

Nagaremono
Offline
Зарегистрирован: 12.08.2015

Gippopotam пишет:

Подозреваю, что вы все-таки запутались в терминах. Иначе - "Ну-ну" (с)

По ENC у Осипова разжевано.
https://www.youtube.com/watch?v=PPB2Xvubt4s
https://www.youtube.com/watch?v=RgJnYsTmM5A

и пр.

Возможно запутался, не спорю, но поэтому и прошу помощи.

У Осипова разжевано, не спорю, но я там не нашел то что мне нужно.

Я хочу забирать из ТСР пакета байт 0х0036, выделен черным.

Как мне казалось можно использовать конструкции как у Осипова типа

 word len = ether.packetReceive(); 
  word pos = ether.packetLoop(len);

  if (pos){
     Serial.println(pos);
     bfill = ether.tcpOffset();
     char *data = (char *) Ethernet::buffer + pos;
    if (strncmp("T", data, 1) != 0) {  //сравниваем первый значащий символ в полученном пакете
      Serial.println('1');
    }
    else {Serial.println('2');}
}

Serial здесь для отладки стоят. В результате в мониторе пусто. то есть даже нет захода в первое условие

Погонял через Wireshark скетч Осипова с выводом содержимого pos в монитор, получил следующую статистику, при нажатии кнопки на странице происходит отправка 10 ТСР пакетов, а в монитор выводится два раза число 54. После анализа содержимого переданны пакетов первая мысль pos - содержит первый байт передаваемых данных в пакете, так как пакеты с данными (их всего два из 10) содержали  число "54" но по адресу 0х0038, так как по идее данные должны начинаться с адреса 0х0036, этот вариант был отвергнут, перевел адрес 0х0036 в десятичную систему получил искомое "54", то есть адрес первого байта полезных данных.

Начал эксперементировать с участком кода,приведенным выше и о чудо получил ответ, но опять странный ответ появляется только если я отправляю больше 8-ми байт. И похоже получил подтверждение что приходит в pos первый байт полезных данных. Потому что в коде нет функции подтверждения о получении пакета и с ПК он шлется несколько раз, сколько отправит столько и сообщений в мониторе.

Пока писал это сообщение на часть вопросов уже сам нашел ответ, но не факт что правильный, поэтому небольшой итог

По функциям:

word len = ether.packetReceive(); //как описано в библиотеке копирует принятые данные в буфер и возвращает длину пакета данных

word pos = ether.packetLoop(len); //как описано в библиотеке анализирует полученные данные определенной длины, возвращает адрес смещения полезных данных в пакете или ноль, если ничего нет или служебные данные, как выяснилось также возвращает ноль если длина данных меньши восьми байт.

Погружаясь глубже в библиотеку нашел участок кода этой функции в файле tcpip.cpp

if (tcp_client_state==3 && len>0)
        {   //TCP connection established so read data
            if (client_tcp_result_cb) {
                uint16_t tcpstart = TCP_DATA_START; // TCP_DATA_START is a formula
                if (tcpstart>plen-8)
                    tcpstart = plen-8; // dummy but save
                uint16_t save_len = len;
                if (tcpstart+len>plen)
                    save_len = plen-tcpstart;
                (*client_tcp_result_cb)((gPB[TCP_DST_PORT_L_P]>>5)&0x7,0,tcpstart,save_len); //Call TCP handler (callback) function

Как мне кажется ответ про восемь байт скрыт где-то здесь, особые подозрения вызывает последняя строчка, но не могу понять что в ней происходит, кто-нибудь может подсказать? и вопрос вызывает tcpstart, как она вычисляется, формулу то я нашел, но что в ней происходит не очень понял:

TCP_DATA_START ((uint16_t)TCP_SRC_PORT_H_P+(gPB[TCP_HEADER_LEN_P]>>4)*4)

Ну и еще один вопрос как работать с функцией вывода bfill.emit_p(), как выбрать параметры чтобы отправить один байт?

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Ну, батенька...
У меня от таких умных слов эпилепсия приключиться может.

NeiroN
NeiroN аватар
Offline
Зарегистрирован: 15.06.2013

Для ENC28j60 лучше UDP - так как он более проще.

AlexandrK
Offline
Зарегистрирован: 03.05.2015

Поищите библиотеку UIPEthernet.h, там есть примеры TCPServer, UDPServer. Готовые, прямо под Ваши задачи.