MCP2515 + Arduino vs CAN + Volkswagen :)

svi
Offline
Зарегистрирован: 19.10.2017

Добрый день) 

Расскажу что сделал, а потом ругайте :D

С китая заказал пару плат MCP2515. Сразу на обеих платах заменил кварц с 8 на 16 МГц, что бы можно было работать с оригинальной билиотекой CAN_BUS_Shield (так мне подсказал великий Google).

Подключил согласно распиновке к Arduno Nano и Arduino Pro Mini.

На Pro Mini загрузил скетч из примера с генерацией данных в CAN

// demo: CAN-BUS Shield, send data
// loovee@seeed.cc

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

// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 10;

MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin

void setup()
{
    Serial.begin(115200);

    while (CAN_OK != CAN.begin(CAN_500KBPS))              // init can bus : baudrate = 500k
    {
        Serial.println("CAN BUS Shield init fail");
        Serial.println(" Init CAN BUS Shield again");
        delay(100);
    }
    Serial.println("CAN BUS Shield init ok!");
}

unsigned char stmp[8] = {0, 0, 0, 0, 0, 0, 0, 0};
void loop()
{
    // send data:  id = 0x00, standrad frame, data len = 8, stmp: data buf
    stmp[7] = stmp[7]+1;
    if(stmp[7] == 100)
    {
        stmp[7] = 0;
        stmp[6] = stmp[6] + 1;
        
        if(stmp[6] == 100)
        {
            stmp[6] = 0;
            stmp[5] = stmp[6] + 1;
        }
    }
    
    CAN.sendMsgBuf(0x00, 0, 8, stmp);
    delay(100);                       // send data per 100ms
}

// END FILE

На Nano загрузил скетч приема данных с CAN

// demo: CAN-BUS Shield, receive data with check mode
// send data coming to fast, such as less than 10ms, you can use this way
// loovee, 2014-6-13


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


// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 10;

MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin

void setup()
{
    Serial.begin(115200);

    while (CAN_OK != CAN.begin(CAN_500KBPS))              // init can bus : baudrate = 500k
    {
        Serial.println("CAN BUS Shield init fail");
        Serial.println(" Init CAN BUS Shield again");
        delay(100);
    }
    Serial.println("CAN BUS Shield init ok!");
}


void loop()
{
    unsigned char len = 0;
    unsigned char buf[8];

    if(CAN_MSGAVAIL == CAN.checkReceive())            // check if data coming
    {
        CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf

        unsigned long canId = CAN.getCanId();
        
        Serial.println("-----------------------------");
        Serial.print("Get data from ID: 0x");
        Serial.println(canId, HEX);

        for(int i = 0; i<len; i++)    // print the data
        {
            Serial.print(buf[i], HEX);
            Serial.print("\t");
        }
        Serial.println();
    }
}

/*********************************************************************************************************
  END FILE
*********************************************************************************************************/

Так ВООООТ))) между собой они данные шлют и принимают. Хотя тоже голову сломал пока добился результата. Оказалось провод даже витой не всякий подходит даже на малых дистанциях.

А как только  подключаюсь в OBD II в Volkswagen Polo 2018 г/в то в Serial тишина (по всем скоростям прошелся с резистором и без). Подключаюсь к 6 CAN-H и к 14 CAN-L. Так же по рекомендациям великого Googla соеденил GND авто и ардуины вместе, хотя читал про CAN шину небольшую статью где было написанно землю общая не нужна, т.к. уровни измеряются не относитеьно земли, а относительно друг друга. 

svi
Offline
Зарегистрирован: 19.10.2017

Не кто не сталкивался?

MaksVV
Offline
Зарегистрирован: 06.08.2015

вообще между двумя модулями на скорости 500кбит вообще никаких проблем не должно было быть, если джампер терминатора подключен. для CAN земля не обязательна. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

вот вам библиотека для программы CanHacker (для кварцев 16Мгц).  Загружаете в ардуино пример usb_cdc из библиотеки. Программа CanHacker  и схема подключения тут. Этой прогой гораздо удобнее CAN тестить. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

