Comments 86
Отмечу, что для профессиональной разработки с использованием CAN стоит присмотреться к соответствующим продуктам, а не разрабатывать самостоятельно.
Например я использую USB-to-CAN Адаптер от Ixxat. Есть аналогичные от Vector, Марафон.
Во всех случаях такой адаптер поставляется с софтом, который обычно может гораздо больше, чем тот, что идет с различными no-name снифферами или самостоятельно разработанный. Также с адаптером идет отличный API для использования в любом софте.
Ну и естественно там нет проблем с производительностью или гальванической развязкой, если надо.
Самый дешёвый со своим API был от PCAN в своё время. :)
Всё никак не спрошу — а вы в итоге в automotive перешли? Или это игры с CANopen? :)
Кстати, вопрос: а сколько упомянутый адаптер от IXXAT стоит? Думаю, где-то 200-300 €?
Вы — молодец! Просто здорово! :)
Да, если есть возможность, то наиболее наглядной будет "комбинация приборов".
Можно попробовать, к примеру, кондиционерный блок или мультимедиаблок.
Ой как вовремя вы нашлись!
- Есть некий софт, который зовут readlogs. Древний, зато в нем в виде текстовых файлов лежат расшифровки pid и формул к ним.
- Ещё не придумал, но я вас в покое не оставлю :)
P.S. пытался вчера расковырять журнал opendiag с помощью этих pid, но времени пока не хватило.
И да, читал м86 от весты. Очень похоже на м74 can.
Посмотрите мои посты — может, чего накопаете. :)
Эх, может, наконец, дойдут на каникулах руки до статьи. :))))
Но, с другой стороны, вот вам подробности интересны… :)
Кстати, а что интересно?
Вот данная статья — про то, как человек наблюдает за CAN-шиной, а также объясняет что же такое ELM327 она мне была как бальзам на душу потому что в двух словах рассказано то, что размазано тонким слоем по половине рунета.
То есть мои исследования носят исключительно прикладной характер для борьбы с некоторыми неприятными повадками автомобиля, и данная статья дала очень неплохое направление в какую сторону копать дальше.
Что бы я от вас хотел узнать — не могу сказать, любой automotive будет интересен. Понимаете, я лет 15 не лез в автомобили, и только буквально вчера узнал про моментную модель управления двигателем, например. От того лично мне интересно всё, что появилось после bosch mp 7.0, в чём его ключевое отличие, и, главное, зачем :)
Тогда вам надо больше инфы по гибридам — там и двигатель по моменту, и электродвигатель во многих режимах. ;)
Постараюсь кой-чего поискать, как на работу прийду (у меня, сейчас только 08:02 утра :)
Кстати, а у вас с языками на чтение доков как? :)
всё, что появилось после bosch mp 7.0, в чём его ключевое отличие, и, главное, зачем :)
Вряд-ли вы эту инфу снимите с CANа. Да и в открытом доступе ее не будет.
Смотрите: из-за особенностей CAN-стандарта чем у телеграммы меньший номер, тем более высокий приоритет она будет иметь.
Соответственно, самые важные и критичные сигналы будут в телеграммах с маленькими номерами. Что вы и обнаружили для MCU.
Пятисотые телеграммы — то, скорее всего, телеграммы для системы кондиционирования, вентиляторов и пр.
Примерно там же относительно низко будут телеграммы стеклоподъёмников.
А под "двигательными телеграммами" должны быть телеграммы ABS, иммобалайзера и пр.
0x160 — педаль газа, дроссель
0x180 — обороты мотора, некоторые параметры по мотору
0x280 — приборы, скорость
0x481 — двери, световые приборы, подогревы
0x551 — приборы
0x555 — климат-контроль
0x560 — АКП
АБС точно не помню, кажется в районе 0x35x.
Еще, чтобы легче было находить пакеты можно строить графики по каждому ID, жмешь газ и видишь, на каком ID график полез вверх — это обороты коленвала.
Это сейчас программа, де-факто ставшая стандартом в разработке/отладке/тестировании сетей автомобиля. Стоит очень недёшево. :)
Вот, к примеру:
youtu.be/T4e5HQG2Vxk
Да, и поэтому я бы предложил — софт отдельно, железо отдельно. Если вы сделаете так, что ваш софт будет работать с распространенными CAN-адаптерами, а не только вашим — то это наверняка бы увеличило полезность вашего труда.
Чисто в качестве идеи
Вы, простите, готовы купить для автора "распространённые адаптеры"? Или предлагаете заниматься отладкой по переписке?
Ну на то они и "распространённые адаптеры", что имеются у многих. Например у меня и мог бы спокойно отладить его софт со своим железом у меня.
При том эти "распространённые адаптеры" сопровождаются дровами и документацией, так что их интеграция и отладка может занять гораздо меньше времени, чем даже возня с тем же ардуиновским вариантом.
Ну так отлаживайте, пожалуйста :-)
Там "протокол" в отдельный модуль выделен. В принципе, ничто не мешает его подменить.
Я вот свой велосипед пилю на эту же тему (правда, сейчас забросил...).
И вот совершенно непонятно, откуда у меня должно возникнуть желание поддерживать железо, которое я никогда не видел… Мотивация "может быть, кто-нибудь когда-нибудь будет использовать" какая-то слабая.
Или лучше универсальный какой-то адаптер CAN-to-WiFi (или CAN-to-Bluetooth) посоветуйте, минимально с пайкой чтобы возиться.
еще бы оптимизировать под wine.....
Здравствуйте, у меня Гранта, блок ЭБУ М74CAN, хочу попробовать сделать свой простенький бортовой компьютер с каким-нибудь дисплеем. Для начала попробовать сделать вывод основных параметров, коды ошибок потом может добавить функционал для изменения температуры включения вентилятора и чего нибудь ещё.
Ваша статья очень кстати, может вы уже делали что-то в этом направлении на Ардуино? Я пока что на этапе ожидания шилдов с Али и пытаюсь ковырять инфу по адресации.
По блоку M74CAN все основные параметры довольно легко декодируются. Я себе собрал табличку со всеми найденными параметрами.
Коды ошибок - их нет в CAN шине, они в отдельном протоколе OBD поверх CAN. В статье я об этом написал. Для диагностики часто используются адреса 0x7E0, 0x7E8.
Я делал себе программное управление вентилятором охлаждения, некий TempGuard: включаю вентилятор на 90°C, выключаю при 85°C (параметры настраиваются). Причём включаю первую скорость вентилятора - она и потише, да и хватает её даже в жару. Нюанс в том, что не надо управлять вентиляторами, когда включен кондиционер, там сам ЭБУ будет этими вентиляторами управлять. В статье, последняя анимация и параграф над ней - как раз пример управления выходами ЭБУ (первая скорость вентилятора, муфта кондиционера).
Так же делал программу для телефона, которая различные параметры выводит, графики скорости, оборотов, положения педали газа. Читает всё это через Wi-Fi реализованный через ESP.
PS: Добавил схемы подключения AVR и ESP в проект для микроконтроллера.
А можете поделиться исходники для управления вентилятором? А то шилды пришли, теперь интересно хотя бы увидеть как выглядит код для чтения и записи.
Кратко, логика примерно такая:
По прерыванию получаем необходимый пакет(ы), извлекаем из них значение
При превышении заданной температуры включения - отправляем диагностический пакет на включение первой скорости вентилятора
При снижении температуры ниже заданного порога - отправляем диагностический пакет отключения вентилятора (либо передачи управления вентилятором ЭСУД)
Ниже код для примера.
Скрытый текст
#include <mcp2515_can.h> // CAN_BUS_Shield by Seeed Studio
#include <cppQueue.h> // Queue by SMFSW
// Шилд подключен:
// INT - D2
// CS - D10
// MOSI - D11
// MISO - D12
// SCK - D13
// структура хранения данных
struct CANFrame
{
uint32_t ID; // идентификатор пакета (4 байта)
uint8_t Length; // длина данных (1 байт)
uint8_t Data[8]; // сами данные (8 байтов)
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// заполнение пакетов данными
// запросить состояние первой скорости вентилятора
static const CANFrame CANLadaFan1Req PROGMEM = { 0x7E0, 8, { 0x04, 0x2F, 0x00, 0x0A, 0x01, 0x00, 0x00, 0x00 } };
// ответ если выкл 7E8, 8, 05, 6F, 00, 0A, 01, 00, AA, AA
// ответ если вкл 7E8, 8, 05, 6F, 00, 0A, 01, FF, AA, AA
// включить первую скорость вентилятора
static const CANFrame CANLadaFan1On PROGMEM = { 0x7E0, 8, { 0x05, 0x2F, 0x00, 0x0A, 0x06, 0xFF, 0x00, 0x00 } };
// ответ 7E8, 8, 05, 6F, 00, 0A, 06, FF, AA, AA
// отключить первую скорость вентилятора
static const CANFrame CANLadaFan1Off PROGMEM = { 0x7E0, 8, { 0x05, 0x2F, 0x00, 0x0A, 0x06, 0x00, 0x00, 0x00 } };
// ответ 7E8, 8, 05, 6F, 00, 0A, 06, 00, AA, AA
// вернуть управление первой скоростью вентилятора ЭСУД
static const CANFrame CANLadaFan1ToECU PROGMEM = { 0x7E0, 8, { 0x05, 0x2F, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00 } };
// ответ 7E8, 8, 04, 6F, 00, 0A, 00, AA, AA, AA
// запросить состояние второй скорости вентилятора
static const CANFrame CANLadaFan2Req PROGMEM = { 0x7E0, 8, { 0x04, 0x2F, 0x00, 0x0D, 0x01, 0x00, 0x00, 0x00 } };
// включить вторую скорость вентилятора
static const CANFrame CANLadaFan2On PROGMEM = { 0x7E0, 8, { 0x05, 0x2F, 0x00, 0x0D, 0x06, 0xFF, 0x00, 0x00 } };
// отключить вторую скорость вентилятора
static const CANFrame CANLadaFan2Off PROGMEM = { 0x7E0, 8, { 0x05, 0x2F, 0x00, 0x0D, 0x06, 0x00, 0x00, 0x00 } };
// вернуть управление второй скоростью вентилятора ЭСУД
static const CANFrame CANLadaFan2ToECU PROGMEM = { 0x7E0, 8, { 0x05, 0x2F, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00 } };
// запросить состояние муфты кондиционера
static const CANFrame CANLadaCondReq PROGMEM = { 0x7E0, 8, { 0x04, 0x2F, 0x00, 0x0B, 0x01, 0x00, 0x00, 0x00 } };
// ответ если выкл 7E8, 8, 05, 6F, 00, 0B, 01, 00, AA, AA
// ответ если вкл 7E8, 8, 05, 6F, 00, 0B, 01, FF, AA, AA
// включить муфту кондиционера
static const CANFrame CANLadaCondOn PROGMEM = { 0x7E0, 8, { 0x05, 0x2F, 0x00, 0x0B, 0x06, 0xFF, 0x00, 0x00 } };
// ответ 7E8, 8, 05, 6F, 00, 0B, 06, FF, AA, AA
// отключить муфту кондиционера
static const CANFrame CANLadaCondOff PROGMEM = { 0x7E0, 8, { 0x05, 0x2F, 0x00, 0x0B, 0x06, 0x00, 0x00, 0x00 } };
// ответ 7E8, 8, 05, 6F, 00, 0B, 06, 00, AA, AA
// вернуть управление муфтой кондиционера ЭСУД
static const CANFrame CANLadaCondToECU PROGMEM = { 0x7E0, 8, { 0x05, 0x2F, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00 } };
// ответ 7E8, 8, 04, 6F, 00, 0B, 00, AA, AA, AA
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define CAN_INT0 0 // прерывание 0 на D2
#define CAN_CS 10 // сигнал CS на D10
volatile bool canDataReceived = false; // флаг для обработки прерывания
CANFrame canFrame; // прочитанный пакет шины
uint8_t canErrors = 0; // счётчик ошибок отправки данных в CAN-шину
#define CAN_ERRORS_LIMIT 10 // предел количества ошибок CAN-шины, после которого будет произведена попытка сброса CAN-модуля
// основные таймеры и их интервалы
#define START_DELAY 5000UL // 5 с - пауза до запуска логики
#define LOGIC_INTERVAL 250UL // 250 мс - интервал шагов логики
uint32_t startDelayTimer = 0; // таймер паузы для запуска логики
uint32_t logicTimer = 0; // таймер паузы для логики
uint8_t step = 0; // номер шага логики
// флаги состояния мотора, кнопки кондиционера и вентилятора
bool motorOn = false; // мотор работает
bool motorOn_prev = false; // предыдущее состояние мотора
bool conditionerOn = false; // нажата кнопка кондиционера
bool conditionerOn_prev = false; // предыдущее состояние кнопки кондиционера
bool fanOn = false; // вентилятор работает
int8_t motorTemperatureFanOn = 90; // температура включения первой скорости вентилятора
int8_t motorTemperatureFanOff = 85; // температура отключения первой скорости вентилятора
int8_t motorTemperature = 0; // текущая температура мотора
cppQueue canQueue(sizeof(CANFrame)); // очередь сообщений
mcp2515_can can(CAN_CS); // CAN
// Инициализация
void setup()
{
canInit();
}
// Основной цикл программы
void loop()
{
uint32_t ms = millis(); // для сохранения текущего времени, чтобы не вызывать millis() несколько раз за цикл
canRead();
// обработка логики
if (ms - logicTimer >= LOGIC_INTERVAL)
{
// общие условия
// если накопилось много ошибок отправки данных в CAN-шину - попытаться сбросить CAN-модуль
if (canErrors >= CAN_ERRORS_LIMIT)
step = 0;
// событие останова мотора - остановить вентилятор
else if (motorOn_prev && !motorOn)
step = 30;
// если мотор не работает - перейти на ожидание запуска
else if (!motorOn_prev && !motorOn)
step = 1;
// переключатель шагов логики
switch (step)
{
case 0: // инициализация CAN-модуля
if (canInit())
step = 1;
break;
case 1: // ожидание запуска мотора
if (motorOn)
{
startDelayTimer = ms;
step = 2;
}
break;
case 2: // пауза работы логики после запуска мотора
if (ms - startDelayTimer >= START_DELAY)
step = 10;
else if (!motorOn)
step = 1;
break;
///////////////////////////////////////////////////////////////////////////////////////
case 10: // проверка всех условий работы
// если работает мотор и не работает кондиционер...
if (motorOn && !conditionerOn)
// если температура поднялась...
if (motorTemperature >= motorTemperatureFanOn && !fanOn)
step = 20;
// если температура снизилась...
else if (motorTemperature <= motorTemperatureFanOff && fanOn)
step = 30;
break;
///////////////////////////////////////////////////////////////////////////////////////
case 20: // включить реле вентилятора
canQueue.push(&CANLadaFan1On);
step = 21;
break;
case 21: // ожидание включения вентилятора
if (fanOn)
step = 10;
else
step = 20;
break;
///////////////////////////////////////////////////////////////////////////////////////
case 30: // отключить реле вентилятора
canQueue.push(&CANLadaFan1Off);
step = 31;
break;
case 31: // ожидание отлючения вентилятора
if (!fanOn)
step = 10;
else
step = 30;
break;
default:
step = 1;
break;
}
logicTimer = ms;
motorOn_prev = motorOn;
conditionerOn_prev = conditionerOn;
// отправка пакетов в CAN-шину
if (!canQueue.isEmpty())
{
CANFrame canFrame;
canQueue.pop(&canFrame);
canSendFrame(canFrame);
}
}
}
// Инициализация CAN-модуля
bool canInit()
{
canQueue.clean();
pinMode(CAN_INT0, INPUT_PULLUP);
detachInterrupt(digitalPinToInterrupt(CAN_INT0));
bool canOk = false;
canErrors = 0;
canDataReceived = false;
fanOn = false;
// подключить обработчик прерывания о поступлении данных по спадающему уровню сигнала
attachInterrupt(digitalPinToInterrupt(CAN_INT0), canInterrupt, FALLING);
// настройка скорости обмена и частоты кварца для CAN-шины
if (can.begin(CAN_500KBPS, MCP_8MHz) == CAN_OK)
{
canOk = true;
// типы фильтров и масок
#define STD 0
#define EXT 1
// установка фильтров на необходимые пакеты
can.init_Filt(0, STD, 0x0);
can.init_Filt(1, STD, 0x0);
can.init_Filt(2, STD, 0x0);
can.init_Filt(3, STD, 0x0);
can.init_Filt(4, STD, 0x0);
can.init_Filt(5, STD, 0x0);
// установка масок
can.init_Mask(0, STD, 0x0);
can.init_Mask(1, STD, 0x0);
}
return canOk;
}
// Обработчик прерывания поступивших данных
void canInterrupt()
{
// установить флаг наличия данных в буфере
canDataReceived = true;
}
// Чтение данных из CAN-шины
void canRead()
{
// если в буфере есть принятые данные...
if (canDataReceived)
{
canDataReceived = false;
while (can.checkReceive() == CAN_MSGAVAIL)
{
// чтение данных в буфер
if (can.readMsgBuf(&canFrame.Length, canFrame.Data) == CAN_OK)
{
// получение идентификатора пакета (достоверный только после чтения сообщения в буфер)
canFrame.ID = can.getCanId();
// обработать пакет
canProcessFrame();
}
}
}
}
// Обработчик поступивших данных
void canProcessFrame()
{
switch (canFrame.ID)
{
case 0x180: // моторный пакет - мотор работает если есть обороты мотора
float motorRpm = (float)(word(canFrame.Data[0], canFrame.Data[1]) >> 3); // деление на 8.0
motorOn = (motorRpm > 500.0F);
break;
case 0x551: // если это кадр с содержанием информации о температуре мотора (8 байтов)
// температура представлена со смещением в +40°C
motorTemperature = (int8_t)canFrame.Data[1] - 40;
break;
case 0x555: // пакет от САУКУ (5 байтов)
conditionerOn = canFrame.Data[2] & 0x40;
break;
case 0x7E8: // если это кадр ответа ЭСУД на запрос - расшифровать его и включить индикатор
if (canFrame.Data[0] == 0x05 &&
canFrame.Data[1] == 0x6F &&
canFrame.Data[2] == 0x00 &&
canFrame.Data[3] == 0x0A &&
canFrame.Data[4] == 0x06)
{
// ответ ЭСУД на управление вентилятором 1
fanOn = (canFrame.Data[5] == 0xFF);
}
break;
}
}
// Отправить CAN-пакет
void canSendFrame(CANFrame& outFrame)
{
if (can.sendMsgBuf(outFrame.ID, 0, outFrame.Length, outFrame.Data) != CAN_OK)
{
canErrors++;
}
}
странный вопрос, но... а зачем вообще управлять вентилятором в отрыве от штатной схемы его работы?
вообще мне видится схема из двух релюшек и двух термодатчиков если прям хочется поколхозить, надежность будет в разы выше чем софтина на самодельном контроллере.
Действительно, странный вопрос. :)
Ну даже для того, что не "колхозить" - проводку не трогаем, ничего не врезаем, ничего не изменяем.
А управление вентилятором - наверно одно из самых простых и безопасных воздействие на управляемые элементы. Так то можно и бензонасосом управлять, и всеми свечами зажигания, даже обороты мотора задать (чем не круиз-контроль). Но в здравом уме, такое делать вообще опасно.
Поэтому, пусть температура двигателя будет ближе к нормальным условиям. Это и безобидно, и пусть, хоть и немного, но продлевает срок службы патрубков.
Это и безобидно, и пусть, хоть и немного, но продлевает срок службы патрубков.
это совершенно не влияет на срок службы патрубков, температура двигателя регулируется не вентиялтором и температуру под капотом уменьшить не получится пытаясь както управлять его включением-отключением, более того если думать с этой точки зрения, можно вообще включить вентилятор на постоянку
опятьже, это интересно с точки зрения чёнить подкрутить, но непонятен практический смысл
p.s. я помню хотел сигналы с датчиков АБС считывать чтобы самопальную вариацию TPMS сделать (на моем авто её не было)...но так руки и не дошли
Ну так датчики АБС с каждого колеса в шине есть. Осталось дело за углом поворота рулевого колеса, чтобы выверять равномерное движение и высчитывать дельту каждого колеса. Ну а дальше всё считается формулами.
PS: А температуру всё же снижает. Штатно вентилятор включается на 102°С на первую скорость и на 103°С на вторую. Настройка температуры срабатывания на 90°С не позволяет достигнуть сотни градусов.
высчитывать дельту каждого колеса
На RunFlat это точно не сработает. А обычные шины и так чувствуются, когда что-то не так.
Настройка температуры срабатывания на 90°С не позволяет достигнуть сотни градусов.
Но рабочая температура охлаждающей жидкости выше, где-то 105°C. Под эту температуру рассчитываются трущиеся поверхности и зазоры между ними, на эту же температуру рассчитывается масло. Небольшой недогрев, возможно, не критичен, но без объективной рациональной причины менять температурный режим двигателя я бы не стал - вряд ли я умнее коллектива конструкторского бюро с образованными и часто очень опытными инженерами, специализированным софтом и измерительными стендами. Это не значит, что инженеры никогда не ошибаются - нет, это значит, что они ошибаются реже и имеют широкие возможности ошибки выявить и исправить на этапах проектирования и отладки, каковыми возможностями я не располагаю. Исключения возможны, но они сводятся к ликвидации надстроек для выполнения экологических норм, например спорный EGR и точно вредные катализатор и фильтр частиц, но без них ваши шансы на прохождение техосмотра сильно снижаются до где-то нуля в странах, где техосмотр это осмотр технического состояния, а не коррупционный сбор.
PS: А температуру всё же снижает.
а тут уже другой вопрос, современные двигатели у некоторых авто, термостатируют на более высокие температуры (БМВ?) и её регулировкой занимается термостат, а не вентиляторы
грубо говоря если термостат открывается полностью на 102 градусах, то бесполезно молотить вентилятором на 90...двигатель холоднее не станет... но еще и нарушится логика работы, поскольку прошивка ЭБУ ожидает температуру в повышенном диапазоне.
но вообще кмк это такая себе история, если менять авто каждые 5 лет, то патрубками можно не морочиться вообще
современные двигатели у некоторых авто, термостатируют на более высокие температуры
Современные - это лет двадцать-тридцать точно, а некоторые - это условно все. Да, рабочая температура охлаждающей жидкости нормально где-то в районе 105°C. Обычно у гуманитариев этот простой факт вызывает когнитивный диссонанс, потому что всем им еще со школы хорошо известно, что прямой угол это 100°, а вода кипит при 90°.
её регулировкой занимается термостат, а не вентиляторы
В условно всех двигателях жидкостного охлаждения реализовано именно так. Вентиляторы охлаждают радиаторы с охлаждающей жидкостью, а не непосредственно двигатель. Со времен прекрасного и передового для своего времени FIAT 124 (нет, серьезно, для своего времени это была прекрасная бюджетная машина) тенденции изменились. Изменения никак не принципиальны, но с точки зрения оптимизации довольно существенны: привод вентилятора охлаждения радиатора заменен с непосредственного механического, от двигателя, на управляемый электрический, а конструкция термостата изменилась так, что в случае поломки он намного менее вероятно окажется заклинившим в закрытом состоянии. Изменение типа привода позволило исключить потери на работу вентилятора тогда, когда он не нужен, а также использовать два вентилятора вместо одного там, где это целесообразно с аэродинамической точки зрения, в том числе переключая их включение с последовательного на параллельное для ступенчатой регулировки производительности. А изменение конструкции термостата сделало эксплуатацию в аварийном режиме отказа термостата менее опасной для системы охлаждения и двигателя в целом.
грубо говоря если термостат открывается полностью на 102 градусах, то бесполезно молотить вентилятором на 90...двигатель холоднее не станет...
Движение по междугородней дороге в, скажем, -30°, пусть и где-то скраю, близко к границе, но вполне еще в диапазоне нормальных условий эксплуатации. Никакой вентилятор не даст того же эффекта, что естественный обдув при типичной междугородней скорости. Тем не менее, если все в порядке с термостатом, то даже дизель сможет удерживать нормальную рабочую температуру охлаждающей жидкости около все тех же 105°C - дизель, конечно, остынет потом, на стоящей машине, работая на холостых без нагрузки, но тут уже в дело вступит (электрический обычно) догреватель. С бензином и его адаптациями под LPG/CNG такой проблемы, к счастью, не наблюдается.
но вообще кмк это такая себе история, если менять авто каждые 5 лет, то патрубками можно не морочиться вообще
Безусловно, патрубки иногда рвутся - вибрации никому не приносят пользу и разрывы наиболее часто возникают в механически нагруженных участках недалеко от штуцеров с хомутами. Иногда патрубки рвутся неожиданно быстро с точки зрения возраста и пробега, даже и по гарантии может случиться. Но в то же время в среднестатистическом тридцатилетнем автомобиле почти все патрубки будут еще родными, заводскими. То есть проблема, безусловно, есть, но значимось ее немного слишком преувеличена для автомобилей хорошо старше пяти лет.
вариацию TPMS
Интересно, как? Нормально датчик давления и микромощный передатчик находится внутри колеса и измеряет давление и, возможно, температуру, непосредственно. Как можно измерить давление опосредовано, тем более как при помощи ABS?
Оно не измеряет давление в колёсах, оно измеряет разницу давления в колёсах. То есть, если одно из колёс имеет пониженное или повышенное давление, то внешний его диаметр изменяется, что изменяет частоту его вращения. Эта разница и вычисляется при движении прямо (именно поэтому нужно положение рулевого колеса). А дальше, делается вывод, что вероятность того, что если одно из колёс отличается по частоте вращения от трёх остальных, то вероятнее всего с ним что-то не так - надо проверить давление. Такая штука на корейцах есть, точно знаю на KIA Rio.
То есть, если одно из колёс имеет пониженное или повышенное давление, то внешний его диаметр изменяется, что изменяет частоту его вращения.
Понял, вроде очевидно, но сам не догадался, спасибо! Тем не менее не уверен, что это сработает с RunFlat - с тем типом шин, для которых TPMS по сути обязательна, потому что, знаю по опыту, в отличие от обычных шин там трудно почувствовать падение давления как минимум на городских скоростях и можно ненормально долго ездить на спущенном колесе, ничего не подозревая. Задача конструкции RunFlat - дать возможность доехать до ближайшего шиномонтажа в аварийном режиме, а не ездить на спущенных колесах каждодневно.
Еще минус такого решения в том, что опосредовано измеряется относительное давление, тогда как знать абсолютное давление (да и температуру) очень удобно - намного удобнее видеть давление на условном экране, а не лазить к часто довольно грязным колесам с манометром. Температура - тоже полезный показатель, позволяющий дать намек на возможные аномалии с колесом, но в целом уже только давления достаточно. В этом смысле заводские системы, у которых из индикации - только аварийный сигнал низкого давления в неизвестно каком колесе, вроде как и полезны, но напрасно недостаточны в предоставлении водителю той информации, которая реально собирается. Как для клинических идиотов делают - сродни замены стрелки термостата на две лампы - синюю "еще холодный" и красную "уже перегрев", а про отсутствие индикаторов температуры и давления масла вообще уже устал говорить.
Такая штука на корейцах есть, точно знаю на KIA Rio.
Прикольно, молодцы что так сделали - в бюджетом автомобиле сэкономили на (в общем-то копеечных) аппаратных датчиках давления и просто бесплатно добавили софтовую обработку тех данных, что и так собираются.
Летом в жару в подкапотном пространстве царит ад, когда заканчиваешь поездку приходится думать как остудить двигатель, прежде чем заглушить его. Глушить при температуре около 100 гр. я как-то не хочу, из-за остановки циркуляции антифриза он наверняка разогреется еще выше. Сейчас с этим справляется кондиционер, так как он принудительно включает вентилятор охлаждения :) Ну вот я озадачился сделать что-то на ардуине, чисто ради любопытства пока.
, из-за остановки циркуляции антифриза он наверняка разогреется еще выше.
там же давление высокое в системе охлаждения, фактическая температура кипения антифриза гдето 120-130 градусов, по этому 100градусов под капотом это норма
вообще тут полезнее не вентилятор включать, а электропомпу в систему охлаждения встроить
когда заканчиваешь поездку приходится думать как остудить двигатель, прежде чем заглушить его
Если у вас бензин, вы никак не остудите - двигатель на холостых будет греться, пока не откроется термостат и пока еще позже не включится принудительный обдув радиатора. Дизель, на морозе - тот да, поработав на холостых остынет, но тогда у вас автоматически включатся электрические догреватели охлаждающей жидкости - те самые, которые включаются, когда вы заводите холодный двигатель после долгого простоя.
Глушить при температуре около 100 гр. я как-то не хочу, из-за остановки циркуляции антифриза он наверняка разогреется еще выше.
У вас рабочая температура немного выше ста. Ориентировочно сто пять. Если только автомобиль моложе приблизительно тридцати-сорока лет. Иначе может быть и ниже. Четкой грани по возрасту модели провести нельзя, но как грубая прикидка сойдет.
Сейчас с этим справляется кондиционер, так как он принудительно включает вентилятор охлаждения
Не поручусь, конечно, на ставлю на то, что у вас вообще один вентилятор или, как вариант, одновременно работающие два рядом - если радиатор сильно вытянут в ширину при небольшой высоте, и одним вентилятором его обдувать не слишком хорошо получается. То есть что у вас нет отдельного вентилятора для работы кондиционера.
До сих пор пользовался версией 1.36, и был приятно удивлен, когда увидел, что проект развивается и обновляется. Может и для android приложение планируется? Спасибо за проект!
Мобильное приложение не планировал, но есть написанное для себя, для проверки различных идей. В данном случае приходится использовать связку CAN-ESP-WiFi-Android (или PC). Заморочка тут в том, что через сеть должны передаваться маленькие порции данных (CAN-пакет около 20 байт). А самих пакетов много 500..1000 в секунду. Сетевой стек в ESP просто захлёбывается в таком режиме. В CAN Sniffer я сделал накопление нескольких CAN-пакетов в один сетевой пакет и только потом отправка. По мне - выглядит это не очень хорошо. Поэтому, тут есть над чем подумать.
Что-то не пойму как в программе развернуть нижнюю область где данные для тестовой отправки пакетов?
К сожалению, в какой-то версии wxWidgets убрали возможность настройки ширины области захвата разделителя. Связано это было, вроде бы, с тем, что не на всех операционных системах поддерживается управление этим параметром. Получается, что надо попасть в область, выделенную на снимке (там курсор меняется на стрелки вверх-вниз):

