Очередной "Умный дом", на этот раз модульная система...

riv
Offline
Зарегистрирован: 20.07.2017

Я вот как то так вижу свой УД по автоматике, Мультирум и пр. умы это другой слой

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

Можешь выложить картинку в полном качестве? А то плохо видно. На я диск например. В общем с длинными ID я чето намучился, не получалось у меня. Не только канхакер их не видел, но и не отправлялись они вовсе. Использовал видимо корявую библиотеку. Она называлась также, как ты давал по ссылке, поэтому я твою не стал скачивать. А моя видать корявая с длинными ID не работает. Уже после того, как с 11бит все сделал у себя, твою либу попробовал. Вроде норм 29бит отправляет. Может переделаю еще. А то действительно 16 адресов может и не хватить. Вдруг меня растащщит)

P.S. Или ещё может ничего не получалось, т.к. один CAN модуль у меня был неисправный. Он отправлял СAN феймы, но не принимал. 

riv
Offline
Зарегистрирован: 20.07.2017
riv
Offline
Зарегистрирован: 20.07.2017

Я тоже с якобы неисправным модулем бился. Все дело только в библиотеках. Перепробовал все с github. Выбрал нужную. А расширенный заголовок позволяет сразу из заголовка вынуть от кого, кому, что за событите, что за датчик или исполнительное.

Вот примерно мой can_struct.h (он общий для всех прошивок. Контролллеров то много в сети). И да удобнее с десятичными работать нежели с байтом. Тут на вкус и цвет, просто обработка строки быстрее пишется на мой взгляд. и на этапе прототипа мне так удобнее.

Я не проф. программер, я связист.

#include <mcp_can.h>
#include <SPI.h>

//ID structure   xx.yy.z.a.cc
//      xx              yy                                     z             a                  cc
//  my address   remote address    type message  device address     device type 

//Node Address
int global_mfg;
//Основные помещения
uint32_t  Livingroom_main_11    = 11;  // Гостинная основной
uint32_t  Bedroom_main_21    = 21;  // Спальня основной
uint32_t  Cabinet_main_31   = 31;  // Кабинет основной
uint32_t  Hallway_main_41   = 41;  // Холл основной
//Мокрая зона
uint32_t  Kitchen_main_51   = 51;  // Кухня основной
uint32_t  WC_main_61   = 61;  // Туалет основной
uint32_t  WC_waterleak_62   = 62;  // Туалет защита от протечек
uint32_t  Bathroom_71   = 71;  // Ванна основной
uint32_t  Boxroom_81   = 81;  // Кладовая основной
uint32_t  Loggia_main_82   = 82;  // Лоджия основной
uint32_t  Balcony_83   = 83;  // Балкон основной

//Ядро сети и свет
uint32_t  Hallway_net_center_91   = 91;  // Холл ядро сети
uint32_t  Hallway_light_92   = 92;  // Холл ядро сети свет 
uint32_t  Kitchen_net_center_95   = 95;  // Кухня ядро сети
uint32_t  Kitchen_light_96   = 96;  // Кухня ядро сети свет

uint32_t  rxId;

//Type message
uint32_t  msg_tx_cmd_snd = 1; // NORMAL SEND COMMAND
uint32_t  msg_rx_cmd_ans = 2; // NORMAL ANSVER COMMAND
uint32_t  msg_tx_par_req = 3; // NORMAL SEND REQUEST
uint32_t  msg_rx_par_ans = 4; // NORMAL ANSVER COMMAND
uint32_t  msg_tx_stat_req = 5; //NORMAL SEND STATUS REQUEST
uint32_t  msg_rx_stat_ans = 6; //NORMAL ANSVER STATUS COMMAND

//device type 
//Sensor
uint32_t  air_temp_cens = 1;
uint32_t  air_hum_cens = 2;
uint32_t  air_pres_cens = 3;
uint32_t  motion_pir_cens = 4;
uint32_t  motion_mw_censor = 5;
uint32_t  vibration_censor = 6;
uint32_t  noise_censor = 7;
uint32_t  Illumination_censor = 8;
uint32_t  gas_co_censor = 9;
uint32_t  gas_co2_censor = 10;
uint32_t  gas_metan_censor = 11;
uint32_t  smoke_censor = 12;
uint32_t  fire_censor = 13;  //Огонь
uint32_t  body_temperature_censor = 14;  //Температура тела
uint32_t  jalousie_status_censor  = 15;  //Жалюзи
uint32_t  steam_censor      = 16; //Пар
uint32_t  microwave_censor = 17; //Излучение микроволновки
uint32_t  fridge_temperature_censor = 18; //Холодильник
uint32_t  freezer_temperature_censor = 19; //Морозилка
uint32_t  oven_temperature_censor = 20; //Духовка
uint32_t  electrical_board_censor = 21; //Электрощит концевик
uint32_t  door_lock_censor = 22; //Замок двери
uint32_t  door_close_censor = 23; //Замок двери
uint32_t  motion_door1_censor = 24; //Датчик прохода 1
uint32_t  motion_door2_censor = 25; //Датчик прохода 2
uint32_t  window_close_censor = 26; //Закрыто
uint32_t  water_hot_temperature_censor = 27; //Температура горячей воды
uint32_t  water_cold_temperature_censor = 28; //Температура холодной воды
uint32_t  water_hot_pressure_censor = 29; //Давление горячей воды
uint32_t  water_cold_pressure_censor = 30; //Давление холодной воды
uint32_t  leakage_censor = 31; //Протечка
uint32_t  counter_gas_censor = 32; //Счетчик газа
uint32_t  counter_water_hot_censor = 33; //Счетчик горячей воды
uint32_t  counter_water_cold_censor = 34; //Счетчик холодной воды
uint32_t  counter_electricity_censor = 35; //Счетчик электричества
uint32_t  cupboard_door_censor = 36; //Дверь шкафа
uint32_t  safe_door_censor = 37; //Дверь сейфа
uint32_t  balcony_door_censor = 38; //Дверь балкона
uint32_t  loggia_door_censor = 39; //Дверь лоджии
uint32_t  radiator_temperature_censor = 40; //Температура батареи
uint32_t  lamp_ceiling_censor = 41; //Лампа на потолке
uint32_t  lamp_wall_censor = 42; //Ланпа настенная
uint32_t  lamp_Illumination_censor      = 43; //Лампа подсветки
uint32_t  lamp_accident_censor = 44; //Лампа аварийная
uint32_t  earth_humidity_censor = 45; //Влажность земли
uint32_t  lamp_aquarium_censor = 46; //Лампа аквариум
uint32_t  aquarium_temperature_censor = 47; //Температура аквариум
uint32_t  aquarium_pump_censor          = 48; //Насос аквариум
uint32_t  aquarium_clearing_censor      = 49; //Очистка аквариум
// темп рекуператора
//темп, вл, давл, улица


