can bus obd2 usb interface на АлиЭкспресс — купить онлайн по выгодной цене

can bus obd2 usb interface на АлиЭкспресс — купить онлайн по выгодной цене ОБД2
Содержание
  1. Что делает сканер elm327
  2. Разработка панели приборов на основе raspberry pi и 7″ дисплея
  3. Что такое elm327
  4. Внешний осмотр
  5. Тип подключения
  6. Версия прошивки
  7. Тип диагностического разъёма авто
  8. Can сниффер из arduino uno
  9. Elm327 1.5 vs elm327 2.1
  10. Elm327 интерфейс obd2 протоколы на алиэкспресс — купить онлайн по выгодной цене
  11. Видео работы цифровой панели приборов на базе raspberry pi
  12. Выбор подключения
  13. Как выбрать elm327
  14. Как подключить и настроить диагностический автомобильный сканер кодов obd ii can?
  15. Как подключиться к авто
  16. Как пользоваться сканером elm327
  17. Как проверить сканер elm327
  18. Подключение
  19. Подслушиваем запросы с помощью диагностической системы vag-com (vcds)
  20. Приложение на телефон виртуальная панель приборов
  21. Софт панели приборов на python и kivy (ui framework)
  22. Считывание диагностических данных
  23. Считывание и расшифровка ошибок автомобиля
  24. Шаг 1. установка приложения для диагностики
  25. Эпилог

Что делает сканер elm327

Функциональность ELM327 довольно обширна. Но во многом зависит от поддержки тех или иных возможностей конкретной версией адаптера, ЭБУ самой машины, а также ПО, которое используется для диагностики.

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

В некоторых авто с помощью адаптера ELM327 можно разблокировать и перенастроить автоматическое запирание замков и складывание зеркал, отзывчивость педали газа, данные приборной панели.

Разработка панели приборов на основе raspberry pi и 7″ дисплея


В качестве аппаратной части я выбрал Raspberry Pi. Была идея использовать Android планшет, но показалось, что на Raspberry Pi будет проще и быстрее. В итоге докупил официальный 7″ дисплей, и сделал CAN шилд из модуля TJA1050 Niren.

Код ошибки:  OpenDiag Mobile

OBD2 штекер использовал от старого ELM327 адаптера.

Используются контакты: CAN_L, CAN_H, 12, GND.

Тесты в машине прошли успешно и теперь нужно было все собрать. Плату дисплея, Raspberry Pi и блок питания разместил на куске черного пластика, очень удачно подобрал пластмассовые втулки, с ними ничего не болтается и надежно закреплено.

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

Напильником довел лист черного пластика до размера крышки бардачка, к нему прикрепил бутерброд и дисплей. Для прототипа сойдет, а 3D модель с крышкой для дисплея и всеми нужными крепежами уже в разработке.

Что такое elm327

Обозначение ELM327 хорошо знакомо многим автовладельцам. Это сканер или адаптер, который подключается к бортовому компьютеру машины через разъём OBD-II. Полезный прибор используется для диагностики неисправностей, считывания показателей работы и обнуления ошибок ЭБУ (электронного блока управления).

Внешний осмотр

Визуально определить качественный адаптер не так уж просто. Непрозрачный или тёмный пластиковый корпус делает невозможным осмотр компонентов. Их миниатюрность и трудночитаемая маркировка ещё больше усложняют дело.

Тип подключения

Существует несколько версий ELM327 с разными интерфейсами подключения. Самыми распространёнными являются адаптеры с Bluetooth, Wi-Fi и USB. Отличаются они не только возможностью соединения, но и совместимостью со смартфонами и компьютерами. В остальном функции идентичны.

  • Bluetooth — самые дешёвые сканеры, которые работают только с Android-смартфонами.
  • Wi-Fi — более дорогие версии, совместимые как со смартфонами на Android и iOS, так и с компьютерами.
  • USB — чуть дешевле сканеров с Wi-Fi. Работают только с компьютерами, зато отличаются надёжностью связи.

Версия прошивки

ПО адаптеров постоянно обновляется. На оригинальных ELM327 актуальная версия уже 2.2. Китайские клоны продаются с прошивками 1.5 и 2.1. Как ни странно, более свежий вариант хуже.

Попавший к китайцам чип был с микропрограммой версии 1.5. Все клоны с такой прошивкой имеют ПО оригинального ELM327. Позже появились копии сканеров версии 2.1. Последняя является лишь изменённой прошивкой 1.5, причём не в лучшую сторону — для удешевления производства китайцы убрали многие протоколы связи. Кроме того, есть обычные адаптеры с версией 1.5, которые продаются под видом 2.1.

