Хакаем CAN шину авто. Виртуальная панель приборов +174





В первой статье «Хакаем CAN шину авто для голосового управления» я подключался непосредственно к CAN шине Comfort в двери своего авто и исследовал пролетающий траффик, это позволило определить команды управления стеклоподъемниками, центральным замком и др.

В этой статье я расскажу как собрать свою уникальную виртуальную или цифровую панель приборов и получить данные с любых датчиков в автомобилях группы VAG (Volkswagen, Audi, Seat, Skoda).

Мною был собран новый CAN сниффер и CAN шилд для Raspberry Pi на базе модуля MCP2515 TJA1050 Niren, полученные с их помощью данные я применил в разработке цифровой панели приборов с использованием 7? дисплея для Raspberry Pi. Помимо простого отображения информации цифровая панель реагирует на кнопки подрулевого переключателя и другие события в машине.

В качестве фреймворка для рисования приборов отлично подошел Kivy для Python. Работает без Иксов и для вывода графики использует GL.

  1. CAN сниффер из Arduino Uno
  2. Подслушиваем запросы с помощью диагностической системы VAG-COM (VCDS)
  3. Разработка панели приборов на основе Raspberry Pi и 7? дисплея
  4. Софт панели приборов на Python и Kivy (UI framework)
  5. Видео работы цифровой панели приборов на базе Raspberry Pi

Под катом полная реализация проекта, будет интересно!


Водительская дверь открыта

CAN сниффер из Arduino Uno


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



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


Для прослушивания трафика использовал анализатор CanHackerV2 и прошивку arduino-canhacker для Arduino, которая реализует API совместимое с этой программой. Прошивка в гите https://github.com/autowp/arduino-canhacker.

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



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


Описание VCDS с официального сайта ru.ross-tech.com:

Программно-аппаратный сканер VCDS предназначен для диагностики электронных систем управления, устанавливаемых на автомобилях группы VAG. Доступ ко всем системам: двигатель, ACP, АБС, климат-контроль, кузовая электроника и т.п., считывание и стирание кодов неисправностей, вывод текущих параметров, активация, базовые установки, адаптация, кодирование и т.п.



Подключив сниффер к линиям CAN_L и CAN_H в диагностическом шнурке я смог увидеть какие запросы делает VCDS и что отвечает авто.



Особенность авто группы VAG в том, что OBD2 разъем подключен к CAN шине через шлюз и шлюз не пропускает весь гуляющий по сети трафик, т.е. подключившись в OBD2 разъем сниффером вы ничего не увидите. Чтобы получить данные в OBD2 разъёме нужно отправлять шлюзу специальные запросы. Эти запросы и ответы видно при прослушивании трафика от VCDS. Например вот так можно получить пробег.


В VCDS можно получить информацию почти с любого датчика в машине. Меня в первую очередь интересовала информация, которой вообще нет на моей приборке, это:

  • температура масла
  • какая именно дверь открыта

Скорость, обороты, температура ОЖ, пробег, расход, место в баке и другие запросы я тоже получил, для справки размещу.

// Двери
714 03 22 22 0D 55 55 55 55
77E 05 62 22 0D 55 65 AA AA - все закрыты
77E 05 62 22 0D 00 65 AA AA - все открыты
77E 05 62 22 0D 54 65 AA AA - водительская открыта
77E 05 62 22 0D 51 65 AA AA - пассажирская открыта
77E 05 62 22 0D 50 65 AA AA - водительская и пассажирская открыта
77E 05 62 22 0D 45 65 AA AA - задняя левая открыта
77E 05 62 22 0D 15 65 AA AA - задняя правая открыта
77E 05 62 22 0D 44 65 AA AA - водительская и задняя левая открыта
77E 05 62 22 0D 40 65 AA AA - водительская, пассажирская, задняя левая открыты
01010101 = 0x55 (все закрыты)
0 бит - водительская
2 бит - пассажирская
4 бит - задняя левая
6 бит - задняя правая

// Ручник
714 03 22 22 05 55 55 55 55
77E 05 62 22 05 21 AA AA AA - нажат
77E 05 62 22 05 20 AA AA AA - не нажат

// Наружная температура
714 03 22 22 0С 55 55 55 55
77E 04 62 22 0C 55 AA AA AA - -7.5°С
77E 04 62 22 0C 65 AA AA AA - 0.5 101°С
77E 04 62 22 0C 66 AA AA AA - 1 = 102°С
77E 04 62 22 0C 68 AA AA AA - 2 = 104°С

// Наружная температура отображаемая
714 03 22 10 14 55 55 55 55
77E 04 62 10 14 84 AA AA AA - 16°С

// Запас хода
714 03 22 22 94 55 55 55 55
77E 05 62 22 94 00 8E AA AA - 142км

// Уровень топлива
714 03 22 22 06 55 55 55 55
77E 04 62 22 06 2C AA AA AA - 44л
77E 04 62 22 06 16 AA AA AA - 22л

// Положение стрелки указателя уровня топлива
714 03 22 22 96 55 55 55 55
77E 05 62 22 96 01 9A AA AA - 41.0°

// Температура ОЖ
714 03 22 F4 05 55 55 55 55
77E 04 62 F4 05 85 AA AA AA - 52.5°С
77E 04 62 F4 05 87 AA AA AA - 54°С
77E 04 62 F4 05 С5 AA AA AA - 100.5°С

// Обороты двигателя
714 03 22 F4 0C 55 55 55 55
77E 05 62 F4 0C 0B C6 AA AA - 753.5 об/мин; 0BC6 = 3014/4 = 753
77E 05 62 F4 0C 0B DC AA AA - 759 об/мин; 0BDC = 3036
77E 05 62 F4 0C 0B E8 AA AA - 762 об/мин; 0BE8 = 3048
77E 05 62 F4 0C 1C 32 AA AA - 1804.5 об/мин

// Температура масла
714 03 22 20 2F 55 55 55 55
77E 04 62 20 2F 36 AA AA AA - -4°С
77E 04 62 20 2F 67 AA AA AA - 45°С
77E 04 62 20 2F 68 AA AA AA - 46°С