//Device Digital //Device analog
uint32_t  lamp_ceiling_onoff_device = 60; //Лампа на потолке вкл/выкл
uint32_t  lamp_wall_onoff_device = 61; //Ланпа настенная вкл/выкл
uint32_t  lamp_Illumination_onoff_device = 62; //Лампа подсветки вкл/выкл
uint32_t  lamp_accident_onoff_device = 63; //Лампа аварийная вкл/выкл
uint32_t  lamp_ceiling_dimm_device = 64; //Лампа на потолке диммируемая
uint32_t  lamp_wall_dimm_device = 65; //Ланпа настенная диммируемая
uint32_t  lamp_Illumination_dimm_device = 66; //Лампа подсветки диммируемая
uint32_t  lamp_accident_dimm_device = 67; //Лампа аварийная диммируемая
uint32_t  fan                            = 68;
uint32_t  recuperator                    = 69;
uint32_t  air_conditioning              = 70;
uint32_t  valve_radiator                = 71;
uint32_t  jalousie                      = 72;
uint32_t  valve_gas                      = 73;
uint32_t  valve_hot_water                = 74;
uint32_t  valve_cold_water              = 75;
uint32_t  irda                          = 76;
uint32_t  freshener                      = 77; //Освежитель
uint32_t  humidifier                    = 78; //Увлажнитель
uint32_t  door_lock_magnet              = 79;
uint32_t  door_lock_electromagnet        = 80;
uint32_t  door_lock_electromechanical    = 81;
uint32_t  door_lock_blink                = 82;
uint32_t  siren                          = 83;
uint32_t  blinker                        = 84;
uint32_t  music                          = 85;
uint32_t  tv                            = 86;
uint32_t  radio                          = 87;
uint32_t  power_socket                  = 88; //Розетки

unsigned char len = 0;
unsigned char rxBuf[8];
unsigned char txBuf[8];
char msgString[128];                          // Array to store serial string 
#define CAN0_INT 2                                // Set INT to pin 2
MCP_CAN CAN0(53);                               // Set CS to pin (NANO, UNO etc = 10, MEGA,DUE etc = 53)

 

 

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

Жесть какой широкий у тебя размах). У меня два вопроса. Зачем применяешь uint32_t. Неужели uint16_t не хватит? И второе , смотри самый первый разряд в ID тот который ХХ, имеет не весь диапазон адресов ( не 256) , т.к первый ниббл Х может принимать значения только от 0 до 7. Потому что ID 29 бит, а не 32. Т.е на этот ниббл Х отводится 3 бита вместо четырех.

riv
Offline
Зарегистрирован: 20.07.2017

По поводу размаха - если присмотреться делается типовое изделие практически серийное, все блоки одинаковые, я под них заложил в каждом помещении по 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

 

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

да, прототип хорош. На счет работы без контроллеров, ну не знаю. Вот у меня свет на втором этаже уже два года только в схеме с МК работает - выключатели света слаботочные на 5В, подают только сигнал на МК. Проблем не было никаких, даже в сильную грозу. Главное применять опторазвязки, провода в экране. А если коряво подходить к вопросу, дак и без МК что нибудь сгореть, сломаться может.

По поводу ID поменяй местами разряды и делов то:  Z.XX.YY.A.CC

где Z - тип сообщения, их у тебя 6, ещё 1 в запасе остаётся. 

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

riv пишет:
Так проще писать адреса без пересчета, в десятичной системе.

дак никто не мешает писать в десятичной системе на типе byte . Контроллеру то пофиг, ему всё одно - нули и единицы. просто пишешь число и всё - будет десятичная, если добавить перед записью числа 0x  - это HEX. Если добавить B - бинарная запись (в битах). 

riv
Offline
Зарегистрирован: 20.07.2017

Я не  точно объяснил. 

Использую бистабтльные реле РИО-1М и кнопочные выключатели. В паралель к кнопкам ставлю ТТ реле которым управлю с ардуино. Т.о. даже при отсутствии контроллеров свет управлется. И т.д. В дальнейшем при сбое или поломке контроллера я не сижу при свечах. Опторазвязки я естественно буду использовать. Нарпимер АОТ166 для проверки наличия напржения на лампах освещения.  Строю 2х уровневую, даже 3х уровневую систему. 1 уровень пром. реле. Второй уровень автоматика на МК, 3 уровень сцены на Сервере.

И дело даже не в надежности. Если бы я поше по пути контроллера то сидел бы без света сейчас. А так реле потавил и все работает. Сверху поставлю МК и буду им щелкать реле в паралель с кнопками. 

Насчет стрктуры - отличная идея.

riv
Offline
Зарегистрирован: 20.07.2017

Я вроде с этим тыкался, но для отладки быстрее выводиь все что пришло в сериал, а там опять преобразования. Естественно потом напишу.

Вот тут мои наброски https://yadi.sk/d/7pyVRdHJ3TNYXr

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

имхо, у тебя замороченная схема извлечения разрядов из ID

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

riv пишет:
Использую бистабтльные реле РИО-1М и кнопочные выключатели. В паралель к кнопкам ставлю ТТ реле которым управлю с ардуино. Т.о. даже при отсутствии контроллеров свет управлется. И т.д. В дальнейшем при сбое или поломке контроллера я не сижу при свечах. Опторазвязки я естественно буду использовать. Нарпимер АОТ166 для проверки наличия напржения на лампах освещения.  Строю 2х уровневую, даже 3х уровневую систему. 1 уровень пром. реле. Второй уровень автоматика на МК, 3 уровень сцены на Сервере.