По факту сейчас в продаже доступны три варианта клонов ELM327:

  • ELM327 1.5 — старая, но оригинальная прошивка;
  • ELM327 2.1 — урезанная оригинальная прошивка под видом более новой;
  • ELM327 2.1 — оригинальная прошивка под видом новой, но без изменений.

Очевидно, что стоит покупать адаптер именно с оригинальной прошивкой версии 1.5. Например, вот один из проверенных продавцов, у которого можно купить недорогую Bluetooth-версию ELM327.

Тип диагностического разъёма авто

У некоторых машин, особенно до 2000 года и отечественных, диагностический разъём имеет колодки других стандартов. Подключить к ним сканер напрямую не выйдет. Для таких случаев используют специальные переходники: с одной стороны у них совместимый разъём для конкретной модели авто, а с другой — стандартный OBD-II.

Can сниффер из arduino uno


Чтобы послушать, что отправляет VCDS в CAN шину я собрал сниффер на макетке из Arduino и модуля MCP2515 TJA1050 Niren.

Схема подключения следующая:

Elm327 1.5 vs elm327 2.1

can bus obd2 usb interface на АлиЭкспресс — купить онлайн по выгодной цене

Одной из первых проблем, с которыми можно столкнуться стала проблема выбора непосредственно адаптера, в нашем случае Bluetooth. Оказывается если вам необходимо поддерживать все (по крайней мере большинство) автомобилей необходимо выбирать версию v1.5 вместо v2.

1, что на самом то деле необходимо несколько раз уточнить при покупке адаптера, потому как продавцы пытаются выдать версию адаптера не за ту, которая есть на самом деле, т.к. они особо ничем не отличаются. На деле же в версии v2.1 отсутствует поддержка протоколов J1850 PWM и J1850 VPW, что говорит о том, что у вас не получится подключиться к автомобилям, которые используют эти протоколы.

Elm327 интерфейс obd2 протоколы на алиэкспресс — купить онлайн по выгодной цене

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

Закажите elm327 интерфейс obd2 протоколы онлайн с доставкой по России: товары с пометкой Plus доступны с ускоренной доставкой и улучшенными условиями возврата.

На Алиэкспресс elm327 интерфейс obd2 протоколы всегда в наличии в большом ассортименте: на площадке представлены как надежные мировые бренды, так и перспективные молодые.

Видео работы цифровой панели приборов на базе raspberry pi

ОБНОВЛЕНО 24.06.2021

Выбор подключения

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

Существует несколько вариаций адаптера ELM327, которые классифицируются по способу передачи данных – Bluetooth, WIFI, USB. Исходя из того что целью разработки является мобильное устройство под операционной системой Android можно подобрать две наиболее подходящие версии ELM327, такие как Bluetooth и WIFI.

Как выбрать elm327

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

Как подключить и настроить диагностический автомобильный сканер кодов obd ii can?

Как подключить и настроить диагностический автомобильный сканер кодов OBD II CAN?

КРАТКОЕ СОДЕРЖАНИЕ:

  1. Подключите устройство к телефону по Bluetooth
  2. Подключите устройство в настройках программы Torque

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

Для начала давайте рассмотрим само устройство. Оно представляет собой небольшую коробочку, которая является, фактически, переходником для подключения Вашего смартфона к автомобилю через Bluetooth. Всей расшифровкой и обработкой информации занимается Ваш телефон – при помощи специальной установленной программы. Именно наличие практически у каждого человека небольшого смартфона сделало возможным производство бытовых автомобильных сканеров OBD II. Раньше для расшифровки использовались мощные компьютеры, которые устанавливались только в автосервисах. А теперь проверить состояние всех систем Вашего железного коня можно так же легко, как сделать покупку в обычном магазине! А самое главное – автомобильный сканер является «мультимарочным», то есть, подходит для абсолютно любого автомобиля!

Но вернемся к нашему устройству:

Внешний вид автомобильного диагностического сканера OBD 2

Рис. 1. Внешний вид автомобильного диагностического сканера OBD 2

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

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

Следующим шагом идет установка самого сканера. Желательно производить установку при заглушенном автомобиле. Разъем устроен таким образом, что неправильно вставить устройство невозможно.

После установки в разъем на устройстве загорится индикатор. 