библиотека у вас стремная похоже. Удаляйте её. Вот эти пользуйте (там в архиве также библиотека для канхакер на 8 мгц)

ПС. Скорость  на контактах 6 и 14 ОБД наиболее вероятна 500кбит/с. пробуя другие скорости можно зажечь кучу ошибок. 

svi
Offline
Зарегистрирован: 19.10.2017

Спасибо за ответ, добрый человек)))

Архив с библиотеками уже имею на борту их тоже перепробовал и на 16 и на 8 МГц (пробовал пока помощи ждал), но еще раз СПАСИБО). Мне тут диагност сказал один, что если цеплять к диагностическому разъёму, то какой то пакет сначала шлется подтверждающий готовность или оригинальность оборудования и для прослушки CAN шины нужно цеплять у блока какого нибудь или у панели приборов (со слов Васи диагноста :) ).

Пока ждал помощи впаял 8Мгц обратно, и заметил такую штуку что на скорости 5 10 и через раз 20 KBPS данные не принимаются, хотя отправляются. Странно, думал что пакет большой слишком и частота отправки, но нет вроде. Передачу снизил до минимума с периодом в 1000мс и результата нуль. Подскажите? что опять не так...

И раз автомобиль оставил в покое, подсоединился я на работе между промышленным блоку управления (ПБУ) спец оборудованием с интерфейсом CAN и его родным CAN-USB программатором, дабы подглядеть пакеты которые они друг другу шлют в процессе работы. Скорость у ПБУ 9600 бод я так понял это примерно 1 Кбайт/с (1 KBPS). 1 KBPS в библиотеке нет поставил 5 - тишина, поставил 10 - побежало что-то но рваное то есть то нет. Подскажите все ли правильно делаю?!

И последнее на сегодня и поеду домой спать :D  С горем пополам считал я один пакет с программатора и попытался воспроизвести его используя пример из библиотеки  <mcp2515.h>, но учитывая что протокол и команды у этого ПБУ собственные мне нужно отправить набор байт в свободной форме, что я сделать не смог (чую что то не так делаю))). Эта библиотека навязывает мне вот такой "массив"

canMsg2.can_id  = 0x036;
  canMsg2.can_dlc = 8;
  canMsg2.data[0] = 0x0E;
  canMsg2.data[1] = 0x00;
  canMsg2.data[2] = 0x00;
  canMsg2.data[3] = 0x08;
  canMsg2.data[4] = 0x01;
  canMsg2.data[5] = 0x00;
  canMsg2.data[6] = 0x00;
  canMsg2.data[7] = 0xA0;

в котором первое значение ID второе DLC, так вот если DLC = 0x00, то дальше Data почему-то не принимается. Насколько я понял этот DLC это количество предстоящих байт. Вот проблема в чем: в протоколе к ПБУ такие данные не нужны и более того они будут расценены как то иначе мне кажется. Нужное мне сообщение должно выглядеть так: 0x00 0x08 0x16 0x08 CRC-MODBUS, как его записать?!

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

 

MaksVV
Offline
Зарегистрирован: 06.08.2015
что то вы путаете похоже со своим промышленным МК. 9600 вроде не делают такую скорость на CAN. Скорее всего у вас там RS485? тем более протокол модбас. 
 
Стандартные скорости CAN:  10 20 50 100 125 250 500 800 1000, ну есть еще несколько дробных
 
библиотеки используйте которые я дал, чтобы не путаться, они все похожи с одинаковыми названиями, но у старых версий есть косяки. 
 
Перестаньте трогать кварц, что он вам сдался. библы давно поддерживают и 8 и 16. выбирается в начале скетча в сетапе
 
if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK)
 