И дело даже не в надежности. Если бы я поше по пути контроллера то сидел бы без света сейчас. А так реле потавил и все работает. Сверху поставлю МК и буду им щелкать реле в паралель с кнопками.

ну в общем да, согласен, так наверное лучше. Понятно, что когда строишь систему УД делаешь много ошибок. Я если бы сейчас начинал, всё вообще бы не так сделал. А щас переделывать ужё лень - слишком много делов 

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

riv пишет:

Я вроде с этим тыкался, но для отладки быстрее выводиь все что пришло в сериал, а там опять преобразования.

вот это не понял немного. Какие преобразования. Для отладки я использую CAN сниффер. Мне почему удобнее работать с HEX, так как все анализаторы CAN шины выводят инфу в HEX и визуально уже привыкаешь все адреса и байты видеть в HEX. А без анализаторы шины при построении тайой системы я вообще не знаю как можно обойтись. Я почему в своей 11битной схеме ID  и отказался от 5 битных адресов, потому как их визуально мониторить вообще проблема. Хотя так было бы 32 адреса, а не 16. 

 

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

Я конечно тоже далекооо не крутой программист, вернее вообще не программист, но

с функцией void TX()  нужно тебе подумать 

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)
{
  byte data[8] = {a, b, c, d, e, f, g, h};
  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
//  byte sndStat2 = CAN0.sendMsgBuf(0x40000111, 8, data); //txBuf
  if(sndStat == !CAN_OK){ Serial.print("MSG send error!"); }
  //delay (310);
}

 в качестве параметров этой функции ты передаешь переменные типа флоат (а,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пользуй.

Нельзя так к памяти МК относится, это я уже давно понял. 

 

riv
Offline
Зарегистрирован: 20.07.2017

MaksVV пишет:

riv пишет:

Я вроде с этим тыкался, но для отладки быстрее выводиь все что пришло в сериал, а там опять преобразования.

вот это не понял немного. Какие преобразования. Для отладки я использую CAN сниффер. Мне почему удобнее работать с HEX, так как все анализаторы CAN шины выводят инфу в HEX и визуально уже привыкаешь все адреса и байты видеть в HEX. А без анализаторы шины при построении тайой системы я вообще не знаю как можно обойтись. Я почему в своей 11битной схеме ID  и отказался от 5 битных адресов, потому как их визуально мониторить вообще проблема. Хотя так было бы 32 адреса, а не 16. 

Анализатора нет, подумаю на тему купить. Использовал прямой вывод всего что есть в сериал.

riv
Offline
Зарегистрирован: 20.07.2017

MaksVV пишет:

Я конечно тоже далекооо не крутой программист, вернее вообще не программист

Нельзя так к памяти МК относится, это я уже давно понял.

Я же говорю это был концепт, за выходные накидать, проверить что работает и вперед. Поэтому раньше и не выкладывал это позорище ;-)

Сейчас скинул чтобы идею обмена, работающую показать. Где то в коде вроде даже чтото с датчиками есть.

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

riv пишет:
Анализатора нет, подумаю на тему купить. Использовал прямой вывод всего что есть в сериал.

не надо покупать, делается за 5 мин

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

смотри мой скетч #195, как я разряды вытягивал из переменной заголовка ID , там библиотека только не как у тебя, попроще она. 

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

вот по твоей теме вытянул в переменные byte разряды из 29-битного ID заголовка. Без всяких стрингов. Тип сообщения уже поставил на первый разряд

void RX()
{
  if(!digitalRead(CAN0_INT))                         // If CAN0_INT pin is low, read receive buffer
  {
    CAN0.readMsgBuf(&rxId, &len, rxBuf);      // Read data: len = data length, buf = data byte(s)
    
     byte z,xx,yy,a,cc;

z  = (rxId & 0xF0000000)>>28;
xx = (rxId & 0xFF00000)>>20;
yy = (rxId & 0xFF000)>>12;
a  = (rxId & 0xF00)>>8;
cc = (rxId & 0xFF);
 
Serial.print(" CAN_ID  ");
Serial.print(xx); //если нужно в НЕХ выводить в монитор просто пишешь так Serial.print(xx, HEX);
Serial.print(" ");
Serial.print(yy);
Serial.print(" ");
Serial.print(z);
Serial.print(" ");
Serial.print(a);
Serial.print(" ");
Serial.print(cc);
Serial.print(" ");
Serial.println();
  }

if (z==1){ // если тип сообщения: "1"
  // тогда что-нибудь тут сделаем и т.д.
  
  }

  
}

 

 

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

а вот как обратно запихать в txId необходимые разряды: 

unsigned long txId = 0x1ABCDEF2; // допустим был такой ID

//ниже, например, пусть будут у нас такие разряды 
byte z =  0x05;
byte xx = 0xDD;
byte yy=  0xEE;
byte a =  0xB ;
byte cc = 0xCC;


void setup() {

Serial.begin (9600);
Serial.print ("Old ID:                ");
Serial.println (txId, HEX);


// ниже вобъём наши разряды по одному в существующий ID, не задевая остальные разряды

Serial.println ("z=5, xx=DD, yy=EE, a=B, cc=CC");

txId = (txId & 0x0FFFFFFF)| (z & 0x0FFFFFFF)<<28; // вбиваем в ID разряд z, не трогая остальное

Serial.print ("New ID +z:             ");
Serial.println (txId, HEX);

txId = (txId & 0xF00FFFFF)| (xx & 0xF00FFFFF)<<20; // вбиваем в ID разряд xx, не трогая остальное

Serial.print ("New ID +z,xx:          ");
Serial.println (txId, HEX);

txId = (txId & 0xFFF00FFF)| (yy & 0xFFF00FFF)<<12; // вбиваем в ID разряд xx, не трогая остальное

Serial.print ("New ID +z,xx,yy:       ");
Serial.println (txId, HEX);

txId = (txId & 0xFFFFF0FF)| (a & 0xFFFFF0FF)<<8; // вбиваем в ID разряд a, не трогая остальное

Serial.print ("New ID +z,xx,yy,a:     ");
Serial.println (txId, HEX);

txId = (txId & 0xFFFFFF00)| cc;                  // вбиваем в ID разряд cc, не трогая остальное

Serial.print ("New ID +z,xx,yy,a,cc:  ");
Serial.println (txId, HEX);


  
}

