
Предлагается к повторению устройство для считывания с Хонды (протокол OBD-1) показаний датчиков температуры, скорости, лямбды, времени открытия инжекторов и т.д. также для расчета и отображения мгновенного расхода топлива:
Уточняю, что отображается:
1. обороты,
2. скорость (по датчику скорости)
3. температура антифриза
4. должна быть температура воздуха
5. напряжение на первой лямбде
6. напряжение на второй лямбде ( у меня её нет )
7. MAP
8. Baro
9. положение дроссельной заслонки
10. расход на 100 км/ч (числом)
11. расход в час (числом)
12. напряжение батареи
13. нагрузка генератора (ELD)
14. нагрузка двигателя
15. положение клапана EGR ( у меня его нет )
16. статическая коррекция
17. мгновенная коррекция
18. расход на 100 км/ч шкалой до 30 л/100 км
Проверено на мозге Р-029.
Идея и основная часть программы разработана Nixoid с форума hondaprelude.ru.
Мною сделано для платы Arduino Duemilanove (на первом фото) и для стандартного шилда (второе фото, где он уже вставлен и все работает), где экран 16х2, шесть кнопок и потенциометр регулировки контрастности (вставляется по ножкам, паять только по одному проводку к ножкам 0 и 1 (две самые правые над экраном) и проводок земли).
Сама программа для программирования плат Arduino скачивается с одноименного сайта, устанавливать ее не надо — скопируете в папку и запускаете. Программка для контроллера Arduino назвается "скетч". Соединяется плата для программирования по USB порту.
После загрузки скетча в микроконтроллер соединяем между собой провода с ножек 0 и 1 (TX / RX) и подключаем к ножке K-line диагностического разъема Хонды и провод массы на массу.
В моем разъеме OBD1 нет +12В, питается пока от Кроны.
Кнопками "Up" — "Down" переключаешься по 17 страницам, на каждой один параметр (в первой строке название, во второй величина.
На кнопке "Right" уменьшение яркости подсветки (если сильно тускло — нажмите "Reset")
На 18 странице (или с первой вверх) рисует шкалу мгновенного расхода топлива от 0 до 30 л/100км (сделал копию штатного расходомера на Тойота Виста 2001года).
Формулы составлены для Прелюда, я их не правил, и часть информации показывает нолики.
Кто сможет помочь в доработке — буду благодарен.
Программа сейчас занимает 11 килобайт из 32-х доступных.
Стоимость устройства: Arduino — рублей 700 и шилд экрана — 450р.
Здесь не прикладывают файлы, возьмите с моей страница на Цивик — клабе: www.civic-club.ru/forum/showthread.php?t=156344
Пробуйте.
Расход топлива в режиме кик-даун со скорости 5 км/ч в приличную горку показал 57 л/100км…
Дополню:
Слева под бардачком в резиновом наконечнике два разъемчика — 2-х и 3-х контактный, данная штука включается в крайние клеммы 3-х контактного. Смотрим на разъем, защелка сверху — землю в правый, скрученные RX+TX в левый.
Купить две детали можно в любом городе набрав в поисковике "Arduino". Не обязательно оригинальный, подойдет FreeDuino и т.п.
Код:
//Все формулы и алгоритм общения с Мозгом "Хонда" по протоколу OBD-1 написаны участником сайта HondaPrelude.ru с ником Nixoid
#include <liquidcrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //такие ножки для "LCD1602 Keypad Shield"
int BrightnessPin=10; // нога, задающая яркость
int Brightness=200; // Значение яркости
int NPage = 1; //какая страница печатается
int NPageMax = 18; //Максимальное количество страниц
int rpm=101;
int vss=60;
int temp_cool=103;
int temp_air=104;
float abs_pres=105;
float atm_pres=106;
int thr_pos=107;
float volt_lz1=108;
float volt_lz2=109;
float volt_net=110;
float load_gen=111;
float load_eld=112;
float pos_egr=113;
int st_cor=114;
int lt_cor=115;
float time_inj=1;
int ign=117;
int limit_ign=118;
float valv_idle=119;
float valve_egr=120;
float pos_valve_egr=121;
int fuelc = 1;
// define some values used by the panel and buttons
int lcd_key = 0;
int adc_key_in = 0;
#define btnRIGHT 0 // Уменьшить яркость подсветки
#define btnUP 1 // Предыдущий параметр
#define btnDOWN 2 // Следующий параметр
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5
int i = 1;
// Это для рисования шкалы расхода на 18-й странице
int Rpm_min = 0; //Нижняя возможная граница
int Rpm_max = 30; //Верхняя возможная граница (задайте хоть 10, хоть 100л/100км)
int RightPos = 14; //с какого места печатать правую границу (16 минус количество цифр)
// Это пять символов для шкалы
byte S_1[8] =
{
B10000,
B10000,
B10000,
B10000,
B10000,
B10000,
B10000,
B10000,
};
byte S_2[8] =
{
B11000,
B11000,
B11000,
B11000,
B11000,
B11000,
B11000,
B11000,
};
byte S_3[8] =
{
B11100,
B11100,
B11100,
B11100,
B11100,
B11100,
B11100,
B11100,
};
byte S_4[8] =
{
B11110,
B11110,
B11110,
B11110,
B11110,
B11110,
B11110,
B11110,
};
byte S_5[8] =
{
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
};
void setup()
{
pinMode(BrightnessPin, OUTPUT); //настроим порт для управления яркостью подсветки
pinMode(0, INPUT); //настроим порт для чтения кнопок
Serial.begin(9600); //скорость порта для связи с OBD-1
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.print("HONDA OBD1"); // напечатаем приветствие
lcd.setCursor(14, 1);
lcd.print("YK");
for (i = 1; i < Brightness; i = i * 1.2 + 1) //доведем яркость от 0 до нужного значения
{
analogWrite(BrightnessPin, i-1);
delay(200);
}
analogWrite(BrightnessPin, Brightness); //зададим заданную яркость
delay(1000);
// Регистрируем собственный символы с кодами 1-5 для линейной шкалы
lcd.createChar(1, S_1);
lcd.createChar(2, S_2);
lcd.createChar(3, S_3);
lcd.createChar(4, S_4);
lcd.createChar(5, S_5);
lcd.clear();
}
void loop()
{
int nbyte;
int i;
//clear
nbyte=Serial.available();
check_data24(nbyte);
//00-0f
honda_write_data(0x00,0x10);
delay(50);
nbyte=Serial.available();
if (nbyte>0)
{
if (check_data24(nbyte))
{
honda_read_data_00_0f();
}
}
//10-1f
honda_write_data(0x10,0x10);
delay(50);
nbyte=Serial.available();
if (nbyte>0)
{
if (check_data24(nbyte))
{
honda_read_data_10_1f();
}
}
//20-2f
honda_write_data(0x20,0x10);
delay(50);
nbyte=Serial.available();
if (nbyte>0)
{
if (check_data24(nbyte))
{
honda_read_data_20_2f();
}
}
//A0-AF
honda_write_data(0xA0,0x10);
delay(50);
nbyte=Serial.available();
if (nbyte>0)
{
if (check_data24(nbyte))
{
honda_read_data_a0_af();
}
}
float fuelsc = 230.0 * (float)rpm * time_inj * 0.000002;
float fuelc = 0.0;
if (vss>0)
{
fuelc = fuelsc * 100.0 / (float)vss;
}
// Прочитаем кнопки
lcd_key = read_LCD_buttons(); // read the buttons
switch (lcd_key) // depending on which button was pushed, we perform an action
{
case btnRIGHT:
{
Brightness = Brightness — 20; //уменьшим яркость (вернуть на максимум по кнопке RESET)
analogWrite(BrightnessPin, Brightness); //зададим новую яркость
delay (20);
break;
}
case btnLEFT:
{
// можно что-то сделать по нажатию и этой кнопки
break;
}
case btnUP:
{
NPage--; // уменьшим номер выводимой страницы
if (NPage < 1)
{NPage = NPageMax;}
delay (100);
break;
}
case btnDOWN:
{
NPage++; // увеличим номер выводимой страницы
if (NPage > NPageMax)
{NPage = 1;}
delay (100);
break;
}
case btnSELECT:
{
// можно что-то сделать по нажатию и этой кнопки
break;
}
case btnNONE:
{
// если ничего не нажато
break;
}
}
//щас будем печатать
lcd.clear();
lcd.setCursor(13, 0);
lcd.print(".");
lcd.print(NPage);
lcd.setCursor(0, 0);
switch (NPage) // По номеру страницы
{
case 1: //это первая и т.д.
{
lcd.print("RPM:");
lcd.setCursor(0, 1);
lcd.print(rpm);
break;
}
case 2:
{
lcd.print("Speed:");
lcd.setCursor(0, 1);
lcd.print(vss);
break;
}
case 3:
{
lcd.print("TempCool:");
lcd.setCursor(0, 1);
lcd.print(temp_cool);
break;
}
case 4:
{
lcd.print("TempAir:");
lcd.setCursor(0, 1);
lcd.print(temp_air);
break;
}
case 5:
{
lcd.print("LZ1:");
lcd.setCursor(0, 1);
lcd.print(volt_lz1,2);
break;
}
case 6:
{
lcd.print("LZ2:");
lcd.setCursor(0, 1);
lcd.print(volt_lz2,2);
break;
}
case 7:
{
lcd.print("MAP:");
lcd.setCursor(0, 1);
lcd.print(abs_pres, 2);
break;
}
case 8:
{
lcd.print("Baro:");
lcd.setCursor(0, 1);
lcd.print(atm_pres, 2);
break;
}
case 9:
{
lcd.print("Thr pos:");
lcd.setCursor(0, 1);
lcd.print(thr_pos);
break;
}
case 10:
{
lcd.print("L/100:");
lcd.setCursor(0, 1);
lcd.print(fuelc, 2);
break;
}
case 11:
{
lcd.print("L/h:");
lcd.setCursor(0, 1);
lcd.print(fuelsc, 2);
break;
}
case 12:
{
lcd.print("Volt:");
lcd.setCursor(0, 1);
lcd.print(volt_net, 2);
break;
}
case 13:
{
lcd.print("Load gen:");
lcd.setCursor(0, 1);
lcd.print(load_gen, 2);
break;
}
case 14:
{
lcd.print("Load eld:");
lcd.setCursor(0, 1);
lcd.print(load_eld, 2);
break;
}
case 15:
{
lcd.print("Pos egr:");
lcd.setCursor(0, 1);
lcd.print(pos_egr, 2);
break;
}
case 16:
{
lcd.print("St cor:");
lcd.setCursor(0, 1);
lcd.print(st_cor);
break;
}
case 17:
{
lcd.print("It cor:");
lcd.setCursor(0, 1);
lcd.print(lt_cor);
break;
}
case 18:
{
show_scale(fuelc);
break;
}
}
} // конец основной части
// пошли подпрограммы
// функция чтения
byte check_data24(int nbyte)
{
int i;
if (nbyte!=24)
{
for(i=0;i<nbyte;i++)
{
Serial.read();
}
return 0;
}
else
{
//preamble
for(i=0;i<5;i++)
{
Serial.read();
}
return 1;
}
}
void honda_read_data_00_0f()
{
int i;
byte inData[19];
for(i=0;i<19;i++)
{
inData[i]=Serial.read();
}
int srpm = (inData[2] << 8 | inData[3]);
if (srpm > 0)
{
rpm = 1875000/srpm;
}
else
{
rpm = 0;
}
vss=(int)inData[4];
}
void honda_read_data_10_1f()
{
int i;
byte inData[19];
for(i=0;i<19;i++)
{
inData[i]=Serial.read();
}
temp_cool=temp_function((float)inData[2]);
temp_air=temp_function((float)inData[3]);
abs_pres=(float)inData[4]*0.716-5.0;
atm_pres=(float)inData[5]*0.716-5.0;
thr_pos=(int)(((float)inData[6]-24.0)/2.0);
volt_lz1=(float)inData[7]/51.3;
volt_net=(float)inData[9]/10.45;
load_gen=(float)inData[10]/2.55;
load_eld=77.06-(float)inData[11]/2.5371;
pos_egr=(float)inData[13]/51.3;
}
void honda_read_data_20_2f()
{
int i;
byte inData[19];
for(i=0;i<19;i++)
{
inData[i]=Serial.read();
}
st_cor=((int)inData[2]/128-1)*100;
lt_cor=((int)inData[4]/128-1)*100;
time_inj=( (float)((inData[6] << 8) | inData[7]))/250.0;
ign=((int)inData[8]-128)/2;
limit_ign=((int)inData[9]-24)/4;
valv_idle=(float)inData[10]/2.55;
valve_egr=(float)inData[13]/2.55;
pos_valve_egr=(float)inData[14]/2.55;
}
void honda_read_data_a0_af()
{
int i;
byte inData[19];
for(i=0;i<19;i++)
{
inData[i]=Serial.read();
}
volt_lz2=(float)inData[2]/51.3;
}
// функция вычисления температуры в градусах
int temp_function(float x)
{
float result = 155.04149-x*3.0414878+x*x*0.03952185-x*x*x*0.00029383913+x*x*x*x*0.0000010792568-x*x*x*x*x*0.0000000015618437;
return (int)result;
}
// функция записи в порт
void honda_write_data(byte x, byte y)
{
Serial.write(0x20); // command byte (read mem)
Serial.write(0x05); // length in bytes
Serial.write(x); // offset
Serial.write(y); // Nr bytes to retun
Serial.write(0x0100-(0x20+0x05+x+y)); //crc
}
// Функция опроса кнопок (они через резисторный делитель на нулевом аналоговом порту)
int read_LCD_buttons()
{
adc_key_in = analogRead(0); // read the value from the sensor
// my buttons when read are centered at these valies: 0, 144, 329, 504, 741
// we add approx 50 to those values and check to see if we are close
if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 195) return btnUP;
if (adc_key_in < 380) return btnDOWN;
if (adc_key_in < 555) return btnLEFT;
if (adc_key_in < 790) return btnSELECT;
return btnNONE; // when all others fail, return this…
}
//печать линейной шкалы в диапазоне от Rpm_min до Rpm_max
void show_scale ( int Rpm )
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(Rpm_min); //Печатаем левое значение шкалы
// lcd.print (Rpm); // или для проверки — абсолютное значение измеряемой величены
lcd.setCursor(RightPos, 0);
lcd.print(Rpm_max); //Печатаем правое значение шкалы
int Pos = map (Rpm, Rpm_min, Rpm_max, 0, 160); // Приводим к шкале в 160 значений (хотя у нас каждая риска — "два")
int End_all = int (Pos / 10); // количество полных символов
int Dev = int ((Pos — End_all * 10) / 2); // сколько заполнять вертикальных черточек в неполной фигуре
lcd.setCursor(0, 1);
for (int i = 0; i < End_all; i++)
{
lcd.print("\5"); // печатаем полные квадратики
}
switch (Dev) { // выбираем какую неполную фигуру напечатать
case 1:
lcd.print("\1");
break;
case 2:
lcd.print("\2");
break;
case 3:
lcd.print("\3");
break;
case 4:
lcd.print("\4");
break;
default:
lcd.print (" ");
lcd.print (" "); // забьем справа пробельчиками
}
//а всё;
}







