Конфликт библиотек?
- Войдите на сайт для отправки комментариев
Вс, 17/06/2018 - 22:45
есть скетч для arduino nsno + w500 - работает с серверос websocket без проблем.
есть скетч для arduino nano + VL53L0X(лазерный дальномер) работает норммально - измеряет, отобразает через Serial
второй скетч использует Wire.h для связи ардуино с дальномером.
если в первый скетч просто добавляю #include <Wire.h> то он начинает работать странно, не может определить что связь идет по протоколу websocket.
что может влиять? и как выяснить что влияет?
есть подозрение, что i2c конфликтует из-за прерываний , но прерывания от VL53L0X не используются.
просмотр протокола обмена w500 с сервером с помощью wireShark показывает , что Wire.h отправка с сервера идет нужная, вот только ардуинка не может принять правильно.
и именно в самом начале когда происходит коннект к серверу.
как-то можно отложить работу по подключению и настройке i2c? чтоб сначало w5500 отработал
Ничего не понял, но Wire.h осуждаю за то, что он запрещает принимать. Легалайз надо обсуждать.
Вот вам таблетка - https://github.com/Testato/SoftwareWire
Ничего не понял - могу попытаться ещё подробнее, не вопрос. укажи что нужно для понимания проблемы.
что означает "запрещает принимать" ?
что делает сия таблетка?
чем она отличается от стандартной?
Мне ничего не нужно. У меня нет проблемы работы Ethernet и I2C, потому что они не пересекаются в принципе.
Но если нужно что-то вам, то выражайтесь более ясно, приводите максимально сокращенный код, который не работает, схему подключения и пр. Тащить это из вас никто не собирается, угадывать что такое w500 - тоже.
Библиотека SoftwareWire всем отличается от стандартной. Если со стандартной у вас процесс обмена останавливается и вы не умеете/не хотите локализовать проблему - замените библиотеку. Возможно, что повезет и все зафурычит.
я нехотел никого обижать, мне нужно разобраться почему не работает, поэтому готов ответить на любые вопросы, которые помогут выяснить причину.
w500 - это описка , правильное название модуля w5500 http://iarduino.ru/shop/Expansion-payments/setevoy-modul-w5500-tsr-ip-et...
для него нужна библиотека https://github.com/adafruit/Ethernet2
для нормальной работы с ним необходимо отключать прерывания
где
VL53L0X(лазерный дальномер) - http://roboparts.ru/products/gy-530-lazerniy-dalnomer ,
библиотека взята тут https://www.arduinolibraries.info/libraries/vl53-l0-x
подключён без использования вывода G (GPIO1)
А что происходит, если "прерывания не отключать"? Сколько я читал эти Ethernet.h - в них перывания, которые могли бы использоваться, не обрабатываются вовсе. Поэтому ваше описание пока больше загадок порождает, чем разгадок. Что в вашей конструкции привязано к INT1 ?
происходит потеря данных , т.е. если во время приёма данных срабатыаеи прерывание - оно блокирует прохождение прерываний от w5500. хотя ч видел рекомендации о подключении данного модуля без вывода прерывания, но у меня это не сработало.
видимо w5500 более крутая , чем w5100 :) для неё есть "специальная" библиотека Ethernet2.h
пока у меня привязана к INT1 кнопка через RS-триггер на 555ТМ2 (т.е. дребезга нет). в дальнейшем планируется использование нескольких кнопок, с чтением нажатой через реиистры выводов d6-d9.
меня больше всего смущает, что для "сбойной работы" достаточно только подключить #include <Wire.h>
по подключению - я в инете видел как с подтягивающими резисторами , так и без них - это может влиять?
влияние проявляется как потеря нескольких первых байт сообщения из w5500.
http://radioprog.ru/post/233
TWI модуль вызывает прерывание, когда заканчивает работу, чтобы уведомить процессор об изменениях состояния (включая успешность операций и/или ошибки).
в этом плане наверное https://github.com/Testato/SoftwareWire имет преимущество. только тогда меня интересует вопрос - может ли VL53L0X работать в режиме запрос-ответ? (я этим всем работаю первый раз).
или как-то отключать прерывания от I2C. что мне кжется былобы предпочтительнее
Ей-богу какая-то каша у вас с этими прерываниями. Во-первых - деаттачем вы не отключаете прерывания, а просто игнорируете кнопку. Никаких обработчиков прерываний, насколько мне известно, библиотеки EthernetX не содержат. INT сетевого модуля, как я подозреваю, тоже висит в воздухе.
Если TWI мешается под ногами Ethernet-у, то и простой пример типа WebServer/Webclient тоже должен сразу переставать функционировать нормально, если добавить к нему Wire. Так происходит?
согласно http://arduino.ru/Reference/DetachInterrupt
detachInterrupt(interrupt) - Выключает обработку внешнего прерывания (грубо - отключает прерывания)
INT сетевого модуля в воздухе не висит, первоначально не было подключено - не работало.
такой код работает
т.е. отрабатывает и связь c сервером и как по инициативе сервера, та и по иниуиативе клиента по нажатю на кнопку.
единственно что при старте я не получаю правильное рукопожатие - т.е. клиент (ардуино) отправляет
https://learn.javascript.ru/websockets#%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D0%BE%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F
сервер отвечает, но клиент не принимает ответ, по факту получается , что сервер с клентом "договорились" о протоколе websocket, хотя я в коде не могу этого проконтрольровать, код, отвечающий за данное сообщение сервера, его не получает (при подключенной библиотекt Wire) , но в дальнейшем всё работает по протоколу ws .... вроде правильно. вот это "вроде" не устраивает, если первоначально не принимает ответ, где гарантия, что и остальные данные не искажены/не пропущены
к сожалению отправка данных с дальномера ещё не сделана, поэтому не могу гарантировать что не пропадают какие-то данные.
есть подозрение, что глюк происходит на момент инициализации обеих модулей.
существует ли возможность отложить включение инициализации модуля I2C ? т.е. уже после всех действий по подключению w5500 и получения ответа с сервера.
detachInterrupt действительно отключает обработчик внешнего прерывания, а точнее - перестает вызывать из штатного обработчика вашу функцию. Другие прерывания при этом не прекращают приниматься и обрабатываться. Если вы наблюдаете проблему, когда у вас подключен собственный обработчик, выносите из него все в loop() и исполняйте весь блок инструкций там, ориентируясь на флаг, поднимаемый в обработчике. Вполне вероятно, что вы там висите слишком долго и это сказывается на остальном процессе. Потому что как раз в этом-то случае остальные прерывания обрабатываться перестают.
Задержать Wire, наверное можно через поздний вызов begin(), но я думаю, что дело не в этой библиотеке.
сделал "полный цикл" -
работает как надо.
однако при старте глюк остался.
(если можно данный код сократить/улучшить/ускорить - подскажите что можн сним сделать)
1) Перестать деаттачить обработчик
2) Поднимать в обработчике флаг, после send-а опускать. Читать сенсор/слать данные, когда флаг поднят.
чем плохо деаттачить обработчик?
нажатия кнопки имеют низкий приоритет, поэтому пусть всё спокойно завершится и только потом обработает кнопку,
поднять флаг, опустить флаг - это который флаг?
не есть ли работа с этим флоагом и detachInterrupt(1)/attachInterrupt ?
Вы же хотите оптимизировать? Ну так вот - смысла в аттачах/детачах нет. Только процессор зря напрягается. В обработчике ставьте переменную sendNow = true, а в лупе делайте то, что было в обработчике ранее только если sendNow == true. Меньше дергаете датчики/модули - больше тактов сохраняете для других дел. Не забывайте про ключевое слово volatile для переменных, меняющихся в обработчике.
ведь после инициализации всего всё работает как надо и прерывания обрабатываются нормально. весь баг только в начальной стадии.
В таком случае - какое улучшение/сокращение/ускорение приведенного фрагмента кода вы планировали получить, если у вас всё ок?
там есть такой кусок
11
int
i = 10;
12
while
(dist > 0) {
13
d[i--] = uint8_t ((0x30 + dist % 10));
14
dist /= 10;
15
}
16
uint8_t* g;
17
g = (uint8_t*)(&d);
18
wsclient.send(g,
sizeof
(d));
10
uint8_t d[] =
"xxx03| "
;
вот про него речь.
а по прерываниям - http://robotosha.ru/arduino/arduino-interrupts.html
есть чему удивиться.
и , всё-таки, есть какие-нибудь идеи как разрулить процесс инициализации?
идея с таблеткой, конечно , вариант, но хочется более детально разобраться с причиной, чтоб знать что обходить...
Наверное еще где-то есть неправильно написанный код, как и в случае выше. Искать его и не повторять - это и есть работа программиста.
вот только кода совсем мало
основной код
WebSocketClient.cpp
WebSocketClient.h
нашёл место глюка, в чем причина не могу понять
это только при подключённой либе wire, при её отсутствии всё нормально
куда пропадает строка?
это, канешна, не поможет, но переставь 7 строку перед 11-й
и character никада -1 не будет, иба он беззнаковый.
byte не будет, а char - вполне себе. Только вот стримовский read(), например, возвращает int, который или -1 или 0..255. Так же, как я помню, проверка available() == 0 равносильна read() == -1, так что тут имеется избыточное условие.
А вообще, как я подозреваю, тут есть какая-то проблема с памятью, ибо единственное, что поганого делает Wire - это резервирует под буфера ОЗУ. Плюс тут есть String, который растет, как хочет. Ставлю на то, что если сбросить стринги и работать с char[] - то всё нормализуется.
Плюс тут есть String, который растет, как хочет. Ставлю на то, что если сбросить стринги и работать с char[] - то всё нормализуется.
Ну, а вы думаете, что String никак не ограничен пределом ОЗУ? Надо или парсить на лету или брать SoftwareWire и сэкономить на буферах или использовать общий выделенный глобальный char[] для всех функций, передавая указатель туда-сюда. Чудес-то не бывает.
На крайний случай - проверять что там String выделил... Как-то ЕвгенийП описывал способы в посте про мазохизм.
к сожалению точную причину выяснить не удалось, поэтому с большой степенью вероятности склоняюсь к мнениям sadman41.
рабочий вариант такой
WebSocketClient::readLine выкинул.
И что, работает без readLine() ?
в readHandshake() уж точно можно обойтись без String - размер строки для сравнения точно известен.
И что, работает без readLine() ?
в readHandshake() уж точно можно обойтись без String - размер строки для сравнения точно известен.
ардуинка считывает с дальномера, фильрует, отправляет на сервер, сервер с помощю "серверного рендеринга" строит svg полилайн и отправляет браузеру, браузер вставляет в элемент svg - и на экране бегущая линия - изменение расстояния во времени от положения датчика.
без string обойтись можно, известно что сравнивать и даже где это должно быть , но пока это не критично :) на быстродействие это не скажется , а вот на память. ведь после выхода их функции память занятая под стринг освобождается? или надо как-то её освободить/вернуть основному процессу?
В данном случае, думаю, что все будет ок, но если привыкнуть и начать к стрингу добавлять символы в разных местах программы, то дыр он понаделает в ОЗУ. Думаю, что с байтмассивом быстрее будет, чем с классом. Не по человеческим меркам, по процессорным.
А перед Wire придется извиниться - не виноват он оказался...
А перед Wire придется извиниться - не виноват он оказался...
но ведь он как-то влияет, ведь без него было нормально , жаль , что это влияние не удалось вычислить
А я вот 90% вероятности даю, что String выжирал всю память на входящем реквесте.
Wire только ускорил диагностику. А так бы вешалось всё раз в месяц и вообще бы ничего не понимали б. Я так с ENC28J60 развлекался - эта гадина раз в две недели вешалась у меня. Пока методом тыка нашёл причину - пара месяцев прошла. Так что спасибо скажите такой жирной библиотеке.
и character никада -1 не будет, иба он беззнаковый.
Отнюдь.
Он имеет право быть как знаковым, так и беззнаковым.
Более того, у разных моделей Ардуин этот вопрос решается по-разному.
Поэтому, действительно, сравнивать с -1 - плохая идея.
ну вообщето сравнивается с 0xFF, что и является -1
я не думаю что там вставляется команда на обнуление старшего бита.
и в функции WebSocketClient::monitor () так и сравнивается . и там uint8_t character;
что повлекло за собой data += (char)character;
причем в обоих случаях character = _client.read() вне зависимости от типа character
Более того, у разных моделей Ардуин этот вопрос решается по-разному.
причем сдесь модели? если это программная среда
А я вот 90% вероятности даю, что String выжирал всю память на входящем реквесте.
я тоже к этому склоняюсь, вот только как объснить, что в цикле while - нормально, а после - фигфам?
Какой замысловатый алгоритм. Хорошо, что я не читал этот WebSocketClient на ночь.
я тоже к этому склоняюсь, вот только как объснить, что в цикле while - нормально, а после - фигфам?
Этого я не наблюдал, а вот то, что код в той функции спохмела писан - похоже.
Какой замысловатый алгоритм. Хорошо, что я не читал этот WebSocketClient на ночь.
замысловатость - это проходящее, зато какой кайф от его использоавния, я от ws тащусь в самого момента их появления.
у меня отображение в браузере в темпе считывания с датчика и сервер вообще не нагружен. ни каких запросов ajax.
счас осталость modbus прикрутить и ПИД регулирование....
Более того, у разных моделей Ардуин этот вопрос решается по-разному.
причем сдесь модели? если это программная среда
-1 - это программная среда?
Объясняю еще раз: значение 0xFF, занесенное в переменную типа char, в зависимости от типа Ардуины трактуется либо как -1, либо как 255.
Websockets, как я понимаю, хороши для ситуативной визуализации процессов без ведения архива?
Объясняю еще раз: значение 0xFF, занесенное в переменную типа char, в зависимости от типа Ардуины трактуется либо как -1, либо как 255.
Websockets, как я понимаю, хороши для ситуативной визуализации процессов без ведения архива?
для сервера они абсолютно одинаковы, все клиенты отличаются только по id сессии, ну и логикой кода присваивается имя , чтоб определять клиента по имени его регистрации на сервере.
вот к примеру с регулилировкой, ардуинка с своём темпе обрабатывает/регулирует и отдаёт данные серверу.
серверуне надо запрвшивать переодически нарушая темп работы ардуинки. сервер получает данные если есть необходимость пишет их в базу, если у клиента открыта страница где выводятся данные в темпе обработки ардуикой(т.е. в реальном времени) - сервер будет отправлять клиенту , продолжая писать в базу.
это как один из многих вариантов использования
чем трактуется? кодом?
чем трактуется? кодом?
слава богу , что таого в java нет :)
не и в архив (в базу можно сливать в том же темпе) эта фишка в полном дуплексе с любым устройством с браузером, андроидом, ардуино подобными .
Целиком разделяю восторг от ws. Алгоритм его не сложный (ну понятно кроме альтернативно одаренных ;). По простоте интеграции в проект как на ПК так и на ардуине и скорости работы просто нет равных. На ESP его лепить просто блеск. Только вот почему на ардуинке клиент, а не сервер я не совсем понял. Учитывая что в броузере тоже клиент, получается несколько громоздко. Я обычно на ардуинке делаю сервер выдающий данные пришедшим клиентам (ну и исполняющим их команды если надо). Тогда с любого броузера штатным JS зайти и посмотреть динамичные данные можна, а нужно в БД - так она законектится клиентом и получит свое.
Только вот почему на ардуинке клиент, а не сервер я не совсем понял. Учитывая что в броузере тоже клиент, получается несколько громоздко. Я обычно на ардуинке делаю сервер выдающий данные пришедшим клиентам (ну и исполняющим их команды если надо). Тогда с любого броузера штатным JS зайти и посмотреть динамичные данные можна, а нужно в БД - так она законектится клиентом и получит свое.
Да, Sec-WebSocket-Key по большому счету надо на клиенте генерить псевдослучайно, это требование по безопасности.
Только вот почему на ардуинке клиент, а не сервер я не совсем понял. Учитывая что в броузере тоже клиент, получается несколько громоздко. Я обычно на ардуинке делаю сервер выдающий данные пришедшим клиентам (ну и исполняющим их команды если надо). Тогда с любого броузера штатным JS зайти и посмотреть динамичные данные можна, а нужно в БД - так она законектится клиентом и получит свое.
А как броузером ходить? Или не используете такое. То, что таких устройств несколько не проблема для броузера, просто с одной страницы на JS пишу конект к сколько надо. Прикольно получается по скорости. Никаким аяксом такого не получиш. При регулировку крутиш на планшете крутилку и устройство отрабатывает с незаметной задержкой. При регулировке чего либо это очень важно. Я на ESP по протоколу WS такое http://arduino.ru/forum/apparatnye-voprosy/polzuet-li-kto-wifi-moduli-esp8266-podelites-vpechatleniyami?page=20#comment-262075 делал :)
Да, Sec-WebSocket-Key по большому счету надо на клиенте генерить псевдослучайно, это требование по безопасности.
А как броузером ходить? Или не используете такое. То, что таких устройств несколько не проблема для броузера, просто с одной страницы на JS пишу конект к сколько надо.
http://arduino.ru/forum/apparatnye-voprosy/polzuet-li-kto-wifi-moduli-esp8266-podelites-vpechatleniyami?page=20#comment-262075 - классно получилось.