void loop() {
 

}

 

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

MaksVV пишет:
самый первый разряд в ID тот который ХХ, имеет не весь диапазон адресов ( не 256) , т.к первый ниббл Х может принимать значения только от 0 до 7. Потому что ID 29 бит, а не 32. Т.е на этот ниббл Х отводится 3 бита вместо четырех.

Сейчас подсчитал - что-то я напутал. Это в 11-битном ID на первый разряд 3 бита отводится (от 0 до 7), а в 29-битном на первый разряд отводится 1 бит, т.е. значения может принимать только 0 или 1. Поэтому нельзя туда тип сообщения вешать, придётся тебе жертвовать нибблом a device address. и вместо него этот тип сообщения z ставить. 

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

И я , наконец, разобрался почему ничего не получалось у меня с 29-битными ID. При опробовании этих 29бит наложилось несколько косяков - это нерабочий CAN модуль и плюсом к этому, я в обоих библиотеках (пробовал и твою и мою) просто неправильно отправлял расширенные ID. Поэтому толком не приходили эти 29битные ID и не отправлялись. Теперь разобрался с обоими библиотеками, как отправлять расширенные ID. 

В твоей библиотеке нужно в единичку ставить этот бит - выделен жирным (если он будет 0 то это 11бит) при отправке: 

 CAN0.sendMsgBuf(0x12345678, , 8, stmp);

А в моей библиотеке будет так:

 mcp2515.sendMessage(&canMsg2); // это отправка стандартного фрейма 11 бит
 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 адресов для МК, работающих на одной шине.  

 

 

riv
Offline
Зарегистрирован: 20.07.2017

MaksVV пишет:

Сейчас подсчитал - что-то я напутал. Это в 11-битном ID на первый разряд 3 бита отводится (от 0 до 7), а в 29-битном на первый разряд отводится 1 бит, т.е. значения может принимать только 0 или 1. Поэтому нельзя туда тип сообщения вешать, придётся тебе жертвовать нибблом 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
итого
 
//ID structure   
//   0000 0000      0000 0000            0000 0        0000 000             0000 0000 0
//    0-255             0-255                   0-31             0-127                 0-1023
//  my address   remote address    type message  device address     device type 
Как то так.
Что скажешь?
riv
Offline
Зарегистрирован: 20.07.2017

MaksVV пишет:

А в моей библиотеке будет так:

 mcp2515.sendMessage(&canMsg2); // это отправка стандартного фрейма 11 бит
 mcp2515.sendMessage(MCP2515::TXB1,&canMsg1); // а вот так нужно отправлять фреймы с 29-битным ID

Кинь сылку на свою библиотеку. Может на одной либе начать работать, мне в принципе пока все равно. Я на этапе концепта.

Да и вообще может есть смысл начать плавно объединять усилия. Я сейчас в течении месяца ремонт завершу и займусь активнее разработкой. Мы вроде практически единстренные на форуме из любителей (имею ввиду не зарабатывающих на УД) в CAN двинули, всех 485 устраивает. 

Что я хочу получить на выходе ты увидел на схеме.

Так же хочу сделать аппаратную систему зоновой трансляции. Много аппаратных источников аудио (FM, USB MP3/SD MP3/AUX на УД/Bluetooth/AUX IP радио етс. Делать все буду на аудиопроцах или готовых модулях упр. по i2c (PT2314 TDA7419 или TEA6420)

Я из щита в каждое помещение завел аудиокабель и поставил динамик.

Ну а потом и мультирум.

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

riv пишет:

 
Это двоичная
//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 
 
 
//ID structure   
//   0000 0000      0000 0000            0000 0        0000 000             0000 0000 0
//    0-255             0-255                   0-31             0-127                 0-1023
//  my address   remote address    type message  device address     device type 
Как то так.
Что скажешь?

эмм. не понял откуда ты столько бит взял? тут же больше 29 (посчитай нолики)

по моим подсчетам вот так изначально у тебя затевалось:

//ID structure   
//   0000 0000      0000 0000             0000            0000               0000 0000  // итого 32 нолика многовато для CAN
//    0-255             0-255                   0-15             0-15                  0-255
//  my address   remote address    type message  device address   device type 
 
а по факту вот так выходит (переставим в начало как я хотел type message)
 
//ID structure   
//       0                       0000 0000      0000 0000              0000              0000 0000   // итого 29 ноликов
//      0-1                        0-255             0-255                  0-15                 0-255
//type message           my address   remote address     device address     device type 

как видим на type message что то мало значений приходится))

 

предлагаю убрать device address (ну засунешь его в тело сообщения, это ничего не меняет)

и делить разряды кратно 4 битам, т.е. нибблам. Поверь, это важно при отладке визуально в кан анализаторе. К тому же вытягивать числа из ID не кратные 4 битам вообще жопа (см. на предыдущей странице как я делал 5-битные адреса). В итоге предлагаю сделать так: 

 //ID structure   

//       0               0000           0000 0000       0000 0000       0000 0000   // итого 29 ноликов
//      0-1             0-15               0-255             0-255               0-255
//    no use    type message    my address   remote address    device type 
MaksVV
Онлайн
Зарегистрирован: 06.08.2015

моя библиотека, она работает не используя контакт INT CAN модуля. Что наверное плохо. Хотя ничто не мешает нам самим добавить сюда этот сигнал. (а в твоей либе походу без INT никак).  Просто я, дурень, не подключил этот контакт в МК_свет, а сейчас опять щит вскрывать влом. Но вроде работает пока c моей либой без INT вообще гуд. 

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

вместе всегда проще, конечно. А то я тут один долго демагогию по кану разводил))

/device type 
//Sensor
uint32_t  air_temp_cens = 1;
uint32_t  air_hum_cens = 2;
uint32_t  air_pres_cens = 3; //и т.д.

это предлагаю не заводить на переменные, а просто задефайнить. Так память здорово экономится, учитывая сколько у тебя этих типов.