Теперь нам понадобится сама программа. Мы (сотрудники интернет-магазина «Азиада») пользуемся смартфонами на Андроиде, поэтому статью пишем исходя из собственного опыта. На смартфонах с другими операционными системами процесс будет очень похож, мы уверены, что Вы без труда разберётесь.

Итак, открываем Google Play Market. Существует большое количество программ для диагностики, они отличаются возможностями, интерфейсом и т.д.. Лично мы используем программу Torque – управление в ней интуитивно понятно и не требует каких-либо особых знаний. Впоследствии Вы всегда сможете установить другой софт.

Приложения в Play Market при поисковом запросе «Torque»

Рис. 2. Приложения в Play Market при поисковом запросе «Torque»

Вбив в поисковую строку «Torque», мы увидим, что таких программ две – платная версия и бесплатная (см. рис. 2). Для начала есть смысл не тратить деньги и поставить бесплатную версию. В 99% случаев ее возможностей достаточно.

Устанавливаем…

И получаем вот такой ярлык на рабочем столе: 

Ярлык программы «Torque» на рабочем столе

Рис. 3. Ярлык программы «Torque» на рабочем столе

Теперь нам нужно соединить смартфон и автомобильный диагностический сканер кодов через Bluetooth. Соединение происходит в два этапа – первым этапом мы должны объяснить Андроиду, что у нас есть новое Bluetooth – устройство и нам нужно его подключить к телефону. Вторым этапом мы должны объяснить программе Torque, что подключенное по беспроводному каналу устройство и есть наш сканер.

Для этого открываем в вашем телефоне «настройки», выбираем закладку «Bluetooth», затем в списке ищем сканер. Если его там нет – вытащите и установите его в разъем еще раз, возможно, он просто впал в «спящий режим».

Подключение автомобильного диагностического сканера через Bluetooth

Рис. 4. Подключение автомобильного диагностического сканера через Bluetooth

Иногда прибор определяется весьма странно, например, как на рисунке – 00:11:10:24:03:49. Но после того, как Вы его подключите, он обретет свое «настоящее» имя и станет называться Aut-Tech.

Итак, щелкаем на устройство в списке. Выскочит окошко, в котором нужно будет ввести пароль – 1234. Возможно, у других устройств пароль будет другим, но это всегда простейшее сочетание символов – 1111, 0000, 1234, 123456 и так далее. После ввода пароля нажмите клавишу «ОК».

Запрос пароля для подключения

Рис. 5. Запрос пароля для подключения

Устройство будет подключено. Обратите внимание на забавный факт – на многих смартфонах значок беспроводного соединения не меняет цвет!

Тем не менее, в списке появится надпись – «авторизовано». 

Устройство Aut-Tech авторизовано

Рис. 6. Устройство Aut-Tech авторизовано

Теперь запускаем саму программу. Затем на экране щёлкаем на кнопку с шестеренкой – это «настройки». В зависимости от типа Вашего устройства и диагонали экрана внешний вид может отличаться от наших картинок. В некоторых случаях настройки вызываются нажатием на отдельную кнопку на корпусе смартфона. Это зависит только от модели аппарата, который Вы используете.

После нажатия появится меню, в котором выбираем «настройки»:

Кнопка «Меню» в программе «Torque»

Рис. 7. Кнопка «Меню» в программе «Torque»

В настройках среди прочего нам нужно проверить раздел «Connection» – должно быть установлено «Bluetooth» (бывают адаптеры с подключением по Wi-Fi, настраиваются практически так же).

И самое главное – нажмите на раздел «Device». Выскочит список всех устройств, которые Вы подключали по Bluetooth – Ваши гарнитуры, беспроводные колонки и прочее. В списке выберите Aut-Tech – это и есть наш диагностический сканер.

Интересующие нас пункты меню

Рис. 8. Интересующие нас пункты меню

Выбор устройства Bluetooth

Рис. 9. Выбор устройства Bluetooth

Примечание: В нашем случае мы ничего не подключали к данному планшету ранее, поэтому в списке и присутствует только «Aut-Tech». У Вас ситуация может быть немного иная. 

ПОЗДРАВЛЯЕМ! УСТРОЙСТВО ПОДКЛЮЧЕНО И РАБОТАЕТ!

Как это проверить? Самый простой вариант – считать показания какого-либо датчика. Идеально для этих целей подходит датчик напряжения на аккумуляторе. Для этого в основном меню программы на пустом поле задержите палец на несколько секунд. Появится меню, выберите «Add Display» -> «Display» -> «Voltage». Выберите желаемый размер дисплея, и он будет помещен на рабочий стол программы. Заведите машину – и индикатор покажет напряжение – 14 вольт когда машина заведена, или 12 вольт если мотор заглушен.

