В первой статье «Хакаем 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
    24.04.2019 10:59
    +1

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


    1. tuxi
      24.04.2019 11:25
      +1

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


    1. aivs Автор
      24.04.2019 11:29

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


      1. tuxi
        24.04.2019 12:51

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


      1. LuxLP
        24.04.2019 15:13

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


        1. esaulenka
          24.04.2019 20:53

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


          1. Black_Zerg
            24.04.2019 21:38

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


            1. aivs Автор
              24.04.2019 21:39

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


              1. Black_Zerg
                24.04.2019 21:57

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


            1. kAIST
              25.04.2019 08:27

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


              1. Black_Zerg
                25.04.2019 16:23

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


                1. kAIST
                  25.04.2019 17:01

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


                  1. Black_Zerg
                    25.04.2019 19:06

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


                    1. kAIST
                      25.04.2019 19:11

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


                      1. Black_Zerg
                        25.04.2019 20:23

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


      1. prog_san
        25.04.2019 00:39

        За опускание зеркала при движении задним ходом отвечает 52-й блок «Блок управления пассажирской двери». У SanchoPanso998 есть подробный отчет по доработке зеркала Опускание правого зеркала при включении задней скорости


  1. cyber_roach
    24.04.2019 11:50
    +1

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

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


    1. aivs Автор
      24.04.2019 11:53
      +1

      ELM327 Wi-Fi


      1. adlerm
        24.04.2019 12:21

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


        1. aivs Автор
          24.04.2019 12:31

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


          1. adlerm
            24.04.2019 12:35

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


            1. aivs Автор
              24.04.2019 12:41

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


              1. AllexIn
                24.04.2019 12:42

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

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


                1. aivs Автор
                  24.04.2019 13:08
                  +1

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

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



                  1. gibson_dev
                    24.04.2019 13:43

                    1. aivs Автор
                      24.04.2019 15:32

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


                    1. Alexeyslav
                      24.04.2019 16:53

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


          1. eXtReeM
            24.04.2019 13:37

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


          1. tuxi
            24.04.2019 14:58

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


          1. maxik0
            25.04.2019 10:44

            1. aivs Автор
              25.04.2019 10:45

              Сейчас как раз и делаю мобильное приложение, которое теже данные будет получать по wi-fi от elm327.


              1. maxik0
                25.04.2019 18:50

                Ну тут не wifi а bluetooth. Но пойдет, в общем? Кстати, а ведь распберри умеет блютуз, стоило ли провода тащить к разъёму тогда?


                1. aivs Автор
                  25.04.2019 19:02

                  Через elm327 не получится обновлять обороты каждые 5 мс. Как минимум 50 мс, а в реале все 100 мс.
                  Хочется максимальноц скорости


  1. pewpew
    24.04.2019 11:54
    +1

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


    1. aivs Автор
      24.04.2019 12:17

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


  1. engine9
    24.04.2019 11:55
    +1

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

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



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


    1. aivs Автор
      24.04.2019 12:06

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


    1. lgorSL
      24.04.2019 12:15

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


  1. tarmukar
    24.04.2019 12:06

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


  1. shaggyone
    24.04.2019 12:09

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


    1. aivs Автор
      24.04.2019 12:23

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


    1. AllexIn
      24.04.2019 12:32
      +1

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


      1. shaggyone
        24.04.2019 12:47

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


        1. AllexIn
          24.04.2019 12:49
          +1

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


          1. shaggyone
            24.04.2019 13:33

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


            1. AllexIn
              24.04.2019 13:40
              +1

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


              1. shaggyone
                24.04.2019 13:45

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


                1. shaggyone
                  24.04.2019 13:46

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


                1. Mozg17
                  24.04.2019 15:11

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


                  1. shaggyone
                    24.04.2019 16:20

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


              1. Alexeyslav
                24.04.2019 17:04

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


                1. Tutanhomon
                  24.04.2019 18:27

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


              1. safari2012
                24.04.2019 17:42

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


                1. kolyandex
                  24.04.2019 17:44
                  +1

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


                  1. maxik0
                    25.04.2019 11:01

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


              1. playnet
                25.04.2019 11:38

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


                1. Alexeyslav
                  26.04.2019 11:34
                  +1

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


                1. Squoworode
                  28.04.2019 07:18

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


          1. adlerm
            24.04.2019 16:18

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


            1. AllexIn
              24.04.2019 16:56

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

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


            1. Alexeyslav
              24.04.2019 17:10

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


      1. aivs Автор
        24.04.2019 12:56
        +1

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

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


        1. shaggyone
          24.04.2019 13:46

          оперативно вы )


        1. Kwisatz
          24.04.2019 19:12

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

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


          1. aivs Автор
            24.04.2019 19:16

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


            1. Kwisatz
              24.04.2019 21:09

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


              1. aivs Автор
                24.04.2019 21:37

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


      1. Black_Zerg
        24.04.2019 21:41

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


      1. 200sx_Pilot
        24.04.2019 23:17

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


      1. kAIST
        25.04.2019 09:11

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


        1. BDI
          25.04.2019 12:05

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

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

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

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


      1. Stanislavvv
        26.04.2019 12:39

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


        1. AllexIn
          26.04.2019 13:12

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


          1. Stanislavvv
            26.04.2019 13:33

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

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


            1. AllexIn
              26.04.2019 13:35

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


        1. Alexeyslav
          26.04.2019 13:25

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


    1. ganzmavag
      24.04.2019 18:34

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


      1. Andy_Big
        24.04.2019 20:18

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


        1. Zord
          25.04.2019 09:42

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


      1. johndow
        24.04.2019 20:20

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


        1. kost
          25.04.2019 00:54

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


          1. johndow
            25.04.2019 07:11

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


      1. nevzorofff
        25.04.2019 00:54

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


  1. fenst
    24.04.2019 12:19

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


    1. aivs Автор
      24.04.2019 12:24

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


  1. kolyandex
    24.04.2019 12:32

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


    1. aivs Автор
      24.04.2019 12:39

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


    1. adlerm
      24.04.2019 12:57
      +1

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


      1. aivs Автор
        24.04.2019 13:12

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


        1. kolyandex
          24.04.2019 14:09

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


          1. aivs Автор
            24.04.2019 14:30

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


            1. kolyandex
              24.04.2019 14:38

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


              1. esaulenka
                24.04.2019 20:59

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


  1. AllexIn
    24.04.2019 12:34

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


    1. aivs Автор
      24.04.2019 12:43

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


      1. AllexIn
        24.04.2019 12:45

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


        1. aivs Автор
          24.04.2019 13:04

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


  1. 2ruslank
    24.04.2019 13:47

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


    1. aivs Автор
      24.04.2019 14:27

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


  1. Fox_Alex
    24.04.2019 13:48

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


    1. kolyandex
      24.04.2019 14:10

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


    1. aivs Автор
      24.04.2019 14:26

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


  1. realimba
    24.04.2019 13:51

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

    видос


    1. aivs Автор
      24.04.2019 14:25

      Крутяк!


  1. prm_prg
    24.04.2019 14:12
    +1

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


    1. aivs Автор
      24.04.2019 14:31

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


  1. NickSin
    24.04.2019 14:32

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


    1. aivs Автор
      24.04.2019 14:39

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


      1. NickSin
        24.04.2019 14:47

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


        1. aivs Автор
          24.04.2019 14:50

          Вот так нужно настроить 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 //ответ


          1. NickSin
            24.04.2019 15:53

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


            1. aivs Автор
              24.04.2019 15:56

              // Двери
              714 03 22 22 0D 55 55 55 55

              Посмотрите в статье, я много кодов написал


              1. NickSin
                24.04.2019 15:58

                А что за последовательность команд между «запросом на адрес» и самим запросом? Меня это интересует)


                1. aivs Автор
                  24.04.2019 16:10

                  1. NickSin
                    24.04.2019 16:12

                    Премного благодарен)


      1. Monohedgehog
        24.04.2019 15:42

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


        1. aivs Автор
          24.04.2019 15:51

          Skoda Octavia A5 2011г.


  1. electroneman
    24.04.2019 15:12

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

    Skoda
    1. 2ruslank
      24.04.2019 15:35

      Arduino + ELM327

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


      1. aivs Автор
        24.04.2019 15:39

        .


      1. NickSin
        24.04.2019 15:56

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


      1. electroneman
        24.04.2019 16:17

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


  1. p1ne
    24.04.2019 16:02

    Отличная работа. Я делал нечто подобное под американские форды, только использовал штатный экран
    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


    1. aivs Автор
      24.04.2019 16:19

      Вот ребята для Соляриса делают приборную панель
      www.drive2.ru/b/489658158654947380


  1. alz72
    24.04.2019 17:52

    Просто супер


  1. illo
    24.04.2019 17:54

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


  1. aivs Автор
    24.04.2019 18:43

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


  1. Googlist
    24.04.2019 18:51

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


  1. aivs Автор
    24.04.2019 19:04

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


  1. karmaphob
    24.04.2019 19:25

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


    1. aivs Автор
      24.04.2019 20:18

      Очень крутой!!


  1. Andrey_13
    24.04.2019 20:41

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


  1. taboo1387
    24.04.2019 22:48

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


    1. aivs Автор
      24.04.2019 22:50

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


      1. taboo1387
        24.04.2019 22:58

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


  1. Dee3
    25.04.2019 00:52

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


  1. 2PAE
    25.04.2019 06:19

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


    1. aivs Автор
      25.04.2019 07:37

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


    1. Am0ralist
      25.04.2019 11:07

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


      1. 2PAE
        25.04.2019 11:14

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


        1. Am0ralist
          25.04.2019 11:31

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

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


          1. 2PAE
            25.04.2019 12:28

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

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


            1. Am0ralist
              25.04.2019 12:34

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


              1. Alexeyslav
                26.04.2019 11:46

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


                1. Am0ralist
                  26.04.2019 12:30

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


                  1. Alexeyslav
                    26.04.2019 13:30

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


                    1. AllexIn
                      26.04.2019 13:37

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


                      1. Alexeyslav
                        26.04.2019 13:44

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


  1. svsd_val
    25.04.2019 07:33

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


    1. aivs Автор
      25.04.2019 07:34

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


  1. Ernest88
    25.04.2019 09:24

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


  1. 4e1ovek
    25.04.2019 13:03

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


    1. aivs Автор
      25.04.2019 13:22

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


  1. R33GTRVspec
    25.04.2019 15:10

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


    1. aivs Автор
      25.04.2019 15:29

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


  1. Gorynch
    25.04.2019 16:31

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


    1. aivs Автор
      25.04.2019 16:31

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


      1. Gorynch
        25.04.2019 16:40

        Я имел ввиду pccar.ru


  1. DuMbl4
    25.04.2019 18:45

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

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

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


    1. aivs Автор
      25.04.2019 18:48

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


      1. DuMbl4
        26.04.2019 11:17

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


    1. Gorynch
      25.04.2019 21:14

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

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

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


      1. juray
        25.04.2019 21:21

        У сотой серии STM одномоментно работает или CAN, или USB

        В 105/107 поправили.


        1. Gorynch
          25.04.2019 21:30

          Спасибо за информацию. Надо будет потестить



    1. juray
      25.04.2019 21:29

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


    1. Andy_Big
      26.04.2019 14:29

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

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


      1. DuMbl4
        26.04.2019 15:21

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

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


        1. Andy_Big
          26.04.2019 16:14

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


        1. juray
          26.04.2019 16:18

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

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

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

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

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


          1. DuMbl4
            26.04.2019 16:56

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

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

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

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

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


            1. juray
              26.04.2019 19:33

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

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


              1. DuMbl4
                27.04.2019 21:53

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

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

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