/device type 
//Sensor
#define  AIR_TEMP_CENS  1
#define  AIR_HUM_CENS    2
#define  AIR_PRES_CENS  3
и т.д.

в принципе стратегия CAN шины такая (я тут недавно тоже рассказывал одному человеку про CAN):

МК нижний от верхнего получает инфу о состоянии включенности света в комнатах, движении в комнатах, пож.датчиков. Всего комнат вверху 5 и всё это передается в одном сообщении, всего в 3-х байтах (Одно сообщение CAN может нести до 8 байт инфы). Так компактно получается, потому что переменные булевые, т.е. биты. Значит в одном байте можно передавать 8 таких переменных. в 3 байтах можно передать состояние света в 24 комнатах, а в одном CAN фрейме в 64 комнатах))

Если переменная типа int (занимает 2 байта) передает температуру, то её можно запихать в 1 байт, переделав в однобайтовый int8_t т.к. температура у нас не вылазит из диапазона до -127 до +128, что и является одним байтом. Т.е. в одном CAN фрейме можно передать 8 температур, или ещё чего нибудь в диапазоне от 0 до 255. 

Я научился всё это преобразовывать и туда и и обратно. Ну вот , например, вкачивать в байты отдельные биты (читай булевые переменные) и наоборот вытягивать отдельные биты из байтов.  Как было приятно увидеть, когда всё почти сразу заработало, как было задумано. 

Верхний же МК, получает от нижнего информацию - время, состояние охраны, состояние наличия напряжения 220В. Например, время нужно, чтобы включать и выключать функцию "автосвет" автоматически по времени. напряжение 220В нужно знать  - если его нет, все реле света выключаем, чтобы экономить ИБП и т.д. 

также верхний МК получает команды от нижнего на включение света, например, при имитации хозяев в доме, или просто кто-то через Wi-Fi со смартфона свет хочет включить.  

Короче, устанавливая связь между МК, мы получаем гибчайший инструмент для технического творчества, не протягивая при этом здоровенные пучки проводов. 
МК периодически выкидывает в кан свои параметры с датчиков и.т.д, и также слушает кан шину, получая также параметры от других МК и команды от других МК. 
Полученные параметры понятно, мы просто используем. А вот получив команду, мы кроме реагирования на неё, еще шлем в шину отчет о том, что приняли эту команду, шлём 3 раза. 
И напротив, когда мы шлём кому нибудь команду управления, мы, кроме всего прочего, начинаем ждать ещё отчёт о полученности нашёй отправленной команды. Если через полсекунды не получили отчет - шлём команду ещё раз и так 10 раз. Если же так и не получили отчёт, прекращаем это дело, записываем код неисправности. На практике, более одного раза у меня команде не приходилось отправляться - потому как отчёт мгновенно приходит - всё гуд (а вообще это нужно, если команда прилетела, когда МК во время delay простаивает)

я думаю тебе стоит к ней подтягиваться т.к. у меня уже реально неделю работает, сбоев нет. В скетче #195 вобщем-то всё подробно прокомментировано. 

riv
Offline
Зарегистрирован: 20.07.2017

MaksVV пишет:

моя библиотека

Ок. Готов пользовать ее, единственое что меня смущает что ее доработка остановилась, а 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, делает рассылку оконечным на смену мастера.

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

riv пишет:
2. Работа с исполнительными устройствами

При отправке команды исполнительному у-ву булевому, дискретному, временному ждем квитирование принятия команды к исполнению + ждем отчета о исполнении. Вся логика работы к исполнителным у-вом как и с датчиком лежит в оконечном МК, центр должен работать со всеми датчиками и ИУ абстрагировано, выдал команду получил отчет.

вот тут непонятно, если CAN упадёт, как будут себя вести локальные МК, типа переходить в автономный режим работы? С остальными дополнениями в принципе согласен. 

Эх, как бы это ещё всё запрограммировать . И что со структурой ID, согласен с предложенным мной вариантом?

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

del

riv
Offline
Зарегистрирован: 20.07.2017

MaksVV пишет:

вот тут непонятно, если CAN упадёт, как будут себя вести локальные МК, типа переходить в автономный режим работы? С остальными дополнениями в принципе согласен. 

Да, с минимальным функционалом по жесткому алгоритму (Переход с ДУ на МУ) , хотя я бы просто переводил в режим ожидания.

MaksVV пишет:

Эх, как бы это ещё всё запрограммировать .

Ну дорогу осилит идущий ;-)

MaksVV пишет:

И что со структурой ID, согласен с предложенным мной вариантом?

Извини может я туплю можещь ее формализовать и выложить сюда в формате xyz ?

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

riv пишет:

Извини может я туплю можещь ее формализовать и выложить сюда в формате xyz ?


Читай сообщение #225. Там я предложил в твоем формате, только без adress device

riv
Offline
Зарегистрирован: 20.07.2017

MaksVV пишет:
riv пишет:

Извини может я туплю можещь ее формализовать и выложить сюда в формате xyz ?

Читай сообщение #225. Там я предложил в твоем формате, только без adress device

Вот я и говорю что ступил, простто пропустил сообщение.

riv
Offline
Зарегистрирован: 20.07.2017

Я пока формулирую концепцию для обсуждения,  ведь мы по сути делем протокол 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/

Не забывай про протоколы верхнего уровня

  • MQTT: протокол для сбора данных устройств и передачи их серверам (D2S);
  • XMPP: протокол для соединения устройств с людьми, частный случай D2S-схемы, когда люди соединяются с серверами;
  • DDS: быстрая шина для интегрирования интеллектуальных устройств (D2D);
  • AMQP: система организация очередей для соединения серверов между собой (S2S).

