Так ребята. Раз никто ничего не знает. Или знает, но не говорит. Тогда я сам вам поведую рассказ о том, что удалось выяснить за 3 недели.
Сразу скажу! Текст пишу для себя (Мало ли забуду какие нюансы). Комментариев к коду нет, так что придется разбираться.
Поехали!
Техническое задание: Нужно 4-ре выключателя с 4-мя кнопками и 4-мя светодиодами состояния. У каждого выключателя есть реле которое управляет нагрузкой (лампочкой). Все выключатели объединены в сеть. И каждый выключатель может управлять релюшкой другого выключателя передавая команды по сети. В ответ получая состояние реле.
Первая версия проекта состояла из Arduino+nrf24l01(с усилителем). Работала 2 года. Выявлены конструктивные недочеты. А именно: 1) Я сделал сенсорные кнопки - перестали нормально работать через год. (Вывод: Больше не буду использовать сенсоры. Работают иногда не предсказуемо. Нет тактильной обратной связи. В общем ерунда при практическом использовании) 2) Модуль nrf24l01 постоянно теряет пакеты и из за этого связь. (Думаю из за того, что модуль подделка. (Читал о таком явлении с поддельными модулями)).
Решил развивать проводную сеть и заодно переделать эти выключатели на ethernet кабель.
Выбор пал на модуль W5500 от Wiznet.
Физически модуль выглядит так.
ГЛАВА 1. ARDUINO(328p) + W5500<Ethernet2.h> + MQTT<PubSubClient.h>Брокером MQTT служил
mosquitto. Установленный на ПК Windows.
Видеоинструкция по установке и настройке + Просмотрщик пакетов.Комментарии по работе в среде ARDUINO: Код пишется быстро, сразу начинает работать MQTT.
НО! Лично у меня работает первые 15 минут. Дальше пакеты перестают доходить до адресатов. Постоянно теряется соединение и не восстанавливается. В коде я проверяю коннект.
Код:
if (ethClient.connected() && MQTTclient.connected())
Так вот, иногда он работает иногда нет. Например: Если вытащить Ethernet кабель то все равно в логах соединение есть.
В общем библиотеки не доработанные на потерю и восстановление соединения. Пробовал другие библиотеки, но они работают ещё хуже.
Для информации. По библиотеки <PubSubClient.h>
есть даже подробное описание!!!!
Прилагаю скетч. Пусть будет для истории. Может кому то пригодится.
Вложение:
Arduino_W5500_MQTT.rar [2.95 KiB]
Скачиваний: 321
Добавлено after 1 hour 22 minutes 19 seconds:ГЛАВА 2.После мытарств с ARDUINO решил плюнуть на это дело и написать уже код на С.
AVR(328p) + W5500 + DHCP + MQTTКомпания Wiznet снабдила свой Ethernet модель
уже готовой библиотекой.
НО! Не снабдила внятными примерами как с этим работать.
Так что для понимания смотрим 2 видео:
1)
Электроника в объективе: Ethernet для МК. W5500 и ENC28J60. MQTT2)
Vladimir Medintsev: STM32 + Ethernet / Чип W5500 от WIZnet / Сокеты и простой рассказ о построении WEB сервера. Часть 2.3) Статья:
Микроконтроллеры STM32: выходим в сеть с Wiznet W5500Все! Больше ничего вменяемого на русском языке про библиотеку от Wiznet НЕТ!
После изучения этих 3 ресурсов становится более менее понятно как работать с модулем. Дальше. Открываем код и изучаем что я там понаписал.
В дополнении расскажу о подводных камнях с которыми я сталкивался. Думаю будет полезно так как я убил на это ОЧЕНЬ! много времени.
1. Инициализация W5500. Когда модуль прошел инициализацию, но уже отвечает на команду ping. Если этого нет, то что то идет не так.
Самое смешное, что изначально я брал файлы из библиотеки от WIZnet. И у меня ping не работал.
Потом я взял пример из видео от канала "Электроника в объективе" и использовал файлы оттуда. И все заработало! Решил сравнить файлы и там что то было дофига различий. Разбираться не стал. Библиотеки ОЧЕНЬ! мудреные и остановился на файлах из видео. Далее я использовал только их.
Вложение:
Не забываем сконфигурировать SPI! Есть интересный файл "W5500_driver.с" Там много про инициализацию самого модуля.
PS. Есть интересная функция.
Код:
uint8_t PHYLINK_Status;
ctlwizchip(CW_GET_PHYLINK, (void*)&PHYLINK_Status);
printf("PHYLINK_Status= %d\n",PHYLINK_Status);
Показывает есть ли линк на модуле или нет.
2. DHCP. Эта библиотека меня реально порадовала. Работает как часы, проста в настройке, поддерживает реконнект.
НО! Таймаут на реконнект огромны! И есть выход!
Файл dhcp.с. Строчка
Код:
if ((dhcp_lease_time != INFINITE_LEASETIME) && ((dhcp_lease_time/36) < dhcp_tick_1s))
Изначально вместо 36 стояло значение 2. Вот меняя это значение можно менять реакцию, например на отключение кабеля.
Также в инструкции говорится что нужно вызывать функцию DHCP_time_handler(); раз в секунду. Этот счетчик времени для библиотеки. Он у меня вызывается раз в 100 миллисекунд и все равно таймаюут пришлось поделить на 36.
3. MQTT. Самая жирная из библиотек и самая бестолковая. В идеальных условиях она работает стабильно.
НО! Пропала сеть, выключился брокер или ещё что ни будь произошло. МК зависает. А точнее застревает в как то из циклов внутри библиотеки. Помогает только перезагрузка МК. Кроме того библиотека не оптимизированная. Все типы данных 32 разрядные. Даже там где можно применить 8 разрядов. Все равно используется 32. Я пробовал оптимизировать 2 файла. Выиграл 1,5Кб места. Но это не выход. Вся библиотека в целом не очень.
Камень 1
По инструкции надо постоянно вызывать MQTTYield(&c, 0); Если вызвать функцию до подключения MQTT то это гарантированное зависание.
Так же в функции MQTTYield (файл MQTTClient.с) есть цикл while (!expired(&timer)). Надо его убрать. Бесполезный и по умолчанию в нем все зависает.
Камень 2
В файле MQTTClient.с в функции deliverMessage есть такое условие
Код:
if (c->messageHandlers[i].topicFilter != 0 && (MQTTPacket_equals(topicName, (char*)c->messageHandlers[i].topicFilter) || isTopicMatched((char*)c->messageHandlers[i].topicFilter, topicName)))
Его надо закомментировать. Это условие избыточное и из за него не происходит обработка принятых сообщений.
Общие замечания:
Код разделения сообщения для дальнейшей обработки:
Код:
char _topic_name[10] = "\0";
char _message[10] = "\0";
MQTTMessage* message = md->message;
MQTTString* topic = md->topicName;
strncpy(_topic_name, topic->lenstring.data, topic->lenstring.len);
strncpy(_message, message->payload, message->payloadlen);
printf("MQTT Sub: [%s] %s\n", _topic_name , _message);
Распознавать сообщения лучше сравнением. Кода будет больше, но стабильнее.
Код:
if (strcmp(_message,"10")==0)
Ну и сам проект всего этого безобразия.
Вложение:
AVR_W5500_DHCP_MQTT.rar [602.28 KiB]
Скачиваний: 327
Добавлено after 55 minutes 51 second:ГЛАВА 3.Как вы уже поняли, библиотека MQTT мне не понравилась. Если нет возможности реконнекта то это чушь а не библиотека.
Я конечно рассматривал и другие библиотеки, но они более непонятные + сопровождения и информации по ним нет вообще.
Долго думал что делать дальше..... На одном форуме сказали "Зачем тебе MQTT? Общайся с контроллером напрямую по TCP\IP. Так проще" Больше никакой информации не было, кроме библиотеки loopback.с от Wiznet.
Вот что получилось на данный момент.
AVR(328p) + TCP\IPВ первую очередь надо сказать.
1) TCP\IP это соединение клиент-сервер. Важно! Соединение всегда устанавливает клиент. Сервер просто ожидает соединения. После того как соединение состоялось данные можно слать в обе стороны из любого места в коде.
2) Сокет - это комбинация IP адреса и порта. Модуль W5500 имеет 1 адрес и 8 портов. Другими словами можем работать с 8 сокетами одновременно.
Мне понравилось использовать TCP\IP соединение. Очень просто, удобно и самое главное есть понятный алгоритм переподключения если что то пошло не так.
В общем лучше смотрите код. Он скажет намного больше чем я буду тут описывать.
Вложение:
AVR_TCP_IP.rar [264.68 KiB]
Скачиваний: 397
Когда соединение установлено. То всегда выполняется "case SOCK_ESTABLISHED :"
Подводные камни:
У меня кнопки управления были завязаны на прерывание (это все тянулось с лагучий библиотеки MQTT). Так вот. Иногда при нажатии что то шло не так и в буфер данных попадал мусор. Итак в нем оставался. Из за этого переставали обрабатываться команды.
Отказался от прерывания и все стало нормально работать.
Подводя итоги могу сказать следующее:
На данный момент TCP\IP соединение самое выгодное по месту на МК и самое стабильно. + Можно организовать общение с ПК по сети!
В качестве программы для такого общение я пробовал
TcpClientServer. Не помню откуда скачал. Но программа простая и видно как пересылаются пакеты.
По самому проекту:
Сейчас макетная плата проработало сутки и глюков не обнаружено. Отказался от DHCP - устройство стационарное. Раз настроил и все.
Осталось подкрутить watchdogs. И какую ни будь проверку на зависание самого модуля W5500. (Например считывать IP адрес и сравнивать с настройкой.)