Можешь выложить картинку в полном качестве? А то плохо видно. На я диск например. В общем с длинными ID я чето намучился, не получалось у меня. Не только канхакер их не видел, но и не отправлялись они вовсе. Использовал видимо корявую библиотеку. Она называлась также, как ты давал по ссылке, поэтому я твою не стал скачивать. А моя видать корявая с длинными ID не работает. Уже после того, как с 11бит все сделал у себя, твою либу попробовал. Вроде норм 29бит отправляет. Может переделаю еще. А то действительно 16 адресов может и не хватить. Вдруг меня растащщит)
P.S. Или ещё может ничего не получалось, т.к. один CAN модуль у меня был неисправный. Он отправлял СAN феймы, но не принимал.
Я тоже с якобы неисправным модулем бился. Все дело только в библиотеках. Перепробовал все с github. Выбрал нужную. А расширенный заголовок позволяет сразу из заголовка вынуть от кого, кому, что за событите, что за датчик или исполнительное.
Вот примерно мой can_struct.h (он общий для всех прошивок. Контролллеров то много в сети). И да удобнее с десятичными работать нежели с байтом. Тут на вкус и цвет, просто обработка строки быстрее пишется на мой взгляд. и на этапе прототипа мне так удобнее.
Жесть какой широкий у тебя размах). У меня два вопроса. Зачем применяешь uint32_t. Неужели uint16_t не хватит? И второе , смотри самый первый разряд в ID тот который ХХ, имеет не весь диапазон адресов ( не 256) , т.к первый ниббл Х может принимать значения только от 0 до 7. Потому что ID 29 бит, а не 32. Т.е на этот ниббл Х отводится 3 бита вместо четырех.
По поводу размаха - если присмотреться делается типовое изделие практически серийное, все блоки одинаковые, я под них заложил в каждом помещении по 5 подрозетников под потолком, закрытых заглушками. В итоге это мини ардуино 2560 + CAN контроллер и датчики. Все кабели как я уже сказал затянул. Потолками натяжными закрыл.
uint32_t первое что под руку подвернулось ;-) (Я не проф программер, самоучка можно сказать). Памяти пока хватает. Потом переделаю все на Byte. Так проще писать адреса без пересчета, в десятичной системе. Это была проба пера, в смысле проверить CAN сеть, погонять обмен датчиков, включение выключение светодиодов на обратных концах и пр. Все заработало. Технология выбрана. Кабели запроектированы, заложены, штукатуркой замазаны, потолками закрыты. Я как конструктор ОКР иду от эскизного проекта к опытному образцу, через отработку технологий и макетирование, почти по 203 госту ;-)
По поводу 29 а не 32 я поздно заметил, а сейчас смысла нет пока менять, адресов хватает. Ну и см. выше, это прототип. Важно определиться с концепцией. Мало того твои идеи оч. интересны.
Кстати начал тут глубже копать CAN так вот эти 3 бита забирает т.н. удаленный кадр, в котором нет поля данных но он является запросчиком. (Вернее даже не удаленный кадр а типизация видов сообщений)
"Удаленные кадры можно использовать для реализации управления трафиком шины типа «запрос–ответ». На практике, однако, удаленный кадр используется мало. Это не так важно, поскольку стандарт CAN не предписывает действовать именно так, как здесь обозначено. Большинство контроллеров CAN можно запрограммировать так, что они будут автоматически отвечать на удаленный кадр, или же вместо этого извещать локальный процессор."
Умный дом у меня на самый конец уходит. Сейчас пока автоматика на реле. Бистабильные фото и пр. Т.е базовые вещи типо свет, вода и пр. работают без контроллеров. Все системы при отключении УД продолжают нормально работать.
Ну и мы же реально умный дом делаем а не ПДУ для лампочек, для этого такой огород ведь не городят ;-)
да, прототип хорош. На счет работы без контроллеров, ну не знаю. Вот у меня свет на втором этаже уже два года только в схеме с МК работает - выключатели света слаботочные на 5В, подают только сигнал на МК. Проблем не было никаких, даже в сильную грозу. Главное применять опторазвязки, провода в экране. А если коряво подходить к вопросу, дак и без МК что нибудь сгореть, сломаться может.
По поводу ID поменяй местами разряды и делов то: Z.XX.YY.A.CC
где Z - тип сообщения, их у тебя 6, ещё 1 в запасе остаётся.
Так проще писать адреса без пересчета, в десятичной системе.
дак никто не мешает писать в десятичной системе на типе byte . Контроллеру то пофиг, ему всё одно - нули и единицы. просто пишешь число и всё - будет десятичная, если добавить перед записью числа 0x - этоHEX. Если добавить B - бинарная запись (в битах).
Использую бистабтльные реле РИО-1М и кнопочные выключатели. В паралель к кнопкам ставлю ТТ реле которым управлю с ардуино. Т.о. даже при отсутствии контроллеров свет управлется. И т.д. В дальнейшем при сбое или поломке контроллера я не сижу при свечах. Опторазвязки я естественно буду использовать. Нарпимер АОТ166 для проверки наличия напржения на лампах освещения. Строю 2х уровневую, даже 3х уровневую систему. 1 уровень пром. реле. Второй уровень автоматика на МК, 3 уровень сцены на Сервере.
И дело даже не в надежности. Если бы я поше по пути контроллера то сидел бы без света сейчас. А так реле потавил и все работает. Сверху поставлю МК и буду им щелкать реле в паралель с кнопками.
Использую бистабтльные реле РИО-1М и кнопочные выключатели. В паралель к кнопкам ставлю ТТ реле которым управлю с ардуино. Т.о. даже при отсутствии контроллеров свет управлется. И т.д. В дальнейшем при сбое или поломке контроллера я не сижу при свечах. Опторазвязки я естественно буду использовать. Нарпимер АОТ166 для проверки наличия напржения на лампах освещения. Строю 2х уровневую, даже 3х уровневую систему. 1 уровень пром. реле. Второй уровень автоматика на МК, 3 уровень сцены на Сервере.
И дело даже не в надежности. Если бы я поше по пути контроллера то сидел бы без света сейчас. А так реле потавил и все работает. Сверху поставлю МК и буду им щелкать реле в паралель с кнопками.
ну в общем да, согласен, так наверное лучше. Понятно, что когда строишь систему УД делаешь много ошибок. Я если бы сейчас начинал, всё вообще бы не так сделал. А щас переделывать ужё лень - слишком много делов
Я вроде с этим тыкался, но для отладки быстрее выводиь все что пришло в сериал, а там опять преобразования.
вот это не понял немного. Какие преобразования. Для отладки я использую CAN сниффер. Мне почему удобнее работать с HEX, так как все анализаторы CAN шины выводят инфу в HEX и визуально уже привыкаешь все адреса и байты видеть в HEX. А без анализаторы шины при построении тайой системы я вообще не знаю как можно обойтись. Я почему в своей 11битной схеме ID и отказался от 5 битных адресов, потому как их визуально мониторить вообще проблема. Хотя так было бы 32 адреса, а не 16.
bytesndStat = CAN0.sendMsgBuf(txId*1000000+node_to*10000+msg_type*1000+dev_num*100+dev_type, 1, 8, data); // send data: ID = 0x100, Standard CAN Frame, Data length = 8 bytes, 'data' = array of data bytes to send
в качестве параметров этой функции ты передаешь переменные типа флоат (а,b,c,d,e,f,h). А потом создаёшь массив уже типа byte
и запихиваешь туда эти float, зачем так делать? Если действительно нужно передать float (он занимает в памяти МК 4 байта), то тебе придётся использовать для этого 4 байта поля данных CAN фрейма на каждый float , т.е. a,b,c,d. предварительно например , разбив float на 4 отдельные байта.
а если не надо float, то и нафиг в качестве параметров функции его использовать, если всё равно ты их в массиве byte data[8] к типу byte переводишь. Бери везде тип byte и иcпользуй.
Нельзя так к памяти МК относится, это я уже давно понял.
Я вроде с этим тыкался, но для отладки быстрее выводиь все что пришло в сериал, а там опять преобразования.
вот это не понял немного. Какие преобразования. Для отладки я использую CAN сниффер. Мне почему удобнее работать с HEX, так как все анализаторы CAN шины выводят инфу в HEX и визуально уже привыкаешь все адреса и байты видеть в HEX. А без анализаторы шины при построении тайой системы я вообще не знаю как можно обойтись. Я почему в своей 11битной схеме ID и отказался от 5 битных адресов, потому как их визуально мониторить вообще проблема. Хотя так было бы 32 адреса, а не 16.
Анализатора нет, подумаю на тему купить. Использовал прямой вывод всего что есть в сериал.
самый первый разряд в ID тот который ХХ, имеет не весь диапазон адресов ( не 256) , т.к первый ниббл Х может принимать значения только от 0 до 7. Потому что ID 29 бит, а не 32. Т.е на этот ниббл Х отводится 3 бита вместо четырех.
Сейчас подсчитал - что-то я напутал. Это в 11-битном ID на первый разряд 3 бита отводится (от 0 до 7), а в 29-битном на первый разряд отводится 1 бит, т.е. значения может принимать только 0 или 1. Поэтому нельзя туда тип сообщения z вешать, придётся тебе жертвовать нибблом a device address. и вместо него этот тип сообщения zставить.
И я , наконец, разобрался почему ничего не получалось у меня с 29-битными ID. При опробовании этих 29бит наложилось несколько косяков - это нерабочий CAN модуль и плюсом к этому, я в обоих библиотеках (пробовал и твою и мою) просто неправильно отправлял расширенные ID. Поэтому толком не приходили эти 29битные ID и не отправлялись. Теперь разобрался с обоими библиотеками, как отправлять расширенные ID.
В твоей библиотеке нужно в единичку ставить этот бит - выделен жирным (если он будет 0 то это 11бит) при отправке:
Сейчас подсчитал - что-то я напутал. Это в 11-битном ID на первый разряд 3 бита отводится (от 0 до 7), а в 29-битном на первый разряд отводится 1 бит, т.е. значения может принимать только 0 или 1. Поэтому нельзя туда тип сообщения z вешать, придётся тебе жертвовать нибблом a device address. и вместо него этот тип сообщения zставить.
По моему с твоей помощью вообще ничем жертвовать не придется. 29 бит это всего на 3 бита меньше чем IP адрес, и на всеь интернет числа хостов хватает.
Смотри если работать по битам то получаем при той же концепции следующее:
Это десятичная система, не вроде 16 ричная ;-)
//ID structure xx.yy.z.a.cc
// xx yy z a cc
// my address remote address type message device address device type
Это двоичная
//ID structure
// 0000 0000 0000 0000 0000 0000 0000 0000 0000 0
// 0-255 0-255 0-255 0-255 0-31
// my address remote address type message device address device type
Можно даже подумать о изменении. C адресами ладно пусть в сети до 256 устройств, типов сообщений 32 а не 256 (и так перебор, можно 16, ну да ладно), адресов устройств 64 или 128 (больше на ардуине GPIO не бывает пока, а адрес устройства это номер pin на хосте т.е конкретном контроллере у которого свой адрес, типов устройств можно наоборот увеличить 512 или 1024
mcp2515.sendMessage(&canMsg2); // это отправка стандартного фрейма 11 бит
2
mcp2515.sendMessage(MCP2515::TXB1,&canMsg1); // а вот так нужно отправлять фреймы с 29-битным ID
Кинь сылку на свою библиотеку. Может на одной либе начать работать, мне в принципе пока все равно. Я на этапе концепта.
Да и вообще может есть смысл начать плавно объединять усилия. Я сейчас в течении месяца ремонт завершу и займусь активнее разработкой. Мы вроде практически единстренные на форуме из любителей (имею ввиду не зарабатывающих на УД) в CAN двинули, всех 485 устраивает.
Что я хочу получить на выходе ты увидел на схеме.
Так же хочу сделать аппаратную систему зоновой трансляции. Много аппаратных источников аудио (FM, USB MP3/SD MP3/AUX на УД/Bluetooth/AUX IP радио етс. Делать все буду на аудиопроцах или готовых модулях упр. по i2c (PT2314 TDA7419 или TEA6420)
Я из щита в каждое помещение завел аудиокабель и поставил динамик.
//type message my address remote address device address device type
как видим на type message что то мало значений приходится))
предлагаю убрать device address (ну засунешь его в тело сообщения, это ничего не меняет)
и делить разряды кратно 4 битам, т.е. нибблам. Поверь, это важно при отладке визуально в кан анализаторе. К тому же вытягивать числа из ID не кратные 4 битам вообще жопа (см. на предыдущей странице как я делал 5-битные адреса). В итоге предлагаю сделать так:
моя библиотека, она работает не используя контакт INT CAN модуля. Что наверное плохо. Хотя ничто не мешает нам самим добавить сюда этот сигнал. (а в твоей либе походу без INT никак). Просто я, дурень, не подключил этот контакт в МК_свет, а сейчас опять щит вскрывать влом. Но вроде работает пока c моей либой без INT вообще гуд.
МК нижний от верхнего получает инфу о состоянии включенности света в комнатах, движении в комнатах, пож.датчиков. Всего комнат вверху 5 и всё это передается в одном сообщении, всего в 3-х байтах (Одно сообщение CAN может нести до 8 байт инфы). Так компактно получается, потому что переменные булевые, т.е. биты. Значит в одном байте можно передавать 8 таких переменных. в 3 байтах можно передать состояние света в 24 комнатах, а в одном CAN фрейме в 64 комнатах))
02
03
Если переменная типа int(занимает 2 байта) передает температуру, то её можно запихать в 1 байт, переделав в однобайтовый int8_t т.к. температура у нас не вылазит из диапазона до -127 до +128, что и является одним байтом. Т.е. в одном CAN фрейме можно передать 8 температур, или ещё чего нибудь в диапазоне от 0 до 255.
04
05
Я научился всё это преобразовывать и туда и и обратно. Ну вот , например, вкачивать в байты отдельные биты (читай булевые переменные) и наоборот вытягивать отдельные биты из байтов. Как было приятно увидеть, когда всё почти сразу заработало, как было задумано.
06
07
Верхний же МК, получает от нижнего информацию - время, состояние охраны, состояние наличия напряжения 220В. Например, время нужно, чтобы включать и выключать функцию "автосвет"автоматически по времени. напряжение 220В нужно знать - если его нет, все реле света выключаем, чтобы экономить ИБП и т.д.
08
09
также верхний МК получает команды от нижнего на включение света, например, при имитации хозяев в доме, или просто кто-то через Wi-Fi со смартфона свет хочет включить.
10
11
Короче, устанавливая связь между МК, мы получаем гибчайший инструмент для технического творчества, не протягивая при этом здоровенные пучки проводов.
12
МК периодически выкидывает в кан свои параметры с датчиков и.т.д, и также слушает кан шину, получая также параметры от других МК и команды от других МК.
13
Полученные параметры понятно, мы просто используем. А вот получив команду, мы кроме реагирования на неё, еще шлем в шину отчет о том, что приняли эту команду, шлём 3 раза.
14
И напротив, когда мы шлём кому нибудь команду управления, мы, кроме всего прочего, начинаем ждать ещё отчёт о полученности нашёй отправленной команды. Если через полсекунды не получили отчет - шлём команду ещё раз и так 10 раз. Если же так и не получили отчёт, прекращаем это дело, записываем код неисправности. На практике, более одного раза у меня команде не приходилось отправляться - потому как отчёт мгновенно приходит - всё гуд (а вообще это нужно, если команда прилетела, когда МК во время delay простаивает)
я думаю тебе стоит к ней подтягиваться т.к. у меня уже реально неделю работает, сбоев нет. В скетче #195 вобщем-то всё подробно прокомментировано.
Ок. Готов пользовать ее, единственое что меня смущает что ее доработка остановилась, а coryjfowler либу дорабатывает. Ну да и ладно. Работает и работает.
MaksVV пишет:
это предлагаю не заводить на переменные, а просто задефайнить.
Ок.
MaksVV пишет:
МК нижний от верхнего получает инфу о состоянии включенности света в комнатах, движении в комнатах, пож.датчиков. ...
1. Информация с датчиков (оконечных МК) передается центральному МК
1.1 при включении
1.2 при изменении параметров более чем на 5% для дискретных и при изменении значения для булевых
1.3 периодически (1 раз в 600 секунд например)
1.4 при опросе из центра
2. Работа с исполнительными устройствами
При отправке команды исполнительному у-ву булевому, дискретному, временному ждем квитирование принятия команды к исполнению + ждем отчета о исполнении. Вся логика работы к исполнителным у-вом как и с датчиком лежит в оконечном МК, центр должен работать со всеми датчиками и ИУ абстрагировано, выдал команду получил отчет.
3. Все оконечные МК периодически сообщают центральному что живы, если не живы получают ресет например по питанию.
4. Резервирование
Центральных контроллеров 2 и они имеют одинаковый код за исключением вставки Master-Slave
Slave передает периодически в сторону мастера свое состояние и опрашивает состояние мастера. Если мастер отказал, Slave берет управлени на себя рассылая по сети сообщение что он мастер (по оконечным меняем глобальную переменную адреса с 1 на 2)
Master если оживает в первую очередь шлет запрос Slave не мастер ли он, меняет ему статус на Slave, делает рассылку оконечным на смену мастера.
При отправке команды исполнительному у-ву булевому, дискретному, временному ждем квитирование принятия команды к исполнению + ждем отчета о исполнении. Вся логика работы к исполнителным у-вом как и с датчиком лежит в оконечном МК, центр должен работать со всеми датчиками и ИУ абстрагировано, выдал команду получил отчет.
вот тут непонятно, если CAN упадёт, как будут себя вести локальные МК, типа переходить в автономный режим работы? С остальными дополнениями в принципе согласен.
Эх, как бы это ещё всё запрограммировать . И что со структурой ID, согласен с предложенным мной вариантом?
вот тут непонятно, если CAN упадёт, как будут себя вести локальные МК, типа переходить в автономный режим работы? С остальными дополнениями в принципе согласен.
Да, с минимальным функционалом по жесткому алгоритму (Переход с ДУ на МУ) , хотя я бы просто переводил в режим ожидания.
MaksVV пишет:
Эх, как бы это ещё всё запрограммировать .
Ну дорогу осилит идущий ;-)
MaksVV пишет:
И что со структурой ID, согласен с предложенным мной вариантом?
Извини может я туплю можещь ее формализовать и выложить сюда в формате xyz ?
И работа с ниблами просто ресурс адресации сжигает. По рукам и ногам вяжет. Весь интернет на 32 витах адресуется а мы из-за ниблов не модем 256 GPIO адесовать. Может другой путь обдумать. Потом локти кусать будем.
И работа с ниблами просто ресурс адресации сжигает. По рукам и ногам вяжет. Весь интернет на 32 витах адресуется а мы из-за ниблов не модем 256 GPIO адесовать. Может другой путь обдумать. Потом локти кусать будем.
Не очень понял про какие нибблы речь. Ниббл всего один используется в предложенном мной варианте - это type message, 16 значений разве не хватит?
Я чесно использовал в предложенном варианте 28 бит из 29. А больше 29бит то ведь низя! Не влезает сюда этот device address.
А если значений device type мало. Ну давай оставшийся неиспользуемый бит прилепим к байту типа девайса и будет тебе не 256 типов устройств, а 512.
тебе конечно попроще оперировать всеми этими понятиями. Я так понял, ты варишься частенько в этом всём. В материале так сказать - топологии, всякие верхние уровни.
Мне тяжко столько инфы сразу для восприятия, я ведь всего лишь автомобильный диагност. С компьютером то дружу, но вот с сетями...
1. Есть дом/квартира с n помещений в которых есть датчики и исполнительные устройства (ИУ) и вкоторые из центра идут кабели или радиоканалы. (Перечень датчиков и исполнительных устройств см. на моей схеме)
2. Есть оконечные контроллеры которые являются концентраторами датчиков и ИУ, принимают от них данные передают наверх и получают команды сверху. В общем случае просто расширители от центра. Есть исключения например система защиты от протечек у нее 2 жестких сценария, либо закрыть краны от датчиков либо по команде от центра + сервичные провороты кранов. Управление котлом например. И прочие узкие задачи.
3. Есть центр сосредоточния кабелей т.е. ядро сети от куда будем всем управлять по более сложным но все равно фиксированным сценариям. И откуда работает автоматика-автоматизация по простым алгоритмам ( есть движение зажгли свет, стало жарко включили кондиционер, холодно котел или электрорадиатор, стало много со2 включили рекуператор и т.д)
4. Есть сервер УД который дает возможность визуализации всех событий от датчиков, ИУ и самое главное дает возможность создавать сложные сценарии. Например зимой теплее холоднее это задвижки на радиаторах а летом кондиционер и пр. Режимы освещения и пр. Т.е он через Web например позволяет задать контроллерам параметры для изменения алгоритмов.
Отсюда требования к системе.
1. Потеря контроллера (поломка) не приводит к аварии в доме. Это как раз достигается запаралеливанием управления от МК и от клавиш, кнопок, тумблеров пультов. Т.е мы просто делаем дистанционное управление устройствами и снятие показаний но не убираем возможность управлять в ручную. Например если МК защиты от протечек умрет я не останусь без воды, если МК света то буду выключателями включать и т.д
2. Должны быть заданы минимальные управляющие алгоритмы абстрагирующие нас и верхний уровень от взаимодействия с датчиком или ИУ. Т.е запросил температуру получил значение. Дал команду зажечь свет, он зажегся и получено подтверждение что он зажегся. Независимо как мы его зажигаем. Могут быть разные типы управления светом дискретные если диммер или булевы если реле.
Тут еще оказалось, что у меня товарищ делает overCAN протокол для управления набором модулей , правда он на 11 битном (2.0а) но тоже есть интересные идеи. В наш протокол особо нужные идеи перенесу.
1. Идея это обязательно иметь уникальный номер сообщения, у контроллера, я его в блок данных внесу, крутится счетчик в рамках выделенных бит с сбросом в о после переполнения.
2. Ну это как в CAN Open возможность передачи не только Короткий – любые сообщения длиной до 8 байт но и Составной кадр – любые сообщения длиной более 8 байт.
3. Типы сообщений
Командауправления - сообщение в адрес узла
Команда-Запрос - сообщение в адрес узла с запросом выдачи информации о состоянии
Команда контроля
Технологическая команда
Ответное сообщение - ответ от узла
Инициативное сообщение – сообщение узла , выдаваемое в инициативном порядке.
Я вот как то так вижу свой УД по автоматике, Мультирум и пр. умы это другой слой
Можешь выложить картинку в полном качестве? А то плохо видно. На я диск например. В общем с длинными ID я чето намучился, не получалось у меня. Не только канхакер их не видел, но и не отправлялись они вовсе. Использовал видимо корявую библиотеку. Она называлась также, как ты давал по ссылке, поэтому я твою не стал скачивать. А моя видать корявая с длинными ID не работает. Уже после того, как с 11бит все сделал у себя, твою либу попробовал. Вроде норм 29бит отправляет. Может переделаю еще. А то действительно 16 адресов может и не хватить. Вдруг меня растащщит)
P.S. Или ещё может ничего не получалось, т.к. один CAN модуль у меня был неисправный. Он отправлял СAN феймы, но не принимал.
https://yadi.sk/i/FO4tePMK3TLSFK
Я тоже с якобы неисправным модулем бился. Все дело только в библиотеках. Перепробовал все с github. Выбрал нужную. А расширенный заголовок позволяет сразу из заголовка вынуть от кого, кому, что за событите, что за датчик или исполнительное.
Вот примерно мой can_struct.h (он общий для всех прошивок. Контролллеров то много в сети). И да удобнее с десятичными работать нежели с байтом. Тут на вкус и цвет, просто обработка строки быстрее пишется на мой взгляд. и на этапе прототипа мне так удобнее.
Я не проф. программер, я связист.
001
#include <mcp_can.h>
002
#include <SPI.h>
003
004
//ID structure xx.yy.z.a.cc
005
// xx yy z a cc
006
// my address remote address type message device address device type
007
008
//Node Address
009
int
global_mfg;
010
//Основные помещения
011
uint32_t Livingroom_main_11 = 11;
// Гостинная основной
012
uint32_t Bedroom_main_21 = 21;
// Спальня основной
013
uint32_t Cabinet_main_31 = 31;
// Кабинет основной
014
uint32_t Hallway_main_41 = 41;
// Холл основной
015
//Мокрая зона
016
uint32_t Kitchen_main_51 = 51;
// Кухня основной
017
uint32_t WC_main_61 = 61;
// Туалет основной
018
uint32_t WC_waterleak_62 = 62;
// Туалет защита от протечек
019
uint32_t Bathroom_71 = 71;
// Ванна основной
020
uint32_t Boxroom_81 = 81;
// Кладовая основной
021
uint32_t Loggia_main_82 = 82;
// Лоджия основной
022
uint32_t Balcony_83 = 83;
// Балкон основной
023
024
//Ядро сети и свет
025
uint32_t Hallway_net_center_91 = 91;
// Холл ядро сети
026
uint32_t Hallway_light_92 = 92;
// Холл ядро сети свет
027
uint32_t Kitchen_net_center_95 = 95;
// Кухня ядро сети
028
uint32_t Kitchen_light_96 = 96;
// Кухня ядро сети свет
029
030
uint32_t rxId;
031
032
//Type message
033
uint32_t msg_tx_cmd_snd = 1;
// NORMAL SEND COMMAND
034
uint32_t msg_rx_cmd_ans = 2;
// NORMAL ANSVER COMMAND
035
uint32_t msg_tx_par_req = 3;
// NORMAL SEND REQUEST
036
uint32_t msg_rx_par_ans = 4;
// NORMAL ANSVER COMMAND
037
uint32_t msg_tx_stat_req = 5;
//NORMAL SEND STATUS REQUEST
038
uint32_t msg_rx_stat_ans = 6;
//NORMAL ANSVER STATUS COMMAND
039
040
//device type
041
//Sensor
042
uint32_t air_temp_cens = 1;
043
uint32_t air_hum_cens = 2;
044
uint32_t air_pres_cens = 3;
045
uint32_t motion_pir_cens = 4;
046
uint32_t motion_mw_censor = 5;
047
uint32_t vibration_censor = 6;
048
uint32_t noise_censor = 7;
049
uint32_t Illumination_censor = 8;
050
uint32_t gas_co_censor = 9;
051
uint32_t gas_co2_censor = 10;
052
uint32_t gas_metan_censor = 11;
053
uint32_t smoke_censor = 12;
054
uint32_t fire_censor = 13;
//Огонь
055
uint32_t body_temperature_censor = 14;
//Температура тела
056
uint32_t jalousie_status_censor = 15;
//Жалюзи
057
uint32_t steam_censor = 16;
//Пар
058
uint32_t microwave_censor = 17;
//Излучение микроволновки
059
uint32_t fridge_temperature_censor = 18;
//Холодильник
060
uint32_t freezer_temperature_censor = 19;
//Морозилка
061
uint32_t oven_temperature_censor = 20;
//Духовка
062
uint32_t electrical_board_censor = 21;
//Электрощит концевик
063
uint32_t door_lock_censor = 22;
//Замок двери
064
uint32_t door_close_censor = 23;
//Замок двери
065
uint32_t motion_door1_censor = 24;
//Датчик прохода 1
066
uint32_t motion_door2_censor = 25;
//Датчик прохода 2
067
uint32_t window_close_censor = 26;
//Закрыто
068
uint32_t water_hot_temperature_censor = 27;
//Температура горячей воды
069
uint32_t water_cold_temperature_censor = 28;
//Температура холодной воды
070
uint32_t water_hot_pressure_censor = 29;
//Давление горячей воды
071
uint32_t water_cold_pressure_censor = 30;
//Давление холодной воды
072
uint32_t leakage_censor = 31;
//Протечка
073
uint32_t counter_gas_censor = 32;
//Счетчик газа
074
uint32_t counter_water_hot_censor = 33;
//Счетчик горячей воды
075
uint32_t counter_water_cold_censor = 34;
//Счетчик холодной воды
076
uint32_t counter_electricity_censor = 35;
//Счетчик электричества
077
uint32_t cupboard_door_censor = 36;
//Дверь шкафа
078
uint32_t safe_door_censor = 37;
//Дверь сейфа
079
uint32_t balcony_door_censor = 38;
//Дверь балкона
080
uint32_t loggia_door_censor = 39;
//Дверь лоджии
081
uint32_t radiator_temperature_censor = 40;
//Температура батареи
082
uint32_t lamp_ceiling_censor = 41;
//Лампа на потолке
083
uint32_t lamp_wall_censor = 42;
//Ланпа настенная
084
uint32_t lamp_Illumination_censor = 43;
//Лампа подсветки
085
uint32_t lamp_accident_censor = 44;
//Лампа аварийная
086
uint32_t earth_humidity_censor = 45;
//Влажность земли
087
uint32_t lamp_aquarium_censor = 46;
//Лампа аквариум
088
uint32_t aquarium_temperature_censor = 47;
//Температура аквариум
089
uint32_t aquarium_pump_censor = 48;
//Насос аквариум
090
uint32_t aquarium_clearing_censor = 49;
//Очистка аквариум
091
// темп рекуператора
092
//темп, вл, давл, улица
093
094
095
//Device Digital //Device analog
096
uint32_t lamp_ceiling_onoff_device = 60;
//Лампа на потолке вкл/выкл
097
uint32_t lamp_wall_onoff_device = 61;
//Ланпа настенная вкл/выкл
098
uint32_t lamp_Illumination_onoff_device = 62;
//Лампа подсветки вкл/выкл
099
uint32_t lamp_accident_onoff_device = 63;
//Лампа аварийная вкл/выкл
100
uint32_t lamp_ceiling_dimm_device = 64;
//Лампа на потолке диммируемая
101
uint32_t lamp_wall_dimm_device = 65;
//Ланпа настенная диммируемая
102
uint32_t lamp_Illumination_dimm_device = 66;
//Лампа подсветки диммируемая
103
uint32_t lamp_accident_dimm_device = 67;
//Лампа аварийная диммируемая
104
uint32_t fan = 68;
105
uint32_t recuperator = 69;
106
uint32_t air_conditioning = 70;
107
uint32_t valve_radiator = 71;
108
uint32_t jalousie = 72;
109
uint32_t valve_gas = 73;
110
uint32_t valve_hot_water = 74;
111
uint32_t valve_cold_water = 75;
112
uint32_t irda = 76;
113
uint32_t freshener = 77;
//Освежитель
114
uint32_t humidifier = 78;
//Увлажнитель
115
uint32_t door_lock_magnet = 79;
116
uint32_t door_lock_electromagnet = 80;
117
uint32_t door_lock_electromechanical = 81;
118
uint32_t door_lock_blink = 82;
119
uint32_t siren = 83;
120
uint32_t blinker = 84;
121
uint32_t music = 85;
122
uint32_t tv = 86;
123
uint32_t radio = 87;
124
uint32_t power_socket = 88;
//Розетки
125
126
unsigned
char
len = 0;
127
unsigned
char
rxBuf[8];
128
unsigned
char
txBuf[8];
129
char
msgString[128];
// Array to store serial string
130
#define CAN0_INT 2 // Set INT to pin 2
131
MCP_CAN CAN0(53);
// Set CS to pin (NANO, UNO etc = 10, MEGA,DUE etc = 53)
Жесть какой широкий у тебя размах). У меня два вопроса. Зачем применяешь uint32_t. Неужели uint16_t не хватит? И второе , смотри самый первый разряд в ID тот который ХХ, имеет не весь диапазон адресов ( не 256) , т.к первый ниббл Х может принимать значения только от 0 до 7. Потому что ID 29 бит, а не 32. Т.е на этот ниббл Х отводится 3 бита вместо четырех.
По поводу размаха - если присмотреться делается типовое изделие практически серийное, все блоки одинаковые, я под них заложил в каждом помещении по 5 подрозетников под потолком, закрытых заглушками. В итоге это мини ардуино 2560 + CAN контроллер и датчики. Все кабели как я уже сказал затянул. Потолками натяжными закрыл.
uint32_t первое что под руку подвернулось ;-) (Я не проф программер, самоучка можно сказать). Памяти пока хватает. Потом переделаю все на Byte. Так проще писать адреса без пересчета, в десятичной системе. Это была проба пера, в смысле проверить CAN сеть, погонять обмен датчиков, включение выключение светодиодов на обратных концах и пр. Все заработало. Технология выбрана. Кабели запроектированы, заложены, штукатуркой замазаны, потолками закрыты. Я как конструктор ОКР иду от эскизного проекта к опытному образцу, через отработку технологий и макетирование, почти по 203 госту ;-)
По поводу 29 а не 32 я поздно заметил, а сейчас смысла нет пока менять, адресов хватает. Ну и см. выше, это прототип. Важно определиться с концепцией. Мало того твои идеи оч. интересны.
Кстати начал тут глубже копать CAN так вот эти 3 бита забирает т.н. удаленный кадр, в котором нет поля данных но он является запросчиком. (Вернее даже не удаленный кадр а типизация видов сообщений)
"Удаленные кадры можно использовать для реализации управления трафиком шины типа «запрос–ответ». На практике, однако, удаленный кадр используется мало. Это не так важно, поскольку стандарт CAN не предписывает действовать именно так, как здесь обозначено. Большинство контроллеров CAN можно запрограммировать так, что они будут автоматически отвечать на удаленный кадр, или же вместо этого извещать локальный процессор."
http://www.micromax.ru/solution/theory-practice/articles/2160/
Умный дом у меня на самый конец уходит. Сейчас пока автоматика на реле. Бистабильные фото и пр. Т.е базовые вещи типо свет, вода и пр. работают без контроллеров. Все системы при отключении УД продолжают нормально работать.
Ну и мы же реально умный дом делаем а не ПДУ для лампочек, для этого такой огород ведь не городят ;-)
P.S. использую вот эту библиотеку CAN https://github.com/coryjfowler/MCP_CAN_lib
да, прототип хорош. На счет работы без контроллеров, ну не знаю. Вот у меня свет на втором этаже уже два года только в схеме с МК работает - выключатели света слаботочные на 5В, подают только сигнал на МК. Проблем не было никаких, даже в сильную грозу. Главное применять опторазвязки, провода в экране. А если коряво подходить к вопросу, дак и без МК что нибудь сгореть, сломаться может.
По поводу ID поменяй местами разряды и делов то: Z.XX.YY.A.CC
где Z - тип сообщения, их у тебя 6, ещё 1 в запасе остаётся.
дак никто не мешает писать в десятичной системе на типе byte . Контроллеру то пофиг, ему всё одно - нули и единицы. просто пишешь число и всё - будет десятичная, если добавить перед записью числа 0x - это HEX. Если добавить B - бинарная запись (в битах).
Я не точно объяснил.
Использую бистабтльные реле РИО-1М и кнопочные выключатели. В паралель к кнопкам ставлю ТТ реле которым управлю с ардуино. Т.о. даже при отсутствии контроллеров свет управлется. И т.д. В дальнейшем при сбое или поломке контроллера я не сижу при свечах. Опторазвязки я естественно буду использовать. Нарпимер АОТ166 для проверки наличия напржения на лампах освещения. Строю 2х уровневую, даже 3х уровневую систему. 1 уровень пром. реле. Второй уровень автоматика на МК, 3 уровень сцены на Сервере.
И дело даже не в надежности. Если бы я поше по пути контроллера то сидел бы без света сейчас. А так реле потавил и все работает. Сверху поставлю МК и буду им щелкать реле в паралель с кнопками.
Насчет стрктуры - отличная идея.
Я вроде с этим тыкался, но для отладки быстрее выводиь все что пришло в сериал, а там опять преобразования. Естественно потом напишу.
Вот тут мои наброски https://yadi.sk/d/7pyVRdHJ3TNYXr
имхо, у тебя замороченная схема извлечения разрядов из ID
И дело даже не в надежности. Если бы я поше по пути контроллера то сидел бы без света сейчас. А так реле потавил и все работает. Сверху поставлю МК и буду им щелкать реле в паралель с кнопками.
ну в общем да, согласен, так наверное лучше. Понятно, что когда строишь систему УД делаешь много ошибок. Я если бы сейчас начинал, всё вообще бы не так сделал. А щас переделывать ужё лень - слишком много делов
Я вроде с этим тыкался, но для отладки быстрее выводиь все что пришло в сериал, а там опять преобразования.
вот это не понял немного. Какие преобразования. Для отладки я использую CAN сниффер. Мне почему удобнее работать с HEX, так как все анализаторы CAN шины выводят инфу в HEX и визуально уже привыкаешь все адреса и байты видеть в HEX. А без анализаторы шины при построении тайой системы я вообще не знаю как можно обойтись. Я почему в своей 11битной схеме ID и отказался от 5 битных адресов, потому как их визуально мониторить вообще проблема. Хотя так было бы 32 адреса, а не 16.
Я конечно тоже далекооо не крутой программист, вернее вообще не программист, но
с функцией void TX() нужно тебе подумать
1
void
TX(uint32_t node_to, uint32_t msg_type, uint32_t dev_num, uint32_t dev_type,
float
a,
float
b,
float
c,
float
d,
float
e,
float
f,
float
g,
float
h)
2
{
3
byte
data[8] = {a, b, c, d, e, f, g, h};
4
byte
sndStat = CAN0.sendMsgBuf(txId*1000000+node_to*10000+msg_type*1000+dev_num*100+dev_type, 1, 8, data);
// send data: ID = 0x100, Standard CAN Frame, Data length = 8 bytes, 'data' = array of data bytes to send
5
// byte sndStat2 = CAN0.sendMsgBuf(0x40000111, 8, data); //txBuf
6
if
(sndStat == !CAN_OK){
Serial
.print(
"MSG send error!"
); }
7
//delay (310);
8
}
в качестве параметров этой функции ты передаешь переменные типа флоат (а,b,c,d,e,f,h). А потом создаёшь массив уже типа byte
и запихиваешь туда эти float, зачем так делать? Если действительно нужно передать float (он занимает в памяти МК 4 байта), то тебе придётся использовать для этого 4 байта поля данных CAN фрейма на каждый float , т.е. a,b,c,d. предварительно например , разбив float на 4 отдельные байта.
а если не надо float, то и нафиг в качестве параметров функции его использовать, если всё равно ты их в массиве byte data[8] к типу byte переводишь. Бери везде тип byte и иcпользуй.
Нельзя так к памяти МК относится, это я уже давно понял.
Я вроде с этим тыкался, но для отладки быстрее выводиь все что пришло в сериал, а там опять преобразования.
вот это не понял немного. Какие преобразования. Для отладки я использую CAN сниффер. Мне почему удобнее работать с HEX, так как все анализаторы CAN шины выводят инфу в HEX и визуально уже привыкаешь все адреса и байты видеть в HEX. А без анализаторы шины при построении тайой системы я вообще не знаю как можно обойтись. Я почему в своей 11битной схеме ID и отказался от 5 битных адресов, потому как их визуально мониторить вообще проблема. Хотя так было бы 32 адреса, а не 16.
Анализатора нет, подумаю на тему купить. Использовал прямой вывод всего что есть в сериал.
Я конечно тоже далекооо не крутой программист, вернее вообще не программист
Нельзя так к памяти МК относится, это я уже давно понял.
Я же говорю это был концепт, за выходные накидать, проверить что работает и вперед. Поэтому раньше и не выкладывал это позорище ;-)
Сейчас скинул чтобы идею обмена, работающую показать. Где то в коде вроде даже чтото с датчиками есть.
не надо покупать, делается за 5 мин.
смотри мой скетч #195, как я разряды вытягивал из переменной заголовка ID , там библиотека только не как у тебя, попроще она.
вот по твоей теме вытянул в переменные byte разряды из 29-битного ID заголовка. Без всяких стрингов. Тип сообщения Z уже поставил на первый разряд
01
void
RX()
02
{
03
if
(!digitalRead(CAN0_INT))
// If CAN0_INT pin is low, read receive buffer
04
{
05
CAN0.readMsgBuf(&rxId, &len, rxBuf);
// Read data: len = data length, buf = data byte(s)
06
07
byte
z,xx,yy,a,cc;
08
09
z = (rxId & 0xF0000000)>>28;
10
xx = (rxId & 0xFF00000)>>20;
11
yy = (rxId & 0xFF000)>>12;
12
a = (rxId & 0xF00)>>8;
13
cc = (rxId & 0xFF);
14
15
Serial
.print(
" CAN_ID "
);
16
Serial
.print(xx);
//если нужно в НЕХ выводить в монитор просто пишешь так Serial.print(xx, HEX);
17
Serial
.print(
" "
);
18
Serial
.print(yy);
19
Serial
.print(
" "
);
20
Serial
.print(z);
21
Serial
.print(
" "
);
22
Serial
.print(a);
23
Serial
.print(
" "
);
24
Serial
.print(cc);
25
Serial
.print(
" "
);
26
Serial
.println();
27
}
28
29
if
(z==1){
// если тип сообщения: "1"
30
// тогда что-нибудь тут сделаем и т.д.
31
32
}
33
34
35
}
а вот как обратно запихать в txId необходимые разряды:
01
unsigned
long
txId = 0x1ABCDEF2;
// допустим был такой ID
02
03
//ниже, например, пусть будут у нас такие разряды
04
byte
z = 0x05;
05
byte
xx = 0xDD;
06
byte
yy= 0xEE;
07
byte
a = 0xB ;
08
byte
cc = 0xCC;
09
10
11
void
setup
() {
12
13
Serial
.begin (9600);
14
Serial
.print (
"Old ID: "
);
15
Serial
.println (txId, HEX);
16
17
18
// ниже вобъём наши разряды по одному в существующий ID, не задевая остальные разряды
19
20
Serial
.println (
"z=5, xx=DD, yy=EE, a=B, cc=CC"
);
21
22
txId = (txId & 0x0FFFFFFF)| (z & 0x0FFFFFFF)<<28;
// вбиваем в ID разряд z, не трогая остальное
23
24
Serial
.print (
"New ID +z: "
);
25
Serial
.println (txId, HEX);
26
27
txId = (txId & 0xF00FFFFF)| (xx & 0xF00FFFFF)<<20;
// вбиваем в ID разряд xx, не трогая остальное
28
29
Serial
.print (
"New ID +z,xx: "
);
30
Serial
.println (txId, HEX);
31
32
txId = (txId & 0xFFF00FFF)| (yy & 0xFFF00FFF)<<12;
// вбиваем в ID разряд xx, не трогая остальное
33
34
Serial
.print (
"New ID +z,xx,yy: "
);
35
Serial
.println (txId, HEX);
36
37
txId = (txId & 0xFFFFF0FF)| (a & 0xFFFFF0FF)<<8;
// вбиваем в ID разряд a, не трогая остальное
38
39
Serial
.print (
"New ID +z,xx,yy,a: "
);
40
Serial
.println (txId, HEX);
41
42
txId = (txId & 0xFFFFFF00)| cc;
// вбиваем в ID разряд cc, не трогая остальное
43
44
Serial
.print (
"New ID +z,xx,yy,a,cc: "
);
45
Serial
.println (txId, HEX);
46
47
48
49
}
50
51
void
loop
() {
52
53
54
}
Сейчас подсчитал - что-то я напутал. Это в 11-битном ID на первый разряд 3 бита отводится (от 0 до 7), а в 29-битном на первый разряд отводится 1 бит, т.е. значения может принимать только 0 или 1. Поэтому нельзя туда тип сообщения z вешать, придётся тебе жертвовать нибблом a device address. и вместо него этот тип сообщения z ставить.
И я , наконец, разобрался почему ничего не получалось у меня с 29-битными ID. При опробовании этих 29бит наложилось несколько косяков - это нерабочий CAN модуль и плюсом к этому, я в обоих библиотеках (пробовал и твою и мою) просто неправильно отправлял расширенные ID. Поэтому толком не приходили эти 29битные ID и не отправлялись. Теперь разобрался с обоими библиотеками, как отправлять расширенные ID.
В твоей библиотеке нужно в единичку ставить этот бит - выделен жирным (если он будет 0 то это 11бит) при отправке:
CAN0.sendMsgBuf(0x12345678, 1 , 8, stmp);
А в моей библиотеке будет так:
1
mcp2515.sendMessage(&canMsg2);
// это отправка стандартного фрейма 11 бит
2
mcp2515.sendMessage(MCP2515::TXB1,&canMsg1);
// а вот так нужно отправлять фреймы с 29-битным ID
Единственное, для того, чтобы значение первого разряда в моей библиотеке (<mcp2515.h>) было равно 1, нужно отправлять 9,
и соответственно чтобы было равно 0 - нужно отправлять 8 . Такова особенность библиотеки видимо.
Пример. Для отправки ID 0х0aabbccd нам нужно отправить 0х8aabbccd
Для отправки ID 0х1aabbccd нам нужно отправить 0х9aabbccd
И анализатор шины всё видит как надо. В общем я тоже перейду на 29 бит и будет 255 адресов для МК, работающих на одной шине.
Сейчас подсчитал - что-то я напутал. Это в 11-битном ID на первый разряд 3 бита отводится (от 0 до 7), а в 29-битном на первый разряд отводится 1 бит, т.е. значения может принимать только 0 или 1. Поэтому нельзя туда тип сообщения z вешать, придётся тебе жертвовать нибблом a device address. и вместо него этот тип сообщения z ставить.
По моему с твоей помощью вообще ничем жертвовать не придется. 29 бит это всего на 3 бита меньше чем IP адрес, и на всеь интернет числа хостов хватает.
Смотри если работать по битам то получаем при той же концепции следующее:
Это десятичная система, не вроде 16 ричная ;-)
А в моей библиотеке будет так:
1
mcp2515.sendMessage(&canMsg2);
// это отправка стандартного фрейма 11 бит
2
mcp2515.sendMessage(MCP2515::TXB1,&canMsg1);
// а вот так нужно отправлять фреймы с 29-битным ID
Кинь сылку на свою библиотеку. Может на одной либе начать работать, мне в принципе пока все равно. Я на этапе концепта.
Да и вообще может есть смысл начать плавно объединять усилия. Я сейчас в течении месяца ремонт завершу и займусь активнее разработкой. Мы вроде практически единстренные на форуме из любителей (имею ввиду не зарабатывающих на УД) в CAN двинули, всех 485 устраивает.
Что я хочу получить на выходе ты увидел на схеме.
Так же хочу сделать аппаратную систему зоновой трансляции. Много аппаратных источников аудио (FM, USB MP3/SD MP3/AUX на УД/Bluetooth/AUX IP радио етс. Делать все буду на аудиопроцах или готовых модулях упр. по i2c (PT2314 TDA7419 или TEA6420)
Я из щита в каждое помещение завел аудиокабель и поставил динамик.
Ну а потом и мультирум.
эмм. не понял откуда ты столько бит взял? тут же больше 29 (посчитай нолики)
по моим подсчетам вот так изначально у тебя затевалось:
как видим на type message что то мало значений приходится))
предлагаю убрать device address (ну засунешь его в тело сообщения, это ничего не меняет)
и делить разряды кратно 4 битам, т.е. нибблам. Поверь, это важно при отладке визуально в кан анализаторе. К тому же вытягивать числа из ID не кратные 4 битам вообще жопа (см. на предыдущей странице как я делал 5-битные адреса). В итоге предлагаю сделать так:
//ID structure
моя библиотека, она работает не используя контакт INT CAN модуля. Что наверное плохо. Хотя ничто не мешает нам самим добавить сюда этот сигнал. (а в твоей либе походу без INT никак). Просто я, дурень, не подключил этот контакт в МК_свет, а сейчас опять щит вскрывать влом. Но вроде работает пока c моей либой без INT вообще гуд.
вместе всегда проще, конечно. А то я тут один долго демагогию по кану разводил))
1
/device type
2
//Sensor
3
uint32_t air_temp_cens = 1;
4
uint32_t air_hum_cens = 2;
5
uint32_t air_pres_cens = 3;
//и т.д.
это предлагаю не заводить на переменные, а просто задефайнить. Так память здорово экономится, учитывая сколько у тебя этих типов.
1
/device type
2
//Sensor
3
#define AIR_TEMP_CENS 1
4
#define AIR_HUM_CENS 2
5
#define AIR_PRES_CENS 3
6
и т.д.
в принципе стратегия CAN шины такая (я тут недавно тоже рассказывал одному человеку про CAN):
01
МК нижний от верхнего получает инфу о состоянии включенности света в комнатах, движении в комнатах, пож.датчиков. Всего комнат вверху 5 и всё это передается в одном сообщении, всего в 3-х байтах (Одно сообщение CAN может нести до 8 байт инфы). Так компактно получается, потому что переменные булевые, т.е. биты. Значит в одном байте можно передавать 8 таких переменных. в 3 байтах можно передать состояние света в 24 комнатах, а в одном CAN фрейме в 64 комнатах))
02
03
Если переменная типа
int
(занимает 2 байта) передает температуру, то её можно запихать в 1 байт, переделав в однобайтовый int8_t т.к. температура у нас не вылазит из диапазона до -127 до +128, что и является одним байтом. Т.е. в одном CAN фрейме можно передать 8 температур, или ещё чего нибудь в диапазоне от 0 до 255.
04
05
Я научился всё это преобразовывать и туда и и обратно. Ну вот , например, вкачивать в байты отдельные биты (читай булевые переменные) и наоборот вытягивать отдельные биты из байтов. Как было приятно увидеть, когда всё почти сразу заработало, как было задумано.
06
07
Верхний же МК, получает от нижнего информацию - время, состояние охраны, состояние наличия напряжения 220В. Например, время нужно, чтобы включать и выключать функцию
"автосвет"
автоматически по времени. напряжение 220В нужно знать - если его нет, все реле света выключаем, чтобы экономить ИБП и т.д.
08
09
также верхний МК получает команды от нижнего на включение света, например, при имитации хозяев в доме, или просто кто-то через Wi-Fi со смартфона свет хочет включить.
10
11
Короче, устанавливая связь между МК, мы получаем гибчайший инструмент для технического творчества, не протягивая при этом здоровенные пучки проводов.
12
МК периодически выкидывает в кан свои параметры с датчиков и.т.д, и также слушает кан шину, получая также параметры от других МК и команды от других МК.
13
Полученные параметры понятно, мы просто используем. А вот получив команду, мы кроме реагирования на неё, еще шлем в шину отчет о том, что приняли эту команду, шлём 3 раза.
14
И напротив, когда мы шлём кому нибудь команду управления, мы, кроме всего прочего, начинаем ждать ещё отчёт о полученности нашёй отправленной команды. Если через полсекунды не получили отчет - шлём команду ещё раз и так 10 раз. Если же так и не получили отчёт, прекращаем это дело, записываем код неисправности. На практике, более одного раза у меня команде не приходилось отправляться - потому как отчёт мгновенно приходит - всё гуд (а вообще это нужно, если команда прилетела, когда МК во время delay простаивает)
я думаю тебе стоит к ней подтягиваться т.к. у меня уже реально неделю работает, сбоев нет. В скетче #195 вобщем-то всё подробно прокомментировано.
моя библиотека
Ок. Готов пользовать ее, единственое что меня смущает что ее доработка остановилась, а coryjfowler либу дорабатывает. Ну да и ладно. Работает и работает.
это предлагаю не заводить на переменные, а просто задефайнить.
Ок.
МК нижний от верхнего получает инфу о состоянии включенности света в комнатах, движении в комнатах, пож.датчиков. ...
1
<span style=
"font-size:12px;"
></span>
Я бы еще добавил правил
1. Информация с датчиков (оконечных МК) передается центральному МК
1.1 при включении
1.2 при изменении параметров более чем на 5% для дискретных и при изменении значения для булевых
1.3 периодически (1 раз в 600 секунд например)
1.4 при опросе из центра
2. Работа с исполнительными устройствами
При отправке команды исполнительному у-ву булевому, дискретному, временному ждем квитирование принятия команды к исполнению + ждем отчета о исполнении. Вся логика работы к исполнителным у-вом как и с датчиком лежит в оконечном МК, центр должен работать со всеми датчиками и ИУ абстрагировано, выдал команду получил отчет.
3. Все оконечные МК периодически сообщают центральному что живы, если не живы получают ресет например по питанию.
4. Резервирование
Центральных контроллеров 2 и они имеют одинаковый код за исключением вставки Master-Slave
Slave передает периодически в сторону мастера свое состояние и опрашивает состояние мастера. Если мастер отказал, Slave берет управлени на себя рассылая по сети сообщение что он мастер (по оконечным меняем глобальную переменную адреса с 1 на 2)
Master если оживает в первую очередь шлет запрос Slave не мастер ли он, меняет ему статус на Slave, делает рассылку оконечным на смену мастера.
При отправке команды исполнительному у-ву булевому, дискретному, временному ждем квитирование принятия команды к исполнению + ждем отчета о исполнении. Вся логика работы к исполнителным у-вом как и с датчиком лежит в оконечном МК, центр должен работать со всеми датчиками и ИУ абстрагировано, выдал команду получил отчет.
вот тут непонятно, если CAN упадёт, как будут себя вести локальные МК, типа переходить в автономный режим работы? С остальными дополнениями в принципе согласен.
Эх, как бы это ещё всё запрограммировать . И что со структурой ID, согласен с предложенным мной вариантом?
del
вот тут непонятно, если CAN упадёт, как будут себя вести локальные МК, типа переходить в автономный режим работы? С остальными дополнениями в принципе согласен.
Да, с минимальным функционалом по жесткому алгоритму (Переход с ДУ на МУ) , хотя я бы просто переводил в режим ожидания.
Эх, как бы это ещё всё запрограммировать .
Ну дорогу осилит идущий ;-)
И что со структурой ID, согласен с предложенным мной вариантом?
Извини может я туплю можещь ее формализовать и выложить сюда в формате xyz ?
Извини может я туплю можещь ее формализовать и выложить сюда в формате xyz ?
Читай сообщение #225. Там я предложил в твоем формате, только без adress device
Извини может я туплю можещь ее формализовать и выложить сюда в формате xyz ?
Вот я и говорю что ступил, простто пропустил сообщение.
Я пока формулирую концепцию для обсуждения, ведь мы по сути делем протокол overCAN для роботы сети MK.
Просмотри коротко что придумали до нас не глупые люди, думаю стоит идей от туда надергать, но без фанатизма
Есть три протокола over CAN
— CANopen (CANFestival)
http://can.marathon.ru/page/can-protocols/canopen
https://habrahabr.ru/post/144435/
http://we.easyelectronics.ru/STM32/can-canopen-canfestival-stm32-chast-pervaya.html
— DeviceNet
http://can.marathon.ru/page/can-protocols/devicenet/devicenetintro
— CAN Kingdom
https://habrahabr.ru/post/275895/
Не забывай про протоколы верхнего уровня
(Вот тут почитай http://www.rtsoft.ru/press/articles/detail.php?ID=2718)
Протокол MQTT https://ipc2u.ru/articles/prostye-resheniya/chto-takoe-mqtt/ с которым хочешь не хочешь придется считаться т.к. на нем практически все opensourser сервера УД живут.
И работа с ниблами просто ресурс адресации сжигает. По рукам и ногам вяжет. Весь интернет на 32 витах адресуется а мы из-за ниблов не модем 256 GPIO адесовать. Может другой путь обдумать. Потом локти кусать будем.
почитал бегло, есть над чем задуматься. Не охото велосипед изобретать. Надо более подробно почитать. Инфа полезная.
И ты только не бросайся в меня чем не попадя, мне удалось нормально https://github.com/jgeisler0303/CANFestivino собрать
И работа с ниблами просто ресурс адресации сжигает. По рукам и ногам вяжет. Весь интернет на 32 витах адресуется а мы из-за ниблов не модем 256 GPIO адесовать. Может другой путь обдумать. Потом локти кусать будем.
Не очень понял про какие нибблы речь. Ниббл всего один используется в предложенном мной варианте - это type message, 16 значений разве не хватит?
Я чесно использовал в предложенном варианте 28 бит из 29. А больше 29бит то ведь низя! Не влезает сюда этот device address.
А если значений device type мало. Ну давай оставшийся неиспользуемый бит прилепим к байту типа девайса и будет тебе не 256 типов устройств, а 512.
Ещё раз предложенный вариант
//ID structure
И ты только не бросайся в меня чем не попадя, мне удалось нормально https://github.com/jgeisler0303/CANFestivino собрать
блин, вообще нифига не понятно))
тебе конечно попроще оперировать всеми этими понятиями. Я так понял, ты варишься частенько в этом всём. В материале так сказать - топологии, всякие верхние уровни.
Мне тяжко столько инфы сразу для восприятия, я ведь всего лишь автомобильный диагност. С компьютером то дружу, но вот с сетями...
Давай пойдем от задач. Совсем сверху.
1. Есть дом/квартира с n помещений в которых есть датчики и исполнительные устройства (ИУ) и вкоторые из центра идут кабели или радиоканалы. (Перечень датчиков и исполнительных устройств см. на моей схеме)
2. Есть оконечные контроллеры которые являются концентраторами датчиков и ИУ, принимают от них данные передают наверх и получают команды сверху. В общем случае просто расширители от центра. Есть исключения например система защиты от протечек у нее 2 жестких сценария, либо закрыть краны от датчиков либо по команде от центра + сервичные провороты кранов. Управление котлом например. И прочие узкие задачи.
3. Есть центр сосредоточния кабелей т.е. ядро сети от куда будем всем управлять по более сложным но все равно фиксированным сценариям. И откуда работает автоматика-автоматизация по простым алгоритмам ( есть движение зажгли свет, стало жарко включили кондиционер, холодно котел или электрорадиатор, стало много со2 включили рекуператор и т.д)
4. Есть сервер УД который дает возможность визуализации всех событий от датчиков, ИУ и самое главное дает возможность создавать сложные сценарии. Например зимой теплее холоднее это задвижки на радиаторах а летом кондиционер и пр. Режимы освещения и пр. Т.е он через Web например позволяет задать контроллерам параметры для изменения алгоритмов.
Отсюда требования к системе.
1. Потеря контроллера (поломка) не приводит к аварии в доме. Это как раз достигается запаралеливанием управления от МК и от клавиш, кнопок, тумблеров пультов. Т.е мы просто делаем дистанционное управление устройствами и снятие показаний но не убираем возможность управлять в ручную. Например если МК защиты от протечек умрет я не останусь без воды, если МК света то буду выключателями включать и т.д
2. Должны быть заданы минимальные управляющие алгоритмы абстрагирующие нас и верхний уровень от взаимодействия с датчиком или ИУ. Т.е запросил температуру получил значение. Дал команду зажечь свет, он зажегся и получено подтверждение что он зажегся. Независимо как мы его зажигаем. Могут быть разные типы управления светом дискретные если диммер или булевы если реле.
....
Завтра допишу.
Перебрал все варианты, решил остановиться на твоем, с небольшим изменением
01
long
unsigned
int
Code_can_id_msg(uint8_t direction,uint8_t msg_type,uint8_t dev_addr,uint8_t rem_addr,int8_t dev_type)
02
{
03
long
unsigned
int
can_id_msg;
04
05
Serial
.print(
"TX Direction "
);
Serial
.println(direction);
06
Serial
.print(
"TX Comm_type "
);
Serial
.println(msg_type);
07
Serial
.print(
"TX Node addr "
);
Serial
.println(dev_addr);
08
Serial
.print(
"TX Rem addr"
);
Serial
.println(rem_addr);
09
Serial
.print(
"TX Dev type "
);
Serial
.println(dev_type);
10
11
///can_id_msg=???????????????; Как собрать uint8_t в long unsigned int сохранив структуру байтов??????????
12
Serial
.print(
"TX CAN ID "
);
Serial
.println(can_id_msg, HEX);
13
return
can_id_msg;
14
}
Подскажи Как собрать uint8_t в long unsigned int сохранив структуру байтов CAN ID?
Я чесно использовал в предложенном варианте 28 бит из 29. А больше 29бит то ведь низя! Не влезает сюда этот device address.
А если значений device type мало. Ну давай оставшийся неиспользуемый бит прилепим к байту типа девайса и будет тебе не 256 типов устройств, а 512.
Ещё раз предложенный вариант
//ID structure
вот как будет выглядеть на практике работа с разрядами, если сделать device type 9-битным (512 значений).
01
unsigned
long
ID = 0x1CCDDBBE;
// допустим получили из CAN такой ID
02
03
uint16_t device_adress;
// в эту переменную запишем самый старший 9-битный разряд из ID (1СС)
04
05
uint16_t device_adressNEW = 510;
// а потом обратно, в старший разряд ID запишем этот адрес (в HEX это 1FE)
06
07
void
setup
() {
08
09
Serial
.begin (9600);
10
11
device_adress = (ID & 0xFFF00000)>>20;
// вытянем из старшего разряда ID-заголовка 9-битный device type
12
13
Serial
.println (device_adress, HEX);
14
15
16
// и обратно - запихаем в старший разряд ID-заголовока переменную device_adressNEW:
17
ID = (ID & 0x000FFFFF) | (device_adressNEW & 0x000FFFFF)<<20;
18
19
20
Serial
.println (ID, HEX);
21
22
}
23
24
void
loop
() {}
//ID structure
Я готов использовать твой вариант, только первый бит жалко я его для определения ответ на мой запрос и или запрос ко мне использую
Del
Спасибо, в твоем примере нашел.
can_id_msg=(direction & 0xFFFFFFFF)<<28 | (msg_type & 0x0FFFFFFF)<<24 | (dev_addr & 0x00FFFFFF)<<16 | (rem_addr & 0x0000FFFF)<<8 | (dev_type & 0x000000FF);
Гдеб об этом почитать, а то как сапер примеры разбираю.
можно так
1
can_id_msg= (direction & 0xFFFFFFFF)<<28 | (msg_type & 0xFFFFFFFF)<<24 | (dev_addr & 0xFFFFFFFF)<<16 | (rem_addr & 0xFFFFFFFF)<<8 | dev_type;
читать про побитовые операции. Я сам это плохо понимаю, так допёр опытным путём.
а вот как парсить приходящий ID при таком твоём варианте
01
unsigned
long
rxId = 0x1ABCDEF2;
// допустим был такой ID
02
03
//ниже, например, пусть будут у нас такие разряды
04
05
bool
direction;
06
byte
z;
// type message
07
byte
xx;
// my address
08
byte
yy;
// remote address
09
byte
cc;
// device type
10
11
12
void
setup
() {
13
14
Serial
.begin (9600);
15
16
17
18
direction = (rxId & 0xF0000000)>>28;
19
20
z = (rxId & 0xF000000)>>24;
21
22
yy = (rxId & 0xFF0000)>>16;
23
24
xx = (rxId & 0xFF00)>>8;
25
26
cc = (rxId & 0xFF);
27
28
29
30
Serial
.print (
"RX CAN_ID "
);
Serial
.println (rxId, HEX);
31
32
Serial
.print(
"parse CAN_ID "
);
33
34
35
Serial
.print(direction, HEX);
36
37
Serial
.print(
" "
);
38
39
Serial
.print(z, HEX);
40
41
Serial
.print(
" "
);
42
43
Serial
.print(yy, HEX);
44
45
Serial
.print(
" "
);
46
47
Serial
.print(xx, HEX);
//если нужно в НЕХ выводить в монитор просто пишешь так Serial.print(xx, HEX);
48
49
Serial
.print(
" "
);
50
51
Serial
.print(cc, HEX);
52
53
Serial
.print(
" "
);
54
55
Serial
.println();
56
57
58
59
}
60
61
void
loop
() {}
Я вот так реализовал на своей библиотеке https://github.com/coryjfowler/MCP_CAN_lib
Это прием
01
void
RX()
02
{
03
uint8_t direction, msg_type, dev_addr, rem_addr, dev_type;
04
uint8_t data_b0,data_b1,data_b2,data_b3,data_b4,data_b5,data_b6,data_b7;
05
if
(!digitalRead(CAN0_INT))
//
06
{
07
CAN0.readMsgBuf(&rxId_can, &len_can, rxBuf_can);
// Read data: len = data length, buf = data byte(s)
08
09
direction = (rxId_can & 0x10000000)>>28;
// извлекаем 1-битный идентификатор запроса-ответа из ID
10
msg_type = (rxId_can & 0x0F000000)>>24;
// извлекаем 4-битный идентификатор сообщения из ID
11
dev_addr = (rxId_can & 0x00FF0000)>>16;
// извлекаем 8-битный адрес отправителя из ID
12
rem_addr = (rxId_can & 0x0000FF00)>>8;
// извлекаем 8-битный адрес получателя из ID
13
dev_type = (rxId_can & 0x000000FF);
// извлекаем 8-битный тип устройства у получателя из ID
14
/*data_b0 = rxBuf_can[0]&0xFF;
15
data_b1 = rxBuf_can[1]&0xFF;
16
data_b2 = rxBuf_can[2]&0xFF;
17
data_b3 = rxBuf_can[3]&0xFF;
18
data_b4 = rxBuf_can[4]&0xFF;
19
data_b5 = rxBuf_can[5]&0xFF;
20
data_b6 = rxBuf_can[6]&0xFF;
21
data_b7 = rxBuf_can[7]&0xFF;*/
22
DeCode_can_id_msg(direction,msg_type,dev_addr,rem_addr,dev_type,rxBuf_can);
23
}
24
}
Это декодирование
01
void
DeCode_can_id_msg(uint8_t direction,uint8_t msg_type,uint8_t dev_addr,uint8_t rem_addr,int8_t dev_type,
byte
rxBuf_can)
02
{
03
//Декодируем направление сообщения запрос-ответ
04
if
(direction==0)
05
{
06
Serial
.print(
"RX Reqv"
);
07
}
08
else
if
(direction==1)
09
{
10
Serial
.print(
"RX Ansv"
);
11
}
12
//Декодируем тип сообщения
13
int
i = 0;
14
int
table_size;
15
table_size =
sizeof
(Message_CANData)/
sizeof
(Message_CANvalueData);
16
for
(i = 0; i < table_size; i++)
17
{
18
if
(Message_CANData[i].msg_num == msg_type)
19
{
20
Serial
.print(
" type_msg - "
);
21
Serial
.print(Message_CANData[i].msg_name);
22
}
23
}
24
//Декодируем адрес отправителя
25
i = 0;
26
table_size =
sizeof
(Node_addr_CANData)/
sizeof
(Node_addr_CANvalueData);
27
for
(i = 0; i < table_size; i++)
28
{
29
if
(Node_addr_CANData[i].node_num == dev_addr)
30
{
31
Serial
.print(
" node_addr - "
);
32
Serial
.print(Node_addr_CANData[i].node_name);
33
}
34
}
35
//Декодируем адрес получателя
36
i = 0;
37
table_size =
sizeof
(Node_addr_CANData)/
sizeof
(Node_addr_CANvalueData);
38
for
(i = 0; i < table_size; i++)
39
{
40
41
if
(Node_addr_CANData[i].node_num == rem_addr)
42
{
43
Serial
.print(
" Rem_addr - "
);
44
Serial
.print(Node_addr_CANData[i].node_name);
45
46
}
47
}
48
//Декодируем тип устройства
49
i = 0;
50
table_size =
sizeof
(sens_dev_CANData)/
sizeof
(sens_dev_CANvalueData);
51
for
(i = 0; i < table_size; i++)
52
{
53
if
(sens_dev_CANData[i].dev_num == dev_type)
54
{
55
Serial
.print(
" Dev_type - "
);
56
Serial
.print(sens_dev_CANData[i].dev_name);
57
Serial
.print(
"\n"
);
58
}
59
}
60
61
}
Это передача
01
void
TX(
long
unsigned
int
txId_can,
int
can_msg_type,
int
can_type_id,
byte
data[8])
02
{
03
bool
err =
false
;
04
05
if
(can_type_id == 29)
06
{
07
if
(can_msg_type==0)
08
{
09
10
byte
sndStat = CAN0.sendMsgBuf(txId_can, 1, 8, data);
//send NORMAL EXTERNAL ID
11
if
(sndStat == CAN_OK){err=
false
;}
else
{err=
true
;}
12
}
else
if
(can_msg_type==4)
13
{
14
txId_can=0x40000000;
15
byte
sndStat = CAN0.sendMsgBuf(txId_can, 8, data);
//send REMOTE REQUEST FRAME
16
if
(sndStat == CAN_OK){err=
false
;}
else
{err=
true
;}
17
}
18
else
if
(can_msg_type==8)
19
{
20
byte
sndStat = CAN0.sendMsgBuf(txId_can,1 ,8, data);
//send NORMAL EXTERNAL ID
21
if
(sndStat == CAN_OK){err=
false
;}
else
{err=
true
;}
22
}
23
}
else
if
(can_type_id == 11)
24
{
25
if
(can_msg_type==0)
26
{
27
byte
sndStat = CAN0.sendMsgBuf(txId_can, 0, 8, data);
////send NORMAL STANDART ID
28
if
(sndStat == CAN_OK){err=
false
;}
else
{err=
true
;}
29
}
else
if
(can_msg_type==4)
30
{
31
txId_can = 0x40000000;
// send REMOTE REQUEST FRAME
32
byte
sndStat = CAN0.sendMsgBuf(txId_can, 8, data);
33
if
(sndStat == CAN_OK){err=
false
;}
else
{err=
true
;}
34
}
else
if
(can_msg_type==8)
35
{
36
txId_can = txId_can+0x80000000;
//0x80000000 переводит в расширенный, без нее стандартный
37
byte
sndStat = CAN0.sendMsgBuf(txId_can, 8, data);
38
if
(sndStat == CAN_OK){err=
false
;}
else
{err=
true
;}
39
}
40
}
41
42
//delay(100); // send data per 100ms
43
if
(err ==
false
){
44
//Serial.println("Message Sent Successfully!");
45
}
else
{
46
Serial
.println(
"Error Sending Message..."
);
47
}
48
}
1
long
unsigned
int
Code_can_id_msg(uint8_t direction,uint8_t msg_type,uint8_t dev_addr,uint8_t rem_addr,int8_t dev_type)
2
{
3
long
unsigned
int
can_id_msg;
4
5
can_id_msg=(direction & 0xFFFFFFFF)<<28 | (msg_type & 0x0FFFFFFF)<<24 | (dev_addr & 0x00FFFFFF)<<16 | (rem_addr & 0x0000FFFF)<<8 | (dev_type & 0x000000FF);
6
Serial
.print(
"TX CAN ID "
);
Serial
.println(can_id_msg, HEX);
7
return
can_id_msg;
8
}
1
TX(Code_can_id_msg(1, COMMAND_SEND, node_address, Hallway_net_center,air_h_s),0,29,data);
1
TX(0x02222222,8,29,data);
Декодирую через структуру, кодирую через перечисление
01
// Задаем перечисления и структуры для типов сообщений Y
02
typedef
enum
Message_enum
03
{
04
NULL_C,
//0
05
COMMAND_SEND,
//1
06
COMMAND_ANSVER,
//2
07
REQUEST_SEND,
//3
08
REQUEST_ANSVER,
//4
09
STATUS_REQUEST_SEND,
//5
10
STATUS_REQUEST_ANSVER
//6
11
12
} Message_CAN_ENUM;
13
14
typedef
struct
{
15
uint8_t msg_num;
16
String msg_name;
17
}Message_CANvalueData;
18
19
const
Message_CANvalueData Message_CANData[] =
20
{
21
/*Key KeyName */
22
{ 0 ,
"NULL_C"
},
23
{ 1 ,
"COMMAND SEND"
},
24
{ 2 ,
"COMMAND_ANSVER"
},
25
{ 3 ,
"REQUEST_SEND"
},
26
{ 4 ,
"REQUEST_ANSVER"
},
27
{ 5 ,
"STATUS_REQUEST_SEND"
},
28
{ 6 ,
"STATUS_REQUEST_ANSVER"
}
29
30
};
Тут еще оказалось, что у меня товарищ делает overCAN протокол для управления набором модулей , правда он на 11 битном (2.0а) но тоже есть интересные идеи. В наш протокол особо нужные идеи перенесу.
1. Идея это обязательно иметь уникальный номер сообщения, у контроллера, я его в блок данных внесу, крутится счетчик в рамках выделенных бит с сбросом в о после переполнения.
2. Ну это как в CAN Open возможность передачи не только Короткий – любые сообщения длиной до 8 байт но и Составной кадр – любые сообщения длиной более 8 байт.
3. Типы сообщений
Команда управления - сообщение в адрес узла
Команда-Запрос - сообщение в адрес узла с запросом выдачи информации о состоянии
Команда контроля
Технологическая команда
Ответное сообщение - ответ от узла
Инициативное сообщение – сообщение узла , выдаваемое в инициативном порядке.
В общем обмен написал, сечас подумаю на тему структуры протокола. Выложу сюда. Пока смотри node1.int https://yadi.sk/d/7pyVRdHJ3TNYXr