Комментарии 38
Интересно, сам думал о таком. но у обд же рабочее напряжение 12в (причем кажется инверсное, т.е.-12 это "1"), а у ардуины 3-5 в зависимости от модели. Как она не сгорела ) Вообще, схемы что я видел включали в себя общение через либо согласование уровней, либо через кан контроллер mcp2551, удивительно что через сериал завелос :)
печально что скетч не под oled 128x64
подключается библиотека для вашего lcd, и в каждой строчке где lcd.print подменяется на вывод через этот модуль. Просто посомтреть по интернету примеры как работает вывод в 128х64
Ого. живёт тема то.
Со мной парень из Турции связался, спрашивал схему и код.
пользуешься еще ардуинкой?
Давно не включал…
тоже себе хочу поставить ардуинку с БК, могу обращаться по вопросам в будущем?)
Ок
привет, на любое авто сойдет если есть обд1 т е RX TX ? у меня скайлайн на обд1
Не могу сказать… +Формулы Хондовские…
Понял
Собрал данную штуковину, залил скетч, пошёл проверять в машину, ардуинка включилась поработала, а затем начала перезагружаться и теперь постоянно перезагружается
Перепрограммировать …
Я подключал в три разные машины.
Теперь она в другом устройстве работает.
Как я понял, просто, "три провода спаяли" ?
"…соединяем между собой провода с ножек 0 и 1 (TX / RX) и подключаем к ножке K-line диагностического разъема…"
когда программируешь Ардуино эти ножки должны быть разомкнуты.
Потом да: два провода с Ардуино и один в диагностический разъем, — итого соединяешь три.
Оказывается, есть программный сериал…
arduino.ua/ru/prog/SoftwareSerialConstructor
попробуй…
Я не запустил.
В оригинале (откуда я списывал) — Ардуино Мега, он второй аппаратный использовал.
YuriKun
когда программируешь Ардуино эти ножки должны быть разомкнуты.
Потом да: два провода с Ардуино и один в диагностический разъем, — итого соединяешь три.
В чем смысл соединять Rx и Tx? Получается инфа с мозгов будет идти на передатчик Tx, который должен впринципе лишь передавать, а не принимать, да еще передаваемая информация с передатчика Tx будет возвращаться на приёмник Rx. Можете объяснить для чего?
P.S. И инициализация в коде есть только для Rx
я СПИСАЛ почти весь код … сам делал настройку под кнопки, под экран, оформление по страницам, расходомер…
в ECU Хонда один информационный проводок для обмена со сканером, есть куча схем где из Ардуиновских Tx и Rx делают этот один ДВУНАПРАВЛЕННЫЙ проводок, но проверено, что работает и когда на Ардуино просто физически их соединяешь.
ECU нормально принимает запросы от Ардуино и выдает ответы, Ардуино сама себя не забивает…
Понятно. Просто вопрос не в том что она сама себя забивает, а в том что если одновременно мозг и ардуино отправят единицы, то передатчики могут не выдержать. Раз в мозгах двунаправленная передача предусмотрена, то там наверно есть какая-то защита, а в ардуине точно ее нет, поэтому передатчик может попросту сгореть… Но это как должно быть в теории, если у вас работает и так, то я думаю не стоит волноваться
на тойоту подойдет?
www.civic-club.ru/forum/showthread.php?t=156344
про висту что-то упомяналось
или не попадалось подобного для японской тойоты с 1nz?
Врят-ли.
Для современных машин есть ELM…
На смартфоне покажет всё, что надо.
Стационарный бк лучше
Отличная статья! Спасибо
спасибо за поддержку!
Vozmozhna infu otobrazhat na android ili windows?
Есть варианты и на Андроид и на Винду. Там, откуда я брал исходник — ищи по нику Nixoid с форума hondaprelude.ru. там в программе есть часть для передачи информации по usb в компьютер.
у меня было нечто похожее)
www.xenocron.com/tunerview-large-dash-p-401.html
выглядело вот так