Напряжение на аккумуляторе

Рис. 10. Напряжение на аккумуляторе

Как подключиться к авто

Точная процедура настройки обычно описана в инструкции.

Как пользоваться сканером elm327

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

Как проверить сканер elm327

После покупки адаптера ELM327 проверьте, что он действительно версии 1.5. При заказе с AliExpress уточните, установлен ли в нём чип PIC18F25K80 и подчеркните, что будете диагностировать сканер специальным ПО и откроете спор в случае проблем.

Подключение

Подключение к адаптеру происходит в несколько этапов:

Если с организацией подключения все понятно. Принцип работы такой же как и у любого Bluetooth/WIFI чата. То для того чтоб понять как отправлять инициализационную строку, необходимо изучить какие команды существуют, а также какие функции они выполняют.

Подслушиваем запросы с помощью диагностической системы vag-com (vcds)


Описание VCDS с официального сайта

Приложение на телефон виртуальная панель приборов

can bus obd2 usb interface на АлиЭкспресс — купить онлайн по выгодной цене
can bus obd2 usb interface на АлиЭкспресс — купить онлайн по выгодной цене
Если есть желание поддержать проект, то вот ссылка на приложение, принимаю любые замечания и предложения!
VAG Virtual Cockpit
can bus obd2 usb interface на АлиЭкспресс — купить онлайн по выгодной цене

Софт панели приборов на python и kivy (ui framework)

Параллельно со сборкой самой панели приборов я вел разработку приложения для отображения информации с датчиков. В самом начале я не планировал какой либо дизайн.

can bus obd2 usb interface на АлиЭкспресс — купить онлайн по выгодной цене
Первая версия панели приборов

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

can bus obd2 usb interface на АлиЭкспресс — купить онлайн по выгодной цене
Вторая версия панели приборов

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

can bus obd2 usb interface на АлиЭкспресс — купить онлайн по выгодной цене
Третья версия панели приборов

Ранее, я никогда не разрабатывал графические приложения под Linux поэтому не знал с чего начать. Вариант на вебе простой в разработке, но слишком много лишних компонентов: иксы, браузер, nodejs, хотелось быстрой загрузки. Попробовав Qt PySide2 я понял, что это займет у меня много времени, т.к. мало опыта.

Kivy позволяет запускать приложение без Иксов, прямо из консоли, в качестве рендера используется OpenGL. Благодаря этому полная загрузка системы может происходить за 10 секунд.

import can
import os
import sys
from threading import Thread
import time
os.environ['KIVY_GL_BACKEND'] = 'gl'
os.environ['KIVY_WINDOW'] = 'egl_rpi'
from kivy.app import App
from kivy.properties import NumericProperty
from kivy.properties import BoundedNumericProperty
from kivy.properties import StringProperty
from kivy.uix.label import Label
from kivy.uix.image import Image
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.uix.scatter import Scatter
from kivy.animation import Animation
messageCommands = { 'GET_DOORS_COMMAND': 0x220D, 'GET_OIL_TEMPERATURE' : 0x202F, 'GET_OUTDOOR_TEMPERATURE' : 0x220C, 'GET_INDOOR_TEMPERATURE' : 0x2613, 'GET_COOLANT_TEMPERATURE' : 0xF405, 'GET_SPEED' : 0xF40D, 'GET_RPM' : 0xF40C, 'GET_KM_LEFT': 0x2294, 'GET_FUEL_LEFT': 0x2206, 'GET_TIME': 0x2216
}
bus = can.interface.Bus(channel='can0', bustype='socketcan')
Полный код панели в одном python файле

