Вот скриншот когда-то записаного мной лога. тут группа 3,10,11. По названию столбцов видно.
В 11 группе столбец 2-это требуемое давление, столбец 3-давление которое выдает турбина. У меня турбина с управляемой геометрией.
а ну, собственно, я слукавил походу, что 11 группа не работает. Обороты у вас показывали на тот момент были 840. На таких оборотах давление турбины соответствует атмосферному давлению примерно, т.е. 1000 mBar, у вас так и показывало примено. Резко газоните и посмотрите поднимется ли давление, должно всё работать, парметры поднимутся.
С блоками которые хочу видеть в БК уже почти определился. Хотелось бы придумать как решить с расходом l\100km (Литры / Километраж х 100 = Расход на 100 км). Но надо будет записывать всё в энергонезависимую память. Расход l\h известен. Если просчитать это, то можно будет и подсчитать запас хода... колличество топлива тоже есть в параметрах.
Тут вот расписан стандартный VAGовский.
а для EGR и клапана турбины используется одна и та же формула, немного неправильно сделанная. формулу перелелал. Теперь егр и процент открытия клапана турбы должно показывать
/*
Arduino Nano OBD reader (OBD protocol KW1281, Audi A4 B5 etc.)
wiring:
D2 --- OBD level shifter input (RX) (e.g. LM339)
D3 --- OBD level shifter output (TX) (e.g. LM339)
A5 --- Arduino 20x4 LCD display SCL
A4 --- Arduino 20x4 LCD display SDA
NOTE: For the level shifting, I used a 'AutoDia K409 Profi USB adapter', disassembled it,
and connected the Arduino to the level shifter chip (LM339) - the original FTDI chip TX line
was removed (so it does not influence the communication)
*/
#include <Wire.h>
#include "LiquidCrystal_I2C.h"
#include "NewSoftwareSerial.h"
#define pinKLineRX 10
#define pinKLineTX 11
#define pinLED 13
#define pinBuzzer 9
#define pinButton 5
// https://www.blafusel.de/obd/obd2_kw1281.html
#define ADR_Engine 0x01
#define ADR_Gears 0x02
#define ADR_ABS_Brakes 0x03
#define ADR_Airbag 0x15
#define ADR_Dashboard 0x17
#define ADR_Immobilizer 0x25
#define ADR_Central_locking 0x35
//#define DEBUG 1
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x20 for a 16 chars and 2 line display
NewSoftwareSerial obd(pinKLineRX, pinKLineTX, false); // RX, TX, inverse logic
uint8_t currAddr = 0;
uint8_t blockCounter = 0;
uint8_t errorTimeout = 0;
uint8_t errorData = 0;
bool connected = false;
int sensorCounter = 0;
int pageUpdateCounter = 0;
int alarmCounter = 0;
uint8_t currPage = 2;
int8_t coolantTemp = 0;
int8_t oilTemp = 0;
int8_t intakeAirTemp = 0;
int8_t oilPressure = 0;
float engineLoad = 0;
int engineSpeed = 0;
float throttleValve = 0;
float supplyVoltage = 0;
uint8_t vehicleSpeed = 0;
uint8_t fuelConsumption = 0;
uint8_t fuelLevel = 0;
unsigned long odometer = 0;
// наши параметры
int TurboPressure = 0;
int TurboPressure_target = 0;
uint8_t Turbocharger_valve = 0;
uint8_t EGR_duty = 0;
int EGR_Consumption = 0;
int EGR_Consumption_target = 0;
String floatToString(float v){
String res;
char buf[16];
dtostrf(v,4, 2, buf);
res=String(buf);
return res;
}
void disconnect(){
connected = false;
currAddr = 0;
}
void lcdPrint(int x, int y, String s, int width = 0){
lcd.setCursor(x,y);
while (s.length() < width) s += " ";
lcd.print(s);
}
void obdWrite(uint8_t data){
#ifdef DEBUG
Serial.print("uC:");
Serial.println(data, HEX);
#endif
obd.write(data);
}
uint8_t obdRead(){
unsigned long timeout = millis() + 1000;
while (!obd.available()){
if (millis() >= timeout) {
Serial.println(F("ERROR: obdRead timeout"));
disconnect();
errorTimeout++;
return 0;
}
}
uint8_t data = obd.read();
#ifdef DEBUG
Serial.print("ECU:");
Serial.println(data, HEX);
#endif
return data;
}
// 5Bd, 7O1
void send5baud(uint8_t data){
// // 1 start bit, 7 data bits, 1 parity, 1 stop bit
#define bitcount 10
byte bits[bitcount];
byte even=1;
byte bit;
for (int i=0; i < bitcount; i++){
bit=0;
if (i == 0) bit = 0;
else if (i == 8) bit = even; // computes parity bit
else if (i == 9) bit = 1;
else {
bit = (byte) ((data & (1 << (i-1))) != 0);
even = even ^ bit;
}
Serial.print(F("bit"));
Serial.print(i);
Serial.print(F("="));
Serial.print(bit);
if (i == 0) Serial.print(F(" startbit"));
else if (i == 8) Serial.print(F(" parity"));
else if (i == 9) Serial.print(F(" stopbit"));
Serial.println();
bits[i]=bit;
}
// now send bit stream
for (int i=0; i < bitcount+1; i++){
if (i != 0){
// wait 200 ms (=5 baud), adjusted by latency correction
delay(200);
if (i == bitcount) break;
}
if (bits[i] == 1){
// high
digitalWrite(pinKLineTX, HIGH);
} else {
// low
digitalWrite(pinKLineTX, LOW);
}
}
obd.flush();
}
bool KWP5BaudInit(uint8_t addr){
Serial.println(F("---KWP 5 baud init"));
//delay(3000);
send5baud(addr);
return true;
}
bool KWPSendBlock(char *s, int size){
Serial.print(F("---KWPSend sz="));
Serial.print(size);
Serial.print(F(" blockCounter="));
Serial.println(blockCounter);
// show data
Serial.print(F("OUT:"));
for (int i=0; i < size; i++){
uint8_t data = s[i];
Serial.print(data, HEX);
Serial.print(" ");
}
Serial.println();
for (int i=0; i < size; i++){
uint8_t data = s[i];
obdWrite(data);
/*uint8_t echo = obdRead();
if (data != echo){
Serial.println(F("ERROR: invalid echo"));
disconnect();
errorData++;
return false;
}*/
if (i < size-1){
uint8_t complement = obdRead();
if (complement != (data ^ 0xFF)){
Serial.println(F("ERROR: invalid complement"));
disconnect();
errorData++;
return false;
}
}
}
blockCounter++;
return true;
}
// count: if zero given, first received byte contains block length
// 4800, 9600 oder 10400 Baud, 8N1
bool KWPReceiveBlock(char s[], int maxsize, int &size){
bool ackeachbyte = false;
uint8_t data = 0;
int recvcount = 0;
if (size == 0) ackeachbyte = true;
Serial.print(F("---KWPReceive sz="));
Serial.print(size);
Serial.print(F(" blockCounter="));
Serial.println(blockCounter);
if (size > maxsize) {
Serial.println("ERROR: invalid maxsize");
return false;
}
unsigned long timeout = millis() + 1000;
while ((recvcount == 0) || (recvcount != size)) {
while (obd.available()){
data = obdRead();
s[recvcount] = data;
recvcount++;
if ((size == 0) && (recvcount == 1)) {
size = data + 1;
if (size > maxsize) {
Serial.println("ERROR: invalid maxsize");
return false;
}
}
if ((ackeachbyte) && (recvcount == 2)) {
if (data != blockCounter){
Serial.println(F("ERROR: invalid blockCounter"));
disconnect();
errorData++;
return false;
}
}
if ( ((!ackeachbyte) && (recvcount == size)) || ((ackeachbyte) && (recvcount < size)) ){
obdWrite(data ^ 0xFF); // send complement ack
/*uint8_t echo = obdRead();
if (echo != (data ^ 0xFF)){
Serial.print(F("ERROR: invalid echo "));
Serial.println(echo, HEX);
disconnect();
errorData++;
return false;
}*/
}
timeout = millis() + 1000;
}
if (millis() >= timeout){
Serial.println(F("ERROR: timeout"));
disconnect();
errorTimeout++;
return false;
}
}
// show data
Serial.print(F("IN: sz="));
Serial.print(size);
Serial.print(F(" data="));
for (int i=0; i < size; i++){
uint8_t data = s[i];
Serial.print(data, HEX);
Serial.print(F(" "));
}
Serial.println();
blockCounter++;
return true;
}
bool KWPSendAckBlock(){
Serial.print(F("---KWPSendAckBlock blockCounter="));
Serial.println(blockCounter);
char buf[32];
sprintf(buf, "\x03%c\x09\x03", blockCounter);
return (KWPSendBlock(buf, 4));
}
bool connect(uint8_t addr, int baudrate){
Serial.print(F("------connect addr="));
Serial.print(addr);
Serial.print(F(" baud="));
Serial.println(baudrate);
tone(pinBuzzer, 1200);
delay(100);
noTone(pinBuzzer);
//lcd.clear();
lcdPrint(0,0, F("KW1281 wakeup"), 20);
lcdPrint(0,1, "", 20);
lcdPrint(0,2, "", 20);
blockCounter = 0;
currAddr = 0;
obd.begin(baudrate);
KWP5BaudInit(addr);
// answer: 0x55, 0x01, 0x8A
char s[3];
lcdPrint(0,0, F("KW1281 recv"), 20);
int size = 3;
if (!KWPReceiveBlock(s, 3, size)) return false;
if ( (((uint8_t)s[0]) != 0x55)
|| (((uint8_t)s[1]) != 0x01)
|| (((uint8_t)s[2]) != 0x8A) ){
Serial.println(F("ERROR: invalid magic"));
disconnect();
errorData++;
return false;
}
currAddr = addr;
connected = true;
if (!readConnectBlocks()) return false;
return true;
}
bool readConnectBlocks(){
// read connect blocks
Serial.println(F("------readconnectblocks"));
lcdPrint(0,0, F("KW1281 label"), 20);
String info;
while (true){
int size = 0;
char s[64];
if (!(KWPReceiveBlock(s, 64, size))) return false;
if (size == 0) return false;
if (s[2] == '\x09') break;
if (s[2] != '\xF6') {
Serial.println(F("ERROR: unexpected answer"));
disconnect();
errorData++;
return false;
}
String text = String(s);
info += text.substring(3, size-2);
if (!KWPSendAckBlock()) return false;
}
Serial.print("label=");
Serial.println(info);
//lcd.setCursor(0, 1);
//lcd.print(info);
return true;
}
bool readSensors(int group){
Serial.print(F("------readSensors "));
Serial.println(group);
lcdPrint(0,0, F("KW1281 sensor"), 20);
char s[64];
sprintf(s, "\x04%c\x29%c\x03", blockCounter, group);
if (!KWPSendBlock(s, 5)) return false;
int size = 0;
KWPReceiveBlock(s, 64, size);
if (s[2] != '\xe7') {
Serial.println(F("ERROR: invalid answer"));
disconnect();
errorData++;
return false;
}
int count = (size-4) / 3;
Serial.print(F("count="));
Serial.println(count);
for (int idx=0; idx < count; idx++){
byte k=s[3 + idx*3];
byte a=s[3 + idx*3+1];
byte b=s[3 + idx*3+2];
String n;
float v = 0;
Serial.print(F("type="));
Serial.print(k);
Serial.print(F(" a="));
Serial.print(a);
Serial.print(F(" b="));
Serial.print(b);
Serial.print(F(" text="));
String t = "";
String units = "";
char buf[32];
switch (k){
case 0x01: v=0.2*a*b; units=F("rpm"); break;
case 0x02: v=a*0.002*b; units=F("%%"); break;
case 0x03: v=0.002*a*b; units=F("Deg"); break;
case 0x04: v=abs(b-127)*0.01*a; units=F("ATDC"); break;
case 0x05: v=a*(b-100)*0.1; units=F("°C");break;
case 0x06: v=0.001*a*b; units=F("V");break;
case 0x07: v=0.01*a*b; units=F("km/h");break;
case 0x08: v=0.1*a*b; units=F(" ");break;
case 0x09: v=(b-127)*0.02*a; units=F("Deg");break;
case 0x0A: if (b == 0) t=F("COLD"); else t=F("WARM");break;
case 0x0B: v=0.0001*a*(b-128)+1; units = F(" ");break;
case 0x0C: v=0.001*a*b; units =F("Ohm");break;
case 0x0D: v=(b-127)*0.001*a; units =F("mm");break;
case 0x0E: v=0.005*a*b; units=F("bar");break;
case 0x0F: v=0.01*a*b; units=F("ms");break;
case 0x12: v=0.04*a*b; units=F("mbar");break;
case 0x13: v=a*b*0.01; units=F("l");break;
case 0x14: v=a*(b-128)/128; units=F("%%");break;
case 0x15: v=0.001*a*b; units=F("V");break;
case 0x16: v=0.001*a*b; units=F("ms");break;
case 0x17: v=(b*a)/256; units=F("%%");break;
case 0x18: v=0.001*a*b; units=F("A");break;
case 0x19: v=(b*1.421)+(a/182); units=F("g/s");break;
case 0x1A: v=float(b-a); units=F("C");break;
case 0x1B: v=abs(b-128)*0.01*a; units=F("°");break;
case 0x1C: v=float(b-a); units=F(" ");break;
case 0x1E: v=b/12*a; units=F("Deg k/w");break;
case 0x1F: v=b/2560*a; units=F("°C");break;
case 0x21: v=100*b/a; units=F("%%");break;
case 0x22: v=(b-128)*0.01*a; units=F("kW");break;
case 0x23: v=0.01*a*b; units=F("l/h");break;
case 0x24: v=((unsigned long)a)*2560+((unsigned long)b)*10; units=F("km");break;
case 0x25: v=b; break; // oil pressure ?!
// ADP: FIXME!
/*case 37: switch(b){
case 0: sprintf(buf, F("ADP OK (%d,%d)"), a,b); t=String(buf); break;
case 1: sprintf(buf, F("ADP RUN (%d,%d)"), a,b); t=String(buf); break;
case 0x10: sprintf(buf, F("ADP ERR (%d,%d)"), a,b); t=String(buf); break;
default: sprintf(buf, F("ADP (%d,%d)"), a,b); t=String(buf); break;
}*/
case 0x26: v=(b-128)*0.001*a; units=F("Deg k/w"); break;
case 0x27: v=b/256*a; units=F("mg/h"); break;
case 0x28: v=b*0.1+(25.5*a)-400; units=F("A"); break;
case 0x29: v=b+a*255; units=F("Ah"); break;
case 0x2A: v=b*0.1+(25.5*a)-400; units=F("Kw"); break;
case 0x2B: v=b*0.1+(25.5*a); units=F("V"); break;
case 0x2C: sprintf(buf, "%2d:%2d", a,b); t=String(buf); break;
case 0x2D: v=0.1*a*b/100; units=F(" "); break;
case 0x2E: v=(a*b-3200)*0.0027; units=F("Deg k/w"); break;
case 0x2F: v=(b-128)*a; units=F("ms"); break;
case 0x30: v=b+a*255; units=F(" "); break;
case 0x31: v=(b/4)*a*0.1; units=F("mg/h"); break;
case 0x32: v=(b-128)/(0.01*a); units=F("mbar"); break;
case 0x33: v=((b-128)/255)*a; units=F("mg/h"); break;
case 0x34: v=b*0.02*a-a; units=F("Nm"); break;
case 0x35: v=(b-128)*1.4222+0.006*a; units=F("g/s"); break;
case 0x36: v=a*256+b; units=F("count"); break;
case 0x37: v=a*b/200; units=F("s"); break;
case 0x38: v=a*256+b; units=F("WSC"); break;
case 0x39: v=a*256+b+65536; units=F("WSC"); break;
case 0x3B: v=(a*256+b)/32768; units=F("g/s"); break;
case 0x3C: v=(a*256+b)*0.01; units=F("sec"); break;
case 0x3E: v=0.256*a*b; units=F("S"); break;
case 0x40: v=float(a+b); units=F("Ohm"); break;
case 0x41: v=0.01*a*(b-127); units=F("mm"); break;
case 0x42: v=(a*b)/511.12; units=F("V"); break;
case 0x43: v=(640*a)+b*2.5; units=F("Deg"); break;
case 0x44: v=(256*a+b)/7.365; units=F("deg/s");break;
case 0x45: v=(256*a +b)*0.3254; units=F("Bar");break;
case 0x46: v=(256*a +b)*0.192; units=F("m/s^2");break;
default: sprintf(buf, "%2x, %2x ", a, b); break;
}
switch (currAddr){
case ADR_Engine:
switch(group){
case 3:
switch (idx){
case 0: engineSpeed = v; break;
case 1: EGR_Consumption_target =v; break;
case 2: EGR_Consumption=v; break;
case 3: EGR_duty=v; break;
}
break;
case 11:
switch (idx){
case 0: engineSpeed = v; break;
case 1: TurboPressure_target =v; break;
case 2: TurboPressure =v; break;
case 3: Turbocharger_valve=v; break;
}
break;
}
break;
case ADR_Dashboard:
switch (group){
case 1:
switch (idx){
case 0: vehicleSpeed = v; break;
case 1: engineSpeed = v; break;
case 2: oilPressure = v; break;
}
break;
case 2:
switch (idx){
case 0: odometer = v; break;
case 1: fuelLevel = v; break;
}
break;
case 50:
switch (idx){
case 1: engineSpeed = v; break;
case 2: oilTemp = v; break;
case 3: coolantTemp = v; break;
}
break;
}
break;
}
if (units.length() != 0){
dtostrf(v,4, 2, buf);
t=String(buf) + " " + units;
}
Serial.println(t);
//lcd.setCursor(0, idx);
//while (t.length() < 20) t += " ";
//lcd.print(t);
}
sensorCounter++;
return true;
}
void alarm(){
if (alarmCounter > 10) return;
tone(pinBuzzer, 1200);
delay(100);
noTone(pinBuzzer);
alarmCounter++;
}
void updateDisplay(){
if (!connected){
if ( (errorTimeout != 0) || (errorData != 0) ){
lcdPrint(0,3, F("err to="));
lcdPrint(7,3, String(errorTimeout), 3);
lcdPrint(10,3, F(" da="));
lcdPrint(14,3, String(errorData), 6);
}
} else {
switch (currPage){
case 1:
if (coolantTemp > 99){
lcdPrint(0,1, F("COOL"));
alarm();
} else lcdPrint(0,1, F("cool"));
lcdPrint(6,1,String(coolantTemp),3);
if ( (oilTemp > 99) || ((oilPressure != 30) && (oilPressure != 31)) ){
lcdPrint(10,1,F("OIL "));
alarm();
} else lcdPrint(10,1,F("oil "));
lcdPrint(14,1,String(oilPressure),3);
lcdPrint(0,2, F("rpm "));
lcdPrint(4,2, String(engineSpeed),4);
lcdPrint(10,2, F("km/h "));
lcdPrint(15,2, String(vehicleSpeed, 3));
lcdPrint(0,3, F("fuel "));
lcdPrint(5,3, String(fuelLevel),3);
lcdPrint(10,3, F("odo "));
lcdPrint(14,3, String(odometer),6);
break;
case 2:
if (coolantTemp > 99){
lcdPrint(0,1, F("COOL"));
alarm();
} else lcdPrint(0,1, F("cool"));
lcdPrint(6,1,String(coolantTemp),3);
lcdPrint(10,1, F("air "));
lcdPrint(14,1, String(intakeAirTemp), 3);
lcdPrint(0,2, F("rpm "));
lcdPrint(4,2, String(engineSpeed),4);
lcdPrint(10,2, F("km/h "));
lcdPrint(15,2, String(vehicleSpeed, 3));
lcdPrint(0,3, F("fuel "));
lcdPrint(5,3, String(fuelConsumption),3);
lcdPrint(10,3, F("volt "));
lcdPrint(15,3, String(supplyVoltage),5);
break;
}
}
pageUpdateCounter++;
}
void setup(){
lcd.init();
lcd.backlight();
lcd.init();
pinMode(pinKLineTX, OUTPUT);
digitalWrite(pinKLineTX, HIGH);
pinMode(pinButton, INPUT);
pinMode(pinButton, INPUT_PULLUP);
pinMode(pinBuzzer, OUTPUT);
/*tone(pinBuzzer, 1200);
delay(100);
noTone(pinBuzzer);*/
Serial.begin(19200);
Serial.println(F("SETUP"));
Serial.println(F("START"));
}
void loop(){
if (digitalRead(pinButton) == LOW){
currPage++;
if (currPage > 2) currPage = 1;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(F("page "));
lcd.print(currPage);
errorTimeout = 0;
errorData = 0;
while (digitalRead(pinButton) == LOW);
}
switch (currPage){
case 1:
if (currAddr != ADR_Dashboard){
connect(ADR_Dashboard, 9600);
} else {
readSensors(1);
readSensors(2);
readSensors(50);
}
break;
case 2:
if (currAddr != ADR_Engine) {
connect(ADR_Engine, 9600);
} else {
readSensors(3);
readSensors(11);
}
break;
}
updateDisplay();
Serial.println();
Serial.print ("engineSpeed: "); Serial.println(engineSpeed);
Serial.print ("EGR valve : "); Serial.println(EGR_duty);
Serial.print ("EGR rashod "); Serial.println(EGR_Consumption);
Serial.print ("EGR rashod zadan: "); Serial.println(EGR_Consumption_target);
Serial.print ("Pressure Turbo: "); Serial.println(TurboPressure);
Serial.print ("Pressure Turbo zadan: "); Serial.println(TurboPressure_target);
Serial.print ("Turbo Actuator: "); Serial.println(Turbocharger_valve);
Serial.println();
}
С блоками которые хочу видеть в БК уже почти определился. Хотелось бы придумать как решить с расходом l\100km (Литры / Километраж х 100 = Расход на 100 км). Но надо будет записывать всё в энергонезависимую память. Расход l\h известен.
у вас литров /час это мгновенная величина. И поэтому можно рассчитать будет мгновенный расход топлива л/100км. Средний же считается по другому. Делается цикл измерения:
Записывается пробег и остаток топлива, отмеряется определённое расстояние, чем больше тем лучше. Потом литры делятся на пробег и умножаются на 100.
температура движка не сильно нужна, т.к на приборке есть. может потом куда пригодится.
температура масла- нужна обязательна. не нашел где прячется. в нете смотрел 17 блок(прибока)-3(группа)-3окно. но у меня там её нет. поищу потом. Вроде как(17-50-3)
Скорость - как и температура двигателя ))
Напряжение батареи(аккума) 1-16-4
Пробег(может для расчетов, но он есть и у Александа) 17-2-1
У знакомого одного есть этот NodeMcu. Можно будет взять проэксперементировать. Говорил что c arduino IDE можно подружить. Или это целеком разные платформы ?
Надо будет потом как-нить совместить всё. Я тут раньше прикидывал, что хочу от БК и начал код шкрабать. Надо еще вывести провод от турбинки догревателя, что бы знать крутится она или нет... если крутится то запускать помпу, а потом и печку. Есть идея сделать мигающий стоп-сигнал при экстренном торможении. Некоторые покупают платы с G-сенсором. Я в свое время купил китайский, он просто ставиться перед стоп-сигналом и моргает. А моргает он всегда, что наверное может раздрожать других водителей. Можно попробовать сделать включение его когда сработает ABS и скорость например выше 50 или 60. Только вот как подобрать транзистор((( изначально они по ходу закрыты, а подачей сигнала на их открываются. А тут надо наоборот(простое торможение всегда-открыт, а когда срабатывает ABS - то закрывается).
вроде говоря про бортовой комп имеют в виду дорожный комп - расходы, километражи, ну в крайнем случае параметры работы ДВС) А у вас тут все в кучу будет. Сразу вас предупреждаю, что одно может легко мешать работать другому. Такие вещи невозможно нормально сделать с вашим уровнем программирования. Поэтому рекомендую остановится на чем ни будь одном. Я вам скажу просто, хотя бы обороты и т.д. с ЭБУ на экран выведете, а там посмотрим что из этого получится.
Прислушаюсь к Вашим словам. Надо остановиться на чем то одном, лучше на БК. А управление догревателем, потом сделаю. В боевых действиях на тачке не проверял, только на столе. вместо релюшек стоят диоды. С пульта работает, с кнопки тоже работает. НЕ могу проверить в реальных, так как сам догреватель в ошибку уходит, ругается на обороты турбинки. Мож на днях все сделаю потом - проверю
у вас подключается адаптер к подогревателю? например программой Еdyth ? Если да, то также можно поснифить данные с подогревателя, чтобы провод к турбинке не тянуть.
Вот моя запись на Drive2.ru. Мой котел на прямую к диагностике не подключен. Ну а вы гигант мысли, провод то кинут уже. можно и попробовать ))) https://www.drive2.ru/l/489675201085177968/
ну вот видите, теперь всё совпадает)) ищите также на панель приборов и выбирайте параметры которые вам надо, добавить в скетч я помогу
ок)) ша найдем )))
только вот тут на моё больше похоже:
Илья_69, у тя, вроде как дизель ??? Какой, опять-же ??? В подписи - и Шарабан... и Мерин... а самого главного, кода мотора и г\в - нету...
У бензов, гр.023 (вернее с гр.020 по 029 - Антидетонационное регулирование)
Прилагаю файлик с группами измерений для бензовых моторов (это с Росс-Теха...), ессно, для дизелей - "некатит"...
Для PD с 2001 г.в. :
https://sharanovod.ru/viewtopic.php?t=153&start=40
попробуйте мой скетч #83, исправил
да там подходит точнее, это ваше
вот какие параметры в скетче Александра присутствуют, можно ещё свои добавить.
попробуйте мой скетч #83, исправил
да там подходит точнее, это ваше
ну наконец-то прошли идентификацию)
идём далее , мой скетч
#include <SoftwareSerial.h> SoftwareSerial mySerial(10, 11); //R,T #define TX 11 byte ECUaddress = 0x01; // адрес блока двигателя, можно попробовать с другими адресами bool Init = 0; byte Parameter; //номер передаваемого параметра от ECU byte a; byte b; uint8_t number = 0; byte counter = 0x02; byte countPID = 0; byte countID = 0; int RPM = 0; // переменная оборотов void setup() { Serial.begin (115200); Serial.println(F("---KWP 5 baud init")); delay (500); pinMode (TX, OUTPUT); digitalWrite (TX, HIGH); // BUS IDLE delay (500); send5baud(ECUaddress); // функция отправки адреса блоку mySerial.begin (9600); } void loop() { if( mySerial.available()>0) { delay(5); byte inByte = mySerial.read(); Serial.print(" Rx: "); Serial.print(inByte,HEX); if (!Init){ if (number ==0 && inByte == 0x8A){ countID++; mySerial.write (0x75) ; Serial.print(" Tx: "); Serial.print(0x75,HEX); number++;} else if (number ==1) { mySerial.write (inByte^ 0xFF); Serial.print(" Tx: "); Serial.print(inByte^0xFF,HEX); if (countID>=27) {delay (10); number=4; countID = 0; mySerial.write (0x03); Serial.print(" Tx: "); Serial.print(0x03,HEX); Serial.println (" END of ID_1"); Serial.println ();} countID++;} //первый блок идентификаторов else if (number==4 && inByte == 0xFC){mySerial.write (counter); Serial.print(" Tx: "); Serial.print(counter,HEX); number++;} else if (number==5 && inByte == (counter^0xFF)){ counter++; mySerial.write (0x09); Serial.print(" Tx: "); Serial.print(0x09,HEX); number++;} else if (number==6 && inByte == 0xF6){ mySerial.write (0x03); Serial.print(" Tx: "); Serial.print(0x03,HEX); number++; Serial.println (" END of Present_1"); Serial.println ();} //конец первого 3 FC 2 FD 9 F6 3 else if (number ==7) { if (inByte == 0x03 && countID>5) { number++; counter++ ; countID = 0;mySerial.write (0x03); Serial.print(" Tx: "); Serial.print(0x03,HEX); Serial.println (" END of ID_2"); Serial.println ();} else { mySerial.write (inByte^ 0xFF); Serial.print(" Tx: "); Serial.print(inByte^0xFF,HEX); countID++; }} //второй блок идентификаторов else if (number==8 && inByte == 0xFC){ mySerial.write (counter); Serial.print(" Tx: "); Serial.print(counter,HEX); number++;} else if (number==9 && inByte == (counter^0xFF)){ counter++; mySerial.write (0x09); Serial.print(" Tx: "); Serial.print(0x09,HEX); number++;} else if (number==10 && inByte == 0xF6){ mySerial.write (0x03); Serial.print(" Tx: "); Serial.print(0x03,HEX); number++; Serial.println (" END of Present_2"); Serial.println ();} //конец второго 3 FC 4 FD 9 F6 3 else if (number ==11) { if (inByte == 0x03) { counter++; number++; countID = 0; mySerial.write (0x03); Serial.print(" Tx: "); Serial.print(0x03,HEX); Serial.println (" END of ID_3"); Serial.println (); } else mySerial.write (inByte^ 0xFF); Serial.print(" Tx: "); Serial.print(inByte^0xFF,HEX);} //третий блок идентификаторов else if (number==12 && inByte == 0xFC){ mySerial.write (counter); Serial.print(" Tx: "); Serial.print(counter,HEX); number++;} else if (number==13 && inByte == (counter^0xFF)){ counter++; mySerial.write (0x09); Serial.print(" Tx: "); Serial.print(0x09,HEX); number++;} else if (number==14 && inByte == 0xF6){ mySerial.write (0x03); Serial.print(" Tx: "); Serial.print(0x03,HEX); number++; Serial.println (" END of Present_3"); Serial.println ();} //конец третьего 3 FC 6 FD 9 F6 3 else if (number ==15) { if (inByte == 0x03 && countID>5) { number=0; counter++ ; countID = 0; Serial.println (" END of DTC"); Serial.println ();} else { mySerial.write (inByte^ 0xFF); Serial.print(" Tx: "); Serial.print(inByte^0xFF,HEX); countID++; Init=1;}} // END DTC } else{ if (number ==0){ mySerial.write (0x04); number++;} else if (number ==1 && inByte == 0xFB){ mySerial.write (counter); number++; } else if (number ==2 && inByte == (counter ^ 0xFF)) {counter++; mySerial.write (0x29);number++; } else if (number ==3 && inByte == 0xD6) {mySerial.write (0x01);number++; } else if (number ==4 && inByte == 0xFE) {mySerial.write (0x03);number++; } else if (number ==5 && inByte == 0x0F) {mySerial.write (0xF0);number++; } else if (number ==6 && inByte == counter) {mySerial.write (inByte^0xFF);number++; counter++; } else if (number ==7 && inByte == 0xE7) {mySerial.write (inByte^0xFF);number++; } else if (number ==8) {Parameter=inByte; mySerial.write (inByte^0xFF);number++; } else if (number ==9) {a=inByte; mySerial.write (inByte^0xFF); number++;} else if (number ==10) {b=inByte; mySerial.write (inByte^0xFF); if (Parameter == 0x01) RPM = 0.2*a*b; countPID++; if (countPID>=4) {mySerial.write (0x03); countPID=0; number = 0; Serial.print(" RPM = "); Serial.println(RPM); delay (20);} else number = 8; } } } } //ниже отправка блоку байта адреса на 5бод 1 стартбит, 7бит данных, 1 бит проверки четности odd, 1 стоп бит void send5baud(uint8_t data){ // // 1 start bit, 7 data bits, 1 parity, 1 stop bit #define bitcount 10 byte bits[bitcount]; byte even=1; byte bit; for (int i=0; i < bitcount; i++){ bit=0; if (i == 0) bit = 0; else if (i == 8) bit = even; // computes parity bit else if (i == 9) bit = 1; else { bit = (byte) ((data & (1 << (i-1))) != 0); even = even ^ bit; } Serial.print(F("bit")); Serial.print(i); Serial.print(F("=")); Serial.print(bit); if (i == 0) Serial.print(F(" startbit")); else if (i == 8) Serial.print(F(" parity")); else if (i == 9) Serial.print(F(" stopbit")); Serial.println(); bits[i]=bit; } // now send bit stream for (int i=0; i < bitcount+1; i++){ if (i != 0){ // wait 200 ms (=5 baud), adjusted by latency correction delay(200); if (i == bitcount) break; } if (bits[i] == 1){ // high digitalWrite(TX, HIGH); } else { // low digitalWrite(TX, LOW); } } mySerial.flush(); }Гляну завта уже. Батарея в ноль села. Ну или 40мин надо подождать
ок, до завтра!
эмм, в #107 ошибки, этот к пробам
#include <SoftwareSerial.h> SoftwareSerial mySerial(10, 11); //R,T #define TX 11 byte ECUaddress = 0x01; // адрес блока двигателя, можно попробовать с другими адресами bool Init = 0; byte Parameter; //номер передаваемого параметра от ECU byte a; byte b; uint8_t number = 0; byte counter = 0x02; byte countPID = 0; byte countID = 0; int RPM = 0; // переменная оборотов void setup() { Serial.begin (115200); Serial.println(F("---KWP 5 baud init")); delay (500); pinMode (TX, OUTPUT); digitalWrite (TX, HIGH); // BUS IDLE delay (500); send5baud(ECUaddress); // функция отправки адреса блоку mySerial.begin (9600); } void loop() { if( mySerial.available()>0) { delay(5); byte inByte = mySerial.read(); Serial.print(" Rx: "); Serial.print(inByte,HEX); if (!Init){ if (number ==0 && inByte == 0x8A){ countID++; mySerial.write (0x75) ; Serial.print(" Tx: "); Serial.print(0x75,HEX); number++;} else if (number ==1) { mySerial.write (inByte^ 0xFF); Serial.print(" Tx: "); Serial.print(inByte^0xFF,HEX); if (countID>=27) {delay (10); number=4; countID = 0; mySerial.write (0x03); Serial.print(" Tx: "); Serial.print(0x03,HEX); Serial.println (" END of ID_1"); Serial.println ();} countID++;} //первый блок идентификаторов else if (number==4 && inByte == 0xFC){mySerial.write (counter); Serial.print(" Tx: "); Serial.print(counter,HEX); number++;} else if (number==5 && inByte == (counter^0xFF)){ counter++; mySerial.write (0x09); Serial.print(" Tx: "); Serial.print(0x09,HEX); number++;} else if (number==6 && inByte == 0xF6){ mySerial.write (0x03); Serial.print(" Tx: "); Serial.print(0x03,HEX); number++; Serial.println (" END of Present_1"); Serial.println ();} //конец первого 3 FC 2 FD 9 F6 3 else if (number ==7) { if (inByte == 0x03 && countID>5) { number++; counter++ ; countID = 0;mySerial.write (0x03); Serial.print(" Tx: "); Serial.print(0x03,HEX); Serial.println (" END of ID_2"); Serial.println ();} else { mySerial.write (inByte^ 0xFF); Serial.print(" Tx: "); Serial.print(inByte^0xFF,HEX); countID++; }} //второй блок идентификаторов else if (number==8 && inByte == 0xFC){ mySerial.write (counter); Serial.print(" Tx: "); Serial.print(counter,HEX); number++;} else if (number==9 && inByte == (counter^0xFF)){ counter++; mySerial.write (0x09); Serial.print(" Tx: "); Serial.print(0x09,HEX); number++;} else if (number==10 && inByte == 0xF6){ mySerial.write (0x03); Serial.print(" Tx: "); Serial.print(0x03,HEX); number++; Serial.println (" END of Present_2"); Serial.println ();} //конец второго 3 FC 4 FD 9 F6 3 else if (number ==11) { if (inByte == 0x03) { counter++; number++; countID = 0; mySerial.write (0x03); Serial.print(" Tx: "); Serial.print(0x03,HEX); Serial.println (" END of ID_3"); Serial.println (); } else {mySerial.write (inByte^ 0xFF); Serial.print(" Tx: "); Serial.print(inByte^0xFF,HEX);}} //третий блок идентификаторов else if (number==12 && inByte == 0xFC){ mySerial.write (counter); Serial.print(" Tx: "); Serial.print(counter,HEX); number++;} else if (number==13 && inByte == (counter^0xFF)){ counter++; mySerial.write (0x09); Serial.print(" Tx: "); Serial.print(0x09,HEX); number++;} else if (number==14 && inByte == 0xF6){ mySerial.write (0x03); Serial.print(" Tx: "); Serial.print(0x03,HEX); number++; Serial.println (" END of Present_3"); Serial.println ();} //конец третьего 3 FC 6 FD 9 F6 3 else if (number ==15) { if (inByte == 0x03 && countID>5) { number=0; counter++ ; countID = 0; Serial.println (" END of DTC"); Serial.println (); Init=1;} else { mySerial.write (inByte^ 0xFF); Serial.print(" Tx: "); Serial.print(inByte^0xFF,HEX); countID++; }} // END DTC } else{ if (number ==0){ mySerial.write (0x04); number++;} else if (number ==1 && inByte == 0xFB){ mySerial.write (counter); number++; } else if (number ==2 && inByte == (counter ^ 0xFF)) {counter++; mySerial.write (0x29);number++; } else if (number ==3 && inByte == 0xD6) {mySerial.write (0x01);number++; } else if (number ==4 && inByte == 0xFE) {mySerial.write (0x03);number++; } else if (number ==5 && inByte == 0x0F) {mySerial.write (0xF0);number++; } else if (number ==6 && inByte == counter) {mySerial.write (inByte^0xFF);number++; counter++; } else if (number ==7 && inByte == 0xE7) {mySerial.write (inByte^0xFF);number++; } else if (number ==8) {Parameter=inByte; mySerial.write (inByte^0xFF);number++; } else if (number ==9) {a=inByte; mySerial.write (inByte^0xFF); number++;} else if (number ==10) {b=inByte; mySerial.write (inByte^0xFF); if (Parameter == 0x01) RPM = 0.2*a*b; countPID++; if (countPID>=4) {mySerial.write (0x03); countPID=0; number = 0; Serial.print(" RPM = "); Serial.println(RPM); delay (20);} else number = 8; } } } } //ниже отправка блоку байта адреса на 5бод 1 стартбит, 7бит данных, 1 бит проверки четности odd, 1 стоп бит void send5baud(uint8_t data){ // // 1 start bit, 7 data bits, 1 parity, 1 stop bit #define bitcount 10 byte bits[bitcount]; byte even=1; byte bit; for (int i=0; i < bitcount; i++){ bit=0; if (i == 0) bit = 0; else if (i == 8) bit = even; // computes parity bit else if (i == 9) bit = 1; else { bit = (byte) ((data & (1 << (i-1))) != 0); even = even ^ bit; } Serial.print(F("bit")); Serial.print(i); Serial.print(F("=")); Serial.print(bit); if (i == 0) Serial.print(F(" startbit")); else if (i == 8) Serial.print(F(" parity")); else if (i == 9) Serial.print(F(" stopbit")); Serial.println(); bits[i]=bit; } // now send bit stream for (int i=0; i < bitcount+1; i++){ if (i != 0){ // wait 200 ms (=5 baud), adjusted by latency correction delay(200); if (i == bitcount) break; } if (bits[i] == 1){ // high digitalWrite(TX, HIGH); } else { // low digitalWrite(TX, LOW); } } mySerial.flush(); }вот ещё Александра немного переделал
/* Arduino Nano OBD reader (OBD protocol KW1281, Audi A4 B5 etc.) wiring: D2 --- OBD level shifter input (RX) (e.g. LM339) D3 --- OBD level shifter output (TX) (e.g. LM339) A5 --- Arduino 20x4 LCD display SCL A4 --- Arduino 20x4 LCD display SDA NOTE: For the level shifting, I used a 'AutoDia K409 Profi USB adapter', disassembled it, and connected the Arduino to the level shifter chip (LM339) - the original FTDI chip TX line was removed (so it does not influence the communication) */ #include <Wire.h> #include "LiquidCrystal_I2C.h" #include "NewSoftwareSerial.h" #define pinKLineRX 10 #define pinKLineTX 11 #define pinLED 13 #define pinBuzzer 9 #define pinButton 5 // https://www.blafusel.de/obd/obd2_kw1281.html #define ADR_Engine 0x01 #define ADR_Gears 0x02 #define ADR_ABS_Brakes 0x03 #define ADR_Airbag 0x15 #define ADR_Dashboard 0x17 #define ADR_Immobilizer 0x25 #define ADR_Central_locking 0x35 //#define DEBUG 1 LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x20 for a 16 chars and 2 line display NewSoftwareSerial obd(pinKLineRX, pinKLineTX, false); // RX, TX, inverse logic uint8_t currAddr = 0; uint8_t blockCounter = 0; uint8_t errorTimeout = 0; uint8_t errorData = 0; bool connected = false; int sensorCounter = 0; int pageUpdateCounter = 0; int alarmCounter = 0; uint8_t currPage = 2; int8_t coolantTemp = 0; int8_t oilTemp = 0; int8_t intakeAirTemp = 0; int8_t oilPressure = 0; float engineLoad = 0; int engineSpeed = 0; float throttleValve = 0; float supplyVoltage = 0; uint8_t vehicleSpeed = 0; uint8_t fuelConsumption = 0; uint8_t fuelLevel = 0; unsigned long odometer = 0; // наши параметры int TurboPressure = 0; int TurboPressure_target = 0; uint8_t Turbocharger_valve = 0; uint8_t EGR_duty = 0; int EGR_Consumption = 0; int EGR_Consumption_target = 0; String floatToString(float v){ String res; char buf[16]; dtostrf(v,4, 2, buf); res=String(buf); return res; } void disconnect(){ connected = false; currAddr = 0; } void lcdPrint(int x, int y, String s, int width = 0){ lcd.setCursor(x,y); while (s.length() < width) s += " "; lcd.print(s); } void obdWrite(uint8_t data){ #ifdef DEBUG Serial.print("uC:"); Serial.println(data, HEX); #endif obd.write(data); } uint8_t obdRead(){ unsigned long timeout = millis() + 1000; while (!obd.available()){ if (millis() >= timeout) { Serial.println(F("ERROR: obdRead timeout")); disconnect(); errorTimeout++; return 0; } } uint8_t data = obd.read(); #ifdef DEBUG Serial.print("ECU:"); Serial.println(data, HEX); #endif return data; } // 5Bd, 7O1 void send5baud(uint8_t data){ // // 1 start bit, 7 data bits, 1 parity, 1 stop bit #define bitcount 10 byte bits[bitcount]; byte even=1; byte bit; for (int i=0; i < bitcount; i++){ bit=0; if (i == 0) bit = 0; else if (i == 8) bit = even; // computes parity bit else if (i == 9) bit = 1; else { bit = (byte) ((data & (1 << (i-1))) != 0); even = even ^ bit; } Serial.print(F("bit")); Serial.print(i); Serial.print(F("=")); Serial.print(bit); if (i == 0) Serial.print(F(" startbit")); else if (i == 8) Serial.print(F(" parity")); else if (i == 9) Serial.print(F(" stopbit")); Serial.println(); bits[i]=bit; } // now send bit stream for (int i=0; i < bitcount+1; i++){ if (i != 0){ // wait 200 ms (=5 baud), adjusted by latency correction delay(200); if (i == bitcount) break; } if (bits[i] == 1){ // high digitalWrite(pinKLineTX, HIGH); } else { // low digitalWrite(pinKLineTX, LOW); } } obd.flush(); } bool KWP5BaudInit(uint8_t addr){ Serial.println(F("---KWP 5 baud init")); //delay(3000); send5baud(addr); return true; } bool KWPSendBlock(char *s, int size){ Serial.print(F("---KWPSend sz=")); Serial.print(size); Serial.print(F(" blockCounter=")); Serial.println(blockCounter); // show data Serial.print(F("OUT:")); for (int i=0; i < size; i++){ uint8_t data = s[i]; Serial.print(data, HEX); Serial.print(" "); } Serial.println(); for (int i=0; i < size; i++){ uint8_t data = s[i]; obdWrite(data); /*uint8_t echo = obdRead(); if (data != echo){ Serial.println(F("ERROR: invalid echo")); disconnect(); errorData++; return false; }*/ if (i < size-1){ uint8_t complement = obdRead(); if (complement != (data ^ 0xFF)){ Serial.println(F("ERROR: invalid complement")); disconnect(); errorData++; return false; } } } blockCounter++; return true; } // count: if zero given, first received byte contains block length // 4800, 9600 oder 10400 Baud, 8N1 bool KWPReceiveBlock(char s[], int maxsize, int &size){ bool ackeachbyte = false; uint8_t data = 0; int recvcount = 0; if (size == 0) ackeachbyte = true; Serial.print(F("---KWPReceive sz=")); Serial.print(size); Serial.print(F(" blockCounter=")); Serial.println(blockCounter); if (size > maxsize) { Serial.println("ERROR: invalid maxsize"); return false; } unsigned long timeout = millis() + 1000; while ((recvcount == 0) || (recvcount != size)) { while (obd.available()){ data = obdRead(); s[recvcount] = data; recvcount++; if ((size == 0) && (recvcount == 1)) { size = data + 1; if (size > maxsize) { Serial.println("ERROR: invalid maxsize"); return false; } } if ((ackeachbyte) && (recvcount == 2)) { if (data != blockCounter){ Serial.println(F("ERROR: invalid blockCounter")); disconnect(); errorData++; return false; } } if ( ((!ackeachbyte) && (recvcount == size)) || ((ackeachbyte) && (recvcount < size)) ){ obdWrite(data ^ 0xFF); // send complement ack /*uint8_t echo = obdRead(); if (echo != (data ^ 0xFF)){ Serial.print(F("ERROR: invalid echo ")); Serial.println(echo, HEX); disconnect(); errorData++; return false; }*/ } timeout = millis() + 1000; } if (millis() >= timeout){ Serial.println(F("ERROR: timeout")); disconnect(); errorTimeout++; return false; } } // show data Serial.print(F("IN: sz=")); Serial.print(size); Serial.print(F(" data=")); for (int i=0; i < size; i++){ uint8_t data = s[i]; Serial.print(data, HEX); Serial.print(F(" ")); } Serial.println(); blockCounter++; return true; } bool KWPSendAckBlock(){ Serial.print(F("---KWPSendAckBlock blockCounter=")); Serial.println(blockCounter); char buf[32]; sprintf(buf, "\x03%c\x09\x03", blockCounter); return (KWPSendBlock(buf, 4)); } bool connect(uint8_t addr, int baudrate){ Serial.print(F("------connect addr=")); Serial.print(addr); Serial.print(F(" baud=")); Serial.println(baudrate); tone(pinBuzzer, 1200); delay(100); noTone(pinBuzzer); //lcd.clear(); lcdPrint(0,0, F("KW1281 wakeup"), 20); lcdPrint(0,1, "", 20); lcdPrint(0,2, "", 20); blockCounter = 0; currAddr = 0; obd.begin(baudrate); KWP5BaudInit(addr); // answer: 0x55, 0x01, 0x8A char s[3]; lcdPrint(0,0, F("KW1281 recv"), 20); int size = 3; if (!KWPReceiveBlock(s, 3, size)) return false; if ( (((uint8_t)s[0]) != 0x55) || (((uint8_t)s[1]) != 0x01) || (((uint8_t)s[2]) != 0x8A) ){ Serial.println(F("ERROR: invalid magic")); disconnect(); errorData++; return false; } currAddr = addr; connected = true; if (!readConnectBlocks()) return false; return true; } bool readConnectBlocks(){ // read connect blocks Serial.println(F("------readconnectblocks")); lcdPrint(0,0, F("KW1281 label"), 20); String info; while (true){ int size = 0; char s[64]; if (!(KWPReceiveBlock(s, 64, size))) return false; if (size == 0) return false; if (s[2] == '\x09') break; if (s[2] != '\xF6') { Serial.println(F("ERROR: unexpected answer")); disconnect(); errorData++; return false; } String text = String(s); info += text.substring(3, size-2); if (!KWPSendAckBlock()) return false; } Serial.print("label="); Serial.println(info); //lcd.setCursor(0, 1); //lcd.print(info); return true; } bool readSensors(int group){ Serial.print(F("------readSensors ")); Serial.println(group); lcdPrint(0,0, F("KW1281 sensor"), 20); char s[64]; sprintf(s, "\x04%c\x29%c\x03", blockCounter, group); if (!KWPSendBlock(s, 5)) return false; int size = 0; KWPReceiveBlock(s, 64, size); if (s[2] != '\xe7') { Serial.println(F("ERROR: invalid answer")); disconnect(); errorData++; return false; } int count = (size-4) / 3; Serial.print(F("count=")); Serial.println(count); for (int idx=0; idx < count; idx++){ byte k=s[3 + idx*3]; byte a=s[3 + idx*3+1]; byte b=s[3 + idx*3+2]; String n; float v = 0; Serial.print(F("type=")); Serial.print(k); Serial.print(F(" a=")); Serial.print(a); Serial.print(F(" b=")); Serial.print(b); Serial.print(F(" text=")); String t = ""; String units = ""; char buf[32]; switch (k){ case 0x01: v=0.2*a*b; units=F("rpm"); break; case 0x02: v=a*0.002*b; units=F("%%"); break; case 0x03: v=0.002*a*b; units=F("Deg"); break; case 0x04: v=abs(b-127)*0.01*a; units=F("ATDC"); break; case 0x05: v=a*(b-100)*0.1; units=F("°C");break; case 0x06: v=0.001*a*b; units=F("V");break; case 0x07: v=0.01*a*b; units=F("km/h");break; case 0x08: v=0.1*a*b; units=F(" ");break; case 0x09: v=(b-127)*0.02*a; units=F("Deg");break; case 0x0A: if (b == 0) t=F("COLD"); else t=F("WARM");break; case 0x0B: v=0.0001*a*(b-128)+1; units = F(" ");break; case 0x0C: v=0.001*a*b; units =F("Ohm");break; case 0x0D: v=(b-127)*0.001*a; units =F("mm");break; case 0x0E: v=0.005*a*b; units=F("bar");break; case 0x0F: v=0.01*a*b; units=F("ms");break; case 0x12: v=0.04*a*b; units=F("mbar");break; case 0x13: v=a*b*0.01; units=F("l");break; case 0x14: v=a*(b-128)/128; units=F("%%");break; case 0x15: v=0.001*a*b; units=F("V");break; case 0x16: v=0.001*a*b; units=F("ms");break; case 0x17: v=b/256*a; units=F("%%");break; case 0x18: v=0.001*a*b; units=F("A");break; case 0x19: v=(b*1.421)+(a/182); units=F("g/s");break; case 0x1A: v=float(b-a); units=F("C");break; case 0x1B: v=abs(b-128)*0.01*a; units=F("°");break; case 0x1C: v=float(b-a); units=F(" ");break; case 0x1E: v=b/12*a; units=F("Deg k/w");break; case 0x1F: v=b/2560*a; units=F("°C");break; case 0x21: v=100*b/a; units=F("%%");break; case 0x22: v=(b-128)*0.01*a; units=F("kW");break; case 0x23: v=0.01*a*b; units=F("l/h");break; case 0x24: v=((unsigned long)a)*2560+((unsigned long)b)*10; units=F("km");break; case 0x25: v=b; break; // oil pressure ?! // ADP: FIXME! /*case 37: switch(b){ case 0: sprintf(buf, F("ADP OK (%d,%d)"), a,b); t=String(buf); break; case 1: sprintf(buf, F("ADP RUN (%d,%d)"), a,b); t=String(buf); break; case 0x10: sprintf(buf, F("ADP ERR (%d,%d)"), a,b); t=String(buf); break; default: sprintf(buf, F("ADP (%d,%d)"), a,b); t=String(buf); break; }*/ case 0x26: v=(b-128)*0.001*a; units=F("Deg k/w"); break; case 0x27: v=b/256*a; units=F("mg/h"); break; case 0x28: v=b*0.1+(25.5*a)-400; units=F("A"); break; case 0x29: v=b+a*255; units=F("Ah"); break; case 0x2A: v=b*0.1+(25.5*a)-400; units=F("Kw"); break; case 0x2B: v=b*0.1+(25.5*a); units=F("V"); break; case 0x2C: sprintf(buf, "%2d:%2d", a,b); t=String(buf); break; case 0x2D: v=0.1*a*b/100; units=F(" "); break; case 0x2E: v=(a*b-3200)*0.0027; units=F("Deg k/w"); break; case 0x2F: v=(b-128)*a; units=F("ms"); break; case 0x30: v=b+a*255; units=F(" "); break; case 0x31: v=(b/4)*a*0.1; units=F("mg/h"); break; case 0x32: v=(b-128)/(0.01*a); units=F("mbar"); break; case 0x33: v=((b-128)/255)*a; units=F("mg/h"); break; case 0x34: v=b*0.02*a-a; units=F("Nm"); break; case 0x35: v=(b-128)*1.4222+0.006*a; units=F("g/s"); break; case 0x36: v=a*256+b; units=F("count"); break; case 0x37: v=a*b/200; units=F("s"); break; case 0x38: v=a*256+b; units=F("WSC"); break; case 0x39: v=a*256+b+65536; units=F("WSC"); break; case 0x3B: v=(a*256+b)/32768; units=F("g/s"); break; case 0x3C: v=(a*256+b)*0.01; units=F("sec"); break; case 0x3E: v=0.256*a*b; units=F("S"); break; case 0x40: v=float(a+b); units=F("Ohm"); break; case 0x41: v=0.01*a*(b-127); units=F("mm"); break; case 0x42: v=(a*b)/511.12; units=F("V"); break; case 0x43: v=(640*a)+b*2.5; units=F("Deg"); break; case 0x44: v=(256*a+b)/7.365; units=F("deg/s");break; case 0x45: v=(256*a +b)*0.3254; units=F("Bar");break; case 0x46: v=(256*a +b)*0.192; units=F("m/s^2");break; default: sprintf(buf, "%2x, %2x ", a, b); break; } switch (currAddr){ case ADR_Engine: switch(group){ case 3: switch (idx){ case 0: engineSpeed = v; break; case 1: EGR_Consumption_target; break; case 2: EGR_Consumption; break; case 3: EGR_duty=v; break; } break; case 11: switch (idx){ case 0: engineSpeed = v; break; case 1: TurboPressure_target =v; break; case 2: TurboPressure =v; break; case 3: Turbocharger_valve=v; break; } break; } break; case ADR_Dashboard: switch (group){ case 1: switch (idx){ case 0: vehicleSpeed = v; break; case 1: engineSpeed = v; break; case 2: oilPressure = v; break; } break; case 2: switch (idx){ case 0: odometer = v; break; case 1: fuelLevel = v; break; } break; case 50: switch (idx){ case 1: engineSpeed = v; break; case 2: oilTemp = v; break; case 3: coolantTemp = v; break; } break; } break; } if (units.length() != 0){ dtostrf(v,4, 2, buf); t=String(buf) + " " + units; } Serial.println(t); //lcd.setCursor(0, idx); //while (t.length() < 20) t += " "; //lcd.print(t); } sensorCounter++; return true; } void alarm(){ if (alarmCounter > 10) return; tone(pinBuzzer, 1200); delay(100); noTone(pinBuzzer); alarmCounter++; } void updateDisplay(){ if (!connected){ if ( (errorTimeout != 0) || (errorData != 0) ){ lcdPrint(0,3, F("err to=")); lcdPrint(7,3, String(errorTimeout), 3); lcdPrint(10,3, F(" da=")); lcdPrint(14,3, String(errorData), 6); } } else { switch (currPage){ case 1: if (coolantTemp > 99){ lcdPrint(0,1, F("COOL")); alarm(); } else lcdPrint(0,1, F("cool")); lcdPrint(6,1,String(coolantTemp),3); if ( (oilTemp > 99) || ((oilPressure != 30) && (oilPressure != 31)) ){ lcdPrint(10,1,F("OIL ")); alarm(); } else lcdPrint(10,1,F("oil ")); lcdPrint(14,1,String(oilPressure),3); lcdPrint(0,2, F("rpm ")); lcdPrint(4,2, String(engineSpeed),4); lcdPrint(10,2, F("km/h ")); lcdPrint(15,2, String(vehicleSpeed, 3)); lcdPrint(0,3, F("fuel ")); lcdPrint(5,3, String(fuelLevel),3); lcdPrint(10,3, F("odo ")); lcdPrint(14,3, String(odometer),6); break; case 2: if (coolantTemp > 99){ lcdPrint(0,1, F("COOL")); alarm(); } else lcdPrint(0,1, F("cool")); lcdPrint(6,1,String(coolantTemp),3); lcdPrint(10,1, F("air ")); lcdPrint(14,1, String(intakeAirTemp), 3); lcdPrint(0,2, F("rpm ")); lcdPrint(4,2, String(engineSpeed),4); lcdPrint(10,2, F("km/h ")); lcdPrint(15,2, String(vehicleSpeed, 3)); lcdPrint(0,3, F("fuel ")); lcdPrint(5,3, String(fuelConsumption),3); lcdPrint(10,3, F("volt ")); lcdPrint(15,3, String(supplyVoltage),5); break; } } pageUpdateCounter++; } void setup(){ lcd.init(); lcd.backlight(); lcd.init(); pinMode(pinKLineTX, OUTPUT); digitalWrite(pinKLineTX, HIGH); pinMode(pinButton, INPUT); pinMode(pinButton, INPUT_PULLUP); pinMode(pinBuzzer, OUTPUT); /*tone(pinBuzzer, 1200); delay(100); noTone(pinBuzzer);*/ Serial.begin(19200); Serial.println(F("SETUP")); Serial.println(F("START")); } void loop(){ if (digitalRead(pinButton) == LOW){ currPage++; if (currPage > 2) currPage = 1; lcd.clear(); lcd.setCursor(0,0); lcd.print(F("page ")); lcd.print(currPage); errorTimeout = 0; errorData = 0; while (digitalRead(pinButton) == LOW); } switch (currPage){ case 1: if (currAddr != ADR_Dashboard){ connect(ADR_Dashboard, 9600); } else { readSensors(1); readSensors(2); readSensors(50); } break; case 2: if (currAddr != ADR_Engine) { connect(ADR_Engine, 9600); } else { readSensors(3); readSensors(11); } break; } updateDisplay(); Serial.println(); Serial.print ("engineSpeed: "); Serial.println(engineSpeed); Serial.print ("EGR valve : "); Serial.println(EGR_duty); Serial.print ("EGR rashod "); Serial.println(EGR_Consumption); Serial.print ("EGR rashod zadan: "); Serial.println(EGR_Consumption_target); Serial.print ("Pressure Turbo: "); Serial.println(TurboPressure); Serial.print ("Pressure Turbo zadan: "); Serial.println(TurboPressure_target); Serial.print ("Turbo Actuator: "); Serial.println(Turbocharger_valve); Serial.println(); }Ваш 107
От Александра
По скетчу Александра 11 группа не работает. У вас турбина есть? Также в 3 группе положение клапана ЕГР не видит.
Сравнивайте с ваг комом какие там значения показывает в группах 3 и 11
Вот скриншот когда-то записаного мной лога. тут группа 3,10,11. По названию столбцов видно.
В 11 группе столбец 2-это требуемое давление, столбец 3-давление которое выдает турбина. У меня турбина с управляемой геометрией.
а ну, собственно, я слукавил походу, что 11 группа не работает. Обороты у вас показывали на тот момент были 840. На таких оборотах давление турбины соответствует атмосферному давлению примерно, т.е. 1000 mBar, у вас так и показывало примено. Резко газоните и посмотрите поднимется ли давление, должно всё работать, парметры поднимутся.
С блоками которые хочу видеть в БК уже почти определился. Хотелось бы придумать как решить с расходом l\100km (Литры / Километраж х 100 = Расход на 100 км). Но надо будет записывать всё в энергонезависимую память. Расход l\h известен. Если просчитать это, то можно будет и подсчитать запас хода... колличество топлива тоже есть в параметрах.
Тут вот расписан стандартный VAGовский.
http://automn.ru/vw-sharan/volkswagen-17654-10.m_id-1810.m_id2-1812.html
Но поговаривают на форумах, что он частяком врет
а для EGR и клапана турбины используется одна и та же формула, немного неправильно сделанная. формулу перелелал. Теперь егр и процент открытия клапана турбы должно показывать
/* Arduino Nano OBD reader (OBD protocol KW1281, Audi A4 B5 etc.) wiring: D2 --- OBD level shifter input (RX) (e.g. LM339) D3 --- OBD level shifter output (TX) (e.g. LM339) A5 --- Arduino 20x4 LCD display SCL A4 --- Arduino 20x4 LCD display SDA NOTE: For the level shifting, I used a 'AutoDia K409 Profi USB adapter', disassembled it, and connected the Arduino to the level shifter chip (LM339) - the original FTDI chip TX line was removed (so it does not influence the communication) */ #include <Wire.h> #include "LiquidCrystal_I2C.h" #include "NewSoftwareSerial.h" #define pinKLineRX 10 #define pinKLineTX 11 #define pinLED 13 #define pinBuzzer 9 #define pinButton 5 // https://www.blafusel.de/obd/obd2_kw1281.html #define ADR_Engine 0x01 #define ADR_Gears 0x02 #define ADR_ABS_Brakes 0x03 #define ADR_Airbag 0x15 #define ADR_Dashboard 0x17 #define ADR_Immobilizer 0x25 #define ADR_Central_locking 0x35 //#define DEBUG 1 LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x20 for a 16 chars and 2 line display NewSoftwareSerial obd(pinKLineRX, pinKLineTX, false); // RX, TX, inverse logic uint8_t currAddr = 0; uint8_t blockCounter = 0; uint8_t errorTimeout = 0; uint8_t errorData = 0; bool connected = false; int sensorCounter = 0; int pageUpdateCounter = 0; int alarmCounter = 0; uint8_t currPage = 2; int8_t coolantTemp = 0; int8_t oilTemp = 0; int8_t intakeAirTemp = 0; int8_t oilPressure = 0; float engineLoad = 0; int engineSpeed = 0; float throttleValve = 0; float supplyVoltage = 0; uint8_t vehicleSpeed = 0; uint8_t fuelConsumption = 0; uint8_t fuelLevel = 0; unsigned long odometer = 0; // наши параметры int TurboPressure = 0; int TurboPressure_target = 0; uint8_t Turbocharger_valve = 0; uint8_t EGR_duty = 0; int EGR_Consumption = 0; int EGR_Consumption_target = 0; String floatToString(float v){ String res; char buf[16]; dtostrf(v,4, 2, buf); res=String(buf); return res; } void disconnect(){ connected = false; currAddr = 0; } void lcdPrint(int x, int y, String s, int width = 0){ lcd.setCursor(x,y); while (s.length() < width) s += " "; lcd.print(s); } void obdWrite(uint8_t data){ #ifdef DEBUG Serial.print("uC:"); Serial.println(data, HEX); #endif obd.write(data); } uint8_t obdRead(){ unsigned long timeout = millis() + 1000; while (!obd.available()){ if (millis() >= timeout) { Serial.println(F("ERROR: obdRead timeout")); disconnect(); errorTimeout++; return 0; } } uint8_t data = obd.read(); #ifdef DEBUG Serial.print("ECU:"); Serial.println(data, HEX); #endif return data; } // 5Bd, 7O1 void send5baud(uint8_t data){ // // 1 start bit, 7 data bits, 1 parity, 1 stop bit #define bitcount 10 byte bits[bitcount]; byte even=1; byte bit; for (int i=0; i < bitcount; i++){ bit=0; if (i == 0) bit = 0; else if (i == 8) bit = even; // computes parity bit else if (i == 9) bit = 1; else { bit = (byte) ((data & (1 << (i-1))) != 0); even = even ^ bit; } Serial.print(F("bit")); Serial.print(i); Serial.print(F("=")); Serial.print(bit); if (i == 0) Serial.print(F(" startbit")); else if (i == 8) Serial.print(F(" parity")); else if (i == 9) Serial.print(F(" stopbit")); Serial.println(); bits[i]=bit; } // now send bit stream for (int i=0; i < bitcount+1; i++){ if (i != 0){ // wait 200 ms (=5 baud), adjusted by latency correction delay(200); if (i == bitcount) break; } if (bits[i] == 1){ // high digitalWrite(pinKLineTX, HIGH); } else { // low digitalWrite(pinKLineTX, LOW); } } obd.flush(); } bool KWP5BaudInit(uint8_t addr){ Serial.println(F("---KWP 5 baud init")); //delay(3000); send5baud(addr); return true; } bool KWPSendBlock(char *s, int size){ Serial.print(F("---KWPSend sz=")); Serial.print(size); Serial.print(F(" blockCounter=")); Serial.println(blockCounter); // show data Serial.print(F("OUT:")); for (int i=0; i < size; i++){ uint8_t data = s[i]; Serial.print(data, HEX); Serial.print(" "); } Serial.println(); for (int i=0; i < size; i++){ uint8_t data = s[i]; obdWrite(data); /*uint8_t echo = obdRead(); if (data != echo){ Serial.println(F("ERROR: invalid echo")); disconnect(); errorData++; return false; }*/ if (i < size-1){ uint8_t complement = obdRead(); if (complement != (data ^ 0xFF)){ Serial.println(F("ERROR: invalid complement")); disconnect(); errorData++; return false; } } } blockCounter++; return true; } // count: if zero given, first received byte contains block length // 4800, 9600 oder 10400 Baud, 8N1 bool KWPReceiveBlock(char s[], int maxsize, int &size){ bool ackeachbyte = false; uint8_t data = 0; int recvcount = 0; if (size == 0) ackeachbyte = true; Serial.print(F("---KWPReceive sz=")); Serial.print(size); Serial.print(F(" blockCounter=")); Serial.println(blockCounter); if (size > maxsize) { Serial.println("ERROR: invalid maxsize"); return false; } unsigned long timeout = millis() + 1000; while ((recvcount == 0) || (recvcount != size)) { while (obd.available()){ data = obdRead(); s[recvcount] = data; recvcount++; if ((size == 0) && (recvcount == 1)) { size = data + 1; if (size > maxsize) { Serial.println("ERROR: invalid maxsize"); return false; } } if ((ackeachbyte) && (recvcount == 2)) { if (data != blockCounter){ Serial.println(F("ERROR: invalid blockCounter")); disconnect(); errorData++; return false; } } if ( ((!ackeachbyte) && (recvcount == size)) || ((ackeachbyte) && (recvcount < size)) ){ obdWrite(data ^ 0xFF); // send complement ack /*uint8_t echo = obdRead(); if (echo != (data ^ 0xFF)){ Serial.print(F("ERROR: invalid echo ")); Serial.println(echo, HEX); disconnect(); errorData++; return false; }*/ } timeout = millis() + 1000; } if (millis() >= timeout){ Serial.println(F("ERROR: timeout")); disconnect(); errorTimeout++; return false; } } // show data Serial.print(F("IN: sz=")); Serial.print(size); Serial.print(F(" data=")); for (int i=0; i < size; i++){ uint8_t data = s[i]; Serial.print(data, HEX); Serial.print(F(" ")); } Serial.println(); blockCounter++; return true; } bool KWPSendAckBlock(){ Serial.print(F("---KWPSendAckBlock blockCounter=")); Serial.println(blockCounter); char buf[32]; sprintf(buf, "\x03%c\x09\x03", blockCounter); return (KWPSendBlock(buf, 4)); } bool connect(uint8_t addr, int baudrate){ Serial.print(F("------connect addr=")); Serial.print(addr); Serial.print(F(" baud=")); Serial.println(baudrate); tone(pinBuzzer, 1200); delay(100); noTone(pinBuzzer); //lcd.clear(); lcdPrint(0,0, F("KW1281 wakeup"), 20); lcdPrint(0,1, "", 20); lcdPrint(0,2, "", 20); blockCounter = 0; currAddr = 0; obd.begin(baudrate); KWP5BaudInit(addr); // answer: 0x55, 0x01, 0x8A char s[3]; lcdPrint(0,0, F("KW1281 recv"), 20); int size = 3; if (!KWPReceiveBlock(s, 3, size)) return false; if ( (((uint8_t)s[0]) != 0x55) || (((uint8_t)s[1]) != 0x01) || (((uint8_t)s[2]) != 0x8A) ){ Serial.println(F("ERROR: invalid magic")); disconnect(); errorData++; return false; } currAddr = addr; connected = true; if (!readConnectBlocks()) return false; return true; } bool readConnectBlocks(){ // read connect blocks Serial.println(F("------readconnectblocks")); lcdPrint(0,0, F("KW1281 label"), 20); String info; while (true){ int size = 0; char s[64]; if (!(KWPReceiveBlock(s, 64, size))) return false; if (size == 0) return false; if (s[2] == '\x09') break; if (s[2] != '\xF6') { Serial.println(F("ERROR: unexpected answer")); disconnect(); errorData++; return false; } String text = String(s); info += text.substring(3, size-2); if (!KWPSendAckBlock()) return false; } Serial.print("label="); Serial.println(info); //lcd.setCursor(0, 1); //lcd.print(info); return true; } bool readSensors(int group){ Serial.print(F("------readSensors ")); Serial.println(group); lcdPrint(0,0, F("KW1281 sensor"), 20); char s[64]; sprintf(s, "\x04%c\x29%c\x03", blockCounter, group); if (!KWPSendBlock(s, 5)) return false; int size = 0; KWPReceiveBlock(s, 64, size); if (s[2] != '\xe7') { Serial.println(F("ERROR: invalid answer")); disconnect(); errorData++; return false; } int count = (size-4) / 3; Serial.print(F("count=")); Serial.println(count); for (int idx=0; idx < count; idx++){ byte k=s[3 + idx*3]; byte a=s[3 + idx*3+1]; byte b=s[3 + idx*3+2]; String n; float v = 0; Serial.print(F("type=")); Serial.print(k); Serial.print(F(" a=")); Serial.print(a); Serial.print(F(" b=")); Serial.print(b); Serial.print(F(" text=")); String t = ""; String units = ""; char buf[32]; switch (k){ case 0x01: v=0.2*a*b; units=F("rpm"); break; case 0x02: v=a*0.002*b; units=F("%%"); break; case 0x03: v=0.002*a*b; units=F("Deg"); break; case 0x04: v=abs(b-127)*0.01*a; units=F("ATDC"); break; case 0x05: v=a*(b-100)*0.1; units=F("°C");break; case 0x06: v=0.001*a*b; units=F("V");break; case 0x07: v=0.01*a*b; units=F("km/h");break; case 0x08: v=0.1*a*b; units=F(" ");break; case 0x09: v=(b-127)*0.02*a; units=F("Deg");break; case 0x0A: if (b == 0) t=F("COLD"); else t=F("WARM");break; case 0x0B: v=0.0001*a*(b-128)+1; units = F(" ");break; case 0x0C: v=0.001*a*b; units =F("Ohm");break; case 0x0D: v=(b-127)*0.001*a; units =F("mm");break; case 0x0E: v=0.005*a*b; units=F("bar");break; case 0x0F: v=0.01*a*b; units=F("ms");break; case 0x12: v=0.04*a*b; units=F("mbar");break; case 0x13: v=a*b*0.01; units=F("l");break; case 0x14: v=a*(b-128)/128; units=F("%%");break; case 0x15: v=0.001*a*b; units=F("V");break; case 0x16: v=0.001*a*b; units=F("ms");break; case 0x17: v=(b*a)/256; units=F("%%");break; case 0x18: v=0.001*a*b; units=F("A");break; case 0x19: v=(b*1.421)+(a/182); units=F("g/s");break; case 0x1A: v=float(b-a); units=F("C");break; case 0x1B: v=abs(b-128)*0.01*a; units=F("°");break; case 0x1C: v=float(b-a); units=F(" ");break; case 0x1E: v=b/12*a; units=F("Deg k/w");break; case 0x1F: v=b/2560*a; units=F("°C");break; case 0x21: v=100*b/a; units=F("%%");break; case 0x22: v=(b-128)*0.01*a; units=F("kW");break; case 0x23: v=0.01*a*b; units=F("l/h");break; case 0x24: v=((unsigned long)a)*2560+((unsigned long)b)*10; units=F("km");break; case 0x25: v=b; break; // oil pressure ?! // ADP: FIXME! /*case 37: switch(b){ case 0: sprintf(buf, F("ADP OK (%d,%d)"), a,b); t=String(buf); break; case 1: sprintf(buf, F("ADP RUN (%d,%d)"), a,b); t=String(buf); break; case 0x10: sprintf(buf, F("ADP ERR (%d,%d)"), a,b); t=String(buf); break; default: sprintf(buf, F("ADP (%d,%d)"), a,b); t=String(buf); break; }*/ case 0x26: v=(b-128)*0.001*a; units=F("Deg k/w"); break; case 0x27: v=b/256*a; units=F("mg/h"); break; case 0x28: v=b*0.1+(25.5*a)-400; units=F("A"); break; case 0x29: v=b+a*255; units=F("Ah"); break; case 0x2A: v=b*0.1+(25.5*a)-400; units=F("Kw"); break; case 0x2B: v=b*0.1+(25.5*a); units=F("V"); break; case 0x2C: sprintf(buf, "%2d:%2d", a,b); t=String(buf); break; case 0x2D: v=0.1*a*b/100; units=F(" "); break; case 0x2E: v=(a*b-3200)*0.0027; units=F("Deg k/w"); break; case 0x2F: v=(b-128)*a; units=F("ms"); break; case 0x30: v=b+a*255; units=F(" "); break; case 0x31: v=(b/4)*a*0.1; units=F("mg/h"); break; case 0x32: v=(b-128)/(0.01*a); units=F("mbar"); break; case 0x33: v=((b-128)/255)*a; units=F("mg/h"); break; case 0x34: v=b*0.02*a-a; units=F("Nm"); break; case 0x35: v=(b-128)*1.4222+0.006*a; units=F("g/s"); break; case 0x36: v=a*256+b; units=F("count"); break; case 0x37: v=a*b/200; units=F("s"); break; case 0x38: v=a*256+b; units=F("WSC"); break; case 0x39: v=a*256+b+65536; units=F("WSC"); break; case 0x3B: v=(a*256+b)/32768; units=F("g/s"); break; case 0x3C: v=(a*256+b)*0.01; units=F("sec"); break; case 0x3E: v=0.256*a*b; units=F("S"); break; case 0x40: v=float(a+b); units=F("Ohm"); break; case 0x41: v=0.01*a*(b-127); units=F("mm"); break; case 0x42: v=(a*b)/511.12; units=F("V"); break; case 0x43: v=(640*a)+b*2.5; units=F("Deg"); break; case 0x44: v=(256*a+b)/7.365; units=F("deg/s");break; case 0x45: v=(256*a +b)*0.3254; units=F("Bar");break; case 0x46: v=(256*a +b)*0.192; units=F("m/s^2");break; default: sprintf(buf, "%2x, %2x ", a, b); break; } switch (currAddr){ case ADR_Engine: switch(group){ case 3: switch (idx){ case 0: engineSpeed = v; break; case 1: EGR_Consumption_target =v; break; case 2: EGR_Consumption=v; break; case 3: EGR_duty=v; break; } break; case 11: switch (idx){ case 0: engineSpeed = v; break; case 1: TurboPressure_target =v; break; case 2: TurboPressure =v; break; case 3: Turbocharger_valve=v; break; } break; } break; case ADR_Dashboard: switch (group){ case 1: switch (idx){ case 0: vehicleSpeed = v; break; case 1: engineSpeed = v; break; case 2: oilPressure = v; break; } break; case 2: switch (idx){ case 0: odometer = v; break; case 1: fuelLevel = v; break; } break; case 50: switch (idx){ case 1: engineSpeed = v; break; case 2: oilTemp = v; break; case 3: coolantTemp = v; break; } break; } break; } if (units.length() != 0){ dtostrf(v,4, 2, buf); t=String(buf) + " " + units; } Serial.println(t); //lcd.setCursor(0, idx); //while (t.length() < 20) t += " "; //lcd.print(t); } sensorCounter++; return true; } void alarm(){ if (alarmCounter > 10) return; tone(pinBuzzer, 1200); delay(100); noTone(pinBuzzer); alarmCounter++; } void updateDisplay(){ if (!connected){ if ( (errorTimeout != 0) || (errorData != 0) ){ lcdPrint(0,3, F("err to=")); lcdPrint(7,3, String(errorTimeout), 3); lcdPrint(10,3, F(" da=")); lcdPrint(14,3, String(errorData), 6); } } else { switch (currPage){ case 1: if (coolantTemp > 99){ lcdPrint(0,1, F("COOL")); alarm(); } else lcdPrint(0,1, F("cool")); lcdPrint(6,1,String(coolantTemp),3); if ( (oilTemp > 99) || ((oilPressure != 30) && (oilPressure != 31)) ){ lcdPrint(10,1,F("OIL ")); alarm(); } else lcdPrint(10,1,F("oil ")); lcdPrint(14,1,String(oilPressure),3); lcdPrint(0,2, F("rpm ")); lcdPrint(4,2, String(engineSpeed),4); lcdPrint(10,2, F("km/h ")); lcdPrint(15,2, String(vehicleSpeed, 3)); lcdPrint(0,3, F("fuel ")); lcdPrint(5,3, String(fuelLevel),3); lcdPrint(10,3, F("odo ")); lcdPrint(14,3, String(odometer),6); break; case 2: if (coolantTemp > 99){ lcdPrint(0,1, F("COOL")); alarm(); } else lcdPrint(0,1, F("cool")); lcdPrint(6,1,String(coolantTemp),3); lcdPrint(10,1, F("air ")); lcdPrint(14,1, String(intakeAirTemp), 3); lcdPrint(0,2, F("rpm ")); lcdPrint(4,2, String(engineSpeed),4); lcdPrint(10,2, F("km/h ")); lcdPrint(15,2, String(vehicleSpeed, 3)); lcdPrint(0,3, F("fuel ")); lcdPrint(5,3, String(fuelConsumption),3); lcdPrint(10,3, F("volt ")); lcdPrint(15,3, String(supplyVoltage),5); break; } } pageUpdateCounter++; } void setup(){ lcd.init(); lcd.backlight(); lcd.init(); pinMode(pinKLineTX, OUTPUT); digitalWrite(pinKLineTX, HIGH); pinMode(pinButton, INPUT); pinMode(pinButton, INPUT_PULLUP); pinMode(pinBuzzer, OUTPUT); /*tone(pinBuzzer, 1200); delay(100); noTone(pinBuzzer);*/ Serial.begin(19200); Serial.println(F("SETUP")); Serial.println(F("START")); } void loop(){ if (digitalRead(pinButton) == LOW){ currPage++; if (currPage > 2) currPage = 1; lcd.clear(); lcd.setCursor(0,0); lcd.print(F("page ")); lcd.print(currPage); errorTimeout = 0; errorData = 0; while (digitalRead(pinButton) == LOW); } switch (currPage){ case 1: if (currAddr != ADR_Dashboard){ connect(ADR_Dashboard, 9600); } else { readSensors(1); readSensors(2); readSensors(50); } break; case 2: if (currAddr != ADR_Engine) { connect(ADR_Engine, 9600); } else { readSensors(3); readSensors(11); } break; } updateDisplay(); Serial.println(); Serial.print ("engineSpeed: "); Serial.println(engineSpeed); Serial.print ("EGR valve : "); Serial.println(EGR_duty); Serial.print ("EGR rashod "); Serial.println(EGR_Consumption); Serial.print ("EGR rashod zadan: "); Serial.println(EGR_Consumption_target); Serial.print ("Pressure Turbo: "); Serial.println(TurboPressure); Serial.print ("Pressure Turbo zadan: "); Serial.println(TurboPressure_target); Serial.print ("Turbo Actuator: "); Serial.println(Turbocharger_valve); Serial.println(); }ох, проходили мы это всё с опелем
у вас литров /час это мгновенная величина. И поэтому можно рассчитать будет мгновенный расход топлива л/100км. Средний же считается по другому. Делается цикл измерения:
Записывается пробег и остаток топлива, отмеряется определённое расстояние, чем больше тем лучше. Потом литры делятся на пробег и умножаются на 100.
Блоками вы называете разные ЭБУ? Если да, то вы ещё параметры выделяйте которые надо, и обязательно чтобы их ваг ком корректно показывал.
Ваш скетч проверю завтра утром. И сразу отпишусь
На счет блоков. 01- двигатель 17- приборка.
Ну можно с блоком бортовой сети пофантозировать потом ))
и посмотрите какие группы/параметры в панели приборов есть. Может там уже всё готовое присутсвует.
температура движка не сильно нужна, т.к на приборке есть. может потом куда пригодится.
температура масла- нужна обязательна. не нашел где прячется. в нете смотрел 17 блок(прибока)-3(группа)-3окно. но у меня там её нет. поищу потом. Вроде как(17-50-3)
Скорость - как и температура двигателя ))
Напряжение батареи(аккума) 1-16-4
Пробег(может для расчетов, но он есть и у Александа) 17-2-1
Топливо в баке 17-3-1
блок-группа-окно
у него много чего не совпадает по группам/параметрам с вашим авто
в климате или блоке салонной электроники смотрите наружную и салонную температуру
и да, ардуино Мега закажите, если у вас не она, т.к. памяти не хватит, когда дисплей будете добавлять
и да, ардуино Мега закажите, если у вас не она, т.к. памяти не хватит, когда дисплей будете добавлять
Может на этом попробовать ??? только она 3V
https://ru.aliexpress.com/item/V3-Wireless-module-NodeMcu-4M-bytes-Lua-WIFI-Internet-of-Things-development-board-based-ESP8266-esp/32647542733.html?spm=a2g0s.8937460.0.0.Op7KYJ
Меги тоже есть классные
8МБ+WI-FI
https://ru.aliexpress.com/item/Mega-WiFi-R3-ATmega2560-ESP8266-8Mb-memor...
32МБ+Wi-FI
https://ru.aliexpress.com/item/Mega-WiFi-R3-ATmega2560-ESP8266-32Mb-memo...
а кто это всё программировать будет? вы?
ну мегу с вифи можно конечно, может потом разберётесь
дисплей ООчень желательно как в теме про опель. Чтобы основу скетча оттуда взять.
У знакомого одного есть этот NodeMcu. Можно будет взять проэксперементировать. Говорил что c arduino IDE можно подружить. Или это целеком разные платформы ?
Подружить то можно, а вот библиотеки далекооо не все будут поддерживаться. Тот же дисплей подключить. Ну пробуйте если есть где взять.
ответ на 118
ну вот с группами 3 и 11 разобрались - всё заработало. Поправил ещё 118, теперь и расход газов ЕГР будет показывать.
пора бы тему отдельную создать в разделе проекты. В названии указать про бортовой комп VAG. Так, глядишь, и люди проще этот проект будут находить.
А в первом сообщении ссылку на эту тему - типа как всё начиналось.
ЕГР у меня заглушен(механически) по этому могут быть показания в пределах 500.
Дисплей вот такой ???
https://ru.aliexpress.com/item/TFT-3-95-TFT/32851971529.html?ws_ab_test=...
не знаю, тут не видно какие ноги у него. По идее можно любой, но главное, чтобы библиотека была аналогичная, чтобы много не переделывать
У меня есть в наличии вот такие два дисплейчика. Может на них попробовать сразу вывести ??? Может где пересекались с такими.
неа, такие не ковырял. Дак они маленькие скорее всего для БК будут.
Надо будет потом как-нить совместить всё. Я тут раньше прикидывал, что хочу от БК и начал код шкрабать. Надо еще вывести провод от турбинки догревателя, что бы знать крутится она или нет... если крутится то запускать помпу, а потом и печку. Есть идея сделать мигающий стоп-сигнал при экстренном торможении. Некоторые покупают платы с G-сенсором. Я в свое время купил китайский, он просто ставиться перед стоп-сигналом и моргает. А моргает он всегда, что наверное может раздрожать других водителей. Можно попробовать сделать включение его когда сработает ABS и скорость например выше 50 или 60. Только вот как подобрать транзистор((( изначально они по ходу закрыты, а подачей сигнала на их открываются. А тут надо наоборот(простое торможение всегда-открыт, а когда срабатывает ABS - то закрывается).
ну и как работает?
вроде говоря про бортовой комп имеют в виду дорожный комп - расходы, километражи, ну в крайнем случае параметры работы ДВС) А у вас тут все в кучу будет. Сразу вас предупреждаю, что одно может легко мешать работать другому. Такие вещи невозможно нормально сделать с вашим уровнем программирования. Поэтому рекомендую остановится на чем ни будь одном. Я вам скажу просто, хотя бы обороты и т.д. с ЭБУ на экран выведете, а там посмотрим что из этого получится.
Прислушаюсь к Вашим словам. Надо остановиться на чем то одном, лучше на БК. А управление догревателем, потом сделаю. В боевых действиях на тачке не проверял, только на столе. вместо релюшек стоят диоды. С пульта работает, с кнопки тоже работает. НЕ могу проверить в реальных, так как сам догреватель в ошибку уходит, ругается на обороты турбинки. Мож на днях все сделаю потом - проверю
у вас подключается адаптер к подогревателю? например программой Еdyth ? Если да, то также можно поснифить данные с подогревателя, чтобы провод к турбинке не тянуть.
или даже через штатную VAG диагностику должно подключаться
Вот моя запись на Drive2.ru. Мой котел на прямую к диагностике не подключен. Ну а вы гигант мысли, провод то кинут уже. можно и попробовать )))
https://www.drive2.ru/l/489675201085177968/
список параметров в Едите если работает, можно с котла данные повытягивать, в т.ч. и обороты нагнетателя
список параметров в Едите если работает, можно с котла данные повытягивать, в т.ч. и обороты нагнетателя
ТУТ я думаю вы все поймете. Исходники
http://www.carhelp.info/forums/showthread.php?t=92902&page=2&p=870075&vi...
http://www.carhelp.info/forums/showthread.php?t=92902&page=3&p=871100&vi...