svi пишет:
  С горем пополам считал я один пакет с программатора и попытался воспроизвести его используя пример из библиотеки  <mcp2515.h>, но учитывая что протокол и команды у этого ПБУ собственные мне нужно отправить набор байт в свободной форме, что я сделать не смог (чую что то не так делаю))). 

 так вот если DLC = 0x00, то дальше Data почему-то не принимается. Насколько я понял этот DLC это количество предстоящих байт. Вот проблема в чем: в протоколе к ПБУ такие данные не нужны и более того они будут расценены как то иначе мне кажется. Нужное мне сообщение должно выглядеть так: 0x00 0x08 0x16 0x08 CRC-MODBUS, как его записать?!

что значит в свободной форме? CAN шина четко предусматривает наличие ID, DLC, и поле данных, которое состоит от 1 до 8 байт. По другому данные не передаются на этой шине. Если вы ставите dlc =0, то у вас отправляется только заголовок с ID. 

 

svi
Offline
Зарегистрирован: 19.10.2017

Итак день следующий :)  от идеи поработить сие китайское чудо не отступаю :)

Переосмыслив все решил пере задать вопросы на сущие что бы не утомлять наших ГУРУ :)))

1) как в свободной форме задать скорость передачи данных в CAN шине для этого модуля вплоть до бит/с (это для особо ухищрённых устройств с скоростями в БОДах).

2) как в свободной форме передавать и принимать данные с CAN шины

 

svi
Offline
Зарегистрирован: 19.10.2017

MaksVV пишет:

 

Чтоо значит в свободной форме? CAN шина четко предусматривает наличие ID, DLC, и поле данных, которое состоит от 1 до 8 байт. По другому данные не передаются на этой шине. Если вы ставите dlc =0, то у вас отправляется только заголовок с ID. 

 

В документации к устройству написанно (дословно)

Запрос на тестирование канала связи: Формат запроса состоит из четырех байт.

1 байт - сетевой адрес устройства

2 байт - 0 (код запроса на тестирование)

3 и 4 контрольная сумма CRC

svi
Offline
Зарегистрирован: 19.10.2017

MaksVV пишет:

что то вы путаете похоже со своим промышленным МК. 9600 вроде не делают такую скорость на CAN. Скорее всего у вас там RS485? тем более протокол модбас. 
 
Стандартные скорости CAN:  10 20 50 100 125 250 500 800 1000, ну есть еще несколько дробных
 
библиотеки используйте которые я дал, чтобы не путаться, они все похожи с одинаковыми названиями, но у старых версий есть косяки. 
 
Перестаньте трогать кварц, что он вам сдался. библы давно поддерживают и 8 и 16. выбирается в начале скетча в сетапе

по кварцу понял))) спасибо

по поводу интерфейса не путаю, CAN точно скорость в документации указана в 9600 бод. Распознает пакет от пакета минимальной установленной паузой.
похожий протокол еще у электросчетчиков с CAN но там скорость можно настраивать но тоже в Бодах. Сегодня подключусь к счетчику на него более подробно расписан протокол общения с ним.

MaksVV
Offline
Зарегистрирован: 06.08.2015

вы уж почитайте про то, как устроена CAN шина и перечитайте потом что написали - там нет и не может быть никакой свободной формы. Научитесь сначала между двумя модулями инфу гонять, а потом уж подключайтесь к стандартным устройствам. 

По фольксу да, такое может быть, что шина молчит. Так как в диагностический разъем на некоторых авто перестали выводить моторный CAN, заменив его специальной диагностической шиной CAN, которая, в свою очередь, соединяется с остальной инфраструктурой через гейтвеи. Пока запрос не сделаешь правильный - ничего и не получишь. нужно подсматривать канхкером обмен при подключенной диагностике, что она шлёт. 

скорость до бита в библиотеке не поменять, на сколько знаю. Можно выбрать только стандартные. Хотя, если эту библу покурить, то думаю можно справиться. Попробуйте на скорости 10кбит, может что и получится. 

скиньте ссылку на документацию устройства.  или сюда выложите

MaksVV
Offline
Зарегистрирован: 06.08.2015