(Вот тут почитай http://www.rtsoft.ru/press/articles/detail.php?ID=2718)

Протокол MQTT https://ipc2u.ru/articles/prostye-resheniya/chto-takoe-mqtt/ с которым хочешь не хочешь придется считаться т.к. на нем практически все opensourser сервера УД живут.

riv
Offline
Зарегистрирован: 20.07.2017

И работа с ниблами просто ресурс адресации сжигает. По рукам и ногам вяжет. Весь интернет на 32 витах адресуется а мы из-за ниблов не модем 256 GPIO адесовать. Может другой путь обдумать. Потом локти кусать будем.

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

почитал бегло, есть над чем задуматься. Не охото велосипед изобретать. Надо более подробно почитать. Инфа полезная. 

riv
Offline
Зарегистрирован: 20.07.2017

И ты только не бросайся в меня чем не попадя, мне удалось нормально https://github.com/jgeisler0303/CANFestivino собрать

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

riv пишет:

И работа с ниблами просто ресурс адресации сжигает. По рукам и ногам вяжет. Весь интернет на 32 витах адресуется а мы из-за ниблов не модем 256 GPIO адесовать. Может другой путь обдумать. Потом локти кусать будем.

Не очень понял про какие нибблы речь. Ниббл всего один используется в предложенном мной варианте - это type message, 16 значений разве не хватит?

Я чесно использовал в предложенном варианте 28 бит из 29. А больше 29бит то ведь низя! Не влезает сюда этот device address. 

А если значений device type мало. Ну давай оставшийся неиспользуемый бит прилепим к байту типа девайса и будет тебе не 256 типов устройств, а 512. 

Ещё раз предложенный вариант 

//ID structure   

//       0               0000           0000 0000       0000 0000       0000 0000   // итого 29 бит (показаны нолями)
//      0-1             0-15               0-255             0-255               0-255
//    no use    type message    my address   remote address    device type 
MaksVV
Онлайн
Зарегистрирован: 06.08.2015

riv пишет:

И ты только не бросайся в меня чем не попадя, мне удалось нормально https://github.com/jgeisler0303/CANFestivino собрать

блин, вообще нифига не понятно))

тебе конечно попроще оперировать всеми этими понятиями. Я так понял, ты варишься частенько в этом всём. В материале так сказать  - топологии, всякие верхние уровни. 

Мне тяжко столько инфы сразу для восприятия, я ведь всего лишь автомобильный диагност. С компьютером то дружу, но вот с сетями...

riv
Offline
Зарегистрирован: 20.07.2017

Давай пойдем от задач. Совсем сверху.

1. Есть дом/квартира с n помещений в которых есть датчики и исполнительные устройства (ИУ) и вкоторые из центра идут кабели или радиоканалы. (Перечень датчиков и исполнительных устройств см. на моей схеме)

2. Есть оконечные контроллеры которые являются концентраторами датчиков и ИУ, принимают от них данные передают наверх и получают команды сверху. В общем случае просто расширители от центра. Есть исключения например система защиты от протечек у нее 2 жестких сценария, либо закрыть краны от датчиков либо по команде от центра + сервичные провороты кранов. Управление котлом например. И прочие узкие задачи.

3. Есть центр сосредоточния кабелей т.е. ядро сети от куда будем всем управлять по более сложным но все равно фиксированным сценариям. И откуда работает автоматика-автоматизация по простым алгоритмам ( есть движение зажгли свет, стало жарко включили кондиционер, холодно котел или электрорадиатор, стало много со2 включили рекуператор и т.д)

4. Есть сервер УД который дает возможность визуализации всех событий от датчиков, ИУ и самое главное дает возможность создавать сложные сценарии. Например зимой теплее холоднее это задвижки на радиаторах а летом кондиционер и пр. Режимы освещения и пр. Т.е он через Web например позволяет задать контроллерам параметры для изменения алгоритмов. 

Отсюда требования к системе.

1. Потеря контроллера (поломка) не приводит к аварии в доме. Это как раз достигается запаралеливанием управления от МК и от клавиш, кнопок, тумблеров пультов. Т.е мы просто делаем дистанционное управление устройствами и снятие показаний но не убираем возможность управлять в ручную. Например если МК защиты от протечек умрет я не останусь без воды, если МК света то буду выключателями включать и т.д

2. Должны быть заданы минимальные управляющие алгоритмы абстрагирующие нас и верхний уровень от взаимодействия с датчиком или ИУ. Т.е запросил температуру получил значение. Дал команду зажечь свет, он зажегся и получено подтверждение что он зажегся. Независимо как мы его зажигаем. Могут быть разные типы управления светом дискретные если диммер или булевы если реле.

....

Завтра допишу.  

 

riv
Offline
Зарегистрирован: 20.07.2017

Перебрал все варианты, решил остановиться на твоем, с небольшим изменением

//ID structure   x.y.z.aa.bb
//      X            Y               AA              BB                              CC         
//  direction  type message     node address   remote node address      remote node sensor/device  type 
Набросал немного кода, посмотри если несложно.
Уткнулся в кодирование CAN ID из значений ENUM
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)
{
long unsigned int can_id_msg;

Serial.print("TX Direction " );Serial.println(direction);
Serial.print("TX Comm_type " );Serial.println(msg_type);
Serial.print("TX Node addr " );Serial.println(dev_addr);
Serial.print("TX Rem addr" );Serial.println(rem_addr);
Serial.print("TX Dev type " );Serial.println(dev_type);

///can_id_msg=???????????????; Как собрать uint8_t в long unsigned int сохранив структуру байтов??????????
Serial.print("TX CAN ID " );Serial.println(can_id_msg, HEX);
return can_id_msg;
}

Подскажи Как собрать uint8_t в long unsigned int сохранив структуру байтов CAN ID?

 

 
MaksVV
Онлайн
Зарегистрирован: 06.08.2015

MaksVV пишет:

Я чесно использовал в предложенном варианте 28 бит из 29. А больше 29бит то ведь низя! Не влезает сюда этот device address. 

А если значений device type мало. Ну давай оставшийся неиспользуемый бит прилепим к байту типа девайса и будет тебе не 256 типов устройств, а 512. 

Ещё раз предложенный вариант 

//ID structure   

//       0               0000           0000 0000       0000 0000       0000 0000   // итого 29 бит (показаны нолями)
//      0-1             0-15               0-255             0-255               0-255
//    no use    type message    my address   remote address    device type 

вот как будет выглядеть на практике работа с разрядами, если сделать device type 9-битным (512 значений).

unsigned long ID = 0x1CCDDBBE; // допустим получили из CAN такой ID