// Температура в салоне 
746 03 22 26 13 55 55 55 55
7B0 05 62 26 13 00 5B AA AA - 9.1, 91 == 0x5B
7B0 05 62 26 13 00 5C AA AA - 9.2°С
7B0 05 62 26 13 00 5D AA AA - 9.3°С

// Время
714 03 22 22 16 55 55 55 55
77E 05 62 22 16 11 1E AA AA - 17:30

// Кнопки подрулевого переключателя
714 03 22 22 1B 55 55 55 55
77E 05 62 22 1B 80 AA AA AA - не нажата
77E 05 62 22 1B 81 AA AA AA - нажата вверх
77E 05 62 22 1B 84 AA AA AA - нажата вниз

// Средний расход 2
714 03 22 22 99 55 55 55 55
77E 03 62 22 99 00 91 AA AA - 14.5л/100км

// Текущий расход
714 03 22 22 98 55 55 55 55
77E 05 62 22 98 00 00 AA AA - 0.0л/100км

// Пробег
714 03 22 22 03 55 55 55 55
77E 05 62 22 03 24 С0 AA AA - 94080 км 0x24С0 * 10

Разработка панели приборов на основе Raspberry Pi и 7? дисплея


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



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



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



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



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



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



Софт панели приборов на Python и Kivy (UI framework)


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


Первая версия панели приборов

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


Вторая версия панели приборов

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


Третья версия панели приборов

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

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, чтобы любой мог попробовать цифровую панель приборов.

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

https://github.com/aivs/blackCockpit

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


Вы можете помочь и перевести немного средств на развитие сайта