бод от бит/с отличаются тем, что в боды включена и передача бит полезной информации и передача служебных бит . А в бит/с обычно указавают "чистую" скорость передачи полезной информации (без учета служебных бит). 

svi
Offline
Зарегистрирован: 19.10.2017

Я надеюсь не нервирую вас своими вопросами.

 

Подключил сейчас электросчетчик Меркурий 230 ART-01 CN (где C означает наличие CAN интерфейса, по которому он опрашивается)

Вот счетчик https://www.incotex.com/catalog/schetchiki/3-faznye-mnogotarifnye-schyetchiki/schetchik-merkuriy-230-art/

Вот тут внизу есть описание протокола https://www.incotex.com/catalog/schetchiki/3-faznye-mnogotarifnye-schyetchiki/schetchik-merkuriy-230-art/docs/

настроил я счетчик для верности эксперемента тоже на 9600 бод, получается 7.68 кбит/с посчитал по онлайн калькулятору. Ардуино выставил на 10 кбит/с и получил опять тоже самое. когда на 2 байт попадается 0 то получаю только ID (или в нашем случае сетевой адресс).

MaksVV
Offline
Зарегистрирован: 06.08.2015

сдается мне на этом счетчике совсем не CAN, а только физическая линия CAN. Дело в том, что "правильная" CAN шина подразумевает собой наличие CAN приёмо-передатчика (трансивера) и CAN контроллера. 

В вашем китайском модуле (шилде) трансивер скорее всего MCP2551 или TJA1050. А вот CAN контроллер MCP2515. Дак вот ID, DLC, поле данных, все служебные биты  и аппартный арбитраж шины обеспечивает CAN контроллер. 

Но бывает, люди используют только приёмопередатчик от CAN шины, без CAN контроллера, только чтобы создать физическую среду шины. Т.е. он делает тоже самое, что шинный формирователь RS485 (MAX485). 

По сути такая шина и является RS485 -  только на физическом уровне она CAN. 

Дак вот, посмотрев документацию на этот счётчик, такое впечатление и складывается, что они просто используют CAN трансиверы и называют это CAN шиной, что неверно по идее. 

В таком случае, да, возможно и посылать и принимать байты, как вы говорите, в произвольной форме. Вам  для этого нужен просто приемопередатчик CAN шины. И работать как с обычным УАРТ (Serial). 

Я пробовал так подключать трансиверы CAN - не сразу получилось. потом получилось 

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

эта статья и коменты к ней. подтверждает мои слова. Там ребята подключают CAN счетчики к линии RS485 , просто заменив полярность CAN и добавив резисторы. 

Так что не исключено, что и ваш промышленный блок имеет не полноценную CAN шину, а только CAN на физическом уровне. Как подкдючаться к ней выше описал. 

svi
Offline
Зарегистрирован: 19.10.2017

MaksVV пишет:

сдается мне на этом счетчике совсем не CAN, а только физическая линия CAN. Дело в том, что "правильная" CAN шина подразумевает собой наличие CAN приёмо-передатчика (трансивера) и CAN контроллера. 

В вашем китайском модуле (шилде) трансивер скорее всего MCP2551 или TJA1050. А вот CAN контроллер MCP2515. Дак вот ID, DLC, поле данных, все служебные биты  и аппартный арбитраж шины обеспечивает CAN контроллер. 

Но бывает, люди используют только приёмопередатчик от CAN шины, без CAN контроллера, только чтобы создать физическую среду шины. Т.е. он делает тоже самое, что шинный формирователь RS485 (MAX485). 

По сути такая шина и является RS485 -  только на физическом уровне она CAN. 

Дак вот, посмотрев документацию на этот счётчик, такое впечатление и складывается, что они просто используют CAN трансиверы и называют это CAN шиной, что неверно по идее. 

В таком случае, да, возможно и посылать и принимать байты, как вы говорите, в произвольной форме. Вам  для этого нужен просто приемопередатчик CAN шины. И работать как с обычным УАРТ (Serial). 

Я пробовал так подключать трансиверы CAN - не сразу получилось. потом получилось 

 