# -*- coding: utf-8 -*-
import can
import os
import sys
from threading import Thread
import time
os.environ['KIVY_GL_BACKEND'] = 'gl'
os.environ['KIVY_WINDOW'] = 'egl_rpi'
from kivy.app import App
from kivy.properties import NumericProperty
from kivy.properties import BoundedNumericProperty
from kivy.properties import StringProperty
from kivy.uix.label import Label
from kivy.uix.image import Image
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.uix.scatter import Scatter
from kivy.animation import Animation
messageCommands = { 'GET_DOORS_COMMAND': 0x220D, 'GET_OIL_TEMPERATURE' : 0x202F, 'GET_OUTDOOR_TEMPERATURE' : 0x220C, 'GET_INDOOR_TEMPERATURE' : 0x2613, 'GET_COOLANT_TEMPERATURE' : 0xF405, 'GET_SPEED' : 0xF40D, 'GET_RPM' : 0xF40C, 'GET_KM_LEFT': 0x2294, 'GET_FUEL_LEFT': 0x2206, 'GET_TIME': 0x2216
}
bus = can.interface.Bus(channel='can0', bustype='socketcan')
class PropertyState: def __init__(self, last, current): self.last = last self.current = current def lastIsNotNow(self): return self.last is not self.current
class CanListener(can.Listener): def __init__(self, dashboard): self.dashboard = dashboard self.speedStates = PropertyState(None,None) self.rpmStates = PropertyState(None,None) self.kmLeftStates = PropertyState(None,None) self.coolantTemperatureStates = PropertyState(None,None) self.oilTempratureStates = PropertyState(None,None) self.timeStates = PropertyState(None,None) self.outDoorTemperatureStates = PropertyState(None,None) self.doorsStates = PropertyState(None,None) self.carMinimized = True def on_message_received(self, message): messageCommand = message.data[3] | message.data[2] << 8 if message.arbitration_id == 0x77E and messageCommand == messageCommands['GET_SPEED']: self.speedStates.current = message.data[4] if self.speedStates.lastIsNotNow(): self.dashboard.speedometer.text = str(self.speedStates.current) self.speedStates.last = self.speedStates.current if message.arbitration_id == 0x77E and messageCommand == messageCommands['GET_RPM']: self.rpmStates.current = message.data[5] | message.data[4] << 8 if self.rpmStates.lastIsNotNow(): self.dashboard.rpm.value = self.rpmStates.current/4 self.rpmStates.last = self.rpmStates.current if message.arbitration_id == 0x35B: self.rpmStates.current = message.data[2] | message.data[1] << 8 if self.rpmStates.lastIsNotNow(): self.dashboard.rpm.value = self.rpmStates.current/4 self.rpmStates.last = self.rpmStates.current if message.arbitration_id == 0x77E and messageCommand == messageCommands['GET_KM_LEFT']: self.kmLeftStates.current = message.data[5] | message.data[4] << 8 if self.kmLeftStates.lastIsNotNow(): self.dashboard.kmLeftLabel.text = str(self.kmLeftStates.current) self.kmLeftStates.last = self.kmLeftStates.current if message.arbitration_id == 0x77E and messageCommand == messageCommands['GET_COOLANT_TEMPERATURE']: self.coolantTemperatureStates.current = message.data[4] if self.coolantTemperatureStates.lastIsNotNow(): self.dashboard.coolantLabel.text = str(self.coolantTemperatureStates.current-81) self.coolantTemperatureStates.last = self.coolantTemperatureStates.current if message.arbitration_id == 0x77E and messageCommand == messageCommands['GET_OIL_TEMPERATURE']: self.oilTempratureStates.current = message.data[4] if self.oilTempratureStates.lastIsNotNow(): self.dashboard.oilLabel.text = str(self.oilTempratureStates.current-58) self.oilTempratureStates.last = self.oilTempratureStates.current if message.arbitration_id == 0x77E and messageCommand == messageCommands['GET_TIME']: self.timeStates.current = message.data[5] | message.data[4] << 8 if self.timeStates.lastIsNotNow(): self.dashboard.clock.text = str(message.data[4]) ":" str(message.data[5]) self.timeStates.last = self.timeStates.current if message.arbitration_id == 0x77E and messageCommand == messageCommands['GET_OUTDOOR_TEMPERATURE']: self.outDoorTemperatureStates.current = float(message.data[4]) if self.outDoorTemperatureStates.lastIsNotNow(): self.dashboard.outDoorTemperatureLabel.text = str((self.outDoorTemperatureStates.current - 100)/2) self.outDoorTemperatureStates.last = self.outDoorTemperatureStates.current if message.arbitration_id == 0x77E and messageCommand == messageCommands['GET_DOORS_COMMAND']: self.doorsStates.current = message.data[4] if self.doorsStates.lastIsNotNow(): self.doorsStates.last = self.doorsStates.current self.dashboard.car.doorsStates=message.data[4] # all doors closed -> minimize car if self.doorsStates.current == 0x55: self.dashboard.minimizeCar() self.carMinimized = True else: if self.carMinimized: self.dashboard.maximizeCar() self.carMinimized = False
class Dashboard(FloatLayout): def __init__(self,**kwargs): super(Dashboard,self).__init__(**kwargs) # Background self.backgroundImage = Image(source='bg.png') self.add_widget(self.backgroundImage) # RPM self.rpm = Gauge(file_gauge = "gauge512.png", unit = 0.023, value=0, size_gauge=512, pos=(0,0)) self.add_widget(self.rpm) self.rpm.value = -200 # Speedometer self.speedometer = Label(text='0', font_size=80, font_name='hemi_head_bd_it.ttf', pos=(0,-15)) self.add_widget(self.speedometer) # KM LEFT self.kmLeftLabel = Label(text='000', font_name='Avenir.ttc', halign="right", text_size=self.size, font_size=25, pos=(278,233)) self.add_widget(self.kmLeftLabel) # COOLANT TEMPEARATURE self.coolantLabel = Label(text='00', font_name='hemi_head_bd_it.ttf', halign="right", text_size=self.size, font_size=27, pos=(295,-168)) self.add_widget(self.coolantLabel) # OIL TEMPERATURE self.oilLabel = Label(text='00', font_name='hemi_head_bd_it.ttf', halign="right", text_size=self.size, font_size=27, pos=(-385,-168)) self.add_widget(self.oilLabel) # CLOCK self.clock = Label(text='00:00', font_name='Avenir.ttc', font_size=27, pos=(-116,-202)) self.add_widget(self.clock) # OUTDOOR TEMPERATURE self.outDoorTemperatureLabel = Label(text='00.0', font_name='Avenir.ttc', halign="right", text_size=self.size, font_size=27, pos=(76,-169)) self.add_widget(self.outDoorTemperatureLabel) # CAR DOORS self.car = Car(pos=(257,84)) self.add_widget(self.car) def minimizeCar(self, *args): print("min") anim = Animation(scale=0.5, opacity = 0, x = 400, y = 240, t='linear', duration=0.5) anim.start(self.car) animRpm = Animation(scale=1, opacity = 1, x = 80, y = -5, t='linear', duration=0.5) animRpm.start(self.rpm) def maximizeCar(self, *args): print("max") anim = Animation(scale=1, opacity = 1, x=257, y=84, t='linear', duration=0.5) anim.start(self.car) animRpm = Animation(scale=0.5, opacity = 0, x = 80, y = -5, t='linear', duration=0.5) animRpm.start(self.rpm)
class Car(Scatter): carImage = StringProperty("car362/car.png") driverDoorClosedImage = StringProperty("car362/driverClosedDoor.png") driverDoorOpenedImage = StringProperty("car362/driverOpenedDoor.png") passangerDoorClosedImage = StringProperty("car362/passangerClosedDoor.png") passangerDoorOpenedImage = StringProperty("car362/passangerOpenedDoor.png") leftDoorClosedImage = StringProperty("car362/leftClosedDoor.png") leftDoorOpenedImage = StringProperty("car362/leftOpenedDoor.png") rightDoorClosedImage = StringProperty("car362/rightClosedDoor.png") rightDoorOpenedImage = StringProperty("car362/rightOpenedDoor.png") doorsStates = NumericProperty(0) size = (286, 362) def __init__(self, **kwargs): super(Car, self).__init__(**kwargs) _car = Image(source=self.carImage, size=self.size) self.driverDoorOpened = Image(source=self.driverDoorOpenedImage, size=self.size) self.passangerDoorOpened = Image(source=self.passangerDoorOpenedImage, size=self.size) self.leftDoorOpened = Image(source=self.leftDoorOpenedImage, size=self.size) self.rightDoorOpened = Image(source=self.rightDoorOpenedImage, size=self.size) self.driverDoorClosed = Image(source=self.driverDoorClosedImage, size=self.size) self.passangerDoorClosed = Image(source=self.passangerDoorClosedImage, size=self.size) self.leftDoorClosed = Image(source=self.leftDoorClosedImage, size=self.size) self.rightDoorClosed = Image(source=self.rightDoorClosedImage, size=self.size) self.add_widget(_car) self.add_widget(self.driverDoorOpened) self.add_widget(self.passangerDoorOpened) self.add_widget(self.leftDoorOpened) self.add_widget(self.rightDoorOpened) self.bind(doorsStates=self._update) def _update(self, *args): driverDoorStates = self.doorsStates&1 passangerDoorStates = self.doorsStates&4 leftDoorStates = self.doorsStates&16 rightDoorStates = self.doorsStates&64 if driverDoorStates != 0: try: self.remove_widget(self.driverDoorOpened) self.add_widget(self.driverDoorClosed) except: pass else: try: self.remove_widget(self.driverDoorClosed) self.add_widget(self.driverDoorOpened) except: pass if passangerDoorStates != 0: try: self.remove_widget(self.passangerDoorOpened) self.add_widget(self.passangerDoorClosed) except: pass else: try: self.remove_widget(self.passangerDoorClosed) self.add_widget(self.passangerDoorOpened) except: pass if leftDoorStates != 0: try: self.remove_widget(self.leftDoorOpened) self.add_widget(self.leftDoorClosed) except: pass else: try: self.remove_widget(self.leftDoorClosed) self.add_widget(self.leftDoorOpened) except: pass if rightDoorStates != 0: try: self.remove_widget(self.rightDoorOpened) self.add_widget(self.rightDoorClosed) except: pass else: try: self.remove_widget(self.rightDoorClosed) self.add_widget(self.rightDoorOpened) except: pass
class Gauge(Scatter): unit = NumericProperty(1.125) zero = NumericProperty(116) value = NumericProperty(10) #BoundedNumericProperty(0, min=0, max=360, errorvalue=0) size_gauge = BoundedNumericProperty(512, min=128, max=512, errorvalue=128) size_text = NumericProperty(10) file_gauge = StringProperty("") def __init__(self, **kwargs): super(Gauge, self).__init__(**kwargs) self._gauge = Scatter( size=(self.size_gauge, self.size_gauge), do_rotation=False, do_scale=False, do_translation=False ) _img_gauge = Image(source=self.file_gauge, size=(self.size_gauge, self.size_gauge)) self._needle = Scatter( size=(self.size_gauge, self.size_gauge), do_rotation=False, do_scale=False, do_translation=False ) _img_needle = Image(source="arrow512.png", size=(self.size_gauge, self.size_gauge)) self._gauge.add_widget(_img_gauge) self._needle.add_widget(_img_needle) self.add_widget(self._gauge) self.add_widget(self._needle) self.bind(pos=self._update) self.bind(size=self._update) self.bind(value=self._turn) def _update(self, *args): self._gauge.pos = self.pos self._needle.pos = (self.x, self.y) self._needle.center = self._gauge.center def _turn(self, *args): self._needle.center_x = self._gauge.center_x self._needle.center_y = self._gauge.center_y a = Animation(rotation=-self.value*self.unit self.zero, t='in_out_quad',duration=0.05) a.start(self._needle)
class requestsLoop(Thread): def __init__(self): Thread.__init__(self) self.daemon = True self.start() canCommands = [ can.Message(arbitration_id=0x714, data=[0x03, 0x22, messageCommands['GET_DOORS_COMMAND'] >> 8, messageCommands['GET_DOORS_COMMAND'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False), can.Message(arbitration_id=0x714, data=[0x03, 0x22, messageCommands['GET_SPEED'] >> 8, messageCommands['GET_SPEED'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False), can.Message(arbitration_id=0x714, data=[0x03, 0x22, messageCommands['GET_KM_LEFT'] >> 8, messageCommands['GET_KM_LEFT'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False), can.Message(arbitration_id=0x714, data=[0x03, 0x22, messageCommands['GET_RPM'] >> 8, messageCommands['GET_RPM'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False), can.Message(arbitration_id=0x714, data=[0x03, 0x22, messageCommands['GET_OIL_TEMPERATURE'] >> 8, messageCommands['GET_OIL_TEMPERATURE'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False), can.Message(arbitration_id=0x714, data=[0x03, 0x22, messageCommands['GET_FUEL_LEFT'] >> 8, messageCommands['GET_FUEL_LEFT'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False), can.Message(arbitration_id=0x714, data=[0x03, 0x22, messageCommands['GET_OUTDOOR_TEMPERATURE'] >> 8, messageCommands['GET_OUTDOOR_TEMPERATURE'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False), can.Message(arbitration_id=0x746, data=[0x03, 0x22, messageCommands['GET_INDOOR_TEMPERATURE'] >> 8, messageCommands['GET_INDOOR_TEMPERATURE'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False), can.Message(arbitration_id=0x714, data=[0x03, 0x22, messageCommands['GET_COOLANT_TEMPERATURE'] >> 8, messageCommands['GET_COOLANT_TEMPERATURE'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False), can.Message(arbitration_id=0x714, data=[0x03, 0x22, messageCommands['GET_TIME'] >> 8, messageCommands['GET_TIME'] & 0xff, 0x55, 0x55, 0x55, 0x55], extended_id=False) ] def run(self): while True: for command in self.canCommands: bus.send(command) time.sleep(0.005)
class BoxApp(App): def build(self): dashboard = Dashboard(); listener = CanListener(dashboard) can.Notifier(bus, [listener]) return dashboard
if __name__ == "__main__": # Send requests requestsLoop() _old_excepthook = sys.excepthook def myexcepthook(exctype, value, traceback): if exctype == KeyboardInterrupt: print "Handler code goes here" else: _old_excepthook(exctype, value, traceback) sys.excepthook = myexcepthook # Show dashboard BoxApp().run()

Алгоритм работы следующий, используется 3 потока:

  1. В главном потоке работаем с графическими элементы (спидометр, тахометр, часы, температуры и др) на экране
  2. Во втором потоке каждые 5 мс делаем опрос следующего датчика
  3. В третьем потоке слушаем CAN шину, получив ответ парсим его и обновляем соответствующий графический элемент


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

Проект цифровой панель приборов открытый. Рад буду предложениям и комментариям!

Считывание диагностических данных

Для считывания диагностических данных используются специальные команды PID’s.

PID (Parameter id’s — Бортовые диагностические идентификаторы параметров) – коды, которые используются для запроса показателей определенных датчиков автомобиля.

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

Также есть возможность получать текущие данные от автомобиля при этом команда получения данных от авто будет иметь вначале 01, указывая на то что мы хотим получить real data. Если же мы хотим получить сохраненные данные автомобиля, то вначале команды необходимо указать 02.

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

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

0100 – PIDs supported [01 — 20]0120 – PIDs supported [21 — 40]0140 – PIDs supported [41 — 60]0160 – PIDs supported [61 — 80]0180 – PIDs supported [81 – A0]01A0 – PIDs supported [A1 — C0]

Я продемонстрирую как определить какие датчики присутствуют в автомобиле при помощи одного из пидов. Например:


Переводим ответ от автомобиля в двоичную систему счисления

BB1E3211(16) > 10111011000111100011001000010001(2)

Используя следующую табличку можем определить какие пиды поддерживаются нашим автомобилем, начиная от 01 до 20:

Исходя из получившихся данных можем определить, что наш автомобиль поддерживает следующие пиды:

01, 03, 04, 05, 07, 08, 0C, 0D, 0E, 0F, 13, 14, 17, 1C, 20

Теперь вместо отправки всех 32 команд и ожидания ответа на них, несмотря на то, что некоторые могут отсутствовать, мы будем использовать всего 15 команд. Но и это не предел так называемой оптимизации. Для того чтобы данные обновлялись еще быстрее советую запрашивать только данные о тех датчиках, которые отображаются на экране. Хотя это ограничивает некоторый функционал приложения. Например, запись истории.

Считывание и расшифровка ошибок автомобиля


Ошибки автомобиля тоже могут быть различными и для них тоже существуют отдельные команды. Например:

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

private final static char[] dtcLetters = {'P', 'C', 'B', 'U'};
private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
private void performCalculations(String fault) { final String result = fault; String workingData = ""; int startIndex = 0; troubleCodesArray.clear(); try { if (result.contains("43")) { workingData = result.replaceAll("^43|[rn]43|[rn]", ""); } else if (result.contains("47")) { workingData = result.replaceAll("^47|[rn]47|[rn]", ""); } for(int begin=startIndex; begin < workingData.length(); begin = 4) { String dtc = ""; byte b1 = Utility.hexStringToByteArray(workingData.charAt(begin)); int ch1 = ((b1 & 0xC0) >> 6); int ch2 = ((b1 & 0x30) >> 4); dtc = dtcLetters[ch1]; dtc = hexArray[ch2]; dtc = workingData.substring(begin 1, begin 4); if (dtc.equals("P0000")) { continue; } troubleCodesArray.add(dtc); } } catch (Exception e) { Log.e(TAG, "Error: " e.getMessage()); }
}

А теперь пояснение.

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

Первый символ:

Второй символ:

3, 4, 5 символы формируются по этой таблице:

Исходя из этого можем попробовать разобрать следующий ответ 0001000000111110

Код ошибки: P103E

Шаг 1. установка приложения для диагностики

Для соединения с ЭБУ машины используются различные программы. Существуют как бесплатные, так и платные версии для Android, iOS и Windows. В комплекте с самим сканером нужное ПО часто уже идёт в комплекте. Установите его или одно из популярных приложений.

OpenDiag (Windows) →

Эпилог

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

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

Матвиенко Александр, Хоссейн Фахр.P.S. Оригинальную английскую версию статьи можно найти здесь

Оцените статью
OBD