Очень интересная статья! Буду делать OBD2 — библиотека есть, желание есть, осталось время найти
Спасибо, в группе "Электронные поделки" Вас уже ждут…
Получилось! =)
www.drive2.ru/l/5484741/
Отличное начало.
В скетче не увидел как софтовый сом-порт организован.
Я не смог запустить…
В том скетче все по железному UART было, сейчас так:
pastebin.com/6WZRXctf
Корявый пока, но по сути рабочий
Уточняю, что отображается:
1. обороты,
2. скорость (по датчику скорости)
3. температура антифриза
4. должна быть температура воздуха
5. напряжение на первой лямбде
6. напряжение на второй лямбде ( у меня её нет )
7. MAP
8. Baro
9. положение дроссельной заслонки
10. расход на 100 км/ч (числом)
11. расход в час (числом)
12. напряжение батареи
13. нагрузка генератора
14. нагрузка двигателя
15. положение клапана EGR ( у меня его нет )
16. статическая коррекция
17. мгновенная коррекция
18. расход на 100 км/ч шкалой до 30 л/100 км
Про точность расхода не уверен, там формула сложная, только производительность форсунок явно указана (230).
В личке ссылку показали — Arduino за 450р.
Интересная штуковина, видел такую засовывали вместо штатных часов, правда и умела она меньше. Кстати из косяков такого экрана он зимой замерзает и неприглядное будущее показывает пока не согреется.
Есть такое, по этому на кнопку "вправо" и повесил уменьшение яркости подсветки — ставишь в холодной машине на минимум — что-то видно.
А если добавить датчик температуры и подложку для подогрева: если отрицательный то подогреть экран резисторами с тепло-проводящим клеем (пастой) до n градусов перед включением или во время работы?
Всё можно…
я проверил что лямбда работает, настроил холостой ход, ужаснулся расходу топлива, побаловался и пошел чиповать мозг…