PCCar.ru - Ваш автомобильный компьютер

Вернуться   PCCar.ru - Ваш автомобильный компьютер > MP3Car ТехИнфа > Общение с машиной

Ответ
 
Опции темы Поиск в этой теме
Старый 14.07.2015, 00:46   #1
T_r_D
Старший Пользователь
 
Регистрация: 03.07.2015
Регион: 77, 97, 99, 177
Сообщений: 372
T_r_D is a jewel in the roughT_r_D is a jewel in the roughT_r_D is a jewel in the rough
По умолчанию CITROEN-ARDUINO

Народ, а кто нить дружил Citroen с Arduino+CAN Shield?

Толи я чего-то не понимаю, толи я что-то не правильно делаю.
#include <SPI.h>
#include "mcp_can.h"
MCP_CAN CAN(10);
unsigned char len = 0;
unsigned char buf[8];
INT32U canId = 0x000;

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

START_INIT:

if(CAN_OK == CAN.begin(CAN_500KBPS,MCP_8MHz))
{
Serial.println("Init OK!");
}
else
{
Serial.println("Init fail");
delay(100);
goto START_INIT;
}
}


void loop()
{
if(CAN_MSGAVAIL == CAN.checkReceive()) // check if data coming
{
CAN.readMsgBuf(&len, buf);

canId = CAN.getCanId();
// unsigned long canId = CAN.getCanId();

Serial.print("<");Serial.print(canId);Serial.print (",");

for(int i = 0; i<len; i++)
{
Serial.print(buf[i]);Serial.print(",");
}
Serial.print(">");
Serial.println();
}
}

Пытаюсь отловить обороты. Но получаю на выходе при чтение что-то типо
8 : 1C F0 32 0 4C 30 0 32
68 : 0 0 FF
D : 0 0 0 0 0 0 0 B
8 : 1C F0 31 0 4C 30 0 32
48 : 0 30 2 42 C8 3 1 0
5 : 7F FF 0 5 58 0
5 : 7F FF 1 85 D9 0
8 : 1C F0 31 0 4C 30 0 32
32 : 81 5B 48 FE 0 0
68 : 0 0 FF
D : 0 0 0 0 0 0 0 C
92 : 0 0 0
8 : 1C F2 31 0 4C 30 0 32
48 : 0 30 2 42 C8 3 1 0
5 : 7F FF 0 5 6B 0
12 : 73 20 1 3D 0
4D : 0 0 0 0 0 0 0 0

И не одного упоминания о 0C Обороты двигателя (Engine RPM)!
И почему такие короткие ID у сообщений?
Я чего-то не дописал или у ситроенов обороты под другим ID?

Поделитесь кто что знает!
Я в этом совсем новенький.

Последний раз редактировалось admin; 29.03.2016 в 12:34.
T_r_D вне форума   Ответить с цитированием
Старый 14.07.2015, 13:23   #2
Bersenev
Бывалый писикарщик
 
Аватар для Bersenev
 
Регистрация: 23.04.2009
Возраст: 53
Город: Ставрополь
Регион: 26
Машина: Opel Zafira 2007
Сообщений: 5,275
Bersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant future
По умолчанию

В общем ты путаешь два понятия:

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

второе - это OBD II протокол, то есть диагностический протокол, который должен быть реализован в каждой машине, но из практики могу сказать, что есть он почти во всех новых машинах, но не во всех реализован в полном объёме. Данный протокол работает по запросу, то есть ты сначала запрашиваешь у диагностического устройства с ид 7DF, то что тебе нужно, а потом получаешь ответ от устройства с ид. 7E8 ( возможны варианты от 7E8 до 7EF). Вот именно в этом протоколе 0C это обороты двигателя. Более подробно читаем здесь https://en.wikipedia.org/wiki/OBD-II_PIDs#Mode_1_PID_1C

Теперь по поводу твоего протокола, как я и говорил у каждой машины он свой, допустим в грузовиках ISUZU мы получаем такое сообщение

<217056256,240,125,126,188,18,0,255,255,>

вот именно в сообщениях с идентификатором 217056256 в 4-м и 5-м байтах находятся обороты двигателя, при чём для получения нужного числа надо (18*256+188)/8 = 599,5 об/мин

твой протокол слишком короткий, что бы точно сказать, что именно именно передаёт обороты двигателя, но скорее всего обороты здесь

8 : 1C F2 31 0 4C 30 0 32

Причем вычисляется так 31 это 49 десятичное, F2 - 242.
(49*256+242)/16 = 799,125 об/мин.

Если конечно прокол снимался на холостых оборотах.
Bersenev вне форума   Ответить с цитированием
Старый 14.07.2015, 21:34   #3
T_r_D
Старший Пользователь
 
Регистрация: 03.07.2015
Регион: 77, 97, 99, 177
Сообщений: 372
T_r_D is a jewel in the roughT_r_D is a jewel in the roughT_r_D is a jewel in the rough
По умолчанию