uint16_t  device_adress;  // в эту переменную запишем самый старший 9-битный разряд из ID (1СС)

uint16_t  device_adressNEW = 510; // а потом обратно, в старший разряд ID запишем этот адрес (в HEX это 1FE)

void setup() {

Serial.begin (9600);

device_adress = (ID & 0xFFF00000)>>20;  // вытянем из старшего разряда ID-заголовка 9-битный device type 
 
Serial.println (device_adress, HEX);


// и обратно - запихаем в старший разряд ID-заголовока переменную  device_adressNEW:
ID = (ID & 0x000FFFFF) | (device_adressNEW & 0x000FFFFF)<<20; 


Serial.println (ID, HEX);

}

void loop() {}

 

riv
Offline
Зарегистрирован: 20.07.2017

MaksVV пишет:

//ID structure   

//       0               0000           0000 0000       0000 0000       0000 0000   // итого 29 бит (показаны нолями)
//      0-1             0-15               0-255             0-255               0-255
//    no use    type message    my address   remote address    device type 

Я готов использовать твой вариант, только первый бит жалко я его для определения ответ на мой запрос и или запрос ко мне использую

//       0               0000           0000 0000       0000 0000       0000 0000   // итого 29 бит (показаны нолями)
//      0-1             0-15               0-255             0-255               0-255
//    direction    type message    my address   remote address    device type 
 
512 бит не нужно,  хватит 256.
riv
Offline
Зарегистрирован: 20.07.2017

Del

riv
Offline
Зарегистрирован: 20.07.2017

Спасибо, в твоем примере нашел.

can_id_msg=(direction & 0xFFFFFFFF)<<28 | (msg_type & 0x0FFFFFFF)<<24 | (dev_addr & 0x00FFFFFF)<<16 | (rem_addr & 0x0000FFFF)<<8 | (dev_type & 0x000000FF);

Гдеб об этом почитать, а то как сапер примеры разбираю.

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

 можно так

can_id_msg= (direction & 0xFFFFFFFF)<<28 | (msg_type & 0xFFFFFFFF)<<24 | (dev_addr & 0xFFFFFFFF)<<16 | (rem_addr & 0xFFFFFFFF)<<8 | dev_type;

читать про побитовые операции. Я сам это плохо понимаю, так допёр опытным путём.  

MaksVV
Онлайн
Зарегистрирован: 06.08.2015

riv пишет:
Я готов использовать твой вариант, только первый бит жалко я его для определения ответ на мой запрос и или запрос ко мне использую

а вот как парсить приходящий ID при таком твоём варианте

unsigned long rxId = 0x1ABCDEF2; // допустим был такой ID

//ниже, например, пусть будут у нас такие разряды 

bool direction;
byte z;            // type message 
byte xx;           // my address
byte yy;           // remote address
byte cc;           // device type


void setup() {

Serial.begin (9600);



direction  = (rxId & 0xF0000000)>>28;

z = (rxId & 0xF000000)>>24;

yy = (rxId & 0xFF0000)>>16;

xx  = (rxId & 0xFF00)>>8;

cc = (rxId & 0xFF);



Serial.print ("RX CAN_ID     "); Serial.println (rxId, HEX);

Serial.print("parse CAN_ID  ");


Serial.print(direction, HEX);

Serial.print(" ");

Serial.print(z, HEX);

Serial.print(" ");

Serial.print(yy, HEX);

Serial.print(" ");

Serial.print(xx, HEX); //если нужно в НЕХ выводить в монитор просто пишешь так Serial.print(xx, HEX);

Serial.print(" ");

Serial.print(cc, HEX);

Serial.print(" ");

Serial.println();


  
}

void loop() {}

 

riv
Offline
Зарегистрирован: 20.07.2017

Я вот так реализовал на своей библиотеке https://github.com/coryjfowler/MCP_CAN_lib

Это прием

void RX()
{
  uint8_t direction, msg_type, dev_addr, rem_addr, dev_type;
  uint8_t data_b0,data_b1,data_b2,data_b3,data_b4,data_b5,data_b6,data_b7;
  if(!digitalRead(CAN0_INT))                         // 
  {
    CAN0.readMsgBuf(&rxId_can, &len_can, rxBuf_can);      // Read data: len = data length, buf = data byte(s)

    direction  = (rxId_can & 0x10000000)>>28;   //  извлекаем 1-битный идентификатор запроса-ответа из ID
    msg_type = (rxId_can &   0x0F000000)>>24; //    извлекаем 4-битный идентификатор сообщения из ID  
    dev_addr  = (rxId_can &  0x00FF0000)>>16;   //  извлекаем 8-битный адрес отправителя из ID
    rem_addr = (rxId_can &   0x0000FF00)>>8; //     извлекаем 8-битный адрес получателя из ID
    dev_type = (rxId_can &   0x000000FF); //        извлекаем 8-битный тип устройства у получателя из ID
    /*data_b0 = rxBuf_can[0]&0xFF;
    data_b1 = rxBuf_can[1]&0xFF;
    data_b2 = rxBuf_can[2]&0xFF;
    data_b3 = rxBuf_can[3]&0xFF;
    data_b4 = rxBuf_can[4]&0xFF;
    data_b5 = rxBuf_can[5]&0xFF;
    data_b6 = rxBuf_can[6]&0xFF;
    data_b7 = rxBuf_can[7]&0xFF;*/
    DeCode_can_id_msg(direction,msg_type,dev_addr,rem_addr,dev_type,rxBuf_can); 
  }
} 