Огромное спасибо!!! честно догадывался что в MCP2515 собака зарыта (она не пропускает байты не вошедшие в байт DLC), да боялся сказать думал камнями закидают и слюнями заплюют совсем :)

у меня есть микруха TJA1040 через нее попробую и отпишусь.

svi
Offline
Зарегистрирован: 19.10.2017

Добрый день)

Прошу прощения за долгое отсутствие. Ардуинки сжег :) заказал из Москвы чтоб не шибко долго ждать.

И так на чем я остановился, я собрал два "модуля" на TJA1040 ориентируясь на схему с даташита.

Соединил для теста две Ардуино Мега. Скетч ниже.

void setup()
{
  Serial.begin(9600);
  Serial1.begin(9600);
}

void loop()
{
  if (Serial.available() > 0)
  {
    Serial1.write(Serial.read());
  }
  delay(5);
  if (Serial1.available() > 0)
  {
    Serial.println(Serial1.read(), BIN);
  }
}

Все работает, байты передается  средствами так называемой "физической" CAN шины. Но есть два момента непонятные мне:

1) после отправки данных, на отправляемом устройстве в сериал они тоже дублируются. Причем я думал что это специфика сериал монитора, но нет пробовал отправить массив проблема повторилась. Отключал мой модуль "TJA1040" и дублирование прекращается. Почему так происходит и как этого избежать, подскажите...

2) при отправке "0" возвращает аски код 56, что равно "8"... от 1 до 9 нормально все а 0 выделывается. А так же при отправке из сериал монитора автоматом прилипает перенос строки вконце (аски код 10), как от него избавиться?

MaksVV
Offline
Зарегистрирован: 06.08.2015

в сериал мониторе справа внизу делаем нет конца строки и переноса каретки. То что эхо на шине так и должно быть. т.е. то что отправляем летит сразу в приёмник. про ноль хз

svi
Offline
Зарегистрирован: 19.10.2017

MaksVV пишет:

в сериал мониторе справа внизу делаем нет конца строки и переноса каретки. То что эхо на шине так и должно быть. т.е. то что отправляем летит сразу в приёмник. про ноль хз


про перенос понял, с 0 думаю разберусь
а вот с эхом непончял немного, у меня сейчас так: ардуино1 отправляет 1111 в сериал и тут же получает эти же 1111, в свою очередь ардуино2 просто получает 1111.
если это нормально, то как тогда организовывать двухсторонний обмен данными двух ардуин. Передатчик постоянно будет тут же принимать свой же пакет хммм.... странно

MaksVV
Offline
Зарегистрирован: 06.08.2015

у меня также организовано, когда подключаешь уарт к шине к-лайн автомобиля. К-лайн эхо даёт. И ниче обмен идет. В пакетах данных адрес получателя обычно есть. Домой приду проверю, у меня тоже два кандрайвера мсп2551 есть. Попробуйте на сериал3 переделать, тут выяснилось что меги бывают с перепутанными тх1 и rx1

MaksVV
Offline
Зарегистрирован: 06.08.2015

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

svi
Offline
Зарегистрирован: 19.10.2017

MaksVV пишет:

у меня также организовано, когда подключаешь уарт к шине к-лайн автомобиля. К-лайн эхо даёт. И ниче обмен идет. В пакетах данных адрес получателя обычно есть. Домой приду проверю, у меня тоже два кандрайвера мсп2551 есть. Попробуйте на сериал3 переделать, тут выяснилось что меги бывают с перепутанными тх1 и rx1

Переделал на Serial3, не чего не поменялось.

Извини конечно, но до меня не доходит... так называемое "ЭХО" это результат чего? специфика микросхемы TJA1040, это она шлет обратно пакет в сериал? т.к. убирая оба модуля 1040 и соеденив ардуинки напрямую все работает без ЭХО и более того 0 принимается нормально...

Приложу фото навсякий случай))

MaksVV
Offline
Зарегистрирован: 06.08.2015

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