Bersenev спасибо тебе огромное.
В моём протоколе это лишь кусок.
У меня есть два лога- один без запуска двигателя, а второй с запуском и работой на ХХ.
Ту часть которую привёл это с запуском.
Но похоже это не тот ID поскольку на незапущенном двигателе он тоже меняется.
Если поможешь, то могу выслать два лога.

Какой программой можно анализировать траффик с ком порта?
А то эта угадайка на долго.

И если не сложно объясните мне как при помощи ардуины OBD II запросы слать и принимать ответы.
лог без запуска (выборка по ID с убиранием повторяющихся сообщений)

также попробовал написать
if (canId = 8)
{
C = (buf[3]*256+buf[2])/16;
Serial.println(C);
}
И получил пляшущие цифры ни малейшим образом не намекающие на обороты!

Последний раз редактировалось T_r_D; 16.07.2015 в 21:13.
T_r_D вне форума   Ответить с цитированием
Старый 15.07.2015, 22:09   #4
T_r_D
Старший Пользователь
 
Регистрация: 03.07.2015
Регион: 77, 97, 99, 177
Сообщений: 372
T_r_D is a jewel in the roughT_r_D is a jewel in the roughT_r_D is a jewel in the rough
По умолчанию

Короче понятно.
Нужно идти стандартным путём- ELM327+Arduino
T_r_D вне форума   Ответить с цитированием
Старый 15.07.2015, 23:28   #5
Bersenev
Бывалый писикарщик
 
Аватар для Bersenev
 
Регистрация: 23.04.2009
Возраст: 53
Город: Ставрополь
Регион: 26
Машина: Opel Zafira 2007
Сообщений: 5,275
Bersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant future
По умолчанию

Цитата:
Сообщение от T_r_D Посмотреть сообщение
И если не сложно объясните мне как при помощи ардуины OBD II запросы слать и принимать ответы.
Для тех кому лень читать WIKI (а там всё очень подробно описано), вот пример как запрашивать скорость автомобиля по OBDII

Код:
#include <mcp_can.h>
#include <SPI.h>

INT32U canId = 0x000;

unsigned char len = 0;
unsigned char buf[8];
char str[20];
boolean IsSend = false;

unsigned long IsSend_millis = 0;

unsigned char vspeed[8] = {2, 1, 13, 0, 0, 0, 0, 0};

unsigned char count = 0;

MCP_CAN CAN0(10);

void setup()
{
  Serial.begin(9600);
 
START_INIT:

  if(CAN0.begin(CAN_500KBPS) == CAN_OK)
    {
      Serial.println("CAN BUS Shield init ok!");
    }
    else
    {
            Serial.println("CAN BUS Shield init fail");
            Serial.println("Init CAN BUS Shield again");
            delay(100);
            goto START_INIT;
    }
   
  pinMode(18, INPUT);
 
}

void loop()
{
    if(!IsSend)
    {
      CAN0.sendMsgBuf(0x7DF, 0, 8, vspeed);
      IsSend = true;
      IsSend_millis = millis();
    } 
    if(!digitalRead(18))                        
    {
      CAN0.readMsgBuf(&len, buf);             
      canId = CAN0.getCanId();

      if( (canId == 0x7E8) && (buf[0] == 3) && (buf[1] == 0x41) && (buf[2] == 0xD))
      {
        Serial.println(buf[3]);
        IsSend_millis = millis()-2500;
          Serial.print("Speed: ");
          Serial.println(buf[3]);
      }
    }
    if( IsSend )
    {
      if( IsSend_millis + 3000 < millis() )
      {
        Serial.print("----");
        IsSend = false;
        IsSend_millis = millis();
      }
    }
}
Скетч посылает запросы раз в три секунды, пока не придёт первый ответ. После этого посылается два запроса в секунду.

Только номера пинов надо задать свои.
Bersenev вне форума   Ответить с цитированием
Старый 15.07.2015, 23:39   #6
Bersenev
Бывалый писикарщик
 
Аватар для Bersenev
 
Регистрация: 23.04.2009
Возраст: 53
Город: Ставрополь
Регион: 26
Машина: Opel Zafira 2007
Сообщений: 5,275
Bersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant future
По умолчанию

Цитата:
Сообщение от T_r_D Посмотреть сообщение
также попробовал написать
if (canId = 8)
{
C = (buf[3]*256+buf[2])/16;
Serial.println(C);
}
И получил пляшущие цифры ни малейшим образом не намекающие на обороты!
И не удивительно,

C = (buf[3]*256+buf[2])/16;

Я не знаю тип переменной C , но в принципе это и не важно.

buf[3]*256 - байт умножается на 256 и сохраняется в байт, то есть всегда равно 0. Теперь к нулю прибавляем байт buf[2] и делим на 16 в результате значения от 0 до 15.

а надо так, если C имеет тип unsigned int, то

C = buf[3];
C = (C*256+buf[2])/16;

То есть сначала байт преобразуем в unsigned int, а уже потом выполняем все действия, вот тогда получим правильное значение
Bersenev вне форума   Ответить с цитированием
Старый 15.07.2015, 23:54   #7
Bersenev
Бывалый писикарщик
 
Аватар для Bersenev
 