Комментарии (173):

  1. tuxi
    /#20068738 / +1

    Клево!
    Только одно уточнение, основная прелесть ваговской реализации (в частности VCDS) не только в том, чтобы получать данные, но и вносить изменения в настройки, вплоть до очень тонких. То есть, не только настроить «сколько сигналов поворотника дать при легком нажатии переключателя», но и внести различные коррективы в режимы работы устройств подключенных к этой шине. Например догреватель вебасто, положение кузова/пневмоподвески, калибровка фар и тп и тд

    • tuxi
      /#20068890 / +1

      PS: Еще вспомнил пару интересных вещей. Если модель ВАГ-а оборудована датчиком дождя, электростеклоподьемниками и/или люком, то в некоторых моделях через VCDS (или «Васю») можно активировать функцию автозакрытия стекол, при срабатывании этого датчика.

    • aivs
      /#20068908

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

      • tuxi
        /#20069422

        С зеркалами да, есть такие нюансы. Автоскладывание при постановке на охрану, мне так и не удалось сделать.

      • LuxLP
        /#20070212

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

        • esaulenka
          /#20072094

          Скорее, это связано с датчиком положения зеркала. Т.е. для обычной регулировки нужен только моторчик, за положением следит сам водитель (максимум — концевики надо поставить, чтобы в конце хода ничего не сломать и не сжечь), а чтобы автоматически опустить зеркало и потом поднять его обратно ровно в то же положение, надо измерять, насколько именно оно опустилось и поднялось. В комплектациях «с памятью» эти датчики, очевидно, тоже нужны (но уже везде, не только в зеркалах).

          • Black_Zerg
            /#20072270

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

            • aivs
              /#20072280

              Кстати, я рычажок не пробовал ставить на правое зеркало, может тоже заработает. Через Васю активировал функцию, но результат не было.
              Я на драйве читал, что нужно ставить мезанизм с памятью положения, чтобы это заработало. А так регулировка все равно осуществляется по Кан шине.

              • Black_Zerg
                /#20072344

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

            • kAIST
              /#20073514

              Вам повезло — попался подходящий для этого блок зеркала. Мне не повезло )
              Из полезного, на йети сделал подсветку в поворотах (работает за счёт противотуманок, фича от Тигуана).
              Хочу ещё поменять кондиционер на климат. Блок управления стоит относительно дёшево (в пределах 10 тыс на разборах), правда попадаются в основном от фольцев, поэтому придется подсветку на зелёный перепаивать.

              • Black_Zerg
                /#20076006

                Ну на машинах 12-го года выпуска это делается. А подсветка это стандартная фишка всего VAGа (и на Сеате, и на Шкоде), на всех машинах концерна можно сделать. Кондер я тоже думал поменять, но не только блок надо заменить, там гораздо больше переделывать надо и влетает в копеечку

                • kAIST
                  /#20076172

                  C подсветкой, только если электрика позволяет. На фабии, например, не позволяла, хотя можно было кинуть отдельный провод от одной из туманок.
                  По поводу климата на йети (2012г), насколько узнавал, только блок управления и пару датчиков воткнуть. Все остальное уже и так управляется электроникой, все заслонки сервофицированны, только команды отдает не контроллер а человек.
                  Ну и в бортовой компьютер прописать что теперь есть климат.

                  • Black_Zerg
                    /#20076694

                    Подсветка это не электрика, а блок управления.
                    Надо посмотреть по ETKA, есть ли различия. Вечером гляну, вы меня заинтриговали

                    • kAIST
                      /#20076730

                      Именно электрика. Если две ПТФ по электрике идут на одном проводе, в блок управления смысла нет лезть, они же должны включаться независимо друг от друга. На фабии в комплектации с датчиком света, вроде как идут отдельно, если без, то включаются только вместе.
                      На йети вроде как всегда отдельно. Если есть датчик поворота руля, можно включить от положения руля, если нет, то только от поворотников. Иногда полезная штука, правда только вправо нормально светит )

                      • Black_Zerg
                        /#20077008

                        Датчика света нет. Алгоритм работы следующий. Включается при скорости ниже 40 км/ч, если включен поворотник, то сразу включается, если поворачивается руль, то плавно загорается и также плавно тухнет. Но только при скорости ниже 40 км/ч

  2. cyber_roach
    /#20069012 / +1

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

    А как данные будут поступать на мобильное ПО? придется какую-то железяжку подключать?

    • aivs
      /#20069026 / +1

      ELM327 Wi-Fi

      • adlerm
        /#20069218

        Если для грубой оценки «как это примерно выглядит», то сильно ли оно будет отличаться от того, же, уже готового, приложения вроде torque в которых можно самостоятельно нагромоздить графиков большинства датчиков и параметров… (плюсом, почитать, стереть ошибки и пр.)
        вот пример скрина в описании проги:
        image

        • aivs
          /#20069268

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

          • adlerm
            /#20069314

            Прекрасная идея и проделанная работа… Основная проблема, предполагаю, это эстетический момент внедрения этого в автомобиль?

            • aivs
              /#20069358

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

              • AllexIn
                /#20069372

                Да везде так.
                Ни в одной машине «нет штатного пустого дополнительного места для 7'' дисплея».

                Кстати, а какая модель дисплея используется? Я тут купил очень похожий на ваш, под такую же задачу… А он, собака, не хочет заводится на RPI.

                • aivs
                  /#20069512 / +1

                  У меня оригинальный дисплей, но он не очень мне нравится, черный не черный, круглое выглядит как эллипс.
                  www.raspberrypi.org/products/raspberry-pi-touch-display

                  А вот как я бы хотел чтобы выглядело в машине. Это системе Carsara.


                  • gibson_dev
                    /#20069718
                    • aivs
                      /#20070332

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

                    • Alexeyslav
                      /#20070868

                      Для АМОЛЕД дисплея нужен ещё алгоритм предотвращения выгорания, для статичных картинок и долгой работы он не очень подходит. И если для основных шкал это ещё терпимо(они-то не меняются, хоть и выгорают) то для цифровых областей где цифры мало меняются(область индикатора топливного бака) это будет проблемой.

          • eXtReeM
            /#20069662

            Ну ведь есть штатная цифровая приборка.

          • tuxi
            /#20070096

            Я хочу сделать панель приборов, которая смогла бы заменить штатную
            А у экрана какие хар-ки по части рабочих температур?

  3. pewpew
    /#20069038 / +1

    Круто! Приятно видеть завершённый проект.
    Я пытался сделать нечто подобное для своей шеви-нивы, но столкнулся с особенностями подключения по OBD II к ECU Bosh, и так и не смог заставить гонять даже простую диагностику через Torque из-за хитрой инициализации. Так и не вышло подобрать нужную AT-последовательность. В итоге забил и довольствовался штатным БК, который умел только показывать коды ошибок. До сниффа протокола руки не дошли.

    • aivs
      /#20069188

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

  4. engine9
    /#20069040 / +1

    Мне понравился дизайн, автор молодец.

    А это железо и софт сможет потянуть несложную 3Д графику?
    — Поликаунт примерно 400 000 треугольников или меньше
    — Текстурирование, в идеале две текстуры в два независимых UV канала (освещение и цвет поверхности, как в играх времен half life 1).
    — Шейдеры и всякие модные PBR не обязательно



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

    • aivs
      /#20069116

      На RPi3 Quake 3 работает. В качестве Ui фреймворка у меня Kivy, он умеет с 3d графикой работать, но я не пробовал.

    • lgorSL
      /#20069174

      На википедии пишут, что Raspberri Pi поддерживает OpenGL ES 2.0 — т.е., есть и текстуры и пискльные/вершинные шейдеры. Про производительность можно почитать здесь: https://www.raspberrypi.org/forums/viewtopic.php?t=88058, якобы без текстур и освещения можно рисовать 19миллионов треугольников в секунду.

  5. tarmukar
    /#20069118

    И вот он я не знаю как подключить ШГУ чтобы работала подсветка и bluetooth.

  6. shaggyone
    /#20069140

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

    • aivs
      /#20069224

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

    • AllexIn
      /#20069288 / +1

      Знаете почему ни одна приборка не выводит информацию «тупо в литрах»?
      Потому что не знает её.
      Датчик топлива показывает плюс минус тонну. Поэтому и показывают стрелку или шкалу с примерным количеством. Показать напрямую значение с датчика — ввести пользователя в заблуждение и словить минус в карму от разгневанных владельцев.

      • shaggyone
        /#20069396

        Не поверите, но знаю. Тем не менее я почти 3 года этой информацией руководствовался на заправке и ни разу не прогадал. Точность +- литр. Пожалуй, соглашусь, что в движении это не очень полезная информация, вот на заправке или в начале пути, вполне себе.

        • AllexIn
          /#20069414 / +1

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

          • shaggyone
            /#20069632

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

            • AllexIn
              /#20069688 / +1

              Как?
              Датчик что-то адекватно покажет только на ровной поверхности без движения.
              Если увеличивать точность — надо дополнитиельные датчики и алгоритмы подключать. Что приведет к удорожанию, и не особо нужно.

              • shaggyone
                /#20069724

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

                • shaggyone
                  /#20069732

                  ну и можно сделать инструкцию по калибровке датчика уровня топлива.

                • Mozg17
                  /#20070198

                  Замер на горизонтальной поверхности? Или тогда плюс 3-4 датчика со средним значением.

                  • shaggyone
                    /#20070646

                    Да просто на относительно горизонтальной поверхности.

              • Alexeyslav
                /#20070952

                Нет, там проблема датчика в другом — у него имеется дискретность. Т.к. он представляет собой полавок подключенный к проволочному переменному резистору. Во многих машинах два поплавка или конструкция поплавка такая что его положение слабо зависит от качки. Проблема именно в дискретности. И соответственно датчик показывает в у.е. в литры переводить надо знать объём бака. А поскольку сами у.е. дискретны, потом ещё умножаем на емкость бака, которая тоже варьируется… получается +- лапоть, значения не кратные литрам и откалибровать очень муторно. По литру топливо заливать и записывать значения. Ну да, конечно же у датчика есть нижняя граница, например меньше 5л в баке он уже не покажет и это тоже зависит от того как этот датчик на заводе поставили и как он на кочках погнулся в процессе эксплуатации.

                • Tutanhomon
                  /#20071422

                  А еще эта резистивная оплетка имеет свойство менять свою равномерность, ведь по ней постоянно вверх-вних ползает ползунок, который может смещать витки, в итоге пропадает линейная зависимость, и простой формулой для калибровки не обойтись. У меня так на сивике было, замечал что в середине шкалы расход замирал, а потом ускорялся. Разобрал датчик топлива — там неравномерно витки лежали. Да и степень окисления разная. Так что это дело работает «на глазок».

              • safari2012
                /#20071160

                Четыре датчика в разных точках помогут побороть наклон :)

                • kolyandex
                  /#20071176 / +1

                  Можно под бак встроить весы.

                  • maxik0
                    /#20074284

                    И датчики взять от танка

              • playnet
                /#20074480

                Ровная поверхность — ставим датчик наклона. Неподвижность — датчик ускорения. Калибруем всё на 1 машине, «наклон 5 градусов, бензин 20л, предполагается получение информации с датчиков… реальные показания..» и потом на каждой условно калибруемся по пустому баку, 20л, 20л при наклоне 10 градусов, полный бак, полный бак при наклоне -15 градусов. Ускорение — только расчётные данные.
                Датчики потянут на пару долларов + сертификация.
                Опять же, софтовые изменения — делаются для всех машин сразу, сильно цену не изменят. Другое дело что это сильно не нужно, но я почти уверен что это всё уже в каких-нибудь машинах есть, просто показывают как привычнее пользователю, а привыкли к шкалам. Может через obd можно получить абсолютные значения у каких-то машин.

                • Alexeyslav
                  /#20079610 / +1

                  Есть масса более простых и предсказуемых датчиков для измерения ровня топлива. При программной коррекции появляется масса мест возникновения погрешности, ньюансов работы которые так просто и не выявишь на этапе проектирования и иные сложности которые в итоге имеют конкретный экономический вес не в пользу грубых но простых датчиков. Знать точный объём топлива в баке? Это фетишь… на самом деле водителю нужно знать перед поездкой на 500км хватит ли топлива чтобы доехать без дозаправки, и если по грубым подсчетам в притык, то это лишь повод заехать на ближайшую заправку. И так если посмотреть, то этим обычно страдают водители которые ВЕЧНО ездят на остатках бензина в баке, дескать бензин дорогой, ага. Буд-то это как-то способно сэкономить денег. Нормальное состояние бака перед любой боле-менее длительной поездкой — это полный бак. Если топлива половина бака — это повод при удобной возможности заехать на заправку.

                • Squoworode
                  /#20085560

                  Калибруем всё на 1 машине
                  и потом на каждой условно калибруемся
                  Но ведь у каждой модели своя геометрия бака. Это ж не параллелепипед.

          • adlerm
            /#20070630

            почему же… у одной и той же модели, одинаковые бензобаки, одинаковые датчики… теоретически, на заводе откалибровать один автомобиль из модельного ряда(дело пары часов), а потом эти данные использовать в ПО…

            • AllexIn
              /#20070896

              В данной ситуации — калибровка, это не только настройка датчика. С этим то проблем нет по большей части.
              Много факторов надо учитывать при движении. Сложный алгоритм.
              И опять же — зачем?
              Зачем знать осталость 5 литров, или 10? В любом случае пора заправляться. Потому что на прямой можно ехать при 5, а на склоне можно и заглохнуть. Словить клин насоса из-за осушения бака. ЗАсрать фильтр осадком с бака.
              Бензин — не таштука. которую нужно восполнять на нуле. А если у нас нет требования к знанию точного нуля — то и геморрой с точными показаниями датчика не нужны.

              При это я понимаю желание иметь точное значение на приборке. Это фетиш. Я сам на приборку кучу херни сейчас вывожу, потому что это же круто знать всё о машине! Еще и теллеметрию пишу… Но это именно потому что хочется, а не потому что объективно надо.

            • Alexeyslav
              /#20070982

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

      • aivs
        /#20069444 / +1

        Я обнаружил 3 разных показания о остатке топлива в баке.
        1) Датчик в баке показывает 18л когда стою на месте. При движении показания сильно меняются, от 10 до 30л.
        2) Рассчитанный примерный остаток, показывает 16.5л
        3) Положение стрелки топлива в баке в градусах

        Я ориентируюсь на второй вариант

        • Kwisatz
          /#20071648

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

          ЗЫ смотрю на вашу штуку, хочу) но с железом возиться просто не умею

          • aivs
            /#20071660

            Я пишу приложение Панель приборов для iPad/iPhone, дизайн будет такой же как в текущем проекте, сначала только для VAG, если будет интерес, то для BMW и других марок возможно будет сделать.

            • Kwisatz
              /#20072156

              кого убить? правда вот с айпадами не дружу, хотя где то первый валяется)

              • aivs
                /#20072262

                Убивать никого не нужно )
                Нужно только время на разработку. Там гляди и на Android тоже выпущу

      • Black_Zerg
        /#20072290

        Не знаю у меня показывает остаток топлива в баке в литрах. Точность шага 5 литров. Шкода Йети, концерн ВАГ

      • 200sx_Pilot
        /#20072602

        Почему не знают?
        Древние Супры, Марки, и прочие Ниссан Либерти…
        Точность, правда, ± верста, но её вполне хватает.

      • kAIST
        /#20073652

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

        • BDI
          /#20074628

          Основываясь на каком расходе показывается прогноз пробега в конкретном авто нужно ещё выяснять. Знаю как минимум два варианта:
          1. По среднему расходу с момента последнего сброса счётчика в маршрутном компьютере.
          2. По среднему расходу за последний период(обычно порядка 10км, возможно у кого-то и по времени период).
          При этом диапазон расхода на своём авто обычно представляешь довольно точно — пределы, в зависимости от обстановки. Бортовой комп окружающей обстановкой не владеет. Допустим попал в пробку(например на бетонке), примерно представляешь сколько ты в ней простоишь. Есть две заправки — одна вскоре, прямо на бетонке(но вопрос контроля качества на загородных АЗС очень непредсказуем), другая, проверенная, километров через 70. 70 км это примерно 6 литров(с учётом текущей пробки). У меня бак 54л, и 8 секций на указателе уровня топлива(есть подозрение что две нижние секции по диапазону как одна верхняя — последняя уже минималка, с лампочкой минимального остатка). Получается дискретность показаний уровня топлива примерно 6.75л. И вот смотрю я на уровень — три клетки. А это сколько? 20.25л? Тогда не парюсь, и заправляюсь на проверенной. Или же это уже 13.6л(чуть больше чем при двух секциях уровня)? Тогда лучше рискнуть непроверенной заправкой, и долить в бак чтобы точно хватило до проверенной(не люблю езду с двумя клетками).

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

          Себе поставил мультитроникс — лежит в бардачке, данные выводит по BT на телефон(у них своё приложение). При тарировке бака по двум точкам дал мне точность остатка примерно ± 1 литр в крайних зонах(легко проверяется заправкой до полного бака, с поправкой на борзость АЗС, и объём приёмной трубы). В середине бака может подвирать больше, но не критично — точность указателя на торпеде гораздо хуже во всём диапазоне. Мне хватает :). Кому мало — есть режим калибровки по 7 точкам, вооружаемся мерной ёмкостью и калибруем бак(но мне кажется это для ситуаций с сильно кривым баком, или сильно нелинейным ДУТ).

          По поводу колебания уровня в баке при движении — как минимум мультитрониксовский усредняет показания, и если вы 5 минут(грубо говоря, не мерял) подряд не стоите в горку, то показания не исказятся. Да и стрелочный в зубиле тоже не мгновенно дёргался вслед за поплавком(кстати, потенциометр там был не проволочный).

      • Stanislavvv
        /#20079956

        Хм… Не знаю как, но в моей 2114 аж 2006 г. штатный «компьютер» таки выводил количество топлива в баке с точностью ± литра два в зависимости от того, насколько косо поставил на не особо ровной стоянке. К сожалению, не посмотрел, есть ли это в CAN.
        Так что, подозреваю, что тут дело в чём-то другом.

        • AllexIn
          /#20080126

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

          • Stanislavvv
            /#20080248

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

            Оно, конечно, ориентировочное, но совпадает с реальностью достаточно неплохо, порядка ± 5% в относительно ровном Екатеринбурге и ± 10% в э… холмистой местности. Для большинства применений такой точности более, чем достаточно.

            • AllexIn
              /#20080264

              Совершенно верно. Для большинства применений(собственно применение одно — оценка оставшегося пробега) этого и достаточно. Поэтому и показывают оставшийся пробег, а не количество литров.

        • Alexeyslav
          /#20080202

          Неоднократно видел обсуждение датчиков топлива на радиотехнических форумах, там пытались сделать точный индикатор количества топлива. Так вот это в принципе невозможно со штатными датчиками — это связано с их конструкцией. Датчики эти проволочные ибо дешёвые и меньше стираются со временем и там как раз получается что одному витку такого датчика соответствует шаг уровня топлива в баке порядка 2л. А для грузовых авто с большим баком и того больше.
          Есть, конечно, другие датчики измерения объёма топлива в баке но кроме гораздо большей стоимости у них есть и свои недостатки. Например, зависимость от примесей в топливе, смачиваемость датчика топливом(емкостные датчики), низкая надёжность в целом из-за сложности и т.д.

    • ganzmavag
      /#20071472

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

      • Andy_Big
        /#20071920

        Брешет литров на пять в меньшую сторону. То есть если пишет «Войдет 15 литров», то можно спокойно заливать 20 :)

        • Zord
          /#20073798

          Ну почем сразу брешет-то? 15 же вошло )

      • johndow
        /#20071928

        Я VCDSом включил её себе.
        Перестраховывается он, зараза. До 5 литров как минимум. Люблю заправляться до полного, но чтобы не бегать туда-сюда до кассы. Говорит 30 литров можно заправить, заправляешь 30, а показометр даже не на максимум встаёт.

        • kost
          /#20072866

          А почему просто полный бак нельзя заливать автоматом?

          • johndow
            /#20073370

            Заправок, где сначала заправляешься потом платишь у нас раз-два и обчёлся. А на обычных надо ходить на кассу лишний раз за возвратом, если не влезло оплаченное. Лишние хопы :)

      • nevzorofff
        /#20072868

        С «не вошло» не испытываю никаких проблем. Возвращаюсь на кассу и всё. У Башнефти при оплате через терминал ВБРР(у них два, один для клиентов Сбера, второй для всех) — можно даже не заходить: пистолет повесил и всё. «Император» за кассой как нажмёт окончание заправки — так деньги на карту и вернутся. А если Сбер, то идёшь, отменяют первую транзкцию, и проводят вторую на фактическую сумму.
        Заправляюсь всегда до полного, чтобы реже заезжать на АЗС.

  7. fenst
    /#20069198

    Виталь, интерфейс просто огонь!

    • aivs
      /#20069232

      Пришлось освоить Inkscape и Illustrator, это стоило недели бессонных ночей.

  8. kolyandex
    /#20069286

    Использовать диагностические запросы (я правильно понял?) для получения данных не очень удобно, кмк. Не знаю как у вагов, но у японцев все эти данные можно получить не отправляя никаких запросов, в салонной шине все свободно гуляет.
    Еще заметил, что у вас не значащие байты в кадрах ISO-TP забиты 0x55 или 0xAA, как положено, а вот все у тех же японцев там мусор, оставшийся от предыдущих сообщений в буфере. VAG — Mitsubishi — 1:0

    • aivs
      /#20069330

      У меня есть версия приборки, которая подключается непосредственно к CAN шине, в этом случае не нужно вести опрос. Но вычислять сниффером что означает каждый пакет очень трудоемко, потому что информация с некоторых датчиков не часто обновляется. Вывел только часть приборов и забил.
      В япошках и корейцах через OBD2 можно спокойно слушать CAN шину, там проще.

    • adlerm
      /#20069446 / +1

      У современных ваг 2 кан шины… одна «высокоскоростная» по которой идут «важные данные» и другая «низкоскоростная» по которой шуруют данные, что описаны в статье. Обе они заводятся на блок (вроде, обычно, «19») а он уже подключен к диагностическому разъему. можно, конечно, подключиться непосредственно к низкоскоростной кан шине, но тогда, как написал автор, некоторые датчики редко обновляются. Это первый момент.
      Второй, это то, что некоторые блоки(если их можно так назвать) не подключены к кан шине, а на них заведен другой интерфейс- однопроводной LIN, а он уже подключен к тому же блоку «19»… и через него уже становится возможным прочитать данные с этих блоков. (для примера, так подключены, реле регулятора генератора(выдает довольно много параметров), датчик на АКБ (выдает температуру, зарядный/разрядный ток, и др.)и, вроде, компрессор кондиционера).

      • aivs
        /#20069538

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

        • kolyandex
          /#20069828

          В моем япе сигнал из бака идет прямо в приборку, а она в двух разных пакетах уже выдает обработанные сглаженные данные.

          • aivs
            /#20069926

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

            • kolyandex
              /#20069970

              То то я смотрю они очень похожи. Сеть построена аналогично, очень похожие диагностические запросы.

              • esaulenka
                /#20072114

                Диагностика везде внешне похожа, это вариации на основе ISO 14229.
                Вот со второго взгляда начинаются отличия — другие ID пакетов, нестандартные PID'ы и т.д…

  9. AllexIn
    /#20069296

    Интерфейс жестко прописан или можно кастомизировать положение и внешний вид датчиков?

    • aivs
      /#20069376

      Кастомизация возможно на 100%. Можно в отдельном файле сделать класс Dashboard с полностью другим дизайном и заменить текущий.

      • AllexIn
        /#20069390

        Так-то понятно, что код исправил, вот тебе и кастомизация. :)
        Имел ввиду, без правки кода как раз. Через конфиг, или «режим редактирования».

        • aivs
          /#20069488

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

  10. 2ruslank
    /#20069744

    Как раз на днях тоже заинтересовался этой темой. Кан шина вроде выходит и к магнитоле? Не пытались подключится там?

    • aivs
      /#20069912

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

  11. Fox_Alex
    /#20069746

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

    • kolyandex
      /#20069840

      Везде по-разному. В моей машине данные тахометра и спидометра идут в приборку каждые 50 мс.

    • aivs
      /#20069908

      Я тахометр считывал со скорость 0.005 сек. Быстрее не пробовал

  12. realimba
    /#20069756

    Хорошо когда есть CAN, делал тоже самое (Rpi + Qt) на аналоговый раритет, вот где боль :)

    видос

  13. prm_prg
    /#20069848 / +1

    Отличная статья! Ваш пост сэкономит кучу времени всем желающим поковырять ваговскую шину.

    • aivs
      /#20069932

      Надеюсь кому то будет полезно, я несколько месяцев украдкой делал проект.

  14. NickSin
    /#20069934

    У меня вопрос: а коды доступа к информации привязаны конкретно к авто или они универсальны в рамках всего ВАГ семейства? Просто имею рапид и хотелось бы попробовать сделать что-то подобное.

    • aivs
      /#20069974

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

      • NickSin
        /#20070026

        Насколько я знаю, в Рапиде с 17 модельного года уже стоит бортовая сеть от MQB-A, что очень похожа на последнюю Октавию А7?
        Простым elm327 адаптером я смогу получить те же данные?

        • aivs
          /#20070050

          Вот так нужно настроить ELM327, чтобы отправлять CAN команды:
          atz
          at sh 714 // запрос на адрес 714
          at cra 77e // ждем ответ от 77e
          at fc sh 714 // запрос на адрес 714
          at fc sd 30 00 00
          at fc sm 1
          at al
          at sp 6
          at ca f0
          03 22 22 0d 55 55 55 55 // запрос

          05 62 22 0D 55 65 AA AA //ответ

          • NickSin
            /#20070458

            А что это за запрос был? Просто интересно? Я сам с АТ команды дела не имел, поэтому и интересуюсь.

      • Monohedgehog
        /#20070398

        Скажите, пожалуйста, на какой модели Octavia это реализовано? Давно есть желание что-нибудь подобное замутить, но не решаюсь

  15. electroneman
    /#20070204

    Проделывал года два назад такое на своей

    • 2ruslank
      /#20070358

      Arduino + ELM327

      Подключены по блютуз? или в elm выбросили блютуз-плату и подключили напрямую к ардуино?

      • NickSin
        /#20070494

        Судя по связке там все в wired)

      • electroneman
        /#20070620

        Да напрямую! И использовал библиотеку ELM для ардуино (еле влезло все в arduino pro mini вместе со шрифтами). На разъеме OBD2 есть контакты на которых появляется +12 когда ключ зажигания включен. Я переделал питание ELM на этот пин чтобы не садился аккумулятор машины. Весь индикатор запитал тоже от встроенного в ELM LDO 3v3. Всё уместилось внутри приборной панели кроме ELM а провод идущий от него на панель (+3v3, rx, tx, GND) используется и для данных и для прошивки (не надо каждый раз панель снимать)

  16. p1ne
    /#20070524

    Отличная работа. Я делал нечто подобное под американские форды, только использовал штатный экран
    github.com/p1ne/fdim-controller
    www.drive2.ru/r/mercury/mariner/886255
    и рассказывал www.youtube.com/watch?v=yOIXnQCXnhg

    После пересаживания на ВАГ сделал так же, как автор — подключил кан-сниффер в параллель к VCDS. Хотя интереснее напрямую в гейтвей :) Пока вяло ковыряю кнопки MMI.

    Есть кстати интересный товарищ на драйве — делает дисплейчик под Ауди www.drive2.ru/users/kvaziigor

  17. alz72
    /#20071218

    Просто супер

  18. illo
    /#20071238

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

  19. aivs
    /#20071528

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

  20. Googlist
    /#20071556

    Посмотрите что немцьі уже сделали, может вам как-то коллаборационировать?
    http://raspicarprojekt.de/index.php

  21. aivs
    /#20071600

    Немцы в этом плане красавчики, неоднократно общался на их форумах по поводу VAG Can шины. У них много собрано информации. С помощью ардуино настраивают автоматизацию в машине.
    Закину на этот форум инфу о проекте.

  22. karmaphob
    /#20071682

    а вот этот не подойдёт?
    mysku.ru/blog/aliexpress/72366.html
    IPS/8.9"

  23. Andrey_13
    /#20072038

    Отличная работа. С удовольствием читал обе статьи. Спасибо.

  24. taboo1387
    /#20072520

    Поздравляю с прекрасной реализацией!
    Я сам озадачен похожим проектом, в качестве основного устройства, правда, Google Nexus 7, Arduino и CAN-шилд уже приобрел, буду постепенно это все соединять. Правда, авто у меня GMC, для подобных мало информации, снифферить придется и самому все детально анализировать.

    • aivs
      /#20072534

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

      • taboo1387
        /#20072562

        Я на Авито купил Nexus 7 32Gb Wi-Fi за 3к. Вариант с дисплеем и Raspberry отбросил как раз по причине дороговизны.
        Лаунчер да, но надо научиться писать под Android:)

  25. Dee3
    /#20072854

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

  26. 2PAE
    /#20073310

    В вашем решении для меня две очевидные проблемы безопасности.
    1) Место расположения датчиков. Взгляд вниз вверх быстрее чем вбок вниз вбок вверх.
    2) Материал дисплея. Автомобильные стекла делаются с зажитой от осколков. Что в вашем варианте? Вариант для фильмов ужасов? Когда кусок стекла при аварии разрезает горло водителю? Брррр…

    • aivs
      /#20073430

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

    • Am0ralist
      /#20074334

      Материал дисплея. Автомобильные стекла делаются с зажитой от осколков. Что в вашем варианте? Вариант для фильмов ужасов? Когда кусок стекла при аварии разрезает горло водителю? Брррр…
      Не поверите, защитная пленка сверху экрана должна существенно помочь. Вы думаете, как в шкафах купе стеклянные и зеркальные вставки в человеческий рост делают? Сзади клеят пленку оракал…

      • 2PAE
        /#20074370

        Вы правы, не поверю. :) Машины худо бедно проверяют на краш тестах.
        Краш тест для шкафа купе? Не, не слышал. ;)

        • Am0ralist
          /#20074448

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

          Ламинированное лобовое автостекло (триплекс). Триплекс состоит из трех стеклянных листов, соединенных с помощью прозрачной защитной пленки.

          • 2PAE
            /#20074720

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

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

            • Am0ralist
              /#20074762

              Нет, я пишу, что надо пленку наклеить на стекло планшета.
              Мало ли как они бьются, пленка просто будет удерживать осколки.

              • Alexeyslav
                /#20079680

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

                • Am0ralist
                  /#20079908

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

                  • Alexeyslav
                    /#20080230

                    Какой клей удержит стекло дисплея в корпусе при перегрузке в 100G например? Планшет оторвёт, несомненно. А дальше его разные компоненты будут испытывать разные нагрузки, неизвестно как поведёт себя стекло которое держится только на клею а клей уже 1) высох за 5 лет эксплуатации, 2) размягчился под действием солнца. Планшет ударит, но стекло может пролететь несколько дальше планшета сыграв роль ножа.

                    • AllexIn
                      /#20080276

                      Полагаю, что в машине достаточно плохо закрепленных предметов, которые предоставляют опасность. Например — регистратор на присоске.
                      Так что еще один, хорошо закрепленный и расположенный в стороне врядли что-то сильно изменит.

                      • Alexeyslav
                        /#20080316

                        Вот поэтому там не должно быть ни одного нештатного предмета. Даже обычные лежащие очки могут нанести серьёзные дополнительные травмы. То что это «в стороне» очень относительно, зависит от того с какой стороны придётся удар, не все аварии чистые лоб-в-лоб, пытаясь избежать аварии можешь столкнуться таким образом что планшет полетит аккурат в тебя.

  27. svsd_val
    /#20073424

    Отличная работа! Не задумывались о проекционном выводе на лобовое стекло?

    • aivs
      /#20073426

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

  28. Ernest88
    /#20073704

    Автор — разработчик в широком смысле слова… Крутой проект, требующий знаний во многих областях… Я в восхищении ))

  29. 4e1ovek
    /#20074900

    aivs, я подумывал делать, что-то вроде www.figma.com/blog/what-teslas-model-three-ui-reveals-about-its-vision-for-the-future для ipad + wifi elm327, остановился на проблеме управления климат-контролем. Блок старый 8e0820043H. В «Васе» не удалось найти какое-либо управление температурой, чтоб сохранить сам блок, но управлять им из приложения. Делать какую-либо плату управления климат-контролем через Arduino не хочется.

    • aivs
      /#20074998

      Я тоже не нашел управление климатом в своей машине. Но на штатной магнитоле отображается температура обдува. Может управления по can и нет, а только отображение.

  30. R33GTRVspec
    /#20075550

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

    • aivs
      /#20075664

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

  31. Gorynch
    /#20076038

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

    • aivs
      /#20076044

      У меня пока что вместо pccar — телефон

  32. DuMbl4
    /#20076622

    А почему решили работать через диагностику, а не с сырыми данными? Просто, если решите параллельно подцепить ELM327 или что-то иное, то железо начнёт конфликтовать.

    За климат и отображение его отвечает низкоскоростная шина комфорта, которая живёт отдельно, но, как и высокоскоростная основная, тоже заведена в на шлюз.

    Лучше работать с данными напрямую, не нужно будет дёргать шлюз, выдерживать таймеры, а просто читать прилетевшие данные и отображать. Это будет более оперативно (высокоприоритетные данные могут прилетать каждые 10мс). А чтобы лишнее не прилетало, то задать фильтры. Правда у MCP2515 их всего 6, но что-то в даташите как-то непонятно про них. Тут бы я воспользовался каким-нибудь STM32 (F105 например) с CAN на борту. Там их 28 полноценных штук. Хватит за глаза.
    Если нужно будет как-то стирать ошибки, то можно подсмотреть в шине, что посылает шлюз в шину, когда стирает ошибки из разных блоков.

    • aivs
      /#20076630

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

      • DuMbl4
        /#20079506

        С этим согласен. И когда сканируешь CAN, то лучше это делать на ходу и не одному.
        Я, для одного проекта, как раз записывал в лог данные шины во время поездки, а после сидел и пялился на цифры, припоминая маршрут и что было на пути. А чтобы было проще, то записанный лог проигрывался в программе.
        В итоге нашёл всё необходимое и больше.

    • Gorynch
      /#20077176

      Правда у MCP2515 их всего 6, но что-то в даташите как-то непонятно про них

      Есть маска: принимать все сообщения (фильтры не работают), только стандартные с учётом фильтров, только расширенные с учётом фильтров или и стандартные, и расширенные с учётом фильтров,
      и 6 фильтров, биты которых сравнивают с битами сообщенияё, исходя из чего сообщение помещается в приёмный буфер или игнорируется.

      У сотой серии STM одномоментно работает или CAN, или USB. В своё время был этим неприятно удивлён

    • juray
      /#20077250

      А для тех, кто не дружит с STM, зато хорошо знаком с AVR — AT90CAN128 (есть еще 64, 32, но 128 более доступен у поставщиков).
      У него 15 «мейлбоксов».

    • Andy_Big
      /#20080606

      Просто, если решите параллельно подцепить ELM327 или что-то иное, то железо начнёт конфликтовать.

      Разве два устройства на шине CAN не могут слать запросы и получать ответы? Там же вроде есть какой-то арбитраж.

      • DuMbl4
        /#20080904

        Арбитраж есть, но он по сути также отвечает за приоритет отправки сообщений.
        Стандартная диагностика живёт на запросах широковещательных 7DF или адресных 7E0+X и ответах 7E8+X, где X от 0 до 7. При отправке широковещательного запроса на 7DF, ответ прилетит от 7E8+X.
        А теперь представьте картину, ваши устройства отправили запросы с идентификаторами 7DF и 7E2, а ответы прилетят 7EA и 7EC. Как мы видим, устройство, оправившее адресный запрос 7E2, ожидает ответ от 7EA и корректно отработает, а вот устройство, отправившее 7DF, обработает первый ответ из интервала 7E8+X.

        А так, шина предполагает, что в ней не будет работать 2 устройства, которые посылают сообщения с одним идентификатором.

        • Andy_Big
          /#20081206

          Хм… Но если устройство, например, запрашивало скорость, то оно ведь и будет ждать в ответ пакет с идентификатором скорости? И если в ответ прилетает что-то другое — ну значит нужно ждать дальше, пока не прилетит запрошенный пакет. Он ведь все равно прилетит.

        • juray
          /#20081234

          То есть, подразумевается, что на широковещательный запрос 7DF ответы приходят те же самые, 7E8+X, что и на адресные запросы? (я не в курсе протоколов для легковушек, я по грузовикам и автобусам специализировался — SAE J1939).

          устройство, отправившее 7DF, обработает первый ответ из интервала 7E8+X.

          А что изменится, если не будет адресного запроса 7E2, а только широковещательный? Все равно ведь придут те же 7EA и 7EC, не так ли?

          По-хорошему, при отправке ШВ запроса, следует или обрабатывать все пришедшие, или отфильтровывать какой-то конкретный ответ по ID (в принципе, тогда лучше бы делать адресный запрос, но я могу предположить случай, когда это невозможно — в J1939 такое вполне бывает)

          Полагаться на «первое пришедшее» не стоит — потому что не факт, что первым придёт ответ с максимальным приоритетом из диапазона. Первым будет «с максимальным приоритетом из имеющихся» — а это может быть не весь диапазон. Так, в вашем примере, если на шине присутствуют все узлы диапазона, первым должен прийти 7E8 (от устройства 0), но видимо, на шине есть только устройства 2 и 4. И даже если мы знаем список устройств и закладываемся на подмножество вместо полного диапазона — может случиться, что устройство отвалится от шины или вообще выйдет из строя, и не пошлет ожидаемого сообщения, и тогда если вместо фильтра по ID мы таки ждем «первое пришедшее», то опять же примем не то что ожидали.

          • DuMbl4
            /#20081418

            То есть, подразумевается, что на широковещательный запрос 7DF ответы приходят те же самые, 7E8+X, что и на адресные запросы?
            Да, это так, но это в случае стандартизированной диагностики. Некоторые модули могут слушать сообщения вообще с другими идентификаторами и работать по протоколу UDS.

            А что изменится, если не будет адресного запроса 7E2, а только широковещательный? Все равно ведь придут те же 7EA и 7EC, не так ли?
            Нет, только от того, кто этот запрос может обработать.

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

            Освежил сведения, да, время, в пределах которого ожидается ответ, минимально и равно 50мс. И да, в ответе содержится информация, что за ответ прилетел.

            Но даже если представить, что ответ у нас содержит информацию, что запросили, как будет разруливаться ситуация, когда два устройства посылают 7DF? Тут никакой арбитраж не поможет. Вылезет ошибка.

            • juray
              /#20082118

              Ну, два устройства, посылающих полностью одинаковый ID — это в принципе, недопустимая ситуация для CAN. Но какое это отношение имеет к рассматриваемому примеру? И что вообще должен был проиллюстрировать пример? Мне показалось, что неявно подразумевалось утверждение «устройство, посылающее 7E2, будет мешать устройству, пославшему 7DF».

              Нет, только от того, кто этот запрос может обработать.
              Стоп. Если широковещательный запрос подразумевает получение ответов в диапазоне 7E8+X, то его и должны обрабатывать все, кто посылает такие ответы.

              • DuMbl4
                /#20085140

                Но какое это отношение имеет к рассматриваемому примеру? И что вообще должен был проиллюстрировать пример? Мне показалось, что неявно подразумевалось утверждение «устройство, посылающее 7E2, будет мешать устройству, пославшему 7DF».
                Я плохой пример привёл, а после освежения знаний понял, что он не правильный. Проблема действительно возникнет только когда 2 устройства пошлют сообщения с одним идентификатором.

                Стоп. Если широковещательный запрос подразумевает получение ответов в диапазоне 7E8+X, то его и должны обрабатывать все, кто посылает такие ответы.
                В принципе да.

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