Это декодирование

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)
{
//Декодируем направление сообщения запрос-ответ
if (direction==0)
{
  Serial.print("RX Reqv"); 
}
else if (direction==1)
{
  Serial.print("RX Ansv"); 
}
//Декодируем тип сообщения
    int i = 0;
    int table_size;
    table_size = sizeof(Message_CANData)/sizeof(Message_CANvalueData);
  for (i = 0; i < table_size; i++)
  {
    if (Message_CANData[i].msg_num == msg_type)
    {
      Serial.print(" type_msg - "); 
      Serial.print(Message_CANData[i].msg_name); 
    }
   }
//Декодируем адрес отправителя
i = 0;
    table_size = sizeof(Node_addr_CANData)/sizeof(Node_addr_CANvalueData);
  for (i = 0; i < table_size; i++)
  {
    if (Node_addr_CANData[i].node_num == dev_addr)
    {
      Serial.print(" node_addr - "); 
      Serial.print(Node_addr_CANData[i].node_name); 
    }
   }
//Декодируем адрес получателя
i = 0;
    table_size = sizeof(Node_addr_CANData)/sizeof(Node_addr_CANvalueData);
  for (i = 0; i < table_size; i++)
  {

    if (Node_addr_CANData[i].node_num == rem_addr)
    {
      Serial.print(" Rem_addr - "); 
      Serial.print(Node_addr_CANData[i].node_name); 

    }
   }
//Декодируем тип устройства
i = 0;
    table_size = sizeof(sens_dev_CANData)/sizeof(sens_dev_CANvalueData);
  for (i = 0; i < table_size; i++)
  {
    if (sens_dev_CANData[i].dev_num == dev_type)
    {
      Serial.print(" Dev_type - "); 
      Serial.print(sens_dev_CANData[i].dev_name); 
      Serial.print("\n"); 
    }
   }

}

Это передача

void TX(long unsigned int txId_can, int can_msg_type, int can_type_id, byte data[8])
{
  bool err = false;
  
  if (can_type_id == 29)
  {
    if (can_msg_type==0)
    {

      byte sndStat = CAN0.sendMsgBuf(txId_can, 1, 8, data);  //send NORMAL EXTERNAL ID
      if(sndStat == CAN_OK){err=false;} else {err=true;}
    } else if (can_msg_type==4)
    {
      txId_can=0x40000000;
      byte sndStat = CAN0.sendMsgBuf(txId_can, 8, data); //send REMOTE REQUEST FRAME
      if(sndStat == CAN_OK){err=false;} else {err=true;}
    } 
    else if (can_msg_type==8)
    {
      byte sndStat = CAN0.sendMsgBuf(txId_can,1 ,8, data); //send NORMAL EXTERNAL ID
      if(sndStat == CAN_OK){err=false;} else {err=true;}
    } 
  } else if (can_type_id == 11)
    {
    if (can_msg_type==0)
    {
      byte sndStat = CAN0.sendMsgBuf(txId_can, 0, 8, data); ////send NORMAL STANDART ID
      if(sndStat == CAN_OK){err=false;} else {err=true;}
    } else if (can_msg_type==4)
    {
      txId_can = 0x40000000; // send REMOTE REQUEST FRAME
      byte sndStat = CAN0.sendMsgBuf(txId_can, 8, data);
      if(sndStat == CAN_OK){err=false;} else {err=true;}
    } else if (can_msg_type==8)
    {
      txId_can = txId_can+0x80000000; //0x80000000 переводит в расширенный, без нее стандартный
      byte sndStat = CAN0.sendMsgBuf(txId_can, 8, data);
      if(sndStat == CAN_OK){err=false;} else {err=true;}
    }      
    }
        
    //delay(100);   // send data per 100ms    
      if(err == false){
      //Serial.println("Message Sent Successfully!");
      } else {
      Serial.println("Error Sending Message...");
    }
} 

 

 
Это кодирование
 
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)
{
long unsigned int can_id_msg;

can_id_msg=(direction & 0xFFFFFFFF)<<28 | (msg_type & 0x0FFFFFFF)<<24 | (dev_addr & 0x00FFFFFF)<<16 | (rem_addr & 0x0000FFFF)<<8 | (dev_type & 0x000000FF);
Serial.print("TX CAN ID " );Serial.println(can_id_msg, HEX);
return can_id_msg;
}

 

 
Ну а это вызов
 
TX(Code_can_id_msg(1, COMMAND_SEND, node_address, Hallway_net_center,air_h_s),0,29,data);
 
Так вызываем при ручной передае параметров
 
TX(0x02222222,8,29,data);

Декодирую через структуру, кодирую через перечисление

// Задаем перечисления и структуры для типов сообщений Y
typedef enum Message_enum
{
    NULL_C,                //0
    COMMAND_SEND,          //1
    COMMAND_ANSVER,        //2
    REQUEST_SEND,          //3 
    REQUEST_ANSVER,        //4
    STATUS_REQUEST_SEND,   //5
    STATUS_REQUEST_ANSVER  //6
                   
} Message_CAN_ENUM;               

typedef struct {
    uint8_t          msg_num;
    String           msg_name;
}Message_CANvalueData;

const Message_CANvalueData Message_CANData[] =
{
        /*Key        KeyName */
        { 0 ,    "NULL_C"},
        { 1 ,    "COMMAND SEND"},
        { 2 ,    "COMMAND_ANSVER"},  
        { 3 ,    "REQUEST_SEND"},
        { 4 ,    "REQUEST_ANSVER"},
        { 5 ,    "STATUS_REQUEST_SEND"},
        { 6 ,    "STATUS_REQUEST_ANSVER"}

};

 

 
riv
Offline
Зарегистрирован: 20.07.2017

Тут еще оказалось, что у меня товарищ делает overCAN протокол для управления набором модулей , правда он на 11 битном (2.0а) но тоже есть интересные идеи. В наш протокол особо нужные идеи перенесу.

1. Идея это обязательно иметь уникальный номер сообщения, у контроллера, я его в блок данных внесу, крутится счетчик в рамках выделенных бит с сбросом в о после переполнения.

2. Ну это как в CAN Open возможность передачи не только Короткий – любые сообщения длиной до 8 байт  но и Составной кадр – любые сообщения длиной более 8 байт.

3. Типы сообщений

Команда управления - сообщение в адрес узла 

Команда-Запрос  - сообщение в адрес узла  с запросом выдачи информации о состоянии

Команда контроля 

Технологическая команда 

Ответное сообщение - ответ от узла 

Инициативное сообщение – сообщение узла , выдаваемое в инициативном порядке.

riv
Offline
Зарегистрирован: 20.07.2017

В общем обмен написал, сечас подумаю на тему структуры протокола. Выложу сюда. Пока смотри node1.int https://yadi.sk/d/7pyVRdHJ3TNYXr