Попробовал на гранте такой код и он не заработал, то есть не выводит температуру и напряжение, хотя снифер нормально работает:
ардуино
//#include <mcp_can.h> // подключение библиотеки для работы с контроллером MCP2515
#include <SPI.h> // подключение библиотеки протокола последоваетельного периферийного интерфейса
#include <mcp2515_can.h>
mcp2515_can CAN1(10); // устанавливаем CS для приёма с 1 шины на пин 10
unsigned long timeOut;
unsigned char len = 0; // длина CAN-сообщения
unsigned char rxBuf[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
// CAN-сообщение (Data)
long unsigned int rxId; // id CAN-сообщения
// int parameter; - запрашиваемый параметр
// допустимые значения paramName:
// 0 - температура двигателя
// 1 - напряжение бортовой сети
// 2 - обороты двигателя OBD2
// 3 - скорость OBD2
long int updPeriod[] = {5000, 2000, 500, 1000}; // период обновления данных
long int updTime[sizeof(updPeriod)]; // время последнего обновления
//==========================================================================
// SETUP
//--------------------------------------------------------------------------
void setup() {
Serial.begin(115200);
while (CAN_OK != CAN1.begin(CAN_500KBPS, MCP_16MHz)); // init can bus : baudrate = 500k / 8MHz
Serial.println("CAN init ok.");
//RXB0 - первый приёмный буфер
CAN1.init_Mask(0, 0, 0x7F0); // маска
CAN1.init_Filt(0, 0, 0x7E0); // фильтры
CAN1.init_Filt(1, 0, 0x7E0);
//RXB1 - второй приёмный буфер
CAN1.init_Mask(1, 0, 0x7F0); // маска
CAN1.init_Filt(2, 0, 0x7E0); // фильтры
CAN1.init_Filt(3, 0, 0x7E0);
CAN1.init_Filt(4, 0, 0x7E0);
CAN1.init_Filt(5, 0, 0x7E0);
delay(100);
Serial.println("Masks and filters set.");
}
//==========================================================================
// LOOP
//--------------------------------------------------------------------------
void loop() {
if (millis() > (updTime[0] + updPeriod[0])) {
Serial.print("0 - Температура ДВС: ");
updTime[0] = millis();
Serial.print(enginePIDs(0), 1); // 1 знак после запятой
Serial.print(" С");
Serial.print(" / update_time: ");
Serial.print(millis()-updTime[0]);
Serial.println("");
}
if (millis() > (updTime[1] + updPeriod[1])) {
Serial.print("1 - Напряжение: ");
updTime[1] = millis();
Serial.print(enginePIDs(1), 2); // 2 знака после запятой
Serial.print(" V");
Serial.print(" / update_time: ");
Serial.print(millis()-updTime[1]);
Serial.println("");
}
}
//==========================================================================
// Функция общения с ЭБУ ДВС по протоколу Renault
//--------------------------------------------------------------------------
float enginePIDs(int parameter) {
unsigned char PID[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
float retValue = 9999; // возвращаемое значение (если 9999 - ошибка)
long unsigned int moduleIdRequest = 0x7E0; // id модуля в запросе данных
long unsigned int moduleIdAnswer = 0x7E8; // id модуля в ответе
PID[0] = 0x03; // количество байт в запросе
PID[1] = 0x22; // префикс PID для запроса
PID[2] = 0x00; PID[3] = 0x01;
// посылаем запрос ЭБУ
CAN1.sendMsgBuf(moduleIdRequest, 0, 8, PID);
PID[1] = 0x62; // префикс PID для ответа
rxId = 0x000; // обнуляем идентификатор
timeOut = millis() + 500; // крайнее время ожидания ответа
// ждём нужного ответа
while ((rxId != moduleIdAnswer || rxBuf[1] != PID[1] || rxBuf[2] != PID[2] || rxBuf[3] != PID[3]) && millis() < timeOut) {
if (CAN_MSGAVAIL == CAN1.checkReceive()) {
CAN1.readMsgBuf(&len, rxBuf); // чтение данных: len = data length, buf = data byte(s)
rxId = CAN1.getCanId(); // получаем ID сообщения
//testSniffer(rxId,rxBuf);
}
}
if (rxId == moduleIdAnswer && rxBuf[1] == PID[1] && rxBuf[2] == PID[2] && rxBuf[3] == PID[3]) {
// вычисляем параметр, A = rxBuf[4], B = rxBuf[5], C = rxBuf[6], D = rxBuf[7]
switch (parameter) {
case 0:
// температура двигателя
retValue = (256 * rxBuf[6] + rxBuf[7]) * 0.75 - 48;
break;
case 1:
// напряжение бортовой сети
retValue = 0.1 * rxBuf[5] ;
break;
}
}
return retValue;
}
}
Этот код работает в режиме OBD over CAN, то есть использует только диагностические запросы через CAN ID 0x7E0 (отправка) и 0x7E8 (приём) - я предпочёл так не делать. ЭСУД автомобиля постоянно в CAN-шину выбрасывает необходимые мне параметры, поэтому я их просто читаю, декодирую и вывожу. А вот управление исполнительными устройствами - я не нашёл, как это можно сделать непосредственно через CAN-пакеты, да и нет уверенности, что такое возможно. Поэтому для управления использую отправку управляющего пакета через OBD over CAN. Примеры пакетов есть в приведённом коде несколькими комментариями выше: https://habr.com/ru/articles/479672/comments/#comment_27587222
Поразбирался, получилось прочитать первый фрейм диагностических данных по команде 0x7E0 03 22 00 01, а вот следующие по команде 30 00 00 не получается пока читать(нули почему-то в буфере). Не понимаю как работает буфер у MCP2515 при настройке фильтров.. Фильтры настроил только на 0x7E8, то есть как я понимаю в буфер будут ложится только фреймы от 0x7E8. Нигде не нашел внятного описания этого момента.
CAN sniffer