Мне кажется, чтобы байты туда-сюда не трусить, неплохо было бы начать с реальных сценариев управления. Тогда будет понятно, сколько типов контроллеров действительно необходимо.
Я как раз начал реализовывать этот слой, привязываю конкретные устройства к контроллерам.
Serial.print(F("Attach Node sender to main route..."));if(!ahbNode0.nodeBusAttach(&ahb0) < 0) {Serial.println(F("Error!"));}else{Serial.println(F("Done!"));}
Без реального ahn_node.h и реализации методов можно долго фантазировать, что не так сделано.
Мне кажется, что в реальности создаётся два истанса bme - через дефолтовый конструктор класса и, дополнительный, через new(). Это плохо, нужно что-то одно выбирать Но, с одного данные всё равно должны идти... если присоединение верное, выставлен правильный адрес BME и Wire.h кикстартнуто. Напишите маленький класс для отладки - я прогоню у себя, если не разберётесь по ходу пьесы.
Весь топик я не читал, может зайду на очередной круг... Я так понял, что концептуально контролируется некая условная точка в пространстве (дома) например. Т.е. важно знать, что в кладовке перегрев крупы... Важно ли при этом знать какая нода (тип) с какими наборами датчиков находится в этой кладовой? Наверное, нет. Достаточно, чтобы метрики были привязаны ко времени измерения и его точке. Таким образом - нода, при посылке данных (или коллектор метрик) должна всего лишь оперировать адресом и набором метрик, которые она способна породить. Например, в кладовке с адресом N стоит нода и отсылает метрику “температура“. Нужна влажность - добавляем ноду с адресом N, отсылающую метрику "влажность". Если есть желание - совмещаем ноды в одном устройстве с адресом N, которое отсылает обе метрики. Нужно работать по запросу - коллектор шлёт команду "отчитаться точке N", ноды опознают свой адрес (один и тот же), отчитываются разными метриками. Т.е. железо на нижнем уровне модифицируется и комбинируется как угодно, на протокольном же изменений не требуется.
Тут вот какое дело, Макс поправляй если мыслишь иначе, изначально предполагалось и к этому мы идем, что сеть буде иметь свои мозги хотя бы на минимальном уровне и выполнять определенные функции и сценарии сама. Например контроль температуры, влажности, вентиляции в помещении, используя для этого несколько разных сенсоров, возможно от разных контроллеров и управляя различными устройствами с разных контроллеров, и для решения этой задачи не понадобится управляющий компьютер. Задача управляющего компа это интерфейс и интеграция с доп системами, например той же алисой, мультирумом, почтой, погодой из вне и пр.
В то же время для того же интерфейса нужно видеть температуры, а при наличии датчиков пол, потолок, окна, температура радиатора, входной выходной коллектор вентиляции, за бортом и их тоже.
Так что должны быть как ручное управление, выключить вентиляцию, так и автомат, держи CO2 на 600.
Без реального ahn_node.h и реализации методов можно долго фантазировать, что не так сделано.
Мне кажется, что в реальности создаётся два истанса bme - через дефолтовый конструктор класса и, дополнительный, через new(). Это плохо, нужно что-то одно выбирать Но, с одного данные всё равно должны идти... если присоединение верное, выставлен правильный адрес BME и Wire.h кикстартнуто. Напишите маленький класс для отладки - я прогоню у себя, если не разберётесь по ходу пьесы.
если убираю в объявлении ругается что не знает что такое bme
если не делаю new выпадает в процессе выполнения когда доходит до вызова.
Я могу из скетча вызвать как и все остальное, но будет очень криво. Хотел все в либе спрятать.
new() возвращает в bme указатель, но сама переменная bme объявлена не как указатель. Я в ООП не сильно шарю, не знаю какие спецэффекты бывают, если в ссылку на класс указатель бахнуть, но всё же начал с того, что объявил бы bme как указатель (с *)
А вообще - тут нужен небольшой класс. Разобраться, почему сенсор не заводится в большом проекте - не очень просто. В моём, к примеру, Wire создаётся и стартует только если есть вкомпилированная поддержка I2C сенсоров. Ну и я частенько забывают имплементируемый сенсор в список I2C-устройств добавлять. Обнаруживаю это через полчаса траха с "неработающим датчиком", который отдельно работает.
UPD: адафрутовский begin возвращает код успеха - можно к нему прицепиться и узнать насчёт работы BME в принципе. Или в init() натыкать сериалов - узнать на чём спотыкается.
изначально предполагалось и к этому мы идем, что сеть буде иметь свои мозги хотя бы на минимальном уровне и выполнять определенные функции и сценарии сама. Например контроль температуры, влажности, вентиляции в помещении, используя для этого несколько разных сенсоров, возможно от разных контроллеров и управляя различными устройствами с разных контроллеров, и для решения этой задачи не понадобится управляющий компьютер. Задача управляющего компа это интерфейс и интеграция с доп системами, например той же алисой, мультирумом, почтой, погодой из вне и пр.
В то же время для того же интерфейса нужно видеть температуры, а при наличии датчиков пол, потолок, окна, температура радиатора, входной выходной коллектор вентиляции, за бортом и их тоже.
Так что должны быть как ручное управление, выключить вентиляцию, так и автомат, держи CO2 на 600.
Вот да, примерно так :) Народ, а есть какое-то текстовое/табличное/графическое описание того, что написано на С ? Язык программирования это просто способ записи алгоритма. Сам алгоритм-то есть ?
Я мозг сломал с этими железками. Отопление/свет/розетки работают и хорош. Пока отложил остальное.
Когда начинал думал примерно так:
Вот есть у меня "блок реле". На нем МК с каном и (внезапно) реле 6шт. Тупо делю id на 4 почти равные части. Называю их "тип блока", "номер блока", "тип параметра", "номер параметра". Значения параметров передаю уже в данных пакета.
"Блок реле" тип 0x01, номер блока 0x01. Тип параметра "реле" 0x01, номер параметра 0x01-0x06.
Причем 0x00 в типе блока автоматом означает "все блоки" и имеет наибольший приоритет. Равно как одной командой 0x01 0x00 0x01 0x00 можно включить/выключить все реле на всех блоках "реле" в системе.
Дальше у меня есть блок "температура" тип 0x02, номер 0x01. На нем 6 каналов 1-wire. По аналогии можно одной командой запросить температуру со всех блоков и всех каналов.
Теперь мне нужно или третье устройство, в котором я пропишу что есть блок реле и блок температуры и водружу в него логику работы например "термостат" чтобы он запрашивал температуру в одном блоке и рулил реле на другом. Это ничем не будет отличаться от централизованных систем со всеми их геморроями и кан тут не нужен от слова совсем. Уже на этом этапе можно взять любую из готовых систем, прописать свои блоки и вуаля... Или эту логику повесить на какой-то из этих же существующих блоков. Может на оба сразу для надежности. По сути виртуальный блок "термостат", состоящий из 1 (или нескольких) каналов температуры и 1 (или нескольких) реле. Вот на этом этапе я и застрял. Ибо логика у всех разная. Разорвал сеть на несколько сегментов и завел интерфейсный модуль с вайфаем, которой заканчивается эта микросеть реле-температура. Он и рулит всей логикой. Но тут меня осенило, что микроконтроллеру абсолютно пофигу что вы подключили к реле и где меряете температуру. А по-моему вся логика должна строиться на том, что МК знает что конкретно к нему подключено. То есть помимо низкого уровня "блок"-"канал", нужен еще высокий, где можно указать что вот к этому каналу блока температуры подключен уличный датчик температуры. И вот тут умный дом должен знать, что регулировать эту температуру не возможно. И запрос в сеть должен выглядеть как "температура на улице" а не 0x02 0x01 0x01 0x06. Вы сами можете не помнить к какому блоку и в какой канал этот датчик воткнут, а он работает и выдает температуру на улице. Сущностей в квартире/доме не так много как кажется. Их можно все перечислить и называть вещи своими именами а не настраивать gpio по сети. Так часть логики переедет в тот блок, где его основной параметр. То есть если к блоку реле номер 1 к каналу номер 2 подключен холодильник, то сам блок принимает команды "подключить холодильник" и "отключить холодильник". Это всё что можно с ним сделать. И сам блок реле в данном случае знает, что если "никого нет", то холодильник отключать нельзя. А телевизор например можно. Сомневаюсь что у кого-то по-другому. Как обычно сумбурно, много букв... Сори.
Вот да, примерно так :) Народ, а есть какое-то текстовое/табличное/графическое описание того, что написано на С ? Язык программирования это просто способ записи алгоритма. Сам алгоритм-то есть ?
Лучше адреса не трогать. 255 адресов не очень много. У с учетом маршрутизации (я у себя modbus, bee и пр. сети пробрасываю через CAN)
а какая проблема если раздробить адрес на комнаты? с учётом того, что адрес конечного элемента по факту тройной получается: 4бит *8бит*8бит. Тут уж за миллион переваливает, мало?
по-моему такие одинаковые адреса (см. ниже) как то нелепо выглядят, дублирование какое-то идёт.
Лучше адреса не трогать. 255 адресов не очень много. У с учетом маршрутизации (я у себя modbus, bee и пр. сети пробрасываю через CAN)
а какая проблема если раздробить адрес на комнаты? с учётом того, что адрес конечного элемента по факту тройной получается: 4бит *8бит*8бит. Тут уж за миллион переваливает, мало?
по-моему такие одинаковые адреса (см. ниже) как то нелепо выглядят, дублирование какое-то идёт.
Наши ноды да но повторюсь Modbus имеет жесткую адресацию, и для меня 255 и так мало. Названия не важны, важно количество адресуемых уникальных ID.
Это мои реально используемые адреса и их будет больше
сделай "тип сообщения" - шлюз. "подтипы" - модбас, bee, uart и т.д. И в этих типах сообщений разряд, где должен стоять адрес CAN узла, будет восприниматься как совсем другая адресация - адресация твоих пробросов от других протоколов. и отдавай хоть все 255 на это дело.
Т.е. в зависимости от типа сообщения может меняться не только структура payload , но и младших разрядов ID.
Я вообще не понимаю нафига так сильно усложнять протокол. С CANом то бы разобраться, а тут уже и модбасы и уарты и радиоканалы пошли - повеситься легче. Вся эта шляпа ассортишная без глюков работать точно не будет. CAN в работе ещё не был. Тут только с ним ошибок в реальных условиях ещё выявлять и выявлять. Если уж надо будет CAN с другими сетями сопрячь - шлюз можно отдельно построить, но до этого далеко.
К меня уже межинтрефейсный маршрутизатор написан. При изменении адреса придется почти пол библиотеки переписывать. И я честно говоря не совсем понял зачем менять адресацию. У нас 3 нибла есть msgtype и devtype. Куда больше то?
Сущностей в квартире/доме не так много как кажется. Их можно все перечислить и называть вещи своими именами а не настраивать gpio по сети.
такой дорогой и идём, не понимаю, почему все кто сюда заходит, думают обратное.
За всех не отвечу, но меня сбило обилие других слов типа модбас, зигби и.т.п :) Конечно сразу мысль "какой-то универсальный протокол, соединяющий всё со всем". Тогда у меня только один вопрос: логику где хранить ?
Смотри либу в библиотеке на github. Основной класс ahb. Есть абстракция типа tcp/ip поверх всего железа. Есть виртуальный класс ahb_comm, который определяет функции дочерних классов уже протоколов нижнего уровня. Т.е из главного класса отправка во все шины (протоколы) идёт в одном формате. Если интересно могу как Макс написать мануал. Но только на выходных. Общая инфа есть тут https://github.com/graynet-dev/aHomeBus но это скорее мой блог и хранилище кода. Программную документацию потом буду писать.
И я честно говоря не совсем понял зачем менять адресацию. У нас 3 нибла есть msgtype и devtype. Куда больше то?
Ты ещё забыл про номер датчика. как раз больше не надо. Я наоборот хочу меньше. Я хочу это сделать для более рационального использования адресного пространства без дублирования. Оптимизировать то бишь. Так меньшее количество адресов потребуется.
Вот смотри два разных подхода на примере. Имеем допустим две комнаты: зал и спальню. Нужно по шине подключить три выключателя света, три розетки в зале и по два в спальне; ну и узел подсветки пола, например, какого-нибудь в зале. (розетки и выключатели просто для примера , вместо них могут быть любые сенсоры и ИУ однотипные). То что это, в какой-то степени, идиотизм каждую розетку и выключатель подключать через локальный МК по CAN шине - дело десятое. Речь сейчас про принцип. (А иногда всё таки так удобнее чтобы проводов меньше тянуть).
Вариант 1 . Ниже выполнение поставленной задачи на алгоритме, который сейчас.
При обращении к розетке_1 в зале будет такая цепочка. зал_розетка1->зал_Розетка1-> номер датчика 1. При обращении сверху тебе важен объект - например выключатель, а не узел, к которому он подключен. Но ты обязан пройти через адрес узла (который к слову лишний тут получается). В данном варианте два раза в адресах указывается адрес помещения и два раза тип сенсора -и в адресе узла, и в адресе параметра. Точно также и с ИУ. Обращение к розетке - адрес помещения и тип ИУ присутствует и в адресе узла, и в адресе девайса. Вот тебе дублирование и съедание адресного пространства понапрасну. Для исключения этого мы вроде ввели понятие "тип параметра" и "номера датчиков", но это работает, когда в помещении единственный узел и всё подключено к нему. Если же и в пределах одного помещения идёт разделение функционала по узлам, то такой фокус не прокатывает и приходится кучу лишних адресов добавлять, а "номер датчика" не используется и будет везде = 1.
Вариант 2 . Как я хочу сделать.
Адреса помещений: зал, спальня.
Типы параметров: выключатель
Типы девайсов: розетка, светПлинтус.
А номера розеток и выключателей на узлах конфигурируются через "номер датчика". Всё! Надо обратиться к розетке 3 в зале? Пожалуйста: зал -> розетка -> номер датчика 3. При этом все узлы одной комнаты обрабатывают CAN сообщения, адресованные этой комнате.
Чувствуешь разницу? Т.е. понемногу мы приходим к одной из фишек CAN шины, что идентификатор обозначает не физ узел, а объект данных.
UPD. мы можем и не дробить адрес узла на RoomAddr и PhysAddr. А просто оставить RoomAddr полноценный 8 битный. Т.е. в полезных данных CAN обмена в идентификаторе полностью будет отсутствовать информация с какого физического узла исходит CAN сообщение (только RoomAddr). PhysAddr будет фигурировать в составе ID только в служебных CAN сообщениях (heartbeat, nodeguard, reboot и т.д.), например на месте разряда dev_type, т.к. служебные CAN сообщения призваны работать именно с физическим железом.
Вот и уровни абстракции появляются. RoomAddr - это некий виртуальный узел помещения, состоящий из одного или нескольких физических узлов.
Честно говоря я не думаю что мы умнее разработчиков canopen, devicenet и пр. разработчиков протоколов Овер Кан. Они адреса источника и получателя в id вставили. Правда в device net 7 бит вроде и 127 адресов.
Думаю от 256 адресов отправитель и 256 получатель уходить не стоит. Остальные биты можно объединить это 13 бит итого 2 в 13 это 8192 адреса/параметра/устройства. Либо оставить как есть. Делать только получателя по ID не понимая кто запросил, зачем и имеет ли он на это право, потерять маршрутизацию в сопрягаемые сети думаю не стоит.
Чувствуешь разницу? Т.е. понемногу мы приходим к одной из фишек CAN шины, что идентификатор обозначает не физ узел, а объект данных.
riv пишет:
Делать только получателя по ID не понимая кто запросил, зачем и имеет ли он на это право, потерять маршрутизацию в сопрягаемые сети думаю не стоит.
Посмотрите на CAN-шину не как на интерфейс для связи различных контроллеров, а именно как на ШИНУ данных. Вы же когда вызываете функцию по работе, например, i2c, вы же не передаете ей в качестве аргумента имя функции, ее вызывающую ? И уж тем более не получаете в ответ имя функции, которая отработала вызов с целью проверки, а имела ли она право обрабатывать то, что я ей послал... Если смотреть на CAN как на один большой (просто распределенный) контроллер - жить станет проще. Да, нужна некая диагностика узлов на предмет их онлайности и правильности работы, но в остальном это один МК в созможностью добавления ножек в любой момент.
Посмотрите на CAN-шину не как на интерфейс для связи различных контроллеров, а именно как на ШИНУ данных. Вы же когда вызываете функцию по работе, например, i2c, вы же не передаете ей в качестве аргумента имя функции, ее вызывающую ? И уж тем более не получаете в ответ имя функции, которая отработала вызов с целью проверки, а имела ли она право обрабатывать то, что я ей послал... Если смотреть на CAN как на один большой (просто распределенный) контроллер - жить станет проще. Да, нужна некая диагностика узлов на предмет их онлайности и правильности работы, но в остальном это один МК в созможностью добавления ножек в любой момент.
Если был один CAN, готов был бы наверное согласиться, но у меня CAN это хребет вокруг которого крутится сеть Modbus (контроллер температуры, жалюзи), UART ... которые хочу однозначно адресовать с центрального шлюза и сервера Majordomo.
Так вот эта сеть сейчас для меня прозрачна. Я отправляя команду формата описанного выше у Макса (привелся к его формату) попадаю на нужный мне адрес не зависимо от платформы и протокола. Причем каждый узел может иметь и по 2-3 интерфейса CAN со своей адресацией, НО диапазон адресов от 1 до 255, и узел получив пакет смотрит к нему или нет, если нет то не к сети ли подключенной к нему на другом его интерфейсе. Причем за счет абстракции роутеру плевать что там CAN или Modbus или TCP/IP. Приводись к любой физике или каналу, важно умей отправить то что тебе кинули в нужную шину ну и принять из нее.
Честно говоря я не думаю что мы умнее разработчиков canopen, devicenet и пр. разработчиков протоколов Овер Кан. Они адреса источника и получателя в id вставили.
riv пишет:
Думаю от 256 адресов отправитель и 256 получатель уходить не стоит. .....Делать только получателя по ID не понимая кто запросил, зачем и имеет ли он на это право, потерять маршрутизацию в сопрягаемые сети думаю не стоит.
дак я и предлагаю 256 оставить. Почему не понимая, кто запросил? RoomAddr отправителя то будет присутствовать в ID. Т.е. адрес и отправителя и получателя так и остаётся в ID. Только вот какая тебе разница какой физический узел измерил температуру в комнате, тебе должно быть важно что это за температура - пола, радиатора или воздуха (объект) и в какой именно комнате (локация).
Я не понимаю, как у тебя происходит маршрутизация между разными сетями, да и вообще плохо в этом разбираюсь, но можно пойти на компромисс и просто зарезервировать часть адресов под "виртуальные узлы". Т.е. если нам нужно более одного узла в комнате - создаём в диапазоне виртуальных соответствующий виртуальный (как бы объединяя несколько железных узлов в один виртуальный. При этом настраиваем в фильтре CAN приёмника у всех этих железных узлов пропускать адрес этого виртуального узла, чтобы они все сообщения принимали как один узел). Это очень похоже на рейд массив "страйп" в компе. Часть данных может быть на одном физическом диске, другая часть - на другом. Но винде пофиг - для неё оба физ.диска это один раздел. Винда работает с разделом. Так же и у нас, железный адрес как бы не особо нужен, только для диагностики. Сверху не важно какой физический узел замерил температуру, главное откуда эта температура (раздел диска). А если тебе нужен прям стопудовый узел с железным адресом, к которому другие интерфейсы подключены, заносишь его в диапазон "железных" узлов и у него RoomAddr будет совпадать с PhysAddr.
По тому, в каком диапазоне адресов узел находится, отличать будем - виртуальный узел или железный.
Про какие-то уровни абстракции вроде говорили, чтобы наш протокол был универсальный, не зависящий от железа. А тебе зачем-то "пробросы" других интерфейсов через CAN нужно стало делать с какими то определёнными адресами. Что там, жалюзи у тебя по модбасу? Почему нельзя было сконфигурировать на узле девайс жалюзи в массиве девайсов? В наш протокол сверху мы говорим (по адресу: комната->девайс жалюзи->№окна ) в рамках нашего протокола "открыть", "закрыть" шторы, там не знаю, состояние положения штор можем запросить - всё в рамках нашего протокола. И, раз мы договорились абстракцию взаимодействия с девайсами сделать, то жалюзи на узле будут управляться через функцию прокладку, которая и будет переводить формат команд и параметров нашего протокола в модбас. вот и всё! Если надо с мажордомо управлять, а, насколько я понял, с ним проще взаимодействовать по езернету, то так же делаем через узел-шлюз. Мажордомо <->Езернет <->узел-шлюз<->нашCANпротокол<->функция прокладка<->модбас<->жалюзи.
А ты собрался всё и вся чтоли в протокол добавить? А если что-нибудь забудешь добавить или устройство тебе понадобится подключить с какой нибудь экзотической шиной (например Dali , KNX, DMX512), всё, весь протокол переписывать? Какая же это универсальность?
Как там в CANopen? словарь объектов? Объекты это же наши сенсоры (массив parameter) и ИУ (массив девайсов). Дак всё-же может и будем с объектами взаимодействовать?
НЕ надо сверху взаимодействовать с физическими узлами! Надо взаимодействовать с объектами (сенсоры, ИУ)! НЕ надо напрямую адресовать сверху до узла! НЕ надо взаимодействовать сверху с узлом через (сквозь) наш протокол! Надо взаимодействовать сверху с нашим протоколом! А наш протокол уже будет взаимодействовать с объектом. Сверху должно быть похеру что там на конце модбас или зигбии. Сверху все лишь просто нужно обращаться как мы и задумывали: локация->объект(тип объекта)->конкретный экземпляр. Если хочется наш протокол подготовить для подключения каких-то стандартных вещей, то имхо, нужно просто написать различные функции-прокладки для этих стандартных вещей (Датчики даллас, модбасы и т.д. и т.п.). А ты, получается, не шлюзуешь данные других протоколов, а пробрасываешь их через наш, получается ломая некоторые изначальные принципы нашей адресации. Ты все адреса к одному байту привел. Нафига мы тогда добавили тип параметра (тип девайса), да ещё и номера датчиков (твоя же идея кстати)? Ты щас их не используешь, получается, адресуя свои жалюзи только в общем первом (одном) байте. Конечно тебе 255 не хватает. А если у тебя жалюзи такие в нескольких комнатах? Адресовать будешь: Жалюзи_комната1, Жалюзи_комната2. ? Хреновасто. Надо чётко разделять локацию и объект, а у тебя всё в одном.
Если узлы находятся в одной комнате, то разряд адреса локация у них должен быть один и тот же.
Короче для меня картина "правильного" протокола понемногу проясняется. Знаю теперь как двигаться дальше.
Думал ты хочешь оставить всего 16 адресов в сети. Ты говорил выше про нибл. И хочешь убрать адрес отправителя.
Если остаётся байт получателя и байт отправителя то все остальное на твое усмотрение.
По поводу modbus, у меня ещё мультисплит а это уже сложное устройство.Его датчиком или реле не представишь. И.е если у устройства на модбасе есть свои мозги я хочу с ним работать по адресу.
И, раз мы договорились абстракцию взаимодействия с девайсами сделать, то жалюзи на узле будут управляться через функцию прокладку, которая и будет переводить формат команд и параметров нашего протокола в модбас. вот и всё! Если надо с мажордомо управлять, а, насколько я понял, с ним проще взаимодействовать по езернету, то так же делаем через узел-шлюз. Мажордомо <->Езернет <->узел-шлюз<->нашCANпротокол<->функция прокладка<->модбас<->жалюзи.
А ты собрался всё и вся чтоли в протокол добавить? А если что-нибудь забудешь добавить или устройство тебе понадобится подключить с какой нибудь экзотической шиной (например Dali , KNX, DMX512), всё, весь протокол переписывать? Какая же это универсальность?
Похоже мы говорим об одном и том же но на разных языках. Посмотри выше мой код. Я все это уже реализовал.
Но, ты рассчитываешь на одно устройство на одном RS485 интерфейсе а я на N устройств.
Мало того если нужен новый протокол я его просто реализую отдельным интерфейсом.
Я сначала так хотел (попилить адрес на нибблы). Но сказали 15 комнат мало. Тогда я решил 255 оставить, но имел ввиду что физический адрес контроллера в составе ID (для полезных CAN фреймов) будет отсутствовать. В служебных фреймах физ.адрес поместиться на место разряда dev-type.
все таки сплит система это девайс - имхо. Дак может быть в твою адресацию (маршрутизацию) можно добавить байт и привести к виду: Локация -> девайс ? Тогда тебе адресов будет норм хватать и логичнее всё будет.
Интересно про сложность работы с мультисплитом. Какое-то сверху приложение уже готовое чтоли есть, или модуль в мажордомо для данной сплит системы , раз нужно данные через CAN неизменно в модбас прокидывать? Почему его нельзя представить сенсором и девайсом? просто хочу понять случаи , где может затаиться засада с моим подходом.
Повторюсь, если оставляешь под адресацию устройств 256 отправителю и 256 получателю, то оставшиеся 13 бит пользуй как считаешь нужным. Я от 256 железных устройств в мультипротокольной сети не уйду.
Мало того к каждому узлу с CAN может быть подключено несколько сегментов CAN и других интерфейсов.
А вот датчики уже ниже.
Виртуалить на уровне сети а не на уровне PC считаю утопией. Про поиск неисправности думал? Отказал датчик № 3 в комнате с 10 контроллерами, подключенными к неизвестно какому узлу. А может контроллер отказал и ли провод отпаялся и или код сбойнул или ...
Не. Я слишком хорошо знаю что такое РВР и поиск неисправности. Как диагностировать железо? А ПО? А физ. линии?
Просто прикинь что у тебя в машине есть датчики под капотом 1-10, 11-20 в салоне и 21-30 в багажнике. Подключенные к 3, 6 и 2 контроллерам соответственно. Причем датчик 1,15, 25 отвечают за топливную систему. И вот прикинь у тебя сбой и машина не заводится. А схемы кроме логической нет.
Про поиск неисправности думал? Отказал датчик № 3 в комнате с 10 контроллерами, подключенными к неизвестно какому узлу. А может контроллер отказал и ли провод отпаялся и или код сбойнул или ...
Не. Я слишком хорошо знаю что такое РВР и поиск неисправности. Как диагностировать железо? А ПО? А физ. линии?
Диагностировать точно также как ты это делаешь. Только по физ. адресам. Куда подключен датчик? - смотреть это можно в конфигурации. Диагностическую систему нужно развивать. Можно тип команд специальный придумать, чтоб конфигу в кан МК выбрасывали по команде.
Кроме того я могу легко перекинуть модбас и би местами на разных контроллерах. Просто поднять интерфейс , прописать маршруты и вперед. А вот если будет уникальная логика на узле то все сливай воду. Перелей прошивку перепрограммируй.
Я хочу иметь одинаковые контроллеры, с разъемом переходником (типа шилды ардуино монтажные или под винт) к которым подключаются нужные ИУ и сенсоры и интерфейсные контроллеры и единый софт для НОД. Отличие настройки, адрес и подключенное оборудование. Все как в начале темы. Универсальность и заменяемость полная. Зашел с PC (лучше с WEB) через шлюз по CAN на контроллер, выбрал из списка датчики, привязал их к пинам, указал сценеарий там или еще что, указал соседей куда что потправлять.
Включил и работает. А если конфиг еще на сервере держать то сбойный контроллер просто из ЗИПа поменял, подключил, по чему то типа TFTP (логически естественно) загрузил конфиг и вуаля.
Маршрутизатор работает как просто как топор, пришел пакет узлу смотрим если это мне в обработку или если узлу подключенному ко мне по другой шине, то ретрансляция, если не так то игнор.
Про поиск неисправности думал? Отказал датчик № 3 в комнате с 10 контроллерами, подключенными к неизвестно какому узлу. А может контроллер отказал и ли провод отпаялся и или код сбойнул или ...
Не. Я слишком хорошо знаю что такое РВР и поиск неисправности. Как диагностировать железо? А ПО? А физ. линии?
Диагностировать точно также как ты это делаешь. Только по физ. адресам. Куда подключен датчик? - смотреть в можно в конфигурации. Диагностическую систему нужно развивать. Можно тип команд специальный придумать, чтоб конфигу в кан МК выбрасывали по команде.
Программно диагностировать неисправную систему? Не понимая глючтит софт который и выдает ошибки или физика или ИУ. Это адский труд.
Поверь на слово не усложняй. Виртуальный контроллер лучше делать на мощной машине сверху.
Виртуалить датчики и ИУ в пределах контроллера стоит. Если хочешь виртуалить в пределах комнат и/или систем для сценариев или виртуальных систем то это отдельный слой. Т.е скрыть физ пины от протокола наверное стоит. А вот датчики и устройства нет
а ты как собрался свою диагностировать? В моей все отличие, что комнатах где более одного узла, полезные CAN сообщения не имеют в ID физ. адреса узла. Но это диагностится по служебным CAN фреймам, сердцебиение узла и т.д.
И все же как обращаться к Node 10, 11, C в моей схеме. Или например как обеспечить обмен Node 11 c 22, шлюзом и PC.
Дак говорю надо обращаться не к нодам, а к объектам. Какие объекты у тебя на этих нодах присутствуют? Свет на кухне, например. Kitchen-> lamp_ceil_onoff_d -> #1 . А что есть обмен ?
а ты как собрался свою диагностировать? В моей все отличие, что комнатах где более одного узла, полезные CAN сообщения не имеют в ID физ. адреса узла. Но это диагностится по служебным CAN фреймам, сердцебиение узла и т.д.
На шлюзе или PC контролирую параметры (вернее их выход за диапазон и/или их нестандартное например резкое изменение) и четко понимаю, что на контроллере 7, ага его имя node_7_Hallway_main, ага это главный контроллер в щите коридора, неправильно выдается состояние датчика или съем информации со счетчика.
Самое простое замена из ЗИП на другой.
Не помогло. Смотрю что с подключенным устройством. Тоже замена из ЗИП.
Не помогло. Звоним физику.
Все лаконично и понятно. По схеме Э4 отрабатываем (Схема электрическая соединений Э4).
И все же как обращаться к Node 10, 11, C в моей схеме. Или например как обеспечить обмен Node 11 c 22, шлюзом и PC.
Дак говорю надо обращаться не к нодам, а к объектам. Какие объекты у тебя на этих нодах присутствуют? Свет на кухне, например. Kitchen-> lamp_ceil_onoff_d -> #1 . А что есть обмен ?
Я готов на объекты, даже считаю их обязательными, но без отказа от прямой адресации к датчику/устройству.
Мало того считаю что и вирт объекты нужны но поверх этих слоев.
Например климат система это комбинация привода радиатора, кондея, нагревателя вентсистемы. Контроль температуры с разных датчиков. Сценарии и пр.
И все же как обращаться к Node 10, 11, C в моей схеме. Или например как обеспечить обмен Node 11 c 22, шлюзом и PC.
Дак говорю надо обращаться не к нодам, а к объектам. Какие объекты у тебя на этих нодах присутствуют? Свет на кухне, например. Kitchen-> lamp_ceil_onoff_d -> #1 . А что есть обмен ?
Ну у объекта есть свойства, методы и события. У меня пока нет объектов я только роутер добил а теперь наоборот нижний уровень добиваю. А вот потом займусь прослойкой. Только помоделировать надо.
Обмен это как раз для виртуальных устройств. Обмен данными 11 например сенсор CO2 а 22 это контроллер вентиляции. (это условно, могут быть мульти функц. устройства с кучей датчиков и иу, которые для тебя черный ящик только с протоколом управления и датчиками и иу)
Я хочу и на сервере их видеть и ими управлять в ручном режиме но и пусть они сами трудятся в автоматическом режиме.
ок, у нас системы разного уровня. У тебя прям ЦУП, а у меня так, лампочками по шине помигать. Поэтому и подходы разные , трудно прийти к общему знаменателю.
нифига адреса не будут одинаковые, часть адреса (помещение и тип параметра) да, одинаковая будет, а вторая часть (номер датчика) - будет отличаться.
можно кстати "адрес отправителя" разделить по нибблам. Левый - номер помещения, правый - тип контроллера. Хватит 15 комнат и 15 типов контроллеров?
Лучше адреса не трогать. 255 адресов не очень много. У с учетом маршрутизации (я у себя modbus, bee и пр. сети пробрасываю через CAN)
Кстати по уровням абстракции
https://mklimenko.github.io/russian/2018/05/13/a-guide-to-better-embedded-ru/
https://dic.academic.ru/dic.nsf/ruwiki/1659006
Я как раз начал реализовывать этот слой, привязываю конкретные устройства к контроллерам.
Кстати нубский вопрос.
В библиотеке https://github.com/graynet-dev/aHomeBus есть главный класс
1
class
AHB
к нему указателем через виртуальный класс привязываю разные интерфейсы (CAN, Modbus ....)
1
class
AHB_CAN :
public
AHB_COMM
к нему же (AHB) привязываю в зависимости от типа узла классы
1
class
AHB_MASTER
2
class
AHB_SLAVE
3
class
AHB_NODE
Все классы привязываются из основного скетча
01
#include "ahb.h"
02
uint8_t can_addr_net[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,77,78};
03
int
size_can_addr_net =
sizeof
(can_addr_net)/
sizeof
(can_addr_net[0]);
04
uint8_t uart_addr_net[] = {0,55,56};
05
int
size_uart_addr_net =
sizeof
(uart_addr_net)/
sizeof
(uart_addr_net[0]);
06
uint8_t modbus_rtu_addr_net[] = {100,101,102,103};
07
int
size_modbus_rtu_addr_net =
sizeof
(modbus_rtu_addr_net)/
sizeof
(modbus_rtu_addr_net[0]);
08
AHB ahb0(0,100,Node);
09
AHB_NODE ahbNode0(0);
10
AHB_CAN ahbCan0(53, CAN_250KBPS, MCP_8MHZ , 2,can_addr_net, size_can_addr_net);
11
AHB_UART ahbUart0(
Serial
,uart_addr_net,size_uart_addr_net);
12
AHB_MODBUS_RTU ahbModBusRtu0(0,1,10,modbus_rtu_addr_net, size_modbus_rtu_addr_net);
13
void
setup
() {
14
Serial
.begin(115200);
15
Serial
.print(F(
"AHB Node - "
));
16
Serial
.println(ahb0._nodeId);
17
delay(200*ahb0._nodeId);
18
ahb0.begin();
19
Serial
.print(F(
"Attach CAN..."
));
if
(ahb0.busAttach(&ahbCan0) < 0) {
Serial
.println(F(
"Error!"
));}
else
{
Serial
.println(F(
"Done!"
));}
20
Serial
.print(F(
"Attach Node logic..."
));
if
(!ahb0.nodeAttach(&ahbNode0) < 0) {
Serial
.println(F(
"Error!"
));}
else
{
Serial
.println(F(
"Done!"
));}
21
Serial
.print(F(
"Attach Node sender to main route..."
));
if
(!ahbNode0.nodeBusAttach(&ahb0) < 0) {
Serial
.println(F(
"Error!"
));}
else
{
Serial
.println(F(
"Done!"
));}
22
Serial
.print(F(
"Attach UART..."
));
if
(ahb0.busAttach(&ahbUart0) < 0) {
Serial
.println(F(
"Error!"
));}
else
{
Serial
.println(F(
"Done!"
));
23
Serial
.print(F(
"Attach MODBUS_RTU..."
));
if
(ahb0.busAttach(&ahbModBusRtu0) < 0) {
Serial
.println(F(
"Error!"
));}
else
{
Serial
.println(F(
"Done!"
));
24
}
А вот из класса AHB_NODE хочу вызвать класс из чужой библиотеки.
1
#include "Adafruit_BME280.h"
Вроде делаю все по науке
Объявляю в public ahn_node.h
1
Adafruit_BME280 bme;
Создаю экземпляр класса в конструкторе
1
AHB_NODE::AHB_NODE(uint8_t id){
2
bme =
new
Adafruit_BME280();
3
}
Указываю параметры класса в
1
byte
AHB_NODE::begin() {
2
bme.begin(0x76, &Wire);
3
}
Класс создается но данные с датчика не идут
1
bme.takeForcedMeasurement();
2
Serial
.print(
"Temperature = "
);
3
Serial
.print(bme.readTemperature());
4
Serial
.println(
" *C"
);
Есть мысли?
Без реального ahn_node.h и реализации методов можно долго фантазировать, что не так сделано.
Мне кажется, что в реальности создаётся два истанса bme - через дефолтовый конструктор класса и, дополнительный, через new(). Это плохо, нужно что-то одно выбирать Но, с одного данные всё равно должны идти... если присоединение верное, выставлен правильный адрес BME и Wire.h кикстартнуто. Напишите маленький класс для отладки - я прогоню у себя, если не разберётесь по ходу пьесы.
Тут вот какое дело, Макс поправляй если мыслишь иначе, изначально предполагалось и к этому мы идем, что сеть буде иметь свои мозги хотя бы на минимальном уровне и выполнять определенные функции и сценарии сама. Например контроль температуры, влажности, вентиляции в помещении, используя для этого несколько разных сенсоров, возможно от разных контроллеров и управляя различными устройствами с разных контроллеров, и для решения этой задачи не понадобится управляющий компьютер. Задача управляющего компа это интерфейс и интеграция с доп системами, например той же алисой, мультирумом, почтой, погодой из вне и пр.
В то же время для того же интерфейса нужно видеть температуры, а при наличии датчиков пол, потолок, окна, температура радиатора, входной выходной коллектор вентиляции, за бортом и их тоже.
Так что должны быть как ручное управление, выключить вентиляцию, так и автомат, держи CO2 на 600.
Без реального ahn_node.h и реализации методов можно долго фантазировать, что не так сделано.
Мне кажется, что в реальности создаётся два истанса bme - через дефолтовый конструктор класса и, дополнительный, через new(). Это плохо, нужно что-то одно выбирать Но, с одного данные всё равно должны идти... если присоединение верное, выставлен правильный адрес BME и Wire.h кикстартнуто. Напишите маленький класс для отладки - я прогоню у себя, если не разберётесь по ходу пьесы.
Так либа то вся тут https://github.com/graynet-dev/aHomeBus
https://github.com/graynet-dev/aHomeBus/blob/master/ahb_node.h
https://github.com/graynet-dev/aHomeBus/blob/master/ahb_node.cpp
если убираю в объявлении ругается что не знает что такое bme
если не делаю new выпадает в процессе выполнения когда доходит до вызова.
Я могу из скетча вызвать как и все остальное, но будет очень криво. Хотел все в либе спрятать.
если убираю в объявлении ругается что не знает что такое bme
если не делаю new выпадает в процессе выполнения когда доходит до вызова.
Я могу из скетча вызвать как и все остальное, но будет очень криво. Хотел все в либе спрятать.
new() возвращает в bme указатель, но сама переменная bme объявлена не как указатель. Я в ООП не сильно шарю, не знаю какие спецэффекты бывают, если в ссылку на класс указатель бахнуть, но всё же начал с того, что объявил бы bme как указатель (с *)
А вообще - тут нужен небольшой класс. Разобраться, почему сенсор не заводится в большом проекте - не очень просто. В моём, к примеру, Wire создаётся и стартует только если есть вкомпилированная поддержка I2C сенсоров. Ну и я частенько забывают имплементируемый сенсор в список I2C-устройств добавлять. Обнаруживаю это через полчаса траха с "неработающим датчиком", который отдельно работает.
UPD: адафрутовский begin возвращает код успеха - можно к нему прицепиться и узнать насчёт работы BME в принципе. Или в init() натыкать сериалов - узнать на чём спотыкается.
Переобъявил как указатель
1
Adafruit_BME280 *bme;
убрал new и вызываю
01
byte
AHB_NODE::begin() {
02
03
bme->begin(0x76, &Wire);
04
}
05
void
AHB_NODE::bme280_print(
void
) {
06
07
bme->takeForcedMeasurement();
08
Serial
.print(
"Temperature = "
);
09
Serial
.print(bme->readTemperature());
10
Serial
.println(
" *C"
);
11
12
Serial
.print(
"Pressure = "
);
13
14
Serial
.print(bme->readPressure() / 100.0F);
15
Serial
.println(
" hPa"
);
16
17
Serial
.print(
"Approx. Altitude = "
);
18
Serial
.print(bme->readAltitude(SEALEVELPRESSURE_HPA));
19
Serial
.println(
" m"
);
20
21
Serial
.print(
"Humidity = "
);
22
Serial
.print(bme->readHumidity());
23
Serial
.println(
" %"
);
24
25
Serial
.println();
26
27
}
Та же песня. То же в скетче работает.
Друг. Выбери что-то одно - или инстанс класса без new() или указатель на класс и new().
Друг. Выбери что-то одно - или инстанс класса без new() или указатель на класс и new().
Да все перепробовал, поэтому и извращаюсь, если как ты говоришь, то возвращает 0 в обоих вариантах, я с этого начал.
Сейчас пытаюсь отлаживаться уже глубже.
В общем научным тыком завел.
Выходит, что
1
byte
AHB_NODE::begin() {
2
bme.begin(0x76, &Wire);
3
}
Не отрабатывает
Запихнул сюда
01
void
AHB_NODE::bme280_print(
void
) {
02
03
if
(! bme.begin(0x76, &Wire))
04
{
05
Serial
.println(
"BME ERROR"
);
06
}
07
else
08
{
09
Serial
.println(
"BME OK"
);
10
}
11
12
13
14
bme.takeForcedMeasurement();
15
Serial
.print(
"Temperature = "
);
16
Serial
.print(bme.readTemperature());
17
Serial
.println(
" *C"
);
18
19
Serial
.print(
"Pressure = "
);
20
21
Serial
.print(bme.readPressure() / 100.0F);
22
Serial
.println(
" hPa"
);
23
24
Serial
.print(
"Approx. Altitude = "
);
25
Serial
.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
26
Serial
.println(
" m"
);
27
28
Serial
.print(
"Humidity = "
);
29
Serial
.print(bme.readHumidity());
30
Serial
.println(
" %"
);
31
32
Serial
.println();
33
34
}
Может на момент выполнения ahb_node.begin() wire ещё не запущен? Попробуй рядом его подопнуть.
В то же время для того же интерфейса нужно видеть температуры, а при наличии датчиков пол, потолок, окна, температура радиатора, входной выходной коллектор вентиляции, за бортом и их тоже.
Так что должны быть как ручное управление, выключить вентиляцию, так и автомат, держи CO2 на 600.
Вот да, примерно так :) Народ, а есть какое-то текстовое/табличное/графическое описание того, что написано на С ? Язык программирования это просто способ записи алгоритма. Сам алгоритм-то есть ?
Я мозг сломал с этими железками. Отопление/свет/розетки работают и хорош. Пока отложил остальное.
Когда начинал думал примерно так:
Вот есть у меня "блок реле". На нем МК с каном и (внезапно) реле 6шт. Тупо делю id на 4 почти равные части. Называю их "тип блока", "номер блока", "тип параметра", "номер параметра". Значения параметров передаю уже в данных пакета.
"Блок реле" тип 0x01, номер блока 0x01. Тип параметра "реле" 0x01, номер параметра 0x01-0x06.
Причем 0x00 в типе блока автоматом означает "все блоки" и имеет наибольший приоритет. Равно как одной командой 0x01 0x00 0x01 0x00 можно включить/выключить все реле на всех блоках "реле" в системе.
Дальше у меня есть блок "температура" тип 0x02, номер 0x01. На нем 6 каналов 1-wire. По аналогии можно одной командой запросить температуру со всех блоков и всех каналов.
Теперь мне нужно или третье устройство, в котором я пропишу что есть блок реле и блок температуры и водружу в него логику работы например "термостат" чтобы он запрашивал температуру в одном блоке и рулил реле на другом. Это ничем не будет отличаться от централизованных систем со всеми их геморроями и кан тут не нужен от слова совсем. Уже на этом этапе можно взять любую из готовых систем, прописать свои блоки и вуаля... Или эту логику повесить на какой-то из этих же существующих блоков. Может на оба сразу для надежности. По сути виртуальный блок "термостат", состоящий из 1 (или нескольких) каналов температуры и 1 (или нескольких) реле. Вот на этом этапе я и застрял. Ибо логика у всех разная. Разорвал сеть на несколько сегментов и завел интерфейсный модуль с вайфаем, которой заканчивается эта микросеть реле-температура. Он и рулит всей логикой. Но тут меня осенило, что микроконтроллеру абсолютно пофигу что вы подключили к реле и где меряете температуру. А по-моему вся логика должна строиться на том, что МК знает что конкретно к нему подключено. То есть помимо низкого уровня "блок"-"канал", нужен еще высокий, где можно указать что вот к этому каналу блока температуры подключен уличный датчик температуры. И вот тут умный дом должен знать, что регулировать эту температуру не возможно. И запрос в сеть должен выглядеть как "температура на улице" а не 0x02 0x01 0x01 0x06. Вы сами можете не помнить к какому блоку и в какой канал этот датчик воткнут, а он работает и выдает температуру на улице. Сущностей в квартире/доме не так много как кажется. Их можно все перечислить и называть вещи своими именами а не настраивать gpio по сети. Так часть логики переедет в тот блок, где его основной параметр. То есть если к блоку реле номер 1 к каналу номер 2 подключен холодильник, то сам блок принимает команды "подключить холодильник" и "отключить холодильник". Это всё что можно с ним сделать. И сам блок реле в данном случае знает, что если "никого нет", то холодильник отключать нельзя. А телевизор например можно. Сомневаюсь что у кого-то по-другому. Как обычно сумбурно, много букв... Сори.
Слушай а вариант, у меня много чего заводится. Проект большой...
Спасибо. А то уже не знал куда рыть.
тут
такой дорогой и идём, не понимаю, почему все кто сюда заходит, думают обратное.
а какая проблема если раздробить адрес на комнаты? с учётом того, что адрес конечного элемента по факту тройной получается: 4бит *8бит*8бит. Тут уж за миллион переваливает, мало?
по-моему такие одинаковые адреса (см. ниже) как то нелепо выглядят, дублирование какое-то идёт.
а какая проблема если раздробить адрес на комнаты? с учётом того, что адрес конечного элемента по факту тройной получается: 4бит *8бит*8бит. Тут уж за миллион переваливает, мало?
по-моему такие одинаковые адреса (см. ниже) как то нелепо выглядят, дублирование какое-то идёт.
Наши ноды да но повторюсь Modbus имеет жесткую адресацию, и для меня 255 и так мало. Названия не важны, важно количество адресуемых уникальных ID.
Это мои реально используемые адреса и их будет больше
1
uint8_t can_addr_net[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,77,78};
2
int
size_can_addr_net =
sizeof
(can_addr_net)/
sizeof
(can_addr_net[0]);
3
4
uint8_t uart_addr_net[] = {0,55,56};
5
int
size_uart_addr_net =
sizeof
(uart_addr_net)/
sizeof
(uart_addr_net[0]);
6
7
8
uint8_t modbus_rtu_addr_net[] = {100,101,102,103};
9
int
size_modbus_rtu_addr_net =
sizeof
(modbus_rtu_addr_net)/
sizeof
(modbus_rtu_addr_net[0]);
сделай "тип сообщения" - шлюз. "подтипы" - модбас, bee, uart и т.д. И в этих типах сообщений разряд, где должен стоять адрес CAN узла, будет восприниматься как совсем другая адресация - адресация твоих пробросов от других протоколов. и отдавай хоть все 255 на это дело.
Т.е. в зависимости от типа сообщения может меняться не только структура payload , но и младших разрядов ID.
Я вообще не понимаю нафига так сильно усложнять протокол. С CANом то бы разобраться, а тут уже и модбасы и уарты и радиоканалы пошли - повеситься легче. Вся эта шляпа ассортишная без глюков работать точно не будет. CAN в работе ещё не был. Тут только с ним ошибок в реальных условиях ещё выявлять и выявлять. Если уж надо будет CAN с другими сетями сопрячь - шлюз можно отдельно построить, но до этого далеко.
К меня уже межинтрефейсный маршрутизатор написан. При изменении адреса придется почти пол библиотеки переписывать. И я честно говоря не совсем понял зачем менять адресацию. У нас 3 нибла есть msgtype и devtype. Куда больше то?
такой дорогой и идём, не понимаю, почему все кто сюда заходит, думают обратное.
За всех не отвечу, но меня сбило обилие других слов типа модбас, зигби и.т.п :) Конечно сразу мысль "какой-то универсальный протокол, соединяющий всё со всем". Тогда у меня только один вопрос: логику где хранить ?
Смотри либу в библиотеке на github. Основной класс ahb. Есть абстракция типа tcp/ip поверх всего железа. Есть виртуальный класс ahb_comm, который определяет функции дочерних классов уже протоколов нижнего уровня. Т.е из главного класса отправка во все шины (протоколы) идёт в одном формате. Если интересно могу как Макс написать мануал. Но только на выходных. Общая инфа есть тут https://github.com/graynet-dev/aHomeBus но это скорее мой блог и хранилище кода. Программную документацию потом буду писать.
Ты ещё забыл про номер датчика. как раз больше не надо. Я наоборот хочу меньше. Я хочу это сделать для более рационального использования адресного пространства без дублирования. Оптимизировать то бишь. Так меньшее количество адресов потребуется.
Вот смотри два разных подхода на примере. Имеем допустим две комнаты: зал и спальню. Нужно по шине подключить три выключателя света, три розетки в зале и по два в спальне; ну и узел подсветки пола, например, какого-нибудь в зале. (розетки и выключатели просто для примера , вместо них могут быть любые сенсоры и ИУ однотипные). То что это, в какой-то степени, идиотизм каждую розетку и выключатель подключать через локальный МК по CAN шине - дело десятое. Речь сейчас про принцип. (А иногда всё таки так удобнее чтобы проводов меньше тянуть).
Вариант 1 . Ниже выполнение поставленной задачи на алгоритме, который сейчас.
Адреса узлов: зал_розетка1, зал_розетка2, зал_розетка3, зал_выключатель1, зал_выключатель2, зал_выключатель3, зал_подсветка_пола, спальня_розетка1, спальня_розетка2, спальня_выключатель1, спальня_выключатель2.
Типы параметров: зал_Выключатель1, зал_Выключатель2, зал_Выключатель3, спальня_Выключатель1, спальня_Выключатель2.
Типы девайсов: зал_Розетка1, зал_Розетка2, зал_Розетка3, спальня_Розетка1, спальня_Розетка2, зал_светПлинтус.
При обращении к розетке_1 в зале будет такая цепочка. зал_розетка1->зал_Розетка1-> номер датчика 1. При обращении сверху тебе важен объект - например выключатель, а не узел, к которому он подключен. Но ты обязан пройти через адрес узла (который к слову лишний тут получается). В данном варианте два раза в адресах указывается адрес помещения и два раза тип сенсора -и в адресе узла, и в адресе параметра. Точно также и с ИУ. Обращение к розетке - адрес помещения и тип ИУ присутствует и в адресе узла, и в адресе девайса. Вот тебе дублирование и съедание адресного пространства понапрасну. Для исключения этого мы вроде ввели понятие "тип параметра" и "номера датчиков", но это работает, когда в помещении единственный узел и всё подключено к нему. Если же и в пределах одного помещения идёт разделение функционала по узлам, то такой фокус не прокатывает и приходится кучу лишних адресов добавлять, а "номер датчика" не используется и будет везде = 1.
Вариант 2 . Как я хочу сделать.
Адреса помещений: зал, спальня.
Типы параметров: выключатель
Типы девайсов: розетка, светПлинтус.
А номера розеток и выключателей на узлах конфигурируются через "номер датчика". Всё! Надо обратиться к розетке 3 в зале? Пожалуйста: зал -> розетка -> номер датчика 3. При этом все узлы одной комнаты обрабатывают CAN сообщения, адресованные этой комнате.
Чувствуешь разницу? Т.е. понемногу мы приходим к одной из фишек CAN шины, что идентификатор обозначает не физ узел, а объект данных.
UPD. мы можем и не дробить адрес узла на RoomAddr и PhysAddr. А просто оставить RoomAddr полноценный 8 битный. Т.е. в полезных данных CAN обмена в идентификаторе полностью будет отсутствовать информация с какого физического узла исходит CAN сообщение (только RoomAddr). PhysAddr будет фигурировать в составе ID только в служебных CAN сообщениях (heartbeat, nodeguard, reboot и т.д.), например на месте разряда dev_type, т.к. служебные CAN сообщения призваны работать именно с физическим железом.
Вот и уровни абстракции появляются. RoomAddr - это некий виртуальный узел помещения, состоящий из одного или нескольких физических узлов.
Честно говоря я не думаю что мы умнее разработчиков canopen, devicenet и пр. разработчиков протоколов Овер Кан. Они адреса источника и получателя в id вставили. Правда в device net 7 бит вроде и 127 адресов.
Думаю от 256 адресов отправитель и 256 получатель уходить не стоит. Остальные биты можно объединить это 13 бит итого 2 в 13 это 8192 адреса/параметра/устройства. Либо оставить как есть. Делать только получателя по ID не понимая кто запросил, зачем и имеет ли он на это право, потерять маршрутизацию в сопрягаемые сети думаю не стоит.
Чувствуешь разницу? Т.е. понемногу мы приходим к одной из фишек CAN шины, что идентификатор обозначает не физ узел, а объект данных.
Делать только получателя по ID не понимая кто запросил, зачем и имеет ли он на это право, потерять маршрутизацию в сопрягаемые сети думаю не стоит.
Посмотрите на CAN-шину не как на интерфейс для связи различных контроллеров, а именно как на ШИНУ данных. Вы же когда вызываете функцию по работе, например, i2c, вы же не передаете ей в качестве аргумента имя функции, ее вызывающую ? И уж тем более не получаете в ответ имя функции, которая отработала вызов с целью проверки, а имела ли она право обрабатывать то, что я ей послал... Если смотреть на CAN как на один большой (просто распределенный) контроллер - жить станет проще. Да, нужна некая диагностика узлов на предмет их онлайности и правильности работы, но в остальном это один МК в созможностью добавления ножек в любой момент.
Посмотрите на CAN-шину не как на интерфейс для связи различных контроллеров, а именно как на ШИНУ данных. Вы же когда вызываете функцию по работе, например, i2c, вы же не передаете ей в качестве аргумента имя функции, ее вызывающую ? И уж тем более не получаете в ответ имя функции, которая отработала вызов с целью проверки, а имела ли она право обрабатывать то, что я ей послал... Если смотреть на CAN как на один большой (просто распределенный) контроллер - жить станет проще. Да, нужна некая диагностика узлов на предмет их онлайности и правильности работы, но в остальном это один МК в созможностью добавления ножек в любой момент.
Если был один CAN, готов был бы наверное согласиться, но у меня CAN это хребет вокруг которого крутится сеть Modbus (контроллер температуры, жалюзи), UART ... которые хочу однозначно адресовать с центрального шлюза и сервера Majordomo.
Так вот эта сеть сейчас для меня прозрачна. Я отправляя команду формата описанного выше у Макса (привелся к его формату) попадаю на нужный мне адрес не зависимо от платформы и протокола. Причем каждый узел может иметь и по 2-3 интерфейса CAN со своей адресацией, НО диапазон адресов от 1 до 255, и узел получив пакет смотрит к нему или нет, если нет то не к сети ли подключенной к нему на другом его интерфейсе. Причем за счет абстракции роутеру плевать что там CAN или Modbus или TCP/IP. Приводись к любой физике или каналу, важно умей отправить то что тебе кинули в нужную шину ну и принять из нее.
Я все протоколы привожу к виртуальному вызову
Так CAN реализован
01
bool
AHB_CAN::ahbSend_V(uint8_t type, uint8_t dev_type, uint8_t target, uint8_t msg_type, uint8_t source, uint8_t len,
byte
data[8]) {
02
uint32_t addr = ahbCanAddrAssemble(type, dev_type, target, msg_type, source);
03
if
(addr == 0){
04
return
false
;
05
}
06
07
lastErr = _interface.sendMsgBuf(addr, 1, len, data);
08
if
(lastErr != CAN_OK) {
09
return
false
;
10
}
11
12
return
true
;
13
}
Так пока Modbus (руки не дошли транслятор сделать)
01
bool
AHB_MODBUS_RTU::ahbSend_V(uint8_t type, uint8_t cmd, uint8_t target, uint8_t port, uint8_t source, uint8_t len,
byte
data[8]){
02
//Serial.println("Send Modbus_RTU");
03
// Разбираем ввод и формируем телеграмму
04
//type
05
//cmd
06
//port
07
//data[8]
08
//Из них тянем данные
09
//source куда вернуть ответ при приеме
10
telegram[0].u8id = target;
//Slaves; // slave address
11
telegram[0].u8fct = 3;
// function code (this one is registers read)
12
telegram[0].u16RegAdd = 0;
// start address in slave
13
telegram[0].u16CoilsNo = 11;
// number of elements (coils or registers) to read
14
telegram[0].au16reg = au16data;
// pointer to a memory array in the Arduino
15
if
(!_interface.query(telegram[0])){
//если 0 т.е нормальная отправка
16
//1. Установить флаг что была отправка и можно начать поллинг
17
send_modbus_rtu=
true
;
18
modbus_rtu_request_sender=source;
19
}
20
21
}
Так UART
01
bool
AHB_UART::ahbSend_V(uint8_t type, uint8_t cmd, uint8_t target, uint8_t port, uint8_t source, uint8_t len,
byte
data[8]){
02
03
byte
tlen = 0;
04
_interface->write(0x01);
05
_interface->print(type,HEX);
06
_interface->write(0x1F);
07
_interface->print(target,HEX);
08
_interface->write(0x1F);
09
_interface->print(source,HEX);
10
_interface->write(0x1F);
11
if
(port > 0) {
12
_interface->print(port,HEX);
13
}
else
{
14
//Arduino print internally casts to double :(
15
_interface->print(F(
"FF"
));
16
}
17
_interface->write(0x1F);
18
_interface->print(len,HEX);
19
20
_interface->write(0x02);
21
if
(len > 0) {
22
for
(tlen = 0; tlen < len; tlen++) {
23
_interface->print(data[tlen], HEX);
24
_interface->write(0x1F);
25
}
26
}
27
_interface->write(0x04);
28
_interface->println();
29
return
true
;
30
}
Это интеграция с Majordomo
01
bool
AHB_GW_CAN_TO_OKBIT::ahbSend_V(uint8_t type, uint8_t cmd, uint8_t target, uint8_t port, uint8_t source, uint8_t len,
byte
data[8]){
02
//uint16_t type_gw;
03
//type_gw = 8000+source;
04
//this->build(2, 4, 8004, 13, 0, 0, 5, 6, 1, 4);
05
this
->build(target,source+target*100, 8000+source, cmd, 0, 0, 1, 1, target, source);
06
_interface.beginPacket(_interface.remoteIP(), _interface.remotePort());
07
_interface.write(replyGate);
08
_interface.endPacket();
09
10
//uint32_t rxId = 0x80000000;
11
//rxId = (type & 0xFFFFFFFF)<<28 | (cmd & 0xFFFFFFFF)<<20 | (target & 0xFFFFFFFF)<<12 | (port & 0xFFFFFFFF)<<8 | source ;
12
//sprintf(buffer, "ID: %.8lX Data: %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X\n\r",
13
// rxId, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
14
//Serial.print("Okbit ");Serial.print(dest_gw_can_to_okbit);Serial.print(":");Serial.println(remPort_okbit);
15
16
}
Это отправка по UDP
01
bool
AHB_GW_CAN_TO_UDP::ahbSend_V(uint8_t type, uint8_t cmd, uint8_t target, uint8_t port, uint8_t source, uint8_t len,
byte
data[8]){
02
uint32_t rxId = 0x80000000;
03
rxId = (type & 0xFFFFFFFF)<<28 | (cmd & 0xFFFFFFFF)<<20 | (target & 0xFFFFFFFF)<<12 | (port & 0xFFFFFFFF)<<8 | source ;
04
sprintf(buffer,
"ID: %.8lX Data: %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X\n\r"
,
05
rxId, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
06
//Serial.print("UDP ");Serial.print(dest_gw_can_to_udp);Serial.print(":");Serial.println(remPort);
07
_interface.beginPacket(dest_gw_can_to_udp, remPort);
08
_interface.write(buffer);
//
09
_interface.endPacket();
10
11
}
А вот отправка из центрального класса
01
byte
AHB::ahbSend(uint8_t type, uint8_t cmd, uint8_t target, uint8_t port, uint8_t source,
byte
len,
byte
data[8]) {
//7 Моя логика
02
bool
state,broadcast_route=
false
;
03
byte
errors=0,i;
04
signed
char
busId_route;
05
if
(source == 0) source = _nodeId;
06
busId_route=-1;
07
08
//Определяем в какую шину кидать пакет
09
for
(signed
char
busId=0; busId<AHB_BUSNUM; busId++) {
10
//Проверяем что шина подключена
11
//Serial.println("!"); //_busAddr[busId]->address_network_get(0)
12
if
(_busAddr[busId] != 0x00){
13
14
//Если target broadcast и broadcast есть в этой сети то кидаем туда
15
if
(target==_busAddr[busId]->address_network_get(0)){
16
broadcast_route=
true
;
17
#ifdef AHB_DEBUG
18
Serial
.print(F(
"TX Route target - "
));
Serial
.print(target);
Serial
.print(F(
" to Bus - "
));
19
Serial
.print(busId);
Serial
.print(F(
" Form source - "
));
Serial
.println(source);
20
#endif //AHB_DEBUG
21
//Отправка в шину busId
22
state = _busAddr[busId]->ahbSend_V(type, cmd, target, port, source, len, data);
23
//Отправка в очередь сообщений с busId
24
//////state = ahbAddSendMsgQueue(type, cmd, target, port, source, len, data, busId);
25
if
(!state) errors++;
26
}
27
28
//Пробегаем по таблице маршрутов сети
29
for
(
int
i=0; i<_busAddr[busId]->net_size_get();i++){
30
//Если получатель в сети
31
if
(target==_busAddr[busId]->address_network_get(i)&&_busAddr[busId]->address_network_get(i)!=0){
32
#ifdef AHB_DEBUG
33
Serial
.print(F(
"Target "
));
Serial
.print(target);
Serial
.print(F(
" locate to bus "
));
Serial
.println(busId);
34
#endif //AHB_DEBUG
35
busId_route=busId;
36
}
37
}
38
}
39
}
40
41
if
(busId_route!=-1){
42
if
(_busAddr[busId_route] != 0x00){
43
#ifdef AHB_DEBUG
44
Serial
.print(F(
"TX Route target - "
));
Serial
.print(target);
Serial
.print(F(
" to Bus - "
));
45
Serial
.print(busId_route);
Serial
.print(F(
" Form source - "
));
Serial
.println(source);
46
#endif //AHB_DEBUG
47
//Отправка в шину busId_route
48
state = _busAddr[busId_route]->ahbSend_V(type, cmd, target, port, source, len, data);
49
50
//Отправка в очередь сообщений с busId_route
51
//////state = ahbAddSendMsgQueue(type, cmd, target, port, source, len, data, busId_route);
52
if
(!state) errors++;
53
}
54
}
55
else
{
56
if
(!broadcast_route) {
57
//#ifdef AHB_DEBUG
58
Serial
.print(F(
"TX No route for target - "
));
Serial
.print(target);
59
Serial
.print(F(
" NOT Send !!!!"
));
Serial
.print(F(
" Form source - "
));
Serial
.println(source);
60
//#endif //AHB_DEBUG
61
}
62
}
63
return
errors;
64
}
При сборке скетча я прописываю физ интерфейсы и указываю какие адреса за этим интерфейсом и свой адрес.
В итоге я могу даже не знать в какой шине адрес.
дак я и предлагаю 256 оставить. Почему не понимая, кто запросил? RoomAddr отправителя то будет присутствовать в ID. Т.е. адрес и отправителя и получателя так и остаётся в ID. Только вот какая тебе разница какой физический узел измерил температуру в комнате, тебе должно быть важно что это за температура - пола, радиатора или воздуха (объект) и в какой именно комнате (локация).
Я не понимаю, как у тебя происходит маршрутизация между разными сетями, да и вообще плохо в этом разбираюсь, но можно пойти на компромисс и просто зарезервировать часть адресов под "виртуальные узлы". Т.е. если нам нужно более одного узла в комнате - создаём в диапазоне виртуальных соответствующий виртуальный (как бы объединяя несколько железных узлов в один виртуальный. При этом настраиваем в фильтре CAN приёмника у всех этих железных узлов пропускать адрес этого виртуального узла, чтобы они все сообщения принимали как один узел). Это очень похоже на рейд массив "страйп" в компе. Часть данных может быть на одном физическом диске, другая часть - на другом. Но винде пофиг - для неё оба физ.диска это один раздел. Винда работает с разделом. Так же и у нас, железный адрес как бы не особо нужен, только для диагностики. Сверху не важно какой физический узел замерил температуру, главное откуда эта температура (раздел диска). А если тебе нужен прям стопудовый узел с железным адресом, к которому другие интерфейсы подключены, заносишь его в диапазон "железных" узлов и у него RoomAddr будет совпадать с PhysAddr.
По тому, в каком диапазоне адресов узел находится, отличать будем - виртуальный узел или железный.
Про какие-то уровни абстракции вроде говорили, чтобы наш протокол был универсальный, не зависящий от железа. А тебе зачем-то "пробросы" других интерфейсов через CAN нужно стало делать с какими то определёнными адресами. Что там, жалюзи у тебя по модбасу? Почему нельзя было сконфигурировать на узле девайс жалюзи в массиве девайсов? В наш протокол сверху мы говорим (по адресу: комната->девайс жалюзи->№окна ) в рамках нашего протокола "открыть", "закрыть" шторы, там не знаю, состояние положения штор можем запросить - всё в рамках нашего протокола. И, раз мы договорились абстракцию взаимодействия с девайсами сделать, то жалюзи на узле будут управляться через функцию прокладку, которая и будет переводить формат команд и параметров нашего протокола в модбас. вот и всё! Если надо с мажордомо управлять, а, насколько я понял, с ним проще взаимодействовать по езернету, то так же делаем через узел-шлюз. Мажордомо <->Езернет <->узел-шлюз<->нашCANпротокол<->функция прокладка<->модбас<->жалюзи.
А ты собрался всё и вся чтоли в протокол добавить? А если что-нибудь забудешь добавить или устройство тебе понадобится подключить с какой нибудь экзотической шиной (например Dali , KNX, DMX512), всё, весь протокол переписывать? Какая же это универсальность?
Как там в CANopen? словарь объектов? Объекты это же наши сенсоры (массив parameter) и ИУ (массив девайсов). Дак всё-же может и будем с объектами взаимодействовать?
НЕ надо сверху взаимодействовать с физическими узлами! Надо взаимодействовать с объектами (сенсоры, ИУ)! НЕ надо напрямую адресовать сверху до узла! НЕ надо взаимодействовать сверху с узлом через (сквозь) наш протокол! Надо взаимодействовать сверху с нашим протоколом! А наш протокол уже будет взаимодействовать с объектом. Сверху должно быть похеру что там на конце модбас или зигбии. Сверху все лишь просто нужно обращаться как мы и задумывали: локация->объект(тип объекта)->конкретный экземпляр. Если хочется наш протокол подготовить для подключения каких-то стандартных вещей, то имхо, нужно просто написать различные функции-прокладки для этих стандартных вещей (Датчики даллас, модбасы и т.д. и т.п.). А ты, получается, не шлюзуешь данные других протоколов, а пробрасываешь их через наш, получается ломая некоторые изначальные принципы нашей адресации. Ты все адреса к одному байту привел. Нафига мы тогда добавили тип параметра (тип девайса), да ещё и номера датчиков (твоя же идея кстати)? Ты щас их не используешь, получается, адресуя свои жалюзи только в общем первом (одном) байте. Конечно тебе 255 не хватает. А если у тебя жалюзи такие в нескольких комнатах? Адресовать будешь: Жалюзи_комната1, Жалюзи_комната2. ? Хреновасто. Надо чётко разделять локацию и объект, а у тебя всё в одном.
Если узлы находятся в одной комнате, то разряд адреса локация у них должен быть один и тот же.
Короче для меня картина "правильного" протокола понемногу проясняется. Знаю теперь как двигаться дальше.
Предложи структуру ID c описанием. Что копья ломать. Подробно про роутинг к выходным отвечу.
Думал ты хочешь оставить всего 16 адресов в сети. Ты говорил выше про нибл. И хочешь убрать адрес отправителя.
Если остаётся байт получателя и байт отправителя то все остальное на твое усмотрение.
По поводу modbus, у меня ещё мультисплит а это уже сложное устройство.Его датчиком или реле не представишь. И.е если у устройства на модбасе есть свои мозги я хочу с ним работать по адресу.
И, раз мы договорились абстракцию взаимодействия с девайсами сделать, то жалюзи на узле будут управляться через функцию прокладку, которая и будет переводить формат команд и параметров нашего протокола в модбас. вот и всё! Если надо с мажордомо управлять, а, насколько я понял, с ним проще взаимодействовать по езернету, то так же делаем через узел-шлюз. Мажордомо <->Езернет <->узел-шлюз<->нашCANпротокол<->функция прокладка<->модбас<->жалюзи.
А ты собрался всё и вся чтоли в протокол добавить? А если что-нибудь забудешь добавить или устройство тебе понадобится подключить с какой нибудь экзотической шиной (например Dali , KNX, DMX512), всё, весь протокол переписывать? Какая же это универсальность?
Похоже мы говорим об одном и том же но на разных языках. Посмотри выше мой код. Я все это уже реализовал.
Но, ты рассчитываешь на одно устройство на одном RS485 интерфейсе а я на N устройств.
Мало того если нужен новый протокол я его просто реализую отдельным интерфейсом.
Смотри внимательно
Так CAN реализован
расечатать?
01
bool
AHB_CAN::ahbSend_V(uint8_t type, uint8_t dev_type, uint8_t target, uint8_t msg_type, uint8_t source, uint8_t len,
byte
data[8]) {
Так пока Modbus (руки не дошли транслятор сделать)
расечатать?
01
bool
AHB_MODBUS_RTU::ahbSend_V(uint8_t type, uint8_t cmd, uint8_t target, uint8_t port, uint8_t source, uint8_t len,
byte
data[8]){
Так UART
01
bool
AHB_UART::ahbSend_V(uint8_t type, uint8_t cmd, uint8_t target, uint8_t port, uint8_t source, uint8_t len,
byte
data[8]){
Это интеграция с Majordomo
01
bool
AHB_GW_CAN_TO_OKBIT::ahbSend_V(uint8_t type, uint8_t cmd, uint8_t target, uint8_t port, uint8_t source, uint8_t len,
byte
data[8]){
Это отправка по UDP
01
bool
AHB_GW_CAN_TO_UDP::ahbSend_V(uint8_t type, uint8_t cmd, uint8_t target, uint8_t port, uint8_t source, uint8_t len,
byte
data[8]){
А теперь вуаля это вызов этих функций которые вытаскивает маршрутизатор по ID шины
_busAddr[busId_route]->ahbSend_V(type, cmd, target, port, source, len, data);
Я сначала так хотел (попилить адрес на нибблы). Но сказали 15 комнат мало. Тогда я решил 255 оставить, но имел ввиду что физический адрес контроллера в составе ID (для полезных CAN фреймов) будет отсутствовать. В служебных фреймах физ.адрес поместиться на место разряда dev-type.
все таки сплит система это девайс - имхо. Дак может быть в твою адресацию (маршрутизацию) можно добавить байт и привести к виду: Локация -> девайс ? Тогда тебе адресов будет норм хватать и логичнее всё будет.
Интересно про сложность работы с мультисплитом. Какое-то сверху приложение уже готовое чтоли есть, или модуль в мажордомо для данной сплит системы , раз нужно данные через CAN неизменно в модбас прокидывать? Почему его нельзя представить сенсором и девайсом? просто хочу понять случаи , где может затаиться засада с моим подходом.
.
Повторюсь, если оставляешь под адресацию устройств 256 отправителю и 256 получателю, то оставшиеся 13 бит пользуй как считаешь нужным. Я от 256 железных устройств в мультипротокольной сети не уйду.
Мало того к каждому узлу с CAN может быть подключено несколько сегментов CAN и других интерфейсов.
А вот датчики уже ниже.
Виртуалить на уровне сети а не на уровне PC считаю утопией. Про поиск неисправности думал? Отказал датчик № 3 в комнате с 10 контроллерами, подключенными к неизвестно какому узлу. А может контроллер отказал и ли провод отпаялся и или код сбойнул или ...
Не. Я слишком хорошо знаю что такое РВР и поиск неисправности. Как диагностировать железо? А ПО? А физ. линии?
Просто прикинь что у тебя в машине есть датчики под капотом 1-10, 11-20 в салоне и 21-30 в багажнике. Подключенные к 3, 6 и 2 контроллерам соответственно. Причем датчик 1,15, 25 отвечают за топливную систему. И вот прикинь у тебя сбой и машина не заводится. А схемы кроме логической нет.
Но, ты рассчитываешь на одно устройство на одном RS485 интерфейсе а я на N устройств.
Почему одно? Несколько вот так подключать
Не. Я слишком хорошо знаю что такое РВР и поиск неисправности. Как диагностировать железо? А ПО? А физ. линии?
Диагностировать точно также как ты это делаешь. Только по физ. адресам. Куда подключен датчик? - смотреть это можно в конфигурации. Диагностическую систему нужно развивать. Можно тип команд специальный придумать, чтоб конфигу в кан МК выбрасывали по команде.
Кроме того я могу легко перекинуть модбас и би местами на разных контроллерах. Просто поднять интерфейс , прописать маршруты и вперед. А вот если будет уникальная логика на узле то все сливай воду. Перелей прошивку перепрограммируй.
Я хочу иметь одинаковые контроллеры, с разъемом переходником (типа шилды ардуино монтажные или под винт) к которым подключаются нужные ИУ и сенсоры и интерфейсные контроллеры и единый софт для НОД. Отличие настройки, адрес и подключенное оборудование. Все как в начале темы. Универсальность и заменяемость полная. Зашел с PC (лучше с WEB) через шлюз по CAN на контроллер, выбрал из списка датчики, привязал их к пинам, указал сценеарий там или еще что, указал соседей куда что потправлять.
Включил и работает. А если конфиг еще на сервере держать то сбойный контроллер просто из ЗИПа поменял, подключил, по чему то типа TFTP (логически естественно) загрузил конфиг и вуаля.
Маршрутизатор работает как просто как топор, пришел пакет узлу смотрим если это мне в обработку или если узлу подключенному ко мне по другой шине, то ретрансляция, если не так то игнор.
Не. Я слишком хорошо знаю что такое РВР и поиск неисправности. Как диагностировать железо? А ПО? А физ. линии?
Диагностировать точно также как ты это делаешь. Только по физ. адресам. Куда подключен датчик? - смотреть в можно в конфигурации. Диагностическую систему нужно развивать. Можно тип команд специальный придумать, чтоб конфигу в кан МК выбрасывали по команде.
Программно диагностировать неисправную систему? Не понимая глючтит софт который и выдает ошибки или физика или ИУ. Это адский труд.
Поверь на слово не усложняй. Виртуальный контроллер лучше делать на мощной машине сверху.
Но, ты рассчитываешь на одно устройство на одном RS485 интерфейсе а я на N устройств.
Почему одно? Несколько вот так подключать
pin 14, 15, 9 это адреса в модбасе или физ пины?
"пин ардуино" столбец тут не используется. Он остался от начальной задумки, где девайсы рулились только по GPIO.
Виртуалить датчики и ИУ в пределах контроллера стоит. Если хочешь виртуалить в пределах комнат и/или систем для сценариев или виртуальных систем то это отдельный слой. Т.е скрыть физ пины от протокола наверное стоит. А вот датчики и устройства нет
"пин ардуино" столбец тут не используется. Он остался от начальной задумки, где девайсы рулились только по GPIO.
И все же как обращаться к Node 10, 11, C в моей схеме. Или например как обеспечить обмен Node 11 c 22, шлюзом и PC.
а ты как собрался свою диагностировать? В моей все отличие, что комнатах где более одного узла, полезные CAN сообщения не имеют в ID физ. адреса узла. Но это диагностится по служебным CAN фреймам, сердцебиение узла и т.д.
Дак говорю надо обращаться не к нодам, а к объектам. Какие объекты у тебя на этих нодах присутствуют? Свет на кухне, например. Kitchen-> lamp_ceil_onoff_d -> #1 . А что есть обмен ?
а ты как собрался свою диагностировать? В моей все отличие, что комнатах где более одного узла, полезные CAN сообщения не имеют в ID физ. адреса узла. Но это диагностится по служебным CAN фреймам, сердцебиение узла и т.д.
На шлюзе или PC контролирую параметры (вернее их выход за диапазон и/или их нестандартное например резкое изменение) и четко понимаю, что на контроллере 7, ага его имя node_7_Hallway_main, ага это главный контроллер в щите коридора, неправильно выдается состояние датчика или съем информации со счетчика.
Самое простое замена из ЗИП на другой.
Не помогло. Смотрю что с подключенным устройством. Тоже замена из ЗИП.
Не помогло. Звоним физику.
Все лаконично и понятно. По схеме Э4 отрабатываем (Схема электрическая соединений Э4).
Дак говорю надо обращаться не к нодам, а к объектам. Какие объекты у тебя на этих нодах присутствуют? Свет на кухне, например. Kitchen-> lamp_ceil_onoff_d -> #1 . А что есть обмен ?
Я готов на объекты, даже считаю их обязательными, но без отказа от прямой адресации к датчику/устройству.
Мало того считаю что и вирт объекты нужны но поверх этих слоев.
Например климат система это комбинация привода радиатора, кондея, нагревателя вентсистемы. Контроль температуры с разных датчиков. Сценарии и пр.
Давай все же отработаем сначала структуру ID и уровни абстракции (уровни виртуализации). Я всю следующую неделю дома. Вот и поработаем удаленно ;-)
Дак говорю надо обращаться не к нодам, а к объектам. Какие объекты у тебя на этих нодах присутствуют? Свет на кухне, например. Kitchen-> lamp_ceil_onoff_d -> #1 . А что есть обмен ?
Ну у объекта есть свойства, методы и события. У меня пока нет объектов я только роутер добил а теперь наоборот нижний уровень добиваю. А вот потом займусь прослойкой. Только помоделировать надо.
Обмен это как раз для виртуальных устройств. Обмен данными 11 например сенсор CO2 а 22 это контроллер вентиляции. (это условно, могут быть мульти функц. устройства с кучей датчиков и иу, которые для тебя черный ящик только с протоколом управления и датчиками и иу)
Я хочу и на сервере их видеть и ими управлять в ручном режиме но и пусть они сами трудятся в автоматическом режиме.
ок, у нас системы разного уровня. У тебя прям ЦУП, а у меня так, лампочками по шине помигать. Поэтому и подходы разные , трудно прийти к общему знаменателю.