Т.е когда уарт ттл. У вас тх и рх это два разных канала передачи (относит. Gnd) а can там один канал - разность потенциалов между can-h и can-l. Поэтому в приеме мы видим все то, что отдали

svi
Offline
Зарегистрирован: 19.10.2017

MaksVV пишет:

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

Т.е когда уарт ттл. У вас тх и рх это два разных канала передачи (относит. Gnd) а can там один канал - разность потенциалов между can-h и can-l. Поэтому в приеме мы видим все то, что отдали

Понял.

MaksVV огромное спасибо что не покидаете меня :)

Сегодня буду с счетчиком связь налаживать... по результатам отпишусь. Я просто думаю что проблема с с 0x00 возникнет, т.к. неправельно передается отправляю 0x00 получаю 0x38 причем даже в ЭХО

MaksVV
Offline
Зарегистрирован: 06.08.2015

0x00 и '0' это разные вещи если что

MaksVV
Offline
Зарегистрирован: 06.08.2015

а что будет ,если '8' отправить?

MaksVV
Offline
Зарегистрирован: 06.08.2015

и что с передачей остальных символов, не цифр, а  букв и знаков?

svi
Offline
Зарегистрирован: 19.10.2017

MaksVV пишет:

0x00 и '0' это разные вещи если что

Конечно же вы правы, голова уже кругом... 

отправлял символы A F ) все было в порядке. 8 отправлял, получал как и положено 56

сейчас отправил массив, скрин прикладываю

сервер ужимает картинку если плохо видно вот еще ссылка https://ibb.co/i46Yh0

MaksVV
Offline
Зарегистрирован: 06.08.2015

может задержку между отправкой байт ставить?, ну хз.

byte a[] = {0x01, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x0C, 0x8B};

#define CAN_BUS Serial3

unsigned long prev = 0;

void setup() {
Serial.begin (9600);
CAN_BUS.begin (9600);
             }

void loop() 
{

// раз в три секунды отправляем сообщение
if (millis() - prev > 3000) {
    Serial.println();
    for (byte i =0; i < sizeof(a); i++) {CAN_BUS.write(a[i]); delay(1);}
prev = millis();            }


if (CAN_BUS.available()) {Serial.print (CAN_BUS.read(), HEX);  Serial.print(" ");} 

}

Или скорости повыше попробуйте 128000 или 256000. Помнится были проблемыс кан на низких скоростях. 

svi
Offline
Зарегистрирован: 19.10.2017

MaksVV, спасибо огромное) 

Залил скетч с задержками между байтами, не помог. Да и вообще в протоколе счетчика задержки запрещены между байтами. Помогло повышение скорости, начало работать, только начиная с 38400 бод. Я уж думал обосаться от радости, но тут еще одни грабли))) (куда же без них). Полез в протокол счетчика, а там скорость только до 19200 бод поддерживается. И тут я психанул J и разобрал нахрен счетчик чтоб раскрыть тайный занавес. Ориентируясь на мои догадки в счетчике тоже используется CAN transceiver, т.к. эти счетчики выпускаются в двух исполнениях с CAN и RS-485 и было бы глупо менять сам МК из за изменения интерфейса. Так вот если используется, то нахрен какой раз он может работать на таких малых скоростях (от 300 до 19200 бод). Я разобрал (нарушив все пломбы, и тем самым купив этот счетчик себе как подставку под кофе) и мои ожидания оправдались. Стоит там МК и микруха CAN transceiver, только с названием VP251 которая в свою очередь совпадает с распиновкой и типовой схемой включения с TJA1040. Я нарыл таких 2 шт просто перепаял их в свои модули и БОЖЕ МОЙ! Все заработало и на 9600 бод!!!

Тему можно закрывать, своего я добился :) хотя начинал совершенно не с этого :D Если будут еще попросы я создам новую тему, но это уже совсем другая история... :)

Надеюсь, данный материал будет полезен кому-то, т.к. информации для таких чайников как я, я не нашел...

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

Поздравляю с победой.