Регистрация: 23.04.2009
Возраст: 53
Город: Ставрополь
Регион: 26
Машина: Opel Zafira 2007
Сообщений: 5,275
Bersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant future
По умолчанию

Цитата:
Сообщение от T_r_D Посмотреть сообщение
Какой программой можно анализировать траффик с ком порта?
А то эта угадайка на долго.
А это как повезёт, по работе приходится искать в протоколах в основном скорость и уровень топлива, иногда на это уходит часов шесть, а иногда 5 минут.

Я сделал себе программу для анализа протокола, протокол формирует этот скетч.

Код:
#include <mcp_can.h>
#include <SPI.h>

INT32U canId = 0x000;

unsigned char len = 0;
unsigned char buf[8];
char str[20];
int count = 0;

MCP_CAN CAN0(10);

void setup()
{
  Serial.begin(38400);
  while(!Serial){}
  
START_INIT:

  if(CAN0.begin(CAN_500KBPS) == CAN_OK) 
    {
      Serial.println("CAN BUS Shield init ok!");
    }
    else 
    {
            Serial.println("CAN BUS Shield init fail");
            Serial.println("Init CAN BUS Shield again");
            delay(100);
            goto START_INIT;
    }
    
  pinMode(18, INPUT); 
}

void loop()
{
      
    if(!digitalRead(18))                         
    {
      CAN0.readMsgBuf(&len, buf);              
      canId = CAN0.getCanId();                    
      
      Serial.print("<");Serial.print(canId);Serial.print(",");
      for(int i = 0; i<len; i++)
      {
        Serial.print(buf[i]);Serial.print(",");
      }
      Serial.print(">");
      Serial.println();
    }
}
Так что можешь сделать файл этим скетчем, отправь мне, а я посмотрю.

Только для того что бы найти обороты надо сделать следующее:

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

Для скорости почти тоже самое, только надо равномерно разогнать машину километров до 40 - 50-ти, а потом также спокойно остановиться.

Для уровня топлива нужны протоколы до и после заправок.
Bersenev вне форума   Ответить с цитированием
Старый 16.07.2015, 00:59   #8
T_r_D
Старший Пользователь
 
Регистрация: 03.07.2015
Регион: 77, 97, 99, 177
Сообщений: 372
T_r_D is a jewel in the roughT_r_D is a jewel in the roughT_r_D is a jewel in the rough
По умолчанию

С имеет тип unsigned int. Задаётся в начале поэтому и небыло в куске.
С байт ты прав, но там числа получались до 65000.
Можно попробовать ещё раз.

Твой скетч тоже что и мой, только вывод строк в другом формате.
у меня в хексе и без всяких скобок и разделителей кроме ":" между ID и сообщением, а у тя с доп символами.
Ща перепишу свой чтоб выводилось в твоём формате.

С посылкой по OBD II ща попробую сам разобраться
Реально мне с ардуиной пока очень сложно так как опыта программирования МК у меня нет.

PS А что делает строчка?
INT32U canId = 0x000;
и отличается ли она от моей
unsigned char canId = CAN.getCanId();
T_r_D вне форума   Ответить с цитированием
Старый 16.07.2015, 08:00   #9
Bersenev
Бывалый писикарщик
 
Аватар для Bersenev
 
Регистрация: 23.04.2009
Возраст: 53
Город: Ставрополь
Регион: 26
Машина: Opel Zafira 2007
Сообщений: 5,275
Bersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant future
По умолчанию

Цитата:
Сообщение от T_r_D Посмотреть сообщение
также попробовал написать
if (canId = 8)
{
C = (buf[3]*256+buf[2])/16;
Serial.println(C);
}
И получил пляшущие цифры ни малейшим образом не намекающие на обороты!
и ещё по этому куску, речь действительно шла про 2 и 3-ий байты, но индексы в скетче у них 1 и 2, то есть правильно это должно выглядеть так

C = buf[2];
C = (C*256+buf[1])/16;
Bersenev вне форума   Ответить с цитированием
Старый 16.07.2015, 08:10   #10
Bersenev
Бывалый писикарщик
 
Аватар для Bersenev
 
Регистрация: 23.04.2009
Возраст: 53
Город: Ставрополь
Регион: 26
Машина: Opel Zafira 2007
Сообщений: 5,275
Bersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant futureBersenev has a brilliant future
По умолчанию

Цитата:
Сообщение от T_r_D Посмотреть сообщение

PS А что делает строчка?
INT32U canId = 0x000;
и отличается ли она от моей
unsigned char canId = CAN.getCanId();
Объявляет переменную canId, только в твоём случае она динамическая, так как создаётся внутри цикла.

Но самое главное у тебя здесь ошибка, так как идентификаторы могут быть 11-ти или 29-битные (в зависимости от системы адресации в конкретной can шине), а ты выделяешь под него один байт, то есть всего восемь бит.

Правильно должно быть так

unsigned long canId = CAN.getCanId();

или так

INT32U canId = CAN.getCanId();
Bersenev вне форума   Ответить с цитированием
Ответ


Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.



Часовой пояс GMT +4, время: 21:58.


Работает на vBulletin® версия 3.8.4.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot