OBD2, библиотека. Автор накосячил

zilibob4ik
Offline
Зарегистрирован: 02.06.2014

Привет всем.

Собираю бортовой компьютер на Ардуино.

Всё на основе библиотеки работающей с ОБД2.

https://github.com/stanleyhuangyc/ArduinoOBD/tree/master/libraries/OBD

Сначала не понимал. почему данные не понятные.

Оказывается автору достаточно было переменных тип INT. Я долго смеялся.

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

В общем, не могу разобраться, как переделать библиотеку. 

Может кто сталкивался с эти делом и переделал.

 

Если читать что нибудь типа RPM, то понятно обороты с точностью до десятых и не нужны.

А вот датчик МАФ (расход воздуха) даёт данные с долями,

а на выходе округлённое или 1 или 2 грамма в сек.

что категориески не правильно, т.к к примеру 1.5 грамма в сек, это никак не 1 и не 2.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А что именно Вас не устраивает? Какие именно функции? Напряжения он во float считывает

virtual float getVoltage();

А Вам что нужно?

zilibob4ik
Offline
Зарегистрирован: 02.06.2014

Посмотрите внимательно код.

Вот именно Напряжение сети читается совершенно по другому, чем всё остальное.

А именно напряжение выдаёт сама ЕЛМ, а не ЭБУ авто.

Для чтения напряжение используется совершенно отдельная функция:

float COBD::getVoltage()
{
    char buf[OBD_RECV_BUF_SIZE];
    write("ATRV\r");
    byte n = receive(buf, 100);
    if (n > 0) {
        return atof(buf);
    }
    return 0;
}

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

 

__Alexander
Offline
Зарегистрирован: 24.10.2012

ну собственно там всё выдает ELM.

zilibob4ik
Offline
Зарегистрирован: 02.06.2014

Это само собой, но напряжение бортовой сети ЕЛМ выдаёт самостоятельно. без участия ЭБУ.

Напряжение можно откалибровать, дав соответствующую команду в АТ формате.

Напряжение можно запросить не подключая разъём к авто

(ради эксперимента, просто подключив питание к разъёму).

 

Те данные, которые могут иметь формат INT, интересуют меньше всего.

обороты, температура и тд.

А фот МАФ датчик интересует, но полные данные, а не округлённые до единиц.

На основе точных данных от МАФ датчика, можно достаточно точно посчитать расход топлива.

__Alexander
Offline
Зарегистрирован: 24.10.2012

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

__Alexander
Offline
Зарегистрирован: 24.10.2012

не, не так, я вас обманул. то что вы видите по комманде atrv это напряжение elm, но эбу я уверен тоже может вернуть свое напряжение и всё остальное, это надо знать в каком пиде оно лежит.

zilibob4ik
Offline
Зарегистрирован: 02.06.2014

В таком случае их тоже не удастся получить с точностью до десятых.

если не исправить библиотеку.

__Alexander
Offline
Зарегистрирован: 24.10.2012

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

zilibob4ik
Offline
Зарегистрирован: 02.06.2014

Библиотека в пользовательскую программу выдаёт при запросе готовые данные, которые в формате ИНТ.

Что она внутри себя получает НЕХ, это ясно, но с преобразованиями не ясно.

Вы сейчас говорите прописные истины которые все и так ясны тем, кто с этим стакивался.

Вопрос другой, кто может переделать и имеет желание - я попросил помочь.

Этот же вопрос с преобразованиями у меня (если делать самостоятельно), 

займёт времени гораздо больше,

чем у человека (или с его помощью) которые с этим сталкивался и имеет опыт

 

__Alexander
Offline
Зарегистрирован: 24.10.2012

так сначала надо уточнить какие идут с плавающей точкой.

вот вы пишите "А вот датчик МАФ (расход воздуха) даёт данные с долями,", я посмотрел что этот параметр выдает граммы/сек, никаких долей там нет. я сталкивался с квп2000, там тоже приходят два байта в инт, допустим 1245, я знаю что это параметр напряжения и что для вывода на дисплей с долями его надо поделить на сто, это будут целые, остаток сотые. вот и всё, возможно вам этот инт тоже надо делить, я бы не заморачивался, а просто закоментировал преобразования в библиотеке и работал бы с сырыми данными, делил бы на что надо.

zilibob4ik
Offline
Зарегистрирован: 02.06.2014

Вот как читаются правильные данные:

К сожалению, стабильность этих функций, оставляет желать лучшего.

Но данные нормальные, с десятыми долями.

Что то с таймингами не так. Данные часто "высыпаются" в неизвестном направлении.

А библиотека читает стабильно, ровно, но данные не точные.

void Maf(void) {
  delay(delay_var);
  blueToothSerial.flush();
  blueToothSerial.print("0110");  // Массовый расход воздуха
  blueToothSerial.print("\r");
  getResponse();
  getResponse();
  if ((strtol(&rxData[0], 0, 16) == 65) and (strtol(&rxData[3], 0, 16) == 16)) {
    maf_var = double((strtol(&rxData[6], 0, 16) * 256) + strtol(&rxData[9], 0, 16)) / 100.0;
  }
  else {
    maf_error++;
    ; // считаем кол-во ошибок чтения
  }
}
void getResponse(void) {
  char inChar = 0; //int loop_=0;
  if (off2)
  {
    while (inChar != '\r') {
      if (blueToothSerial.available() > 0) {
        if (blueToothSerial.peek() == '\r') {
          inChar = blueToothSerial.read();
          rxData[rxIndex] = '\0';
          rxIndex = 0;
        }
        else {
          inChar = blueToothSerial.read();
          rxData[rxIndex++] = inChar;
        }
      }

    }
  }

 

zilibob4ik
Offline
Зарегистрирован: 02.06.2014

а по поводу " я бы не заморачивался, а просто закоментировал преобразования в библиотеке и работал бы с сырыми данными, делил бы на что надо."

так библиотека, кажется работаетс с одним байтом, 

я не могу разобраться, где она берёт 2 байта, чтобы выдать их сырыми.

__Alexander
Offline
Зарегистрирован: 24.10.2012

она работает и с одим и с двумя, возвращает то она int, а это уже два байта если что.

zilibob4ik
Offline
Зарегистрирован: 02.06.2014

Т.е Вы предлагаете преобразование в функции Normalize закомментировать,

с полученным INT произвести разделение на 2 байта?

X- данные в ИНТ

Y - старш. байт

Z - младш байт

Y=x/256

Z=x-(x/256)

__Alexander
Offline
Зарегистрирован: 24.10.2012

если там формулы правильные то можно переименовать ее во float и result тоже сделать флоат. а можно да, убрать формулы, оно вернет целое значение, а там уже где-то во флоате поделить на ту-же формулу, будет вам с точкой.

zilibob4ik
Offline
Зарегистрирован: 02.06.2014

Переименовывание во float ничегоне дало, пробовал.

В общем, буду разбираться, есть новая почва для размышлений.

Спасибо за наводку...

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

не заходил, а это всё целые значения и они его устроили. 

__Alexander
Offline
Зарегистрирован: 24.10.2012

а возвращаемое значение функции переименовывали?

float COBD::normalizeData(byte pid, char* data)
{
	float result;

странно что ничего не дало.

zilibob4ik
Offline
Зарегистрирован: 02.06.2014

__Alexander пишет:

а возвращаемое значение функции переименовывали?

float COBD::normalizeData(byte pid, char* data)
{
	float result;

странно что ничего не дало.

Я правда переименовывал в double, но результат по сути должен быть тот же.

__Alexander
Offline
Зарегистрирован: 24.10.2012

ну да

zilibob4ik
Offline
Зарегистрирован: 02.06.2014

Там, похоже сами функции преобразования являются проблеммными. 

Которые из шестнадцатиричных преобразуют.

ошибка при компиляции

 
C:\arduino-1.6.5-r5\libraries\OBD\OBD.cpp:114:7: error: prototype for 'float COBD::normalizeData(byte, char*)' does not match any in class 'COBD'
 float COBD::normalizeData(byte pid, char* data)
       ^
In file included from C:\arduino-1.6.5-r5\libraries\OBD\OBD.cpp:10:0:
C:\arduino-1.6.5-r5\libraries\OBD\OBD.h:165:6: error: candidate is: int COBD::normalizeData(byte, char*)
  int normalizeData(byte pid, char* data);
__Alexander
Offline
Зарегистрирован: 24.10.2012

та не, в .h файле определение этой функции тоже надо заменить на флоат.

zilibob4ik
Offline
Зарегистрирован: 02.06.2014

В общем, везде заменил, нормально компилится

но увы,

данные так же обрезаны :(

sergeyksv45
Offline
Зарегистрирован: 24.02.2016

Приветствую!!! Столкнулся также с проблемой в переменных. Пишу прогу круиз контроля на авто и пробег нужно отображать 35620 т.к. а у автора эта переменная INT максимум пробега получается отобразить 32 767, пришлось посидеть денек и поправить библиотеку. Все вычисления остались по формулам автора, но переменные теперь LONG на выходе. Напряжение с ЭБУ не читаю так что не стал заморачиваться и дальше править для FLOAT.