Нет уж, я направлю свою энергию сразу на постройку протокола общения, не тратя время на борьбу с ошибками и коллизиями.
Ну, кому что нравится. Многие и на Модбасе делают, и на 1-wire, и даже на I2C пытаются. А свободная топология прокладки кабелей - весьма лакомый кусочек.
Насчет дешeвизны MCP2515: цена у него почти такая же, как у Ардуино Мини Про.
Что же касается "распростаненности CAN" - так ведь UART еще более стандартный и широко распростаненный. Построить CSMA/CD займет несколько десятков строчек кода. Надстройка над CAN-ом, позволяющая передавать длинные сообщения по кусочкам, займет больше. Даже просто общение с MCP2515 займет больше. Не говоря уж о куче всяких разномастных регистров у него (как и любого другого CAN контроллера), с которыми надо работать - настраивать фильтры и маски, обрабатывать ошибки, и т.д. и т.п.
Есть еще одна проблема, которую я пока не затронул. Работа любой системы состоит из двух этапов: конфигурирования и, собственно, самой работы. Вот про конфигурирование все как-то забывают. А делать конфигурирование при помощи CAN - нетривиальное занятие: получится или сложно, или ограниченно по возможностям, или вообще и то и другое.
Любительские системы обычно полагаются на непосредственный доступ к узлам и прямую заливку кода программатором. "Своя ноша не тянет", подумаешь, лишний десяток раз, пока все не отладишь: слазить на чердак, вытащить узел, принести его к РС, залить скомпилированный конкретно под него код, опять залезть на чердак и поставить его на место.
Профессиональные системы позволяют конфигурировать узлы уже после установки. Но программное обеспечение, которое позволяет это делать, сложное.
Используя UART, Ардуино и свой протокол, эту проблему можно решить, например, так. В протокол вводятся две обязательные к исполнению всеми узлами команды:
- "Сброс" - программный сброс для конкретного узла (выбор узла производится по уникальному адресу узла или по его серийному номеру), после чего у него запускается бутлодер
- "Пауза" - запрет всем узлам реагировать на любой трафик в сети на некоторое время, скажем, на 10 сек
Подав эти две команды, можно дистанционно залить скетч в выбранный узел.
Что же касается "распростаненности CAN" - так ведь UART еще более стандартный и широко распростаненный. Построить CSMA/CD займет несколько десятков строчек кода. Надстройка над CAN-ом, позволяющая передавать длинные сообщения по кусочкам, займет больше. Даже просто общение с MCP2515 займет больше. Не говоря уж о куче всяких разномастных регистров у него (как и любого другого CAN контроллера), с которыми надо работать - настраивать фильтры и маски, обрабатывать ошибки, и т.д. и т.п.
Дело в том, что низкий (канальный) уровень общения с CAN уже налажен, в общем-то, до нас - при помощи библиотеки. Поэтому во все эти регистры мы особо не вникаем и не тратим на это время. А вот надстройку (прикладной уровень) над CAN ом (в том числе и длинные сообщения) мы сейчас и делаем. Эта надстройка и есть, собственно, протокол общения элементов умного дома. Т.е. какие типы сообщений в шине, какие ответы от узлов, что будет если узел "отпал", что будет если получил одну и туже команду дважды, какие полезные данные будут летать между узлами, и т.д. и т.п. перечислять можно бесконечно. Такую надстройку нужно всё равно придумывать при ЛЮБОМ физическом протоколе подключения, будь то RS485, 1-wire , CAN или другой канал связи.
А про несколько десяток строк кода с CSMA/CD, про которые вы говорите, в нашем случае это только лишь та составляющая общения, которая реализована аппаратно в MCP2515 и за счёт библиотеки работы с MCP2515 (канальный уровень). Всё остальное точно также городить придётся (прикладной уровень).
triac пишет:
Есть еще одна проблема, которую я пока не затронул. Работа любой системы состоит из двух этапов: конфигурирования и, собственно, самой работы. Вот про конфигурирование все как-то забывают. А делать конфигурирование при помощи CAN - нетривиальное занятие: получится или сложно, или ограниченно по возможностям, или вообще и то и другое.
Любительские системы обычно полагаются на непосредственный доступ к узлам и прямую заливку кода программатором. "Своя ноша не тянет", подумаешь, лишний десяток раз, пока все не отладишь: слазить на чердак, вытащить узел, принести его к РС, залить скомпилированный конкретно под него код, опять залезть на чердак и поставить его на место.
Профессиональные системы позволяют конфигурировать узлы уже после установки. Но программное обеспечение, которое позволяет это делать, сложное.
если почитать посты выше, то можно увидеть, что мой , скажем так, коллега по CANу, решил этот вопрос при помощи ESP wifi. И теперь заливает прошивки по воздуху. К тому же по wifi, я так понял, у него будет дублирование общения с узлами в случае возникновения проблем с шиной CAN.
Эта надстройка и есть, собственно, протокол общения элементов умного дома. Т.е. какие типы сообщений в шине, какие ответы от узлов, что будет если узел "отпал", что будет если получил одну и туже команду дважды, какие полезные данные будут летать между узлами, и т.д. и т.п. перечислять можно бесконечно. Такую надстройку нужно всё равно придумывать при ЛЮБОМ физическом протоколе подключения, будь то RS485, 1-wire , CAN или другой канал связи.
В этом треде сообщений много, большинство из них чисто "технические", искать по зернышку в этом потоке сознания текущее состояние вашего проекта довольно затруднительно. Поэтому я не особо вникаю в детали вашей реализации. Тем более что CAN мне неинтересен. Я когда-то тоже на него западАл, но потом одумался.
Что касается протокола "вообще", то замечу, что RS485 в принципе не позволяет сделать интерфейс типа "производитель-потребитель", который можно сделать при помощи "открытого коллектора" (или при помощи шинного формирователя CAN, что по сути то же самое). А вот наоборот - можно. Можно сделать из CAN ординарный интерфейс мастер-слэйв, а ля Модбас.
Так что надстройку придумывать, конечно, придется, но ход мыслей будет задан как физическим уровнем, так и шаблонами мышления.
Там у вас в переписке упоминаются какие-то "адреса узлов". Для конфигурирования они нужны, для работы в режиме "производитель-потребитель" - категорически нет. Поскольку выясняется, что конфигурирование у вас через WiFi, то, наверное, все-таки вы из CAN подобие Модбаса делаете.
MaksVV пишет:
если почитать посты выше, то можно увидеть, что мой , скажем так, коллега по CANу, решил этот вопрос при помощи ESP wifi. И теперь заливает прошивки по воздуху. К тому же по wifi, я так понял, у него будет дублирование общения с узлами в случае возникновения проблем с шиной CAN.
Я видел это сообщение, но не придал ему особого значения. Подумал, что вы шлюз в интернет на WiFi делаете, что было бы логично. А вы, значит, в каждый узел собрались WiFi ставить, просто для заливки кода? Но если у вас в каждом узле уже есть WiFi, зачем вам вообще CAN? И неужели лишних 80 мА тока потребления не жалко тратить на одну только редко используемую заливку кода?
Нет, перебрал скорости, терминаторы, всеравно глючит, и видимо все же CAN контроллер, начинает выдавать в мегу то, что он получает Standart ID то нули, т.е получается нужно видимо фильтровать лишнее. Вот разбираюсь.
попробуй такой скетч залить на узлы и мастер (выбираешь соответственно адрес , тип и железо МК вверху скетча. ) Поставь на ночь и наблюдай канхакером что будет происходить.
Serial.println(); Serial.print(F("Мой адрес в сети CAN: ")); PrintADDR (node_address);
16
#ifdef type_node_master
17
Serial.println (F(" MASTER!"));
18
#endif
19
Serial.println();
20
21
timeoutsConfigControl ();
22
#endif
23
24
can.setMode(MCP_NORMAL);
25
26
pinmode(); // настройка портов (в зависимости от конфигурации массива device)
27
28
}
Заметь, строка инита MCP отличается. Данная фильтрация пропускает все широковещательные сообщения и с нашим адресом, а также все фреймы со стандартным (маленьким 0х000) ID.
Заметь, строка инита MCP отличается. Данная фильтрация пропускает все широковещательные сообщения и с нашим адресом, а также все фреймы со стандартным (маленьким 0х000) ID.
Мы делаем протокол над CAN но под MQTT анологичный ModbusRTU. Если бы был Modbus не только overTCP но и overCAN, даже заморачиваться не стали бы.
Для справки:
- Modbus был разработан в 70-е годы
- CAN был разработан в 80-е годы
- KNX был разработан в 90-е годы
riv пишет:
Все зависит от требований и задач. Мы с уважаемым MaksVV ставим требование к системе по задержкам 0,01 а то и 0,001 сек. Это конечно не "реальное время" но что то рядом.
Основные применения таких скоростей это управление светом (согласитесь ждать 1-2 сек когда мастер опросит датчики движения а потом передаст УК команду включить реле света, немного не комфортно), управление медиа (звук, видео - переключение радио, оповещения о событиях) и др. приложениях где задержка вызывает дискомфорт или просто опасна.
Повторю, что за счет работы по принципу "производитель-потребитель" KNX способен без задержек управлять светом даже в многоэтажных оффисных зданиях и т.п., но при этом работает на скорости 9.6 кбит/сек. Модбас, работающий по принципу "мастер-слэйв", на это не способен даже при 1 Мбит/сек. И если вы сделаете нечто подобное Модбасу на CAN, то от этого ничего не изменится, это все равно будет "мастер-слэйв".
Впрочем, делайте как хотите, меня это не касается.
Мы делаем протокол над CAN но под MQTT анологичный ModbusRTU. Если бы был Modbus не только overTCP но и overCAN, даже заморачиваться не стали бы.
Для справки:
- Modbus был разработан в 70-е годы
- CAN был разработан в 80-е годы
- KNX был разработан в 90-е годы
riv пишет:
Все зависит от требований и задач. Мы с уважаемым MaksVV ставим требование к системе по задержкам 0,01 а то и 0,001 сек. Это конечно не "реальное время" но что то рядом.
Основные применения таких скоростей это управление светом (согласитесь ждать 1-2 сек когда мастер опросит датчики движения а потом передаст УК команду включить реле света, немного не комфортно), управление медиа (звук, видео - переключение радио, оповещения о событиях) и др. приложениях где задержка вызывает дискомфорт или просто опасна.
Повторю, что за счет работы по принципу "производитель-потребитель" KNX способен без задержек управлять светом даже в многоэтажных оффисных зданиях и т.п., но при этом работает на скорости 9.6 кбит/сек. Модбас, работающий по принципу "мастер-слэйв", на это не способен даже при 1 Мбит/сек. И если вы сделаете нечто подобное Модбасу на CAN, то от этого ничего не изменится, это все равно будет "мастер-слэйв".
Впрочем, делайте как хотите, меня это не касается.
1. Не совсем понятна логика по первому утверждению. Я пишу если бы был аналог протокола over CAN то мы бы свой не писали. (Кстати аналог есть это CanOPEN и еще несколько протоколов, но оин черезмерно сложны). Вы отвечаете годами разработки протоколов. Возможно я что то упустил и потерял цепь размышлений.
2. У нас есть задача автоматизировать дом. Есть дешевое железо. Есть понятная среда программирования. Мы решаем свою задачу. Не для продажи, для себя.
Предложите KNX контроллер для связки с ардуино за разумные деньги, и я готов буду воспользоваться предложенным решением.
Иначе получаются теоретические изыскания на практическом форуме который на минуточку называется http://arduino.ru, что по моему скромному мнению означает, что здесь собрались самодельщики которым близка именно платформа ардуино, модульная сборка изделий без трассировки плат, разработки Э3 и Т5М и самое главное использование готовых плат и модулей.
На сегдня для ардуино есть коммуникационные модули
да я так, на скорую руку просто поставил, можешь вообще запретить короткие ID. Ты упрощённый скетч то попробовал?
pinmode () она и раньше была (см. большой скетч). в фунции pinmode () настраиваются порты ардуино автоматически в зависимости от конфигурации исполнительных устройств в can_struct.h
И если вы сделаете нечто подобное Модбасу на CAN, то от этого ничего не изменится, это все равно будет "мастер-слэйв".
от этого много что изменится. На модбасе rs485 всё идёт через мастера, и как бы слейв не хотел крикнуть в шину что-нибудь, ему нужно дождаться запроса мастера.
В CAN шине: захотел - сразу сказал. Реакция мгновенна. В нашей системе любой узел может говорить с любым узлом, даже если мастера вообще отключить. На Мастер лишь стекается вся информация от узлов для передачи её на уровень выше.
1. Не совсем понятна логика по первому утверждению. Я пишу если бы был аналог протокола over CAN то мы бы свой не писали. (Кстати аналог есть это CanOPEN и еще несколько протоколов, но оин черезмерно сложны). Вы отвечаете годами разработки протоколов. Возможно я что то упустил и потерял цепь размышлений.
Намек на то, что вы движитесь в обратном направлении, надстраивая нечто наподобие Модбаса поверх CAN для того, чтобы решать задачи, на которые заточен KNX.
riv пишет:
Дадите ссылку на KNX модуль?
Ссылка на KNX дана не для того, чтобы все бросить и перейти на KNX. Но знать, как он устроен, полезно, хотя бы на самом базовом уровне: https://www.ixbt.com/home/knx-intro.shtml
Все команды можно разделить на два класса:
- точка-точка, с индивидуальной адресацией узлов; эти команды используются для конфигурирования и диагностики системы
- точка-многоточка, т.е. бродкаст, адрес узла отсутствует; эти команды используются для собственно работы
Ключевое понятие - "групповой адрес". Его можно назвать "виртуальным проводом", которым связана группа устройств. Устройства ввода (выключатели, регуляторы) меняют состояние этого "провода". Устройства вывода (релейные выключатели, диммеры) выполняют действия в соответствии с текущим состоянием "провода". Все устройства (т.е. и устройства ввода, и устройства вывода) в группе отслеживают текущее состояние "провода".
При конфигурировании создаются эти группы, т.е. устройства настраиваются на принадлежность той или иной группе. Заодно настраиваются и другие параметры устройств, например, скорость диммирования при нажатии на кнопку, и т.п. Устройства могут входить в несколько групп. Например, кнопочный выключатель с двумя кнопками управляет двумя группами, релейный модуль на 4 реле отрабатывает состояния 4-х "виртуальных проводов".
Это достаточно хорошо ложится на MQTT, групповой адрес вполне соответствует топику. Ну а все команды конфигурирования в принципе можно свести в один топик.
riv пишет:
Иначе получаются теоретические изыскания на практическом форуме который на минуточку называется http://arduino.ru, что по моему скромному мнению означает, что здесь собрались самодельщики которым близка именно платформа ардуино, модульная сборка изделий без трассировки плат, разработки Э3 и Т5М и самое главное использование готовых плат и модулей.
В принципе вполне возможно сделать KNX узел на 8-битном Ардуино, ресурсов зватает с лихвой. Более того, я уверен, что рано или поздно кто-то это сделает. Однако я не призываю вас это делать. Мне просто странно видеть, как вы на CAN натягиваете допотопный Модбас. Хотя вольному воля, конечно, делайте что хотите.
Залил. Та же петрушка. Узлы по одному перестают отвечать. Пока пропал №9.
значит дело не в софте, а в железе. остаётся попробовать тоже самое, положив рядом все МК на коротком проводе CAN. Если будет гуд - то кабель неправильный и/или неправильная топология и/или длина и/или терминаторы нужно както по сопротивлению подбирать. Видимо от разных свойств кабеля (волновое сопротивление? хз чё это , почитать нужно) нужны разные терминаторы.
у меня валяется два кан трансивера. Не поленюсь подключу к уарт. Посмотрим, долетят ли байты от одного МК до другого. Что то я сомневаюсь, если честно.
у меня валяется два кан трансивера. Не поленюсь подключу к уарт. Посмотрим, долетят ли байты от одного МК до другого. Что то я сомневаюсь, если честно.
А почему сомневаетесь, если не секрет? Что особенного есть в контроллере CAN, из-за чего байты, отправленные им, непременно доходят до другого МК? И какой волшебной субстанции не хватает обычному UART, чтобы достичь того же результата?
у меня валяется два кан трансивера. Не поленюсь подключу к уарт. Посмотрим, долетят ли байты от одного МК до другого. Что то я сомневаюсь, если честно.
А почему сомневаетесь, если не секрет? Что особенного есть в контроллере CAN, из-за чего байты, отправленные им, непременно доходят до другого МК? И какой волшебной субстанции не хватает обычному UART, чтобы достичь того же результата?
The SN65HVD230, SN65HVD231, and SN65HVD232 controller area network (CAN) transceivers are designed
for use with the Texas Instruments TMS320Lx240x 3.3-V DSPs with CAN controllers, or with equivalent
devices. They are intended for use in applications employing the CAN serial communication physical layer in
accordance with the ISO 11898 standard. Each CAN transceiver is designed to provide differential transmit
capability to the bus and differential receive capability to a CAN controller at speeds up to 1 Mbps.
И видим что SN65HVD230 просто передатчик к которому нужно подвести сигнал. Без DSP или МК который этот сигнал сформирует, определив логику обмена, ничего не заработает.
Как точка точка на UART возможно пойдет, тут мысмль интересная. Хотя для этого есть 485.
И видим что SN65HVD230 просто передатчик к которому нужно подвести сигнал. Без DSP или МК который этот сигнал сформирует, определив логику обмена, ничего не заработает.
Как точка точка на UART возможно пойдет, тут мысмль интересная. Хотя для этого есть 485.
Можно попробовать.
На приемопередатчике (трансивере) RS485 нельзя сделать обмен "производитель-потребитель", поскольку он не расчитан на коллизии. А на на трансивере CAN - можно, для него коллизии - это обычное дело. Не играет роли, что протокол делается при помощи UART с программным обнаружением коллизий, CSMA/CD. Для малонагруженных сетей это практически неотличимо от CSMA/CA (иногда то же самое обозначают CSMA/CR), поскольку коллизии очень редки. Я об этом уже писал выше. И точка-точка можно, и точка-многоточка.
На PIC-ах, у которых есть CLC (конфигурируемая логика) при помощи UART-а можно даже CSMA/CA сделать, но для домашних сетей это лишнее, овчинка выделки не стоит.
И видим что SN65HVD230 просто передатчик к которому нужно подвести сигнал. Без DSP или МК который этот сигнал сформирует, определив логику обмена, ничего не заработает.
Как точка точка на UART возможно пойдет, тут мысмль интересная. Хотя для этого есть 485.
Можно попробовать.
На приемопередатчике (трансивере) RS485 нельзя сделать обмен "производитель-потребитель", поскольку он не расчитан на коллизии. А на на трансивере CAN - можно, для него коллизии - это обычное дело. Не играет роли, что протокол делается при помощи UART с программным обнаружением коллизий, CSMA/CD. Для малонагруженных сетей это практически неотличимо от CSMA/CA (иногда то же самое обозначают CSMA/CR), поскольку коллизии очень редки. Я об этом уже писал выше. И точка-точка можно, и точка-многоточка.
На PIC-ах, у которых есть CLC (конфигурируемая логика) при помощи UART-а можно даже CSMA/CA сделать, но для домашних сетей это лишнее, овчинка выделки не стоит.
Просьба всеже внимательно прочитать датиашит и не путать трансивер CAN который по сути просто усилитель и формироватиель биимпульса и CAN контроллера который как раз протокол CSMA делает.
Для MaksVV
Именно это я имел виду выше говоря что в связке с 232 может и полететь, а наш MCP2515 состоит из 2х частей
ТРАНСИВЕРА TJA1050 и КОНТРОЛЛЕРА MCP2515. SN65HVD230 имеет только ТРАНСИВЕР SN65 и его можно использовать например в связке с DUE.
Мы с уважаемым MaksVV пишем протокол обмена уровня 3 модели OSI (даже скорее 3-4) , вы же насколько я понял используя трансивер хотите замахнуться на уровень 2 и 3 одновременно, обеспечивая управление коллизиями и передачу данных, так как Вас не устраивает обработка колизий у CAN.
Просьба всеже внимательно прочитать датиашит и не путать трансивер CAN который по сути просто усилитель и формироватиель биимпульса и CAN контроллера который как раз протокол CSMA делает.
ТРАНСИВЕРА TJA1050 и КОНТРОЛЛЕРА MCP2515. SN65HVD230 имеет только ТРАНСИВЕР SN65 и его можно использовать например в связке с DUE.
Я-то не путаю. Скорей это вы невнимательно читаете то, что я написал. Я уже несколько раз повторил, что контроллер CAN мне не нужен. Мне нужен любой микроконтроллер, имеющий обычный UART, например, Атмега 328 в составе Ардуино Мини Про. И к нему мне нужен трансивер CAN, т.е. шинный формирователь, один только физический уровень CAN. Это все, что нужно, чтобы создать узел сети, функционально соответствующий узлу KNX.
Я более-менее в курсе, как делаются узлы KNX и C-bus. Их уже 25 лет делают серийно. И микроконтроллер, который использовался для такого узла, в разы слабее Атмеги, и по скорости, и по памяти.
А в CAN меня не обработка коллизий не устраивает, а ненужная для такой задачи сложность.
Из 7-уровневой модели ISO/OSI под эту задачу нужны только 1,2 и 7, остальное лишнее.
А в CAN меня не обработка коллизий не устраивает, а ненужная для такой задачи сложность.
Я не совсем понял про сложность.
У нас есть MCP2515, это трансивер и контроллер перекрывающи задачу не только фиксации но разрешения колизий, т.е на уровне 2 сообщение гарантированно будет доставлено.
Т.е мы сразу пошли к уровню 3 адресация и контроль доставки сообщений уровень 4. Пробустив СЛОЖНЕЙШИЙ уровень 2.
Т.е вы считаете что уровень 2 аналогичный Ethernet, ATM, CAN и пр. протоколам проще чем просейший протокол который мы делаем?
И еще вопрос, алгоритм работы KNX на уровне бит байт фрейм у Вас есть чтобы его повторять. Ну или алгоритм работы Вашего протокола. Интересно посмотреть.
короче не смог я найти второй трансивер. Один только есть.
Вместо CAN трансивера вы можете использовать RS-485 трансивер. Они довольно хорошо совместимы, особенно на малых скоростях. Выход UART-а надо подать на DE трансивера, а вход DI посадить на землю.
Когда-то очень давно, пока не разработали специальные CAN трансиверы, все так и делали.
Т.е вы считаете что уровень 2 аналогичный Ethernet, ATM, CAN и пр. протоколам проще чем просейший протокол который мы делаем?
Проще
riv пишет:
И еще вопрос, алгоритм работы KNX на уровне бит байт фрейм у Вас есть чтобы его повторять. Ну или алгоритм работы Вашего протокола. Интересно посмотреть.
Весь обмен идет на скорости 19.2 кбит/сек. Любой узел может начать обмен, если шина находится в пассивном состоянии в течении не менее 3 мс. При передаче узел обязан контролировать свое "эхо" на шине, если принятый символ не совпал с переданным он немедленно переводит трансивер в режим Standby и ждет псевдо-случайный интервал. Длительность этого интервала зависит от номера попытки передачи, при повторных попытках он ждет меньше, т.е. его приоритет становится выше.
Те, узлы кто принял фрейм, но CRC не совпал, могут выдать однобайтный NACK, тогда фрейм будет передан повторно.
Для организации фреймов я использую байт-стаффинг, специальным символом выбран 0xFF
- начало фрейма (старт) для обмена точка-точка - пара 0xFF-0x02
- начало фрейма (старт) для обмена точка-многоточка - пара 0xFF-0x03
- конец фрейма (стоп) - пара 0xFF-0x04
- одиночные байты 0xFF в потоке данных заменяются на пару 0xFF-0x05
- пары байт 0xFF-0xFF в потоке данных заменяются на пару 0xFF-0x06
Между стартом и стопом идут данные (от 8 до 128 байт), после данных - 2 байта CRC.
triac, бит/байт стаффинг обычно используют в синхронных каналах передачи данных. UART по определению асинхронный, есть более простые способы обозначить начало пакета: 9й бит, бит паритета, межпакетный интервал.
В общем полная победа, суточный прогон прошли без сбоев.
Помогли фильтры, причем пробовал оба варианта. Видимо все же буфер приемный переполнялся и в МК начинал просачиваться мусор, на который тот уже переставал реагировать.
Да и скорость до 250 уронил, думаю твою прошивку уже на 500 гонять.
Так, что вопрос был не в топологиии и терминаторах
Я только сейчас понял что один из основных Ваших аргументов за KNX это дальность 1000м на скорости 19,2 кбит.
Вот что пишут про CAN
1000 кбит - 40м
500 кбит - 110м
250 кбит - 240м
125 кбит - 500м
50 кбит - 1 300м
20 кбит - 3 300м
10 кбит - 6 300м
5 кбит - 13 000м
Да и CAN все же мультимастер, как и Ethernet. Т.е любой узел может начать передачу самостоятельно (инициативно) любому узлу сети с гарантией доставки сообщения.
Наш с уважаемым MaksVV мастер и слейв находятся на 4-7 уровне модели OSI и их задача контроль состояния сети и узлов, сбор информации датчиках и ИУ, шлюзование в MQTT поверх TCP/IP с возможностью послать reset любому контроллеру сети.
В общем полная победа, суточный прогон прошли без сбоев.
Помогли фильтры, причем пробовал оба варианта. Видимо все же буфер приемный переполнялся и в МК начинал просачиваться мусор, на который тот уже переставал реагировать.
это не может не радовать! Сейчас хоть дальше скетч писать можно. Вечером выложу основной скетч с фильтрами.
бит/байт стаффинг обычно используют в синхронных каналах передачи
Представьте какой-нибудь пруф своему утверждению, если можно. Чтобы стало понятно, почему байт-стаффинг как-то связан с синхронными каналами, и почему в асинхронных его использовать некошерно.
Andy пишет:
И причем здесь вообще KNX?
Все было уже сказано много раз выше. KNX является определенным эталоном сети домашней автоматизации, успешной и проверенной временем. Поэтому любые другие сети для таких применений имеет смысл делать с оглядкой на KNX. Кроме KNX есть и другие сети для этих же применений, построенные на совсем иных принципах, LonWorks, например (передача токена), и даже и Модбас кое-кто применяет (мастер-слэйв), и как ни странно не только любители. Однако для автоматизации домов/зданий менее распространены и, соответственно, менее успешны. Поэтому я ориентируюсь на перечисленные ранее сети автоматизации зданий, построенные по принципу "производитель-потребитель": KNX, C-Bus, VelBus. Из перечисленных трех наименее распространен бельгийский VelBus, построенный на CAN.
Весь обмен идет на скорости 19.2 кбит/сек. Любой узел может начать обмен, если шина находится в пассивном состоянии в течении не менее 3 мс. При передаче узел обязан контролировать свое "эхо" на шине, если принятый символ не совпал с переданным он немедленно переводит трансивер в режим Standby и ждет псевдо-случайный интервал. Длительность этого интервала зависит от номера попытки передачи, при повторных попытках он ждет меньше, т.е. его приоритет становится выше.
Те, узлы кто принял фрейм, но CRC не совпал, могут выдать однобайтный NACK, тогда фрейм будет передан повторно.
Для организации фреймов я использую байт-стаффинг, специальным символом выбран 0xFF
- начало фрейма (старт) для обмена точка-точка - пара 0xFF-0x02
- начало фрейма (старт) для обмена точка-многоточка - пара 0xFF-0x03
- конец фрейма (стоп) - пара 0xFF-0x04
- одиночные байты 0xFF в потоке данных заменяются на пару 0xFF-0x05
- пары байт 0xFF-0xFF в потоке данных заменяются на пару 0xFF-0x06
Между стартом и стопом идут данные (от 8 до 128 байт), после данных - 2 байта CRC.
Правильно ли я понял, что Вы собираетесь эту логику на ардуино поднимать? Вместо специализированного контроллера MCP2515?
Практические опыты уже проводили? Код, железо? Или вы пока на этапе НИР?
Наш с уважаемым MaksVV мастер и слейв находятся на 4-7 уровне модели OSI
Вам приходится этим заниматься вследствие изначальной кривизны протокола CAN: всего 8 или 11 байт во фрейме, а по жизни надо больше. Если же уровень 2 настроен на прикладное применение, как в KNX, C-bus или у меня, то все уровни от 3 до 6 не нужны. Мне 128 байт во фрейме и порядка 100 узлов в сегменте хватает для того, чтобы для моего дома не заботиться ни о маршрутах, ни о сегментах, ни о сеансах.
Что касается 6-го уровня, то рассматривал разные варианты представления и шифрование тоже. Но потом решил все это пока отложить. В принципе представление типа MessagePack и шифрование типа XTEA можно ввести, но пока особой нужды в этом нет.
riv пишет:
и их задача контроль состояния сети и узлов, сбор информации датчиках и ИУ, шлюзование в MQTT поверх TCP/IP с возможностью послать reset любому контроллеру сети.
Вы перечисляете в основном задачи, принадлежащие 7 уровню.
Пока ваш пакет из 128 байт летит на низкой скорости кстати, остальные молчат?
Угу. Такой пакет передается примерно 70 мс. В это время все молчат. Правда, передается он редко когда. Но раз уж передается, то не беда, помолчат 70 мс. Все равно никто этого не заметит.
В статусе узла один параметр поменялся и что весь длинный пакет изза одного например бита отправлять?
Вообще-то статус передается по запросу, это точка-точка.
Ну а в случаях, когда некий статус бродкастится по каким-то причинам, то да, передавать весь пакет. Это решение принимается на стадии проектирования, когда и что передавать. Скажем, температуру вам вряд ли надо бродкастить каждую миллисекунду.
Представьте какой-нибудь пруф своему утверждению, если можно. Чтобы стало понятно, почему байт-стаффинг как-то связан с синхронными каналами
Забавный ты. Прежде чем изобретать "колёсное транспортное средство, приводимое в движение мускульной силой человека" посмотри, что такое велосипед.
В синхронных каналах нет другого способа формирования пакетов кроме, как битстаффинг и байтстаффинг. Познакомься хотя бы с HDLC, Frame Relay (биториентированные протоколы), или ATM, BSC (байториентированные протоколы).
triac пишет:
KNX является определенным эталоном сети домашней автоматизации
Другими словами предлагаемая реализация не имеет ничего общего с KNX, потому как, ни аппаратно, ни программно не совместима с KNX
riv пишет:
Вот что пишут про CAN 1000 кбит - 40м 500кбит - 110м 250кбит - 240м 125кбит - 500м 50кбит - 1 300м 20кбит - 3 300м 10кбит - 6 300м 5кбит - 13 000м
Это только для UTP с согласованием. Подели на 100 если простые провода и без согласования.
MaksVV пишет:
Кто нибудь приведите пример использования кадра размером более 8 байт информации. мне на ум не приходят.
В синхронных каналах нет другого способа формирования пакетов кроме, как битстаффинг и байтстаффинг.
Это неверно. Например, C-bus - синхронный, но не использует ни бит-стаффинг, ни байт-стаффинг, ни даже кодирование по типу 8b/10b или 6b/8b, при помощи которого это тоже можно сделать.
Или посмотрите как сделан синхронный интерфейc чипов WS2812 для управления RGB лентами. Там вообще ничего из перечисленного выше не использовано, а тем не менее работает.
Andy пишет:
Познакомься хотя бы с HDLC, Frame Relay (биториентированные протоколы), или ATM, BSC (байториентированные протоколы).
Каким образом из того, что некоторые синхронные протоколы используют бит-стаффинг, следует, что мне не надо использовать байт-стаффинг там, где мне это удобно? Где логика?
По-вашему SLIP или COBS можно только в синхронных интерфейсах применять? Скорей всего вы вообще не знаете что такое байт-стаффинг. Для примера, ознакомьтесь с Wake http://caxapa.ru/lib/wake/
Andy пишет:
Другими словами предлагаемая реализация не имеет ничего общего с KNX, потому как, ни аппаратно, ни программно не совместима с KNX
Совершенно верно, несовместима. Задачи сделать их совместимыми не ставилось и нигде этого не обещалось. Непонятно с чего вы вдруг заговорили о совместимости.
Более того, KNX (EIB) и C-Bus тоже между собой несовместимы, хотя изначально их разрабатывали одни и те же люди. По сути своей они очень похожи, однако C-bus синхронный, а KNX - асинхронный
Ну, кому что нравится. Многие и на Модбасе делают, и на 1-wire, и даже на I2C пытаются. А свободная топология прокладки кабелей - весьма лакомый кусочек.
Насчет дешeвизны MCP2515: цена у него почти такая же, как у Ардуино Мини Про.
Что же касается "распростаненности CAN" - так ведь UART еще более стандартный и широко распростаненный. Построить CSMA/CD займет несколько десятков строчек кода. Надстройка над CAN-ом, позволяющая передавать длинные сообщения по кусочкам, займет больше. Даже просто общение с MCP2515 займет больше. Не говоря уж о куче всяких разномастных регистров у него (как и любого другого CAN контроллера), с которыми надо работать - настраивать фильтры и маски, обрабатывать ошибки, и т.д. и т.п.
Есть еще одна проблема, которую я пока не затронул. Работа любой системы состоит из двух этапов: конфигурирования и, собственно, самой работы. Вот про конфигурирование все как-то забывают. А делать конфигурирование при помощи CAN - нетривиальное занятие: получится или сложно, или ограниченно по возможностям, или вообще и то и другое.
Любительские системы обычно полагаются на непосредственный доступ к узлам и прямую заливку кода программатором. "Своя ноша не тянет", подумаешь, лишний десяток раз, пока все не отладишь: слазить на чердак, вытащить узел, принести его к РС, залить скомпилированный конкретно под него код, опять залезть на чердак и поставить его на место.
Профессиональные системы позволяют конфигурировать узлы уже после установки. Но программное обеспечение, которое позволяет это делать, сложное.
Используя UART, Ардуино и свой протокол, эту проблему можно решить, например, так. В протокол вводятся две обязательные к исполнению всеми узлами команды:
- "Сброс" - программный сброс для конкретного узла (выбор узла производится по уникальному адресу узла или по его серийному номеру), после чего у него запускается бутлодер
- "Пауза" - запрет всем узлам реагировать на любой трафик в сети на некоторое время, скажем, на 10 сек
Подав эти две команды, можно дистанционно залить скетч в выбранный узел.
Есть еще одна проблема, которую я пока не затронул. Работа любой системы состоит из двух этапов: конфигурирования и, собственно, самой работы. Вот про конфигурирование все как-то забывают. А делать конфигурирование при помощи CAN - нетривиальное занятие: получится или сложно, или ограниченно по возможностям, или вообще и то и другое.
Любительские системы обычно полагаются на непосредственный доступ к узлам и прямую заливку кода программатором. "Своя ноша не тянет", подумаешь, лишний десяток раз, пока все не отладишь: слазить на чердак, вытащить узел, принести его к РС, залить скомпилированный конкретно под него код, опять залезть на чердак и поставить его на место.
Профессиональные системы позволяют конфигурировать узлы уже после установки. Но программное обеспечение, которое позволяет это делать, сложное.
если почитать посты выше, то можно увидеть, что мой , скажем так, коллега по CANу, решил этот вопрос при помощи ESP wifi. И теперь заливает прошивки по воздуху. К тому же по wifi, я так понял, у него будет дублирование общения с узлами в случае возникновения проблем с шиной CAN.
Я видел это сообщение, но не придал ему особого значения. Подумал, что вы шлюз в интернет на WiFi делаете, что было бы логично. А вы, значит, в каждый узел собрались WiFi ставить, просто для заливки кода? Но если у вас в каждом узле уже есть WiFi, зачем вам вообще CAN? И неужели лишних 80 мА тока потребления не жалко тратить на одну только редко используемую заливку кода?
Разобрался я с фильтрами.
01
#ifdef ARD_DUE
02
CAN3.init_Mask(0,1,0x0000FF00);
// Init first mask...
03
CAN3.init_Mask(1,1,0x0000FF00);
// Init second mask...
04
CAN3.init_Filt(1,1,0x00000000);
//Broadcast // Init first filter...
05
CAN3.init_Filt(2,1,0x00000400);
//Node addr // Init second filter...
06
CAN3.setMode(MCP_NORMAL);
// Set operation mode to normal so the MCP2515 sends acks to received data.
07
08
#else
09
CAN0.init_Mask(0,1,0x0000FF00);
// Init first mask...
10
CAN0.init_Mask(1,1,0x0000FF00);
// Init second mask...
11
CAN0.init_Filt(1,1,0x00000000);
//Broadcast // Init first filter...
12
CAN0.init_Filt(2,1,0x00000400);
//Node addr // Init second filter...
13
CAN0.setMode(MCP_NORMAL);
// Set operation mode to normal so the MCP2515 sends acks to received data.
14
15
#endif
как дела со стабильностью ? разобрался в чем косяк?
Нет, перебрал скорости, терминаторы, всеравно глючит, и видимо все же CAN контроллер, начинает выдавать в мегу то, что он получает Standart ID то нули, т.е получается нужно видимо фильтровать лишнее. Вот разбираюсь.
Тут пример https://yadi.sk/d/ozOcbX7B3V5hYy can_mask1 и can_mask2
попробуй такой скетч залить на узлы и мастер (выбираешь соответственно адрес , тип и железо МК вверху скетча. ) Поставь на ночь и наблюдай канхакером что будет происходить.
001
#include <mcp_can.h>
002
#include <SPI.h>
003
004
// Выбираем аппаратную часть узла
005
006
#define ARD_UNO
007
//#define ARD_MEGA
008
//#define ARD_DUE
009
010
011
#ifdef ARD_UNO
012
#define can CAN0
013
MCP_CAN can(10);
014
#endif
015
#ifdef ARD_MEGA
016
#define can CAN0
017
MCP_CAN can(53);
018
#endif
019
#ifdef ARD_DUE
020
#define can CAN3
021
MCP_CAN can(52);
022
#endif
023
024
typedef
enum
Node_addr_enum
025
{
026
broadcast,
//0
027
node_1_Net_center_PC,
//1
028
node_2_Net_center_oraPi1,
//2
029
node_3_Net_center_oraPi2,
//3
030
node_4_Net_center_Due1,
//4
031
node_5_Net_center_Due2,
//5
032
node_6_Hallway_net_center,
//6
033
node_7_Hallway_main,
//7
034
node_8_Hallway_light,
//8
035
node_9_Kitchen_net_center,
//9
036
node_10_Kitchen_main,
//10
037
node_11_Kitchen_light,
//11
038
node_12_WC_main,
//12
039
node_13_WC_waterleak,
//13
040
node_14_Bathroom_main,
//14
041
node_15_Boxroom_main,
//15
042
node_16_Balcony_meteo,
//16
043
node_17_Loggia_main,
//17
044
node_18_Loggia_recuperator,
//18
045
node_19_Livingroom_main,
//19
046
node_20_Bedroom_main,
//20
047
node_21_Cabinet_main,
//21
048
SIZE_Node_addr_ENUM
//22 size
049
}Node_addr_enum;
050
051
const
byte
NODS_NUMBER = SIZE_Node_addr_ENUM;
052
053
054
055
// Назначаем адрес данного узла
056
057
//const byte node_address = node_1_Net_center_PC; //1
058
//const byte node_address = node_2_Net_center_oraPi1; //2
059
//const byte node_address = node_3_Net_center_oraPi2; //3
060
//const byte node_address = node_4_Net_center_Due1; //4
061
//const byte node_address = node_5_Net_center_Due2; //5
062
//const byte node_address = node_6_Hallway_net_center; //6
063
//const byte node_address = node_7_Hallway_main; //7
064
//const byte node_address = node_8_Hallway_light; //8
065
//const byte node_address = node_9_Kitchen_net_center //9
066
const
byte
node_address = node_10_Kitchen_main;
//10
067
//const byte node_address = node_11_Kitchen_light; //11
068
//const byte node_address = node_12_WC_main; //12
069
//const byte node_address = node_13_WC_waterleak; //13
070
//const byte node_address = node_14_Bathroom_main; //14
071
//const byte node_address = node_15_Boxroom_main; //15
072
//const byte node_address = node_16_Balcony_meteo; //16
073
//const byte node_address = node_17_Loggia_main; //17
074
//const byte node_address = node_18_Loggia_recuperator; //18
075
//const byte node_address = node_19_Livingroom_main; //19
076
//const byte node_address = node_20_Bedroom_main; //20
077
//const byte node_address = node_21_Cabinet_main; //21
078
079
080
// Выбираем смысловую нагрузку узла
081
082
083
//#define type_node_master
084
//#define type_node_slave
085
#define type_node_mk
086
087
088
089
long
unsigned
int
rxId;
090
unsigned
char
len = 0;
091
unsigned
char
rxBuf[8];
092
093
094
#define CAN0_INT 2 // Set INT to pin 2
095
096
097
098
099
unsigned
long
prevtimeStatus = 0;
100
bool
TimerStatus = 0;
101
102
103
void
setup
()
104
{
105
Serial
.begin(115200);
106
107
// Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
108
if
(can.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK)
109
Serial
.println(
"MCP2515 Initialized Successfully!"
);
110
else
111
Serial
.println(
"Error Initializing MCP2515..."
);
112
113
can.setMode(MCP_NORMAL);
// Set operation mode to normal so the MCP2515 sends acks to received data.
114
115
pinMode(CAN0_INT, INPUT);
// Configuring pin for /INT input
116
117
Serial
.println(
"MCP2515 Library Receive Example..."
);
118
}
119
120
void
loop
()
121
{
122
if
(!digitalRead(CAN0_INT))
123
{
124
can.readMsgBuf(&rxId, &len, rxBuf);
125
#if defined (type_node_slave) or defined (type_node_mk)
126
if
(rxId == 0x000) {prevtimeStatus = millis(); TimerStatus = 1;}
127
#endif
128
}
129
130
#if defined (type_node_slave) or defined (type_node_mk)
131
if
(TimerStatus && millis() - prevtimeStatus > node_address*50) {
132
byte
data[8]= {0,1,2,3,4,5,6,7};
133
can.sendMsgBuf(node_address, 0, 8, data);
134
TimerStatus = 0;}
135
#endif
136
137
#ifdef type_node_master
138
if
(millis() -prevtimeStatus > 2000) {
139
byte
data[8]= {15,14,13,12,11,10,9,8};
140
can.sendMsgBuf(0x000, 0, 8, data);
141
prevtimeStatus = millis();}
142
#endif
143
144
}
по поводу аппаратной фильтрации нужно так сделать . Проверил, работает.
01
void
CAN_Start () {
// это setup
02
03
bool
can_ok = 0;
04
if
(can.begin(MCP_STDEXT, CAN_500KBPS, MCP_8MHZ) == CAN_OK) can_ok = 1;
05
can.init_Mask(0,1,0x0000FF00);
// Init first mask...
06
can.init_Filt(0,1,(node_address & 0xFFFFFFFF)<<8);
// Init first filter...
07
can.init_Filt(1,1,0x00000000);
// Init second filter...
08
can.init_Mask(1,0,0x7FF);
// Init second mask...
09
#ifdef debug
10
Serial
.begin(115200);
11
if
(can_ok)
Serial
.println(F(
"MCP2515 Initialized Successfully!"
));
12
else
13
Serial
.println(F(
"Error Initializing MCP2515..."
));
14
15
Serial
.println();
Serial
.print(F(
"Мой адрес в сети CAN: "
)); PrintADDR (node_address);
16
#ifdef type_node_master
17
Serial
.println (F(
" MASTER!"
));
18
#endif
19
Serial
.println();
20
21
timeoutsConfigControl ();
22
#endif
23
24
can.setMode(MCP_NORMAL);
25
26
pinmode();
// настройка портов (в зависимости от конфигурации массива device)
27
28
}
Заметь, строка инита MCP отличается. Данная фильтрация пропускает все широковещательные сообщения и с нашим адресом, а также все фреймы со стандартным (маленьким 0х000) ID.
Заметь, строка инита MCP отличается. Данная фильтрация пропускает все широковещательные сообщения и с нашим адресом, а также все фреймы со стандартным (маленьким 0х000) ID.
А смысл пропускать все 0х000 ID?
И что за зверь
pinmode();?
Полистал топик, нашел такую декларацию:
Для справки:
- Modbus был разработан в 70-е годы
- CAN был разработан в 80-е годы
- KNX был разработан в 90-е годы
Основные применения таких скоростей это управление светом (согласитесь ждать 1-2 сек когда мастер опросит датчики движения а потом передаст УК команду включить реле света, немного не комфортно), управление медиа (звук, видео - переключение радио, оповещения о событиях) и др. приложениях где задержка вызывает дискомфорт или просто опасна.
Повторю, что за счет работы по принципу "производитель-потребитель" KNX способен без задержек управлять светом даже в многоэтажных оффисных зданиях и т.п., но при этом работает на скорости 9.6 кбит/сек. Модбас, работающий по принципу "мастер-слэйв", на это не способен даже при 1 Мбит/сек. И если вы сделаете нечто подобное Модбасу на CAN, то от этого ничего не изменится, это все равно будет "мастер-слэйв".
Впрочем, делайте как хотите, меня это не касается.
Полистал топик, нашел такую декларацию:
Для справки:
- Modbus был разработан в 70-е годы
- CAN был разработан в 80-е годы
- KNX был разработан в 90-е годы
Основные применения таких скоростей это управление светом (согласитесь ждать 1-2 сек когда мастер опросит датчики движения а потом передаст УК команду включить реле света, немного не комфортно), управление медиа (звук, видео - переключение радио, оповещения о событиях) и др. приложениях где задержка вызывает дискомфорт или просто опасна.
Повторю, что за счет работы по принципу "производитель-потребитель" KNX способен без задержек управлять светом даже в многоэтажных оффисных зданиях и т.п., но при этом работает на скорости 9.6 кбит/сек. Модбас, работающий по принципу "мастер-слэйв", на это не способен даже при 1 Мбит/сек. И если вы сделаете нечто подобное Модбасу на CAN, то от этого ничего не изменится, это все равно будет "мастер-слэйв".
Впрочем, делайте как хотите, меня это не касается.
1. Не совсем понятна логика по первому утверждению. Я пишу если бы был аналог протокола over CAN то мы бы свой не писали. (Кстати аналог есть это CanOPEN и еще несколько протоколов, но оин черезмерно сложны). Вы отвечаете годами разработки протоколов. Возможно я что то упустил и потерял цепь размышлений.
2. У нас есть задача автоматизировать дом. Есть дешевое железо. Есть понятная среда программирования. Мы решаем свою задачу. Не для продажи, для себя.
Предложите KNX контроллер для связки с ардуино за разумные деньги, и я готов буду воспользоваться предложенным решением.
Иначе получаются теоретические изыскания на практическом форуме который на минуточку называется http://arduino.ru, что по моему скромному мнению означает, что здесь собрались самодельщики которым близка именно платформа ардуино, модульная сборка изделий без трассировки плат, разработки Э3 и Т5М и самое главное использование готовых плат и модулей.
На сегдня для ардуино есть коммуникационные модули
1. RS485 - 100 руб
2. Ethernet -400 руб
3. Wi-Fi - 200 руб
4. CAN - 200 руб
5. X-bee - 400 руб
Дадите ссылку на KNX модуль?
А смысл пропускать все 0х000 ID?
И что за зверь
pinmode();?
да я так, на скорую руку просто поставил, можешь вообще запретить короткие ID. Ты упрощённый скетч то попробовал?
pinmode () она и раньше была (см. большой скетч). в фунции pinmode () настраиваются порты ардуино автоматически в зависимости от конфигурации исполнительных устройств в can_struct.h
Сегодня скомпилирую и залью.
Залил. Та же петрушка. Узлы по одному перестают отвечать. Пока пропал №9.
от этого много что изменится. На модбасе rs485 всё идёт через мастера, и как бы слейв не хотел крикнуть в шину что-нибудь, ему нужно дождаться запроса мастера.
В CAN шине: захотел - сразу сказал. Реакция мгновенна. В нашей системе любой узел может говорить с любым узлом, даже если мастера вообще отключить. На Мастер лишь стекается вся информация от узлов для передачи её на уровень выше.
В общем пора брать осцилограф и смотреть топологию. Буду отключать кустами и смотреть что получится.
Намек на то, что вы движитесь в обратном направлении, надстраивая нечто наподобие Модбаса поверх CAN для того, чтобы решать задачи, на которые заточен KNX.
Ссылка на KNX дана не для того, чтобы все бросить и перейти на KNX. Но знать, как он устроен, полезно, хотя бы на самом базовом уровне: https://www.ixbt.com/home/knx-intro.shtml
Все команды можно разделить на два класса:
- точка-точка, с индивидуальной адресацией узлов; эти команды используются для конфигурирования и диагностики системы
- точка-многоточка, т.е. бродкаст, адрес узла отсутствует; эти команды используются для собственно работы
Ключевое понятие - "групповой адрес". Его можно назвать "виртуальным проводом", которым связана группа устройств. Устройства ввода (выключатели, регуляторы) меняют состояние этого "провода". Устройства вывода (релейные выключатели, диммеры) выполняют действия в соответствии с текущим состоянием "провода". Все устройства (т.е. и устройства ввода, и устройства вывода) в группе отслеживают текущее состояние "провода".
При конфигурировании создаются эти группы, т.е. устройства настраиваются на принадлежность той или иной группе. Заодно настраиваются и другие параметры устройств, например, скорость диммирования при нажатии на кнопку, и т.п. Устройства могут входить в несколько групп. Например, кнопочный выключатель с двумя кнопками управляет двумя группами, релейный модуль на 4 реле отрабатывает состояния 4-х "виртуальных проводов".
Это достаточно хорошо ложится на MQTT, групповой адрес вполне соответствует топику. Ну а все команды конфигурирования в принципе можно свести в один топик.
В принципе вполне возможно сделать KNX узел на 8-битном Ардуино, ресурсов зватает с лихвой. Более того, я уверен, что рано или поздно кто-то это сделает. Однако я не призываю вас это делать. Мне просто странно видеть, как вы на CAN натягиваете допотопный Модбас. Хотя вольному воля, конечно, делайте что хотите.
Сам-то я планирую к обычному UART-у Ардуино Мини Про присоединить голый CAN трансивер, например, такой: https://ru.aliexpress.com/item/SN65HVD230-CAN-bus-transceiver-communication-module-for-arduino/32686393467.html Шина CAN трансивер связи-модуль для Arduino
То есть, возьму от CAN один только шинный формирователь, от KNX - принцип работы, а от Ардуино - наидешевейшую процессорную плату, среду программирования и бутлодер. Благо тут в теме ранее вы http://arduino.ru/forum/proekty/ocherednoi-umnyi-dom-na-etot-raz-modulnaya-sistema?page=3 давали ссылку на Optiboot, за что вам отдельное спасибо, это как раз то, что мне нужно.
Залил. Та же петрушка. Узлы по одному перестают отвечать. Пока пропал №9.
значит дело не в софте, а в железе. остаётся попробовать тоже самое, положив рядом все МК на коротком проводе CAN. Если будет гуд - то кабель неправильный и/или неправильная топология и/или длина и/или терминаторы нужно както по сопротивлению подбирать. Видимо от разных свойств кабеля (волновое сопротивление? хз чё это , почитать нужно) нужны разные терминаторы.
Сам-то я планирую к обычному UART-у Ардуино Мини Про присоединить голый CAN трансивер, например, такой: https://ru.aliexpress.com/item/SN65HVD230-CAN-bus-transceiver-communication-module-for-arduino/32686393467.html Шина CAN трансивер связи-модуль для Arduino
у меня валяется два кан трансивера. Не поленюсь подключу к уарт. Посмотрим, долетят ли байты от одного МК до другого. Что то я сомневаюсь, если честно.
у меня валяется два кан трансивера. Не поленюсь подключу к уарт. Посмотрим, долетят ли байты от одного МК до другого. Что то я сомневаюсь, если честно.
А почему сомневаетесь, если не секрет? Что особенного есть в контроллере CAN, из-за чего байты, отправленные им, непременно доходят до другого МК? И какой волшебной субстанции не хватает обычному UART, чтобы достичь того же результата?
у меня валяется два кан трансивера. Не поленюсь подключу к уарт. Посмотрим, долетят ли байты от одного МК до другого. Что то я сомневаюсь, если честно.
А почему сомневаетесь, если не секрет? Что особенного есть в контроллере CAN, из-за чего байты, отправленные им, непременно доходят до другого МК? И какой волшебной субстанции не хватает обычному UART, чтобы достичь того же результата?
вечером подключу, отпишусь.
Просьба всеже внимательно прочитать датиашит и не путать трансивер CAN который по сути просто усилитель и формироватиель биимпульса и CAN контроллера который как раз протокол CSMA делает.
Для MaksVV
Именно это я имел виду выше говоря что в связке с 232 может и полететь, а наш MCP2515 состоит из 2х частей
ТРАНСИВЕРА TJA1050 и КОНТРОЛЛЕРА MCP2515. SN65HVD230 имеет только ТРАНСИВЕР SN65 и его можно использовать например в связке с DUE.
Для triac
Мы с уважаемым MaksVV пишем протокол обмена уровня 3 модели OSI (даже скорее 3-4) , вы же насколько я понял используя трансивер хотите замахнуться на уровень 2 и 3 одновременно, обеспечивая управление коллизиями и передачу данных, так как Вас не устраивает обработка колизий у CAN.
Задача весьма интересная но и весьма сложная.
Просьба всеже внимательно прочитать датиашит и не путать трансивер CAN который по сути просто усилитель и формироватиель биимпульса и CAN контроллера который как раз протокол CSMA делает.
ТРАНСИВЕРА TJA1050 и КОНТРОЛЛЕРА MCP2515. SN65HVD230 имеет только ТРАНСИВЕР SN65 и его можно использовать например в связке с DUE.
Я-то не путаю. Скорей это вы невнимательно читаете то, что я написал. Я уже несколько раз повторил, что контроллер CAN мне не нужен. Мне нужен любой микроконтроллер, имеющий обычный UART, например, Атмега 328 в составе Ардуино Мини Про. И к нему мне нужен трансивер CAN, т.е. шинный формирователь, один только физический уровень CAN. Это все, что нужно, чтобы создать узел сети, функционально соответствующий узлу KNX.
Я более-менее в курсе, как делаются узлы KNX и C-bus. Их уже 25 лет делают серийно. И микроконтроллер, который использовался для такого узла, в разы слабее Атмеги, и по скорости, и по памяти.
А в CAN меня не обработка коллизий не устраивает, а ненужная для такой задачи сложность.
Из 7-уровневой модели ISO/OSI под эту задачу нужны только 1,2 и 7, остальное лишнее.
Это все, что нужно, чтобы создать узел сети, функционально соответствующий узлу KNX.
В следующем сооющении я как раз об этом и написал, про Ваше желание написать протокол канального уровня. +сетевого.
Из 7-уровневой модели ISO/OSI под эту задачу нужны только 1,2 и 7, остальное лишнее.
Модель оси создана конечно не как догма а как руководство к действию.
Но как обойтись без адресации сетевого уровня и контроля доставки транспортного и сразу перейти к передаче сообщений и команд я не понимаю.
А в CAN меня не обработка коллизий не устраивает, а ненужная для такой задачи сложность.
Я не совсем понял про сложность.
У нас есть MCP2515, это трансивер и контроллер перекрывающи задачу не только фиксации но разрешения колизий, т.е на уровне 2 сообщение гарантированно будет доставлено.
Т.е мы сразу пошли к уровню 3 адресация и контроль доставки сообщений уровень 4. Пробустив СЛОЖНЕЙШИЙ уровень 2.
Т.е вы считаете что уровень 2 аналогичный Ethernet, ATM, CAN и пр. протоколам проще чем просейший протокол который мы делаем?
И еще вопрос, алгоритм работы KNX на уровне бит байт фрейм у Вас есть чтобы его повторять. Ну или алгоритм работы Вашего протокола. Интересно посмотреть.
короче не смог я найти второй трансивер. Один только есть. Заказал ещё пару (на этот раз другой решил взять) - mcp2551
короче не смог я найти второй трансивер. Один только есть.
Вместо CAN трансивера вы можете использовать RS-485 трансивер. Они довольно хорошо совместимы, особенно на малых скоростях. Выход UART-а надо подать на DE трансивера, а вход DI посадить на землю.
Когда-то очень давно, пока не разработали специальные CAN трансиверы, все так и делали.
Проще
И еще вопрос, алгоритм работы KNX на уровне бит байт фрейм у Вас есть чтобы его повторять. Ну или алгоритм работы Вашего протокола. Интересно посмотреть.
Весь обмен идет на скорости 19.2 кбит/сек. Любой узел может начать обмен, если шина находится в пассивном состоянии в течении не менее 3 мс. При передаче узел обязан контролировать свое "эхо" на шине, если принятый символ не совпал с переданным он немедленно переводит трансивер в режим Standby и ждет псевдо-случайный интервал. Длительность этого интервала зависит от номера попытки передачи, при повторных попытках он ждет меньше, т.е. его приоритет становится выше.
Те, узлы кто принял фрейм, но CRC не совпал, могут выдать однобайтный NACK, тогда фрейм будет передан повторно.
Для организации фреймов я использую байт-стаффинг, специальным символом выбран 0xFF
- начало фрейма (старт) для обмена точка-точка - пара 0xFF-0x02
- начало фрейма (старт) для обмена точка-многоточка - пара 0xFF-0x03
- конец фрейма (стоп) - пара 0xFF-0x04
- одиночные байты 0xFF в потоке данных заменяются на пару 0xFF-0x05
- пары байт 0xFF-0xFF в потоке данных заменяются на пару 0xFF-0x06
Между стартом и стопом идут данные (от 8 до 128 байт), после данных - 2 байта CRC.
triac, бит/байт стаффинг обычно используют в синхронных каналах передачи данных. UART по определению асинхронный, есть более простые способы обозначить начало пакета: 9й бит, бит паритета, межпакетный интервал.
И причем здесь вообще KNX?
Для MaksVV
В общем полная победа, суточный прогон прошли без сбоев.
Помогли фильтры, причем пробовал оба варианта. Видимо все же буфер приемный переполнялся и в МК начинал просачиваться мусор, на который тот уже переставал реагировать.
Да и скорость до 250 уронил, думаю твою прошивку уже на 500 гонять.
Так, что вопрос был не в топологиии и терминаторах
1
#ifdef ARD_DUE
2
if
(CAN3.begin(MCP_STDEXT, CAN_250KBPS, MCP_8MHZ) == CAN_OK)
3
#else
4
if
(CAN0.begin(MCP_STDEXT, CAN_250KBPS, MCP_8MHZ) == CAN_OK)
5
#endif
01
#ifdef ARD_DUE
02
//CAN3.init_Mask(0,1,0x0000FF00); // Init first mask...
03
//CAN3.init_Filt(0,1,(node_address & 0xFFFFFFFF)<<8); // Init first filter...
04
//CAN3.init_Filt(1,1,0x00000000); // Init second filter...
05
//CAN3.init_Mask(1,0,0x7FF); // Init second mask...
06
CAN3.init_Mask(0,1,0x0000FF00);
// Init first mask...
07
CAN3.init_Mask(1,1,0x0000FF00);
// Init second mask...
08
CAN3.init_Filt(1,1,0x00000000);
//Broadcast // Init first filter...
09
CAN3.init_Filt(0,1,(node_address & 0xFFFFFFFF)<<8);
// Init first filter...
10
CAN3.setMode(MCP_NORMAL);
// Set operation mode to normal so the MCP2515 sends acks to received data.
11
#else
12
//CAN0.init_Mask(0,1,0x0000FF00); // Init first mask...
13
//CAN0.init_Filt(0,1,(node_address & 0xFFFFFFFF)<<8); // Init first filter...
14
//CAN0.init_Filt(1,1,0x00000000); // Init second filter...
15
//CAN0.init_Mask(1,0,0x7FF); // Init second mask...
16
CAN0.init_Mask(0,1,0x0000FF00);
// Init first mask...
17
CAN0.init_Mask(1,1,0x0000FF00);
// Init second mask...
18
CAN0.init_Filt(1,1,0x00000000);
//Broadcast // Init first filter...
19
CAN0.init_Filt(0,1,(node_address & 0xFFFFFFFF)<<8);
// Init first filter...
20
CAN0.setMode(MCP_NORMAL);
// Set operation mode to normal so the MCP2515 sends acks to received data.
21
#endif
Так что давай последнюю прошивку с фильтрами, буду компилировать и заливать.
Для triac
Я только сейчас понял что один из основных Ваших аргументов за KNX это дальность 1000м на скорости 19,2 кбит.
Вот что пишут про CAN
1000 кбит - 40м
500 кбит - 110м
250 кбит - 240м
125 кбит - 500м
50 кбит - 1 300м
20 кбит - 3 300м
10 кбит - 6 300м
5 кбит - 13 000м
Да и CAN все же мультимастер, как и Ethernet. Т.е любой узел может начать передачу самостоятельно (инициативно) любому узлу сети с гарантией доставки сообщения.
Наш с уважаемым MaksVV мастер и слейв находятся на 4-7 уровне модели OSI и их задача контроль состояния сети и узлов, сбор информации датчиках и ИУ, шлюзование в MQTT поверх TCP/IP с возможностью послать reset любому контроллеру сети.
Помогли фильтры, причем пробовал оба варианта. Видимо все же буфер приемный переполнялся и в МК начинал просачиваться мусор, на который тот уже переставал реагировать.
это не может не радовать! Сейчас хоть дальше скетч писать можно. Вечером выложу основной скетч с фильтрами.
Кстати шлюзование в MQTT для мастера я тоже отладил, потом оформлю отдельным файлом mqtt.ino, так же как web
в коде до setup && loop
01
///MQTT begin
02
#ifdef node_mqtt_eth
03
#include <PubSubClient.h>
04
IPAddress mqtt_server(192, 168, 2, 101);
05
void
callback(
char
* topic,
byte
* payload, unsigned
int
length)
06
{
07
/*
08
Serial.print(F("Message arrived ["));
09
Serial.print(topic);
10
Serial.print(F("] "));
11
for (int i=0;i<length;i++)
12
{
13
Serial.print(F((char)payload[i]));
14
}
15
Serial.println();
16
*/
17
}
18
19
EthernetClient ethClient;
20
PubSubClient mqttClient(ethClient);
21
22
void
reconnect()
23
{
24
// Loop until we're reconnected
25
while
(!mqttClient.connected())
26
{
27
Serial
.print(
"Attempting MQTT connection..."
);
28
if
(mqttClient.connect(
"node_4_Net_center_Due1_Eth"
,
"test"
,
"test"
))
29
{
30
Serial
.println(
"connected"
);
31
mqttClient.subscribe(
"inTopic"
);
32
}
33
else
34
{
35
Serial
.print(
"failed, rc="
);
36
Serial
.print(mqttClient.state());
37
Serial
.println(
" try again in 5 seconds"
);
38
delay(5000);
///!!!!!!!!Заменить на миллс
39
}
40
}
41
}
42
43
#endif
44
//MQTT END
setup()
1
#ifdef node_mqtt_eth
2
mqttClient.setServer(mqtt_server, 1883);
3
mqttClient.setCallback(callback);
4
if
(!mqttClient.connected()) {
5
reconnect(); }
6
#endif
в loop()
1
#ifdef node_mqtt_eth
2
mqtt();
3
#endif
1
print_nodes_status()
В коде
1
#ifdef node_mqtt_eth
2
void
mqtt()
3
{
4
if
(!mqttClient.connected()) {
5
reconnect();
6
}
7
mqttClient.
loop
();
8
}
9
#endif
Ну и основная функция - она выводит статус опроса в serial, в UDP порт, на MQTT сервер, с которого подбирает Majordomo. Пока только отдаю на сервер.
001
void
print_nodes_status()
002
{
003
char
mqqt_string;
004
char
buffer[50];
005
006
if
(curMillis - prev_print > interval_repeat_req_mk1+10000)
007
{
008
UDP.beginPacket(dest, remPort);
009
UDP.write(
"\n\r"
);
010
UDP.write(
"--------------------------\n\r"
);
011
UDP.write(
"\n\r"
);
012
UDP.endPacket();
013
014
Serial
.println(
" Состояние опроса узлов по CAN от RIV"
);
015
Serial
.println(
"-----------------------------------------------------"
);
016
017
for
(
int
i = 4; i<NODS_NUMBER; i++)
018
{
019
Serial
.print(
" "
);
020
//PrintADDR(i);
021
Serial
.print(
"Node_"
);
Serial
.print(i);
022
023
Serial
.print (F(
" "
)) ;
Serial
.print (i);
024
Serial
.print(
" Статус"
);
025
if
(array_request_status[i][4])
026
{
027
Serial
.println (F(
" OK"
)) ;
028
mqqt_string=2;
029
}
030
else
031
{
032
if
(i==node_address || i==16 || i==17)
033
{
034
if
(i==node_address)
035
{
036
Serial
.println (F(
" OK"
));
037
mqqt_string=2;
038
}
039
else
040
{
041
Serial
.println (F(
" >>>OFF"
));
042
mqqt_string=1;
043
}
044
}
045
else
046
{
047
Serial
.println (F(
" >>>>> FAIL"
)) ;
048
mqqt_string=0;
049
}
050
}
051
052
#ifdef node_mqtt_eth
053
char
buf1[12];
054
char
buf2[12];
055
itoa(i, buf1, 10);
056
itoa(mqqt_string, buf2, 10);
057
mqttClient.publish(buf1, buf2);
058
#endif
059
060
061
if
(mqqt_string==2)
062
sprintf(buffer,
"Node_%.ld - ON\n\r"
,i);
063
else
if
(mqqt_string==1)
064
sprintf(buffer,
"Node_%.ld - OFF\n\r"
,i);
065
else
if
(mqqt_string==0)
066
sprintf(buffer,
"Node_%.ld - FAIL\n\r"
,i);
067
068
UDP.beginPacket(dest, remPort);
069
UDP.write(buffer);
070
UDP.endPacket();
071
072
073
}
074
Serial
.println(
"-----------------------------------------------------"
);
075
076
int
time=curMillis/1000;
077
if
(time/60/60<10) {
Serial
.print (
"0"
); }
078
Serial
.print (time/60/60);
079
Serial
.print (
":"
);
080
if
(time/60%60<10) {
Serial
.print (
"0"
); }
081
Serial
.print ((time/60)%60);
082
Serial
.print (
":"
);
083
if
(time%60<10) {
Serial
.print (
"0"
); }
084
Serial
.println (time%60);
085
086
087
088
089
UDP.beginPacket(dest, remPort);
090
sprintf(buffer,
"Time - %.2d:%.2d:%.2d\n\r"
, time/60/60, (time/60)%60, time%60);
091
UDP.write(
"\n\r"
);
092
UDP.write(buffer);
093
UDP.write(
"\n\r"
);
094
UDP.write(
"--------------------------\n\r"
);
095
UDP.endPacket();
096
097
098
prev_print = curMillis;
099
100
}
101
102
}
Да кстати здесь вывод времени в часах, минутах секундах от запуска, можно еще дни добавить для полного счастья, Millis раз в 50 суток обнуляется. Кстати нужно еще watchdog ставить на МК. (https://uscr.ru/arduino-watchdog-bootloop-i-proshivka-zagruzchika-optiboot/)
Представьте какой-нибудь пруф своему утверждению, если можно. Чтобы стало понятно, почему байт-стаффинг как-то связан с синхронными каналами, и почему в асинхронных его использовать некошерно.
Все было уже сказано много раз выше. KNX является определенным эталоном сети домашней автоматизации, успешной и проверенной временем. Поэтому любые другие сети для таких применений имеет смысл делать с оглядкой на KNX. Кроме KNX есть и другие сети для этих же применений, построенные на совсем иных принципах, LonWorks, например (передача токена), и даже и Модбас кое-кто применяет (мастер-слэйв), и как ни странно не только любители. Однако для автоматизации домов/зданий менее распространены и, соответственно, менее успешны. Поэтому я ориентируюсь на перечисленные ранее сети автоматизации зданий, построенные по принципу "производитель-потребитель": KNX, C-Bus, VelBus. Из перечисленных трех наименее распространен бельгийский VelBus, построенный на CAN.
Весь обмен идет на скорости 19.2 кбит/сек. Любой узел может начать обмен, если шина находится в пассивном состоянии в течении не менее 3 мс. При передаче узел обязан контролировать свое "эхо" на шине, если принятый символ не совпал с переданным он немедленно переводит трансивер в режим Standby и ждет псевдо-случайный интервал. Длительность этого интервала зависит от номера попытки передачи, при повторных попытках он ждет меньше, т.е. его приоритет становится выше.
Те, узлы кто принял фрейм, но CRC не совпал, могут выдать однобайтный NACK, тогда фрейм будет передан повторно.
Для организации фреймов я использую байт-стаффинг, специальным символом выбран 0xFF
- начало фрейма (старт) для обмена точка-точка - пара 0xFF-0x02
- начало фрейма (старт) для обмена точка-многоточка - пара 0xFF-0x03
- конец фрейма (стоп) - пара 0xFF-0x04
- одиночные байты 0xFF в потоке данных заменяются на пару 0xFF-0x05
- пары байт 0xFF-0xFF в потоке данных заменяются на пару 0xFF-0x06
Между стартом и стопом идут данные (от 8 до 128 байт), после данных - 2 байта CRC.
Правильно ли я понял, что Вы собираетесь эту логику на ардуино поднимать? Вместо специализированного контроллера MCP2515?
Практические опыты уже проводили? Код, железо? Или вы пока на этапе НИР?
Кто нибудь приведите пример использования кадра размером более 8 байт информации. мне на ум не приходят.
Что аудио или видео что ли передавать или страницы текста?
в своём дейсвующем протоколе я использую каждый бит в байте. Таким образом, в одном 8-байтном фрейме я могу передать состояние света в 64 комнатах
Наш с уважаемым MaksVV мастер и слейв находятся на 4-7 уровне модели OSI
Вам приходится этим заниматься вследствие изначальной кривизны протокола CAN: всего 8 или 11 байт во фрейме, а по жизни надо больше. Если же уровень 2 настроен на прикладное применение, как в KNX, C-bus или у меня, то все уровни от 3 до 6 не нужны. Мне 128 байт во фрейме и порядка 100 узлов в сегменте хватает для того, чтобы для моего дома не заботиться ни о маршрутах, ни о сегментах, ни о сеансах.
Что касается 6-го уровня, то рассматривал разные варианты представления и шифрование тоже. Но потом решил все это пока отложить. В принципе представление типа MessagePack и шифрование типа XTEA можно ввести, но пока особой нужды в этом нет.
и их задача контроль состояния сети и узлов, сбор информации датчиках и ИУ, шлюзование в MQTT поверх TCP/IP с возможностью послать reset любому контроллеру сети.
Вы перечисляете в основном задачи, принадлежащие 7 уровню.
Практические опыты уже проводили? Код, железо? Или вы пока на этапе НИР?
Есть работающий шлюз в USB, с гальваноразвязкой. Сделан на PIC24, так мне было удобнее. Узлы на Ардуинах в процессе.
Кто нибудь приведите пример использования кадра размером более 8 байт информации. мне на ум не приходят.
- Ответ на запрос о типе и текущей ревизии узла (если не разбивать на много мелких команд и ответов)
- Ответ на запрос статуса узла (аналогично, без разбивки)
- Практически любой текст.
- Дата лог
- Данные от сенсора в XML или JSON
Пока ваш пакет из 128 байт летит на низкой скорости кстати, остальные молчат?
В статусе узла один параметр поменялся и что весь длинный пакет изза одного например бита отправлять?
Угу. Такой пакет передается примерно 70 мс. В это время все молчат. Правда, передается он редко когда. Но раз уж передается, то не беда, помолчат 70 мс. Все равно никто этого не заметит.
Вообще-то статус передается по запросу, это точка-точка.
Ну а в случаях, когда некий статус бродкастится по каким-то причинам, то да, передавать весь пакет. Это решение принимается на стадии проектирования, когда и что передавать. Скажем, температуру вам вряд ли надо бродкастить каждую миллисекунду.
Для MaksVV
Вот еще код автономной метеостанции без CAN только на ESP8266 через esp-link mqtt
Как я и предполагал, скорость реакции очень низкая и годится только для сенсоров. Реального времени добится не получится.
001
#include <BME280I2C.h>
002
#include <Wire.h> // Needed for legacy versions of Arduino.
003
#include <LiquidCrystal_I2C.h>
004
//node_16_Balcony_meteo
005
LiquidCrystal_I2C lcd(0x27,20,2);
// set the LCD address to 0x27 for a 16 chars and 2 line display
006
007
#include <ELClient.h>
008
#include <ELClientCmd.h>
009
#include <ELClientMqtt.h>
010
011
// Initialize a connection to esp-link using the normal hardware serial port both for
012
// SLIP and for debug messages.
013
ELClient esp(&
Serial
, &
Serial
);
014
015
// Initialize CMD client (for GetTime)
016
ELClientCmd cmd(&esp);
017
018
// Initialize the MQTT client
019
ELClientMqtt mqtt(&esp);
020
021
// Callback made from esp-link to notify of wifi status changes
022
// Here we just print something out for grins
023
void
wifiCb(
void
* response) {
024
ELClientResponse *res = (ELClientResponse*)response;
025
if
(res->argc() == 1) {
026
uint8_t status;
027
res->popArg(&status, 1);
028
029
if
(status == STATION_GOT_IP) {
030
Serial
.println(
"WIFI CONNECTED"
);
031
}
else
{
032
Serial
.print(
"WIFI NOT READY: "
);
033
Serial
.println(status);
034
}
035
}
036
}
037
038
bool
connected;
039
040
// Callback when MQTT is connected
041
void
mqttConnected(
void
* response) {
042
Serial
.println(
"MQTT connected!"
);
043
mqtt.subscribe(
"/node_16_Balcony_meteo/sensors/Temp"
);
044
mqtt.subscribe(
"/node_16_Balcony_meteo/sensors/Hum"
);
045
mqtt.subscribe(
"/node_16_Balcony_meteo/sensors/Press"
);
046
mqtt.subscribe(
"/node_16_Balcony_meteo/sensors/CO2"
);
047
mqtt.subscribe(
"/node_16_Balcony_meteo/sensors/RZero_CO2"
);
048
mqtt.subscribe(
"/node_16_Balcony_meteo/sensors/CO"
);
049
mqtt.subscribe(
"/node_16_Balcony_meteo/sensors/Light"
);
050
mqtt.subscribe(
"/node_16_Balcony_meteo/sensors/Noise"
);
051
052
connected =
true
;
053
}
054
055
// Callback when MQTT is disconnected
056
void
mqttDisconnected(
void
* response) {
057
Serial
.println(
"MQTT disconnected"
);
058
connected =
false
;
059
}
060
061
// Callback when an MQTT message arrives for one of our subscriptions
062
void
mqttData(
void
* response) {
063
ELClientResponse *res = (ELClientResponse *)response;
064
065
Serial
.print(
"Received: topic="
);
066
String topic = res->popString();
067
Serial
.println(topic);
068
069
Serial
.print(
"data="
);
070
String data = res->popString();
071
Serial
.println(data);
072
}
073
074
void
mqttPublished(
void
* response) {
075
Serial
.println(
"MQTT published"
);
076
}
077
078
079
080
#define analogPin A0 // аналоговый выход MQ135 подключен к пину A0 Arduino
081
#define digitalPin 3 // цифровой выход подключен к пину 3
082
083
float
analogValue;
// для аналогового значения
084
byte
digitalValue;
// для цифрового значения, можно, кстати и boolean, но не суть
085
086
#define analogPin2 A1 // аналоговый выход MQ7 подключен к пину A1 Arduino
087
#define digitalPin2 4 // цифровой выход подключен к пину 4
088
089
float
analogValue2;
// для аналогового значения
090
byte
digitalValue2;
// для цифрового значения, можно, кстати и boolean, но не суть
091
092
#define analogPin3 A2 // аналоговый выход MQ7 подключен к пину A1 Arduino
093
float
analogValue3;
// для аналогового значения
094
095
#define analogPin4 A3 // аналоговый выход MQ7 подключен к пину A1 Arduino
096
float
analogValue4;
// для аналогового значения
097
098
//m35 2
099
100
#include "MQ135.h"
101
102
MQ135 gasSensor = MQ135(A0);
//ANALOGPIN
103
float
rzero = gasSensor.getRZero();
104
//#define RZERO 76.63
105
106
107
#define SERIAL_BAUD 115200
108
109
110
BME280I2C::Settings settings(
111
BME280::OSR_X1,
112
BME280::OSR_X1,
113
BME280::OSR_X1,
114
BME280::Mode_Forced,
115
BME280::StandbyTime_1000ms,
116
BME280::Filter_Off,
117
BME280::SpiEnable_False,
118
BME280I2C::I2CAddr_0x76
// I2C address. I2C specific.
119
);
120
121
BME280I2C bme(settings);
122
123
//////////////////////////////////////////////////////////////////
124
void
setup
()
125
{
126
Serial
.begin(SERIAL_BAUD);
127
128
while
(!
Serial
) {}
// Wait
129
130
Wire.begin();
131
while
(!bme.begin())
132
{
133
Serial
.println(
"Could not find BME280I2C sensor!"
);
134
delay(1000);
135
}
136
137
switch
(bme.chipModel())
138
{
139
case
BME280::ChipModel_BME280:
140
Serial
.println(
"Found BME280 sensor! Success."
);
141
break
;
142
case
BME280::ChipModel_BMP280:
143
Serial
.println(
"Found BMP280 sensor! No Humidity available."
);
144
break
;
145
default
:
146
Serial
.println(
"Found UNKNOWN sensor! Error!"
);
147
}
148
149
150
settings.tempOSR = BME280::OSR_X4;
151
152
bme.setSettings(settings);
153
154
155
156
pinMode(analogPin, INPUT);
// режим работы аналогового пина
157
pinMode(digitalPin, INPUT);
// режим работы цифрового пина
158
159
pinMode(analogPin2, INPUT);
// режим работы аналогового пина
160
pinMode(digitalPin2, INPUT);
// режим работы цифрового пина
161
162
lcd.init();
// initialize the lcd
163
// Print a message to the LCD.
164
lcd.backlight();
165
166
Serial
.println(
"EL-Client starting!"
);
167
168
// Sync-up with esp-link, this is required at the start of any sketch and initializes the
169
// callbacks to the wifi status change callback. The callback gets called with the initial
170
// status right after Sync() below completes.
171
esp.wifiCb.attach(wifiCb);
// wifi status change callback, optional (delete if not desired)
172
bool
ok;
173
do
{
174
ok = esp.Sync();
// sync up with esp-link, blocks for up to 2 seconds
175
if
(!ok)
Serial
.println(
"EL-Client sync failed!"
);
176
}
while
(!ok);
177
Serial
.println(
"EL-Client synced!"
);
178
179
// Set-up callbacks for events and initialize with es-link.
180
mqtt.connectedCb.attach(mqttConnected);
181
mqtt.disconnectedCb.attach(mqttDisconnected);
182
mqtt.publishedCb.attach(mqttPublished);
183
mqtt.dataCb.attach(mqttData);
184
mqtt.
setup
();
185
186
//Serial.println("ARDUINO: setup mqtt lwt");
187
//mqtt.lwt("/lwt", "offline", 0, 0); //or mqtt.lwt("/lwt", "offline");
188
189
Serial
.println(
"EL-MQTT ready"
);
190
191
delay(1000);
// устаканимся
192
193
}
194
195
//static int count;
196
static
uint32_t last;
197
198
//////////////////////////////////////////////////////////////////
199
void
loop
()
200
{
201
esp.Process();
202
if
(connected && (millis()-last) > 4000) {
203
printBME280Data(&
Serial
);
204
last = millis();
205
}
206
}
207
208
//////////////////////////////////////////////////////////////////
209
void
printBME280Data
210
(
211
Stream* client
212
)
213
{
214
float
temp(NAN), hum(NAN), pres(NAN);
215
216
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
217
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
218
219
bme.read(pres, temp, hum, tempUnit, presUnit);
220
221
222
223
// client->print("Температура: ");
224
// client->print(temp); //client->print(" / "); client->print(temperature); client->print(" / ");Serial.print(t);
225
// client->println("°"+ String(tempUnit == BME280::TempUnit_Celsius ? 'C' :'F'));
226
// client->print("Влажность: ");
227
// client->print(hum); //client->print(" / "); client->print(humidity); client->print(" / ");Serial.print(h);
228
// client->println("% RH");
229
// client->print("Давление: ");
230
// client->print(pres/133.3224);
231
// client->println(" мм рт.ст.");
232
233
234
235
236
//MQ135 lib
237
float
ppm = gasSensor.getPPM();
238
239
//MQ135
240
analogValue = analogRead(analogPin);
// чтение аналогового значения
241
digitalValue = digitalRead(3);
// чтение цифрового значения
242
//Serial.print("CO2: ");Serial.print(ppm);Serial.print(" ppm | значение - "); Serial.print(analogValue);
243
//Serial.print(" порог - ");
244
//if(digitalValue) Serial.println("превышен"); else Serial.println("не превышен");
245
246
//MQ7
247
analogValue2 = analogRead(analogPin2);
// чтение аналогового значения
248
digitalValue2 = digitalRead(4);
// чтение цифрового значения
249
//Serial.print("Угарный газ: "); // вывод аналогового значения в последовательный порт
250
//Serial.print(analogValue2);
251
//Serial.print(" ppm , порог - "); // вывод цифрового значения в аналоговый порт
252
//if(digitalValue2) Serial.println("превышен"); else Serial.println("не превышен");
253
254
//Освещенность
255
analogValue3 = analogRead(analogPin3);
// чтение аналогового значения
256
//Serial.print("Освещенность: "); // вывод аналогового значения в последовательный порт
257
//Serial.println(analogValue3);
258
//Шум
259
analogValue4 = analogRead(analogPin4);
// чтение аналогового значения
260
//Serial.print("Шум: "); // вывод аналогового значения в последовательный порт
261
//Serial.println(analogValue4);
262
//Serial.println(gasSensor.getRZero()) ;
263
lcd.setCursor(0,0);
264
lcd.print(temp);
265
lcd.setCursor(8,0);
266
lcd.print(hum);
267
lcd.setCursor(0,1);
268
lcd.print(pres/133.3224);
269
lcd.setCursor(8,1);
270
lcd.print(ppm);
271
272
Serial
.println(
"publishing"
);
273
char
buf[12];
274
itoa(temp, buf, 10);
275
mqtt.publish(
"/node_16_Balcony_meteo/sensors/Temp"
, buf);
276
itoa(hum, buf, 10);
277
mqtt.publish(
"/node_16_Balcony_meteo/sensors/Hum"
, buf);
278
itoa(pres/133.3224, buf, 10);
279
mqtt.publish(
"/node_16_Balcony_meteo/sensors/Press"
, buf);
280
itoa(ppm, buf, 10);
281
mqtt.publish(
"/node_16_Balcony_meteo/sensors/CO2"
, buf);
282
itoa(gasSensor.getRZero(), buf, 10);
283
mqtt.publish(
"/node_16_Balcony_meteo/sensors/RZero_CO2"
, buf);
284
itoa(analogValue2, buf, 10);
285
mqtt.publish(
"/node_16_Balcony_meteo/sensors/CO"
, buf);
286
itoa(analogValue3, buf, 10);
287
mqtt.publish(
"/node_16_Balcony_meteo/sensors/Light"
, buf);
288
itoa(analogValue4, buf, 10);
289
mqtt.publish(
"/node_16_Balcony_meteo/sensors/Noise"
, buf);
290
291
uint32_t t = cmd.GetTime();
292
// Serial.print("Time: "); Serial.println(t);
293
294
//Serial.println("--------------------------------------------------------");
295
296
// delay(1000);
297
}
RIV_full_typemsg6
В синхронных каналах нет другого способа формирования пакетов кроме, как битстаффинг и байтстаффинг. Познакомься хотя бы с HDLC, Frame Relay (биториентированные протоколы), или ATM, BSC (байториентированные протоколы).
1000 кбит - 40м
500кбит - 110м
250кбит - 240м
125кбит - 500м
50кбит - 1 300м
20кбит - 3 300м
10кбит - 6 300м
5кбит - 13 000м
Дистанционная загрузка ПО.
Забавный ты.
Я не заметил, когда мы с вами перешли на "ты".
В синхронных каналах нет другого способа формирования пакетов кроме, как битстаффинг и байтстаффинг.
Это неверно. Например, C-bus - синхронный, но не использует ни бит-стаффинг, ни байт-стаффинг, ни даже кодирование по типу 8b/10b или 6b/8b, при помощи которого это тоже можно сделать.
Или посмотрите как сделан синхронный интерфейc чипов WS2812 для управления RGB лентами. Там вообще ничего из перечисленного выше не использовано, а тем не менее работает.
Познакомься хотя бы с HDLC, Frame Relay (биториентированные протоколы), или ATM, BSC (байториентированные протоколы).
Каким образом из того, что некоторые синхронные протоколы используют бит-стаффинг, следует, что мне не надо использовать байт-стаффинг там, где мне это удобно? Где логика?
По-вашему SLIP или COBS можно только в синхронных интерфейсах применять? Скорей всего вы вообще не знаете что такое байт-стаффинг. Для примера, ознакомьтесь с Wake http://caxapa.ru/lib/wake/
Другими словами предлагаемая реализация не имеет ничего общего с KNX, потому как, ни аппаратно, ни программно не совместима с KNX
Совершенно верно, несовместима. Задачи сделать их совместимыми не ставилось и нигде этого не обещалось. Непонятно с чего вы вдруг заговорили о совместимости.
Более того, KNX (EIB) и C-Bus тоже между собой несовместимы, хотя изначально их разрабатывали одни и те же люди. По сути своей они очень похожи, однако C-bus синхронный, а KNX - асинхронный
Выпало 3 узла
7 через 03:46:30
9 через 04:02:30
14 через 06:34:30
У них в логе
Принято из CAN: NULL_C От Кого: ШИРОКОВЕЩАТЕЛЬНО
Лог с мастера смотри https://yadi.sk/d/ozOcbX7B3V5hYy
файл log_13.05.18-14.05.18.txt