В общем, пошел в машину. Беру скеч из 1250. Заливаю. Побежала инфа. Получил 3 сообщения с ОК, остальные CRC FAIL. Ну ок, думаю, играемся с задержками. И тут начинаются чудеса! Поменял в 87 строке задержку на 15 и получил только успешную инициализацию. Т.е.
Дальше какие бы значения не ставил, все оставалось так же. И даже вернувшись на значение 10 - тоже самое. Более того! Загрузил предыдущий скеч, коим я логи то и получил, из поста 1234. И тут опять такая же ерунда, несмотря на все значения, что ставил раньше, т.е. 150 мс. Опытным путем выяснил, что если Ардуину со скетчем из 1234 раза 4-5 сбросить кнопкой, то получим
скорее всего гдето беда с задержками . при рестарте ардуины несколько раз одно накладывается на другое с задержкой - в итоге прокатывает. Нужно попробовать еще в #1250 между 048 и 049 delay поставить например 10мс.
накатал эмулятор панели, но так и не смог добиться отображения текущих данных от проги ОПКОМ. Странно программа себя ведёт. Даже страницы и наименование данных можно листать, а в окошках пусто. Нужно попробовать подсунуть этот эмулятор программе ОПКОМ ориг , а также второму вашему сканеру, может заработает.
Постоянно первые 3 сообщения Ок, потом Фэил. И постоянно после сброса Ардуино он коннектится со второго раза. Может, мы не шлем запрос на закрытие соединения и в первый сброс приборка его закрывает? В любом случае, только три правильных ответа как-то маловато....
Почему три правильных мало? Хватит за глаза - километраж и остаток топлива считать. Нужно заснифить какая команда идет на закрытие диагностической сессии. После двух например правильных ответов закрываем сессию и связываемся с PCM.
понятно только что первый байт после нулей 0х78 (120DEC/10) это напряжение акб. и пятый байт 0х32 (в dec 50) это температуа ДВС. Остальное зашифровано както
Возможно второй байт это напряжение датчика уровня топлива. 0x2С в DEC 44 делим на 10 получаем 4,4 В
Хотя нет, есть трип. В первом случае 03 03 это и есть 771, т.е. без запятой пробег Во втором случае 74 06 это и есть 1652, только байты местами поменяны. 7C FF 24 так же справа на лево это пробег - 2424700
Тут изменилась только температура двигателя. (ну трип и одометр не в счет)
И судя по третьему логу, он где-то в первых трех значащих байтах. Причем, первый байт с наполнением бака уменьшился, что позволяет думать, что это вольты. А второй и третий байт увеличился. Значит это литры. Вот теперь как бы это увязать с формулой. 40,5л =0х51 = 81; 22л = 0х2c = 44
Тьфу млин, да банально на два делить. Дискретность измерения бака 0,5 литра.
Интересный вопрос - где ж он напряжение берет. но в принципе оно нас не интересует, как и скорость.
Уфффф..... Кажись все данные есть. Теперь самое сложное - сам БК написать :)
Скетч из 1272 работает хорошо. Цепляет одно сообщение с CRC Fail, думаю не проблема. Задержку уменьшил до 10 мс, работает. Одометр нужно на 10 делить, отсекая сотые метра. Убрал выбор протокола и адреса, уже ведь не нужны. Глянь, ничего не пропустил?
#include <SoftwareSerial.h>
#define RX_gauge 7
#define TX_gauge 8
SoftwareSerial Gauge_K_line (RX_gauge, TX_gauge);
bool InitGauge = 0; // флаг инита панели
byte EndSession []= {0x02, 0xB2, 0x00, 0xB4};
void setup() {
Serial.begin (9600); //открываем соединение терминала для отладки
pinMode (TX_gauge, OUTPUT);
digitalWrite (TX_gauge, 1); // BUS idle
delay (2000);
// далее посылаем на панель адрес на скорости 5 baud
Serial.print("Delayu zapros na panel. Adress: "); Serial.println("0xE0, 5 baud");
digitalWrite (TX_gauge, 0); delay (5); // старт бит
for(byte i = 0; i<8; i++) {digitalWrite (TX_gauge, bitRead(0xE0,i)); delay(5);}
digitalWrite (TX_gauge, 1); delay (5); // стоп бит
Gauge_K_line.begin(4800); // открываем к-лайн на приборку на 4800
}
byte head_count = 0;
byte head[4] = {0};
void loop() {
while(!InitGauge){
if (Gauge_K_line.available()) {
byte inByte = Gauge_K_line.read();
Serial.print(" ");
Serial.print(inByte,HEX);
if (inByte==0x80) {delay (10); Gauge_K_line.write (0x7F); }
delay (10);
if (inByte==0x78) {
Gauge_K_line.write (0x02); delay (2);
Gauge_K_line.write (0x11); delay (2);
Gauge_K_line.write (byte(0x00)); delay (2);
Gauge_K_line.write (0x13); delay (2); InitGauge=1; Serial.println(" Ura! Panel init proshla uspeshno!"); }}}
if (InitGauge && Gauge_K_line.available()) {
// ниже ищем шапку кадра
byte inbyte = Gauge_K_line.read();
delay (7);
if (inbyte == 0x21 && head_count == 0) {head_count = 1; head[0] = inbyte; }
else if (inbyte == 0xA1 && head_count == 1) {head_count = 2; head[1] = inbyte; }
else if (inbyte == 0x04 && head_count == 2) {head_count = 3; head[2] = inbyte; }
else {head_count = 0; for (byte i=0; i<sizeof(head); i++) head[i] = 0;}
// нашли шапку:
if (head_count == 3){
head_count = 0; // очищаем переменную поиска шапки
byte Length = head[0];
if (Length>100)Length=100;
const byte sizeMes = Length+2;
byte MessageRx [sizeMes] = {0};
uint16_t crc = 0;
for (byte i=0; i<3; i++){MessageRx[i]= head[i]; crc += MessageRx[i]; head[i] = 0; Serial.print (MessageRx[i], HEX); Serial.print (" ");} // очищаем переменные поиска шапки
bool CRC_OK = 0;
// ниже пишем сообщение в буфер и считаем КС
for (byte i = 3; i < sizeMes; i++) { MessageRx[i] = Gauge_K_line.read(); if (i<=sizeMes-3) crc += MessageRx[i]; delay (7); Serial.print (MessageRx[i], HEX); Serial.print (" "); }
int CRC = ( ( unsigned int )MessageRx [sizeMes-2] << 8 ) | MessageRx [sizeMes-1];
if (CRC==crc) CRC_OK = 1;
if (CRC_OK){
Serial.println (" OK!!!");
uint32_t Odometer = ((uint32_t) MessageRx[26] << 16 ) | ((uint32_t) MessageRx[25] << 8 ) | MessageRx[24];
float FuelLevel = MessageRx[21]/2.0 ;
Serial. print ("Odometer: "); Serial. print (Odometer/10); Serial. print (" km, FuelLevel: "); Serial. print (FuelLevel);Serial.println (" l");
for (byte i = 0; i < sizeof (EndSession); i++ ) { Gauge_K_line.write (EndSession [i]); delay (2);}
} // конец ифа с правильной CRC
else Serial.println(" CRC FAIL!!!");
}
}
}
По периодическому обращению (скетч 1273). Если период так и оставить - 1 минута, то ничего вообще не происходит. Думал, он только через минуту обратиться, но нет. А вот если поставить 1/2, то так:
Т.е. не успев закончить получение, опять начинает запрос, ловит пару последних данных с неверным CRC и на этом виснет.
В принципе, я думаю, это периодическое обращение нужно уже в код готового скетча добавлять, чтоб было видно куда и как. Перед этим запросом нужно ж будет закрывать соединение с ЭБУ.
Кстати, нужно проверить как с ЭБУ данные читаться будут.
Пытаюсь что-то накропать сам. К сожалению, и так не программист, а тут чужой код понять нужно. Для начала постарался вырезать все, что касается LCD, чтоб он мне просто пиды в серийник выводил.
#include <SoftwareSerial.h>
SoftwareSerial mySerial (12, 13); //RХ,TХ
#define TX 13
unsigned long TimewaitPID, timerwaitPID = 0;
bool timerenabledPID = 0;
#define TIMEREXPIRED_PID (TimewaitPID - timerwaitPID)> 200 // здесь задержка на ожидание правильного ответа пидов, мс
unsigned long TimewaitInit, timerwaitInit = 0;
bool timerenabledInit = 0;
#define TIMEREXPIRED_Init (TimewaitInit - timerwaitInit)> 500 // здесь задержка на ожидание ответа об удачной инициализации, мс
byte messageInit[5] = {0x81, 0x11, 0xF1, 0x81, 0x04}; // запрос инициализации
byte messagePids[6] = {0x82,0x11,0xF1,0x21,0x01,0xA6}; // запрос пид 2101
byte messagePresent[5] = {0x81,0x11,0xF1,0x3E,0xC1}; // запрос присутствия
unsigned long prevPID = 0;
int PIDTime = 120; // задержка ожидания запроса следующего pid 2101, мс
unsigned long prevpres = 0;
int PresTime = 8000; // задержка между посылками запросов присутствия, мс
int waitbyte = 1; // задержка между отправкой байт в сообщении, мс
byte MessageRx[55] = {0}; // массив байтов принимаемого сообщения
bool Init = 0;
int MAP = 0; //13 байт Датчик абсолютного давления
float SysVolt = 0; //14 байт Напряжение в сети
int TempAir = 0; //16 байт Температура воздуха в градусах
int Temp = 0; //18 байт Температура охлаждающей жидкости в градусах
int EngLoad = 0; //20 байы нагрузка на двигатель
int Throtle = 0; //28 байт Открытие дроссельной заслонки в процентах
int RPM = 0; //30 байт Оборогты двигателя
int Speed = 0; //29 байт Скорость
float InjPulse = 0; //31 байт Время впрыска форсунок
int IdleAir = 0; //32 байт Клапан холостого хода, шаги
float O2sens = 0; //35 байт Лямбда мВ
float O2int = 0; //36 байт Интегратор лямда, шагов
float FuelRatio = 0; //41 байт Соотношение воздуха/топлива
int STFT = 0; // Краткосрочная коррекция топлива
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//стартовая инициализация 7 пина ОБД
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void fastinit() {
digitalWrite (TX, HIGH); // makes K-line high 3
delay(360); // wait for K-line to be clear 3
digitalWrite (TX, LOW); // makes K-line low 3
delay(25);
digitalWrite (TX, HIGH); // makes K-line high 3
delay(25); //last delay before first message
mySerial.begin(10400); } // baud rate of the OBD
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//отправка запроса на диагностическое соединение
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void initialization() {
Serial.println ("Otpravil zapros Init");
for (int i = 0; i < 5; i++) {
mySerial.write(messageInit[i]);
delay (5); }
delay (55); }
///////////////////////////////////////////////////////////////////////////
//VOID PIDs// отправка запроса пид 2101////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
void PIDs() {
Serial.println ("Otpravil zapros 21 01");
for (int i = 0; i < 6; i++) {
mySerial.write(messagePids[i]);
delay (waitbyte); }}
///////////////////////////////////////////////////////////////////////////
//BOID PIDsGAUGR//отправка запроса присутствия/////////////////////////////
///////////////////////////////////////////////////////////////////////////
void present() {
Serial.println ("Otpravil zapros Present");
for (int i = 0; i < 55; i++) {
mySerial.write(messagePresent[i]);
delay (waitbyte); }}
/////////////////////////////////////////////////////////////////////////////////////////////
//получение данных от ЭБУ, разборка входящих сообщений
/////////////////////////////////////////////////////////////////////////////////////////////
void receive () {
////////////////////////////////////////////////////////////////////
////////////////// работа с К-Line софт сериал 12-13 (7 контакт ОБД)
////////////////////////////////////////////////////////////////////
if (mySerial.available()) {
delay(195);
int k=0;
byte inbyte=0;
while( mySerial.available() && k < 55) {
inbyte = mySerial.read();
MessageRx[k] = inbyte;
k++; }
Serial.print ("Receive: ");
for (int i = 0; i < k; i++) {
Serial.print(MessageRx[i],HEX); Serial.print (" ");}
Serial.println ("");
if (MessageRx[2]==0x83 && MessageRx[3]==0xF1 && MessageRx[4]==0x11 && MessageRx[5]==0xC1 && MessageRx[6]==0x6B && MessageRx[7]==0x8F && MessageRx[8]==0x40) {Init=1;
timerenabledInit=0;
Serial.println (" Initialization OK!!!!: "); }
///////////////////////////////////////////////////////////////////////////////////////////////////
//Чтение и стирание ошибок
///////////////////////////////////////////////////////////////////////////////////////////////////
//при получении этого сообщения выдавать на третий экран "NO ERROR"
if (MessageRx[4]==0x82 && MessageRx[5]==0xF1 && MessageRx[6]==0x11 && MessageRx[7]==0x58 && MessageRx[8]==0x00 && MessageRx[9]==0xDC){
Serial.println (" NO DTC "); }
//при получении этого сообщения выдавать на третий экран "CLEAR DTC"
if (MessageRx[3]==0x83 && MessageRx[4]==0xF1 && MessageRx[5]==0x11 && MessageRx[6]==0x54 && MessageRx[7]==0xFF && MessageRx[8]==0x00 && MessageRx[9]==0xD8){
Serial.println (" DTC CLEARED "); }
// при получении сообщения о наличии ошибок DTC разберем сообщение выведем на экран ошибки
if (MessageRx[5]==0xF1 && MessageRx[6]==0x11 && MessageRx[7]==0x58 && MessageRx[8]>0){
Serial.println ("DTC is found!");
for (int i=0; i<MessageRx[8]; i++ ) {
int y = i*35;
bool nolA=0; bool nolB =0;
if (!bitRead(MessageRx[11+(i*3)],6) && bitRead(MessageRx[11+(i*3)],7)){
Serial.println(" -Passive-");} // если DTC пасивныый делаем цвет зеленый
if (bitRead(MessageRx[11+(i*3)],7) && bitRead(MessageRx[11+(i*3)],6)) {
Serial.println(" -Active-");} // если DTC активный, делаем цвет красный
Serial.println("ERROR ");
Serial.println(i+1);
if (!bitRead(MessageRx[9+(i*3)],6) && !bitRead(MessageRx[9+(i*3)],7)) Serial.println(": P");
if (bitRead(MessageRx[9+(i*3)],6) && !bitRead(MessageRx[9+(i*3)],7)) Serial.println(": C");
if (!bitRead(MessageRx[9+(i*3)],6) && bitRead(MessageRx[9+(i*3)],7)) Serial.println(": B");
if (bitRead(MessageRx[9+(i*3)],6) && bitRead(MessageRx[9+(i*3)],7)) Serial.println(": U");
}}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//прописываем формулы к данным ///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
else if (MessageRx[4]==0xB0 && MessageRx[5]==0xF1 && MessageRx[6]==0x11 && MessageRx[7]==0x61 && MessageRx[8]==0x01) {
MAP = (MessageRx[16]*4,97/255); //13 байт Датчик абсолютного давления
SysVolt = (MessageRx[17]/10); //14 байт Напряжение в сети
TempAir = ((MessageRx[19]*191/255)-40); //16 байт Температура воздуха в градусах
Temp = ((MessageRx[21]*191/255)-40); //18 байт Температура охлаждающей жидкости в градусах
EngLoad = (MessageRx[23]*100/255); //20 байы нагрузка на двигатель
Throtle = (MessageRx[31]*100/255); //28 байт Открытие дроссельной заслонки в процентах
RPM = (MessageRx[33]*6375/255); //30 байт Оборогты двигателя
Speed = (MessageRx[32]); //29 байт Скорость
InjPulse = (MessageRx[34]*21,8/255); //31 байт Время впрыска форсунок
IdleAir = (MessageRx[35]); //32 байт Клапан холостого хода, шаги
O2sens = (MessageRx[38]*1127/255); //35 байт Лямбда мВ
O2int = (MessageRx[39]); //36 байт Интегратор лямда, шагов
FuelRatio = (MessageRx[44]/10); //41 байт Соотношение воздуха/топлива
int STFT = (MessageRx[39]*100/128); // Краткосрочная коррекция топлива
Serial.print("MAP=");Serial.print(MAP);Serial.print(" Battery=");Serial.print(SysVolt);
Serial.print(" Air=");Serial.print(TempAir);Serial.print(" Temp=");Serial.print(Temp);
Serial.print(" EngLoad=");Serial.print(EngLoad);Serial.print(" Throtle=");Serial.print(Throtle);
Serial.print(" RPM=");Serial.print(RPM); Serial.print(" Speed=");Serial.print(Speed);
Serial.print(" Inj=");Serial.print(InjPulse);Serial.print(" IdleAir=");Serial.print(IdleAir);
Serial.print(" O2sens=");Serial.print(O2sens);Serial.print(" O2int=");Serial.print(O2int);
Serial.print(" FuelRatio=");Serial.print(FuelRatio);Serial.print(" STFT=");Serial.print(STFT);
timerenabledPID=0; }
for (int i = 0; i < 55; i++) MessageRx[i]=0; }} // очистка байтов массива
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SETUP
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
Serial.begin(115200);
mySerial.begin(10400);
pinMode(TX, OUTPUT);
fastinit();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//loop
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
TimewaitPID = millis ();
TimewaitInit = millis ();
if (!Init) { if (!timerenabledInit){ timerwaitInit=TimewaitInit; timerenabledInit=1; initialization(); }
else if (TIMEREXPIRED_Init) timerenabledInit=0;}
if (millis() - prevPID > PIDTime) { PIDs(); prevPID = millis(); }
else if (millis() - prevpres > PresTime) {present(); prevpres = millis();}
receive ();
}
И каким-то чудом один раз все же мне выдало показания, но часть из них почему-то неверны. Я бы понял, если б все, но тут только часть. Вот этого вообще не могу понять. Например температура двигателя почему -162 ? По формуле она максимум -40 может быть. Из-за неверного типа переменных такое возможно?
Скобки.... Либо их где-то не хватает, либо они не там, где надо.... Если скобка стоит после GAUGE_SESSION (); , то prevgauge на каждом цикле равен millis :)
#define BAUD_200 0
#define BAUD_5 1
bool Protocol = BAUD_5; // тут выбираем протокол 200 baud или 5 baud
byte GAUGE_ADDRESS = 0xE0; // тут выбираем адрес панели. Возможные варианты 0xE0, 0xE1, 0xB8, 0XB9, 0xBA
uint32_t Odometer = 0;
float FuelLevel = 0,0;
byte interval_gaugesession = 1; // периодичность опроса щитка приборов, мин
uint32_t prevgauge = 0;
byte GAUGE_EndSession []= {0x02, 0xB2, 0x00, 0xB4};
byte GAUGE_DataRequest []= {0x02, 0x11, 0x00, 0x13};
int bit_time = 0;
#include <SoftwareSerial.h>
#define RX_gauge 7
#define TX_gauge 8
SoftwareSerial Gauge_K_line (RX_gauge, TX_gauge);
bool InitGauge = 0; // флаг инита панели
void setup() {
Serial.begin (9600); //открываем соединение терминала для отладки
}
byte head_count = 0;
byte head[4] = {0};
void loop() {
if (millis() - prevgauge > (uint32_t)interval_gaugesession*60000UL){
ZAPROS_GAUGE ();
GAUGE_SESSION ();
prevgauge = millis();
}
}
void ZAPROS_GAUGE () {
pinMode (TX_gauge, OUTPUT);
digitalWrite (TX_gauge, 1); // BUS idle
delay (250);
// далее посылаем на панель адрес на скорости 5 baud или 200 baud
Serial.print("Delayu zapros na panel. Adress: "); Serial.println(GAUGE_ADDRESS, HEX);
if (Protocol) {bit_time = 200; Serial.println("5 baud Init"); }
else {bit_time = 5; Serial.println("200 baud Init"); }
digitalWrite (TX_gauge, 0); delay (bit_time); // старт бит
for(byte i = 0; i<8; i++) {digitalWrite (TX_gauge, bitRead(GAUGE_ADDRESS,i)); delay(bit_time);}
digitalWrite (TX_gauge, 1); delay (bit_time); // стоп бит
Gauge_K_line.begin(4800); // открываем к-лайн на приборку на 4800
}
void GAUGE_SESSION (){
while (1) {
while(!InitGauge){
if (Gauge_K_line.available()) {
byte inByte = Gauge_K_line.read();
Serial.print(" ");
Serial.print(inByte,HEX);
if (inByte==0x80) {delay (150); Gauge_K_line.write (0x7F); }
if (inByte==0x78) {
delay (10);
for (byte i=0; i < sizeof (GAUGE_DataRequest); i++) {Gauge_K_line.write (GAUGE_DataRequest[i]); delay (2);}
InitGauge=1; Serial.println(" Ura! Panel init proshla uspeshno!"); }}}
if (InitGauge && Gauge_K_line.available()) {
// ниже ищем шапку кадра
byte inbyte = Gauge_K_line.read();
delay (7);
if (inbyte == 0x21 && head_count == 0) {head_count = 1; head[0] = inbyte; }
else if (inbyte == 0xA1 && head_count == 1) {head_count = 2; head[1] = inbyte; }
else if (inbyte == 0x04 && head_count == 2) {head_count = 3; head[2] = inbyte; }
else {head_count = 0; for (byte i=0; i<sizeof(head); i++) head[i] = 0;}
// нашли шапку:
if (head_count == 3){
head_count = 0; // очищаем переменную поиска шапки
byte Length = head[0];
if (Length>100)Length=100;
const byte sizeMes = Length+2;
byte MessageRx [sizeMes] = {0};
uint16_t crc = 0;
for (byte i=0; i<3; i++){MessageRx[i]= head[i]; crc += MessageRx[i]; head[i] = 0; Serial.print (MessageRx[i], HEX); Serial.print (" ");} // очищаем переменные поиска шапки
bool CRC_OK = 0;
// ниже пишем сообщение в буфер и считаем КС
for (byte i = 3; i < sizeMes; i++) { MessageRx[i] = Gauge_K_line.read(); if (i<=sizeMes-3) crc += MessageRx[i]; delay (7); Serial.print (MessageRx[i], HEX); Serial.print (" "); }
// Serial.println();
int CRC = ( ( unsigned int )MessageRx [sizeMes-2] << 8 ) | MessageRx [sizeMes-1];
if (CRC==crc) CRC_OK = 1;
if (CRC_OK){
Serial.println (" OK!!!");
Odometer = ((uint32_t) MessageRx[26] << 16 ) | ((uint32_t) MessageRx[25] << 8 ) | MessageRx[24]; Odometer/=10;
FuelLevel = MessageRx[21]/2.0 ;
Serial. print ("Odometer: "); Serial. print (Odometer); Serial. print (" km, FuelLevel: "); Serial. print (FuelLevel);Serial.println (" l");
for (byte i = 0; i < sizeof (GAUGE_EndSession); i++ ) { Gauge_K_line.write (GAUGE_EndSession [i]); delay (2);}
break;
} // конец ифа с правильной CRC
else Serial.println(" CRC FAIL!!!");
}
}
}
}
Для пробы уменьшил интервал до 10 секунд. Так вот, первый запрос проходит хорошо и данные получает. А вот второй, через десять секунд, получает два сообщения CRC Fail и программа дальше никуда уже не двигается. Кажись, что-то не то шлем на закрытие соединения.....
После инициализации, мы ждем байта 0х80 и шлем 0x7F. Затем ищем 0x78 и сразу шлем запрос пидов. Но ведь IDEN от приборки приходит два раза. Может второй раз нужно подождать ответ...
Потом Опель-сканер отправляет 02 B0 00 B2 и получает дважды ответ (присутствия?) 06 F0 AA 10 32 10 01 F2.... И только потом уже шлет запрос на пиды 02 11 00 13.... Не кроется ли тут причина остальных неверных сообщений?
При прекращении запросов пид он шлет 02 B2 00 B4, но в ответ получает еще один отзыв присутствия. Вот интересно как же он все-таки закрывает соединение? Нет ли в описании протокола каких-то подсказок, типа как с инициализацией на 5 бод?
Ок, завтра запроверю че покажет. Пару вопросов, так сказать для общего развития.
MAP = ((uint16_t)buf[12]*100/255); //13 байт Датчик абсолютного давления
Для чего uint16_t? Это ж, если я правильно понимаю, объявление длины переменной в 16 бит.... Просто до этого было вообще MessageRx[16] и усе. И вкладывалось значение в ранее объявленную переменную float MAP = 0; (кстати МАП с точкой, потому с float)
И второй вопросик, я то ориентировался по снифу, где в логе
первые 3 байта - FF, потому вместо 13 байта брал 16. А тут в скейче наоборот, сдвинуто все в лево на один. Ну, хочется понять. Может повтыкаю в код хорошо, да дойдет.... как до жирафа
Почему формулы корявые? Я проверял на эмуляторе, все сошлось отлично.
Для чего uint16_t? Это ж, если я правильно понимаю, объявление длины переменной в 16 бит.... Просто до этого было вообще MessageRx[16] и усе. И вкладывалось значение в ранее объявленную переменную float MAP = 0; (кстати МАП с точкой, потому с float)
когда пишем формулу, то в ней нужно приводить все переменные к одному типу. например MessageRx[16] это тип byte у которого диапазон от 0 до 255. и если его умножить на 100, например, он выйдет за пределы и возможна ошибка в формуле, поэтому я на всякий привел к двухбатовому числу. числовые константы, на сколько знаю, имеют тип int , поэтому их тоже нужно переводить соответвующе.
Targitai пишет:
И второй вопросик, я то ориентировался по снифу, где в логе .......первые 3 байта - FF, потому вместо 13 байта брал 16. А тут в скейче наоборот, сдвинуто все в лево на один. Ну, хочется понять. Может повтыкаю в код хорошо, да дойдет.... как до жирафа
FF пробегали потому что мы с ТС очень корявый вариант разбора входящих сообщений сделали. delay там используется. По факту на шине FF скорее всего не пробегают. Щас опыта прибавилось немного. Поэтому пробуем по правильному принимать, без лишних байт. все как положено с Checksum. А влево сдвинуто на один, т.к номера байт в программировании с нулевого начинаются. а в описании разбайтовки мы написали, начиная с первого.
Так и я по эмулятору. 13 байт ставим равным 0, минимальное значение МАП = 0 Бар, ставим равным 255 - максимальное - 1,04 бар. Вот и получается X*1.04/255=Bar
С остальными параметрами так же. Например, обороты двигателя при 0х00 = 0, а при 0хFF = 6375. Вот и получается X*6375/255
Почему у тебя 245?
У меня формулы вида X*100/255 - выдают проценты. Типа нагрузка на двигатель или процент открытия дроссельной заслонки.
Ладно, собственно, чего думать, пойти и проверить :)
постоянно шлёт инит, т.к. после отправки запроса инита не получаем правильного сообщения от PCM. А это, в свою очередь, происходит из-за того, что keyword при разборе входящего сообщения перепутали.
исправил данный косяк в #1282
ну а скобки ты конечно убрал... Это похоже как студенты на лабораторных работах измерения под результат подгоняют....
Скобки.... Либо их где-то не хватает, либо они не там, где надо.... Если скобка стоит после GAUGE_SESSION (); , то prevgauge на каждом цикле равен millis :)
Для пробы уменьшил интервал до 10 секунд. Так вот, первый запрос проходит хорошо и данные получает. А вот второй, через десять секунд, получает два сообщения CRC Fail и программа дальше никуда уже не двигается. Кажись, что-то не то шлем на закрытие соединения.....
Всё там нормально со скобками. prevgauge присваивается значение millis не каждый проход луп, а только когда выполняется условие if a.
вот сделал интервал можно изменять в секундах, добавил двойное ожидание идентов от панели.
#define BAUD_200 0
#define BAUD_5 1
bool Protocol = BAUD_5; // тут выбираем протокол 200 baud или 5 baud
byte GAUGE_ADDRESS = 0xE0; // тут выбираем адрес панели. Возможные варианты 0xE0, 0xE1, 0xB8, 0XB9, 0xBA
uint32_t Odometer = 0;
float FuelLevel = 0;
byte interval_gaugesession = 10; // периодичность опроса щитка приборов, сек
uint32_t prevgauge = 0-(interval_gaugesession*1000UL);
uint32_t prevsec=0;
byte GAUGE_EndSession []= {0x02, 0xB2, 0x00, 0xB4};
byte GAUGE_DataRequest []= {0x02, 0x11, 0x00, 0x13};
int bit_time = 0;
#include <SoftwareSerial.h>
#define RX_gauge 7
#define TX_gauge 8
SoftwareSerial Gauge_K_line (RX_gauge, TX_gauge);
byte InitGauge = 0; // флаг инита панели
void setup() {
Serial.begin (9600); //открываем соединение терминала для отладки
delay(10);
}
byte head_count = 0;
byte head[4] = {0};
void loop() {
if (millis()-prevsec>1000){ Serial.println ((millis()-prevgauge)/1000+1); prevsec = millis();}
if (millis() - prevgauge > (uint32_t)interval_gaugesession*1000UL){
Serial.println ("Prohod cylce loop"); Serial.println(); // для контроля как часто пробегает цикл луп
ZAPROS_GAUGE ();
GAUGE_SESSION ();
prevgauge = millis();
}
}
void ZAPROS_GAUGE () {
pinMode (TX_gauge, OUTPUT);
digitalWrite (TX_gauge, 1); // BUS idle
delay (250);
// далее посылаем на панель адрес на скорости 5 baud или 200 baud
Serial.print("Delayu zapros na panel. Adress: "); Serial.println(GAUGE_ADDRESS, HEX);
if (Protocol) {bit_time = 200; Serial.println("5 baud Init"); }
else {bit_time = 5; Serial.println("200 baud Init"); }
digitalWrite (TX_gauge, 0); delay (bit_time); // старт бит
for(byte i = 0; i<8; i++) {digitalWrite (TX_gauge, bitRead(GAUGE_ADDRESS,i)); delay(bit_time);}
digitalWrite (TX_gauge, 1); delay (bit_time); // стоп бит
Gauge_K_line.begin(4800); // открываем к-лайн на приборку на 4800
}
void GAUGE_SESSION (){
Serial.println ("function Gauge Session");
uint16_t p = 0;
while (p<2000) {
uint16_t v = 0;
while(InitGauge<2 && v<2000){
if (Gauge_K_line.available()) {
byte inByte = Gauge_K_line.read();
Serial.print(" ");
Serial.print(inByte,HEX);
if (inByte==0x80) {delay (10); Gauge_K_line.write (0x7F); }
if (inByte==0x78) {
delay (10);
for (byte i=0; i < sizeof (GAUGE_DataRequest); i++) {Gauge_K_line.write (GAUGE_DataRequest[i]); delay (2);}
InitGauge++; Serial.print(" Receive Panel ID "); Serial.println (InitGauge);}}v++;}
if (InitGauge && Gauge_K_line.available()) {
// ниже ищем шапку кадра
byte inbyte = Gauge_K_line.read();
delay (7);
if (inbyte == 0x21 && head_count == 0) {head_count = 1; head[0] = inbyte; }
else if (inbyte == 0xA1 && head_count == 1) {head_count = 2; head[1] = inbyte; }
else if (inbyte == 0x04 && head_count == 2) {head_count = 3; head[2] = inbyte; }
else {head_count = 0; for (byte i=0; i<sizeof(head); i++) head[i] = 0;}
// нашли шапку:
if (head_count == 3){
head_count = 0; // очищаем переменную поиска шапки
byte Length = head[0];
if (Length>100)Length=100;
const byte sizeMes = Length+2;
byte MessageRx [sizeMes] = {0};
uint16_t crc = 0;
for (byte i=0; i<3; i++){MessageRx[i]= head[i]; crc += MessageRx[i]; head[i] = 0; Serial.print (MessageRx[i], HEX); Serial.print (" ");} // очищаем переменные поиска шапки
bool CRC_OK = 0;
// ниже пишем сообщение в буфер и считаем КС
for (byte i = 3; i < sizeMes; i++) { MessageRx[i] = Gauge_K_line.read(); if (i<=sizeMes-3) crc += MessageRx[i]; delay (7); Serial.print (MessageRx[i], HEX); Serial.print (" "); }
// Serial.println();
int CRC = ( ( unsigned int )MessageRx [sizeMes-2] << 8 ) | MessageRx [sizeMes-1];
if (CRC==crc) CRC_OK = 1;
if (CRC_OK){
Serial.println (" OK!!!");
Odometer = ((uint32_t) MessageRx[26] << 16 ) | ((uint32_t) MessageRx[25] << 8 ) | MessageRx[24]; Odometer/=10;
FuelLevel = MessageRx[21]/2.0 ;
Serial. print ("Odometer: "); Serial. print (Odometer); Serial. print (" km, FuelLevel: "); Serial. print (FuelLevel);Serial.println (" l");
for (byte i = 0; i < sizeof (GAUGE_EndSession); i++ ) { Gauge_K_line.write (GAUGE_EndSession [i]); delay (2);}
break;
} // конец ифа с правильной CRC
else Serial.println(" CRC FAIL!!!");
}
}
p++;
}
Serial.println("Gauge_session is end");
}
Лог РСМ с моей формулой МАП, т.е. Х*1,04/255, а так же поправил формулу для коррекции, не верно ее написал. Вот так надо: int STFT = (((uint16_t)buf[35]-128)*100/128);
Initialization OK!!!!:
Otpravil zapros 21 01
B0 F1 11 61 1 1 1 70 22 0 0 0 4B 8B 4E 64 6B AB 86 17 34 A 1 0 0 0 1E 0 0 22 25 1B C 44 47 80 12 6F 0 0 92 0 0 4 CC A 7 34 0 0 0 E1
Received message is OK!
Receive DATA
MAP=0.32 Battery=13.90 Air=34 Temp=88 EngLoad=9 Throtle=0 RPM=850 Speed=0 Inj=3.16 IdleAir=27 O2sens=313 O2int=128 FuelRatio=14.60 STFT=0
Otpravil zapros 21 01
B0 F1 11 61 1 1 1 70 22 0 0 0 4B 8B 4E 64 6B AB 86 17 34 A 1 0 0 0 1E 0 0 22 25 1B C 44 47 80 12 6F 0 0 92 0 0 4 CC A 7 34 0 0 0 E1
Received message is OK!
Receive DATA
MAP=0.32 Battery=13.90 Air=34 Temp=88 EngLoad=9 Throtle=0 RPM=850 Speed=0 Inj=3.16 IdleAir=27 O2sens=313 O2int=128 FuelRatio=14.60 STFT=0
Otpravil zapros 21 01
B0 F1 11 61 1 1 1 70 22 0 0 0 4A 8B 4E 64 6B AB 82 17 34 A 1 0 0 0 1E 0 0 23 24 1B C 44 47 80 12 6F 0 0 92 0 0 4 CC A 7 34 0 0 0 DC
Received message is OK!
Все показывает отлично. Осталось с ошибками разобраться как глядеть/расшифорвывать и стирать. Прикрутить кнопку к Дуне для перехода в режим ошибок и стирания?
А вот с приборкой так происходит:
После включения идет до:
Prohod cylce loop
Delayu zapros na panel. Adress: E0
5 baud Init
function Gauge Session
да, твоя правда, почему то не заметил сразу. Смотри ка по панели , ведь после первого идента начинает нормально сыпать сообщениями с данными. поправлю позже код может, нормально заработает
добавил в #1282 округление температур, теперь температуры достоверно показывают. И формулу MAP как у тебя сделал. Не понятно почему в твоём логе показывает мап 0.32 когда должно по эмулю 0,31. С моей формулой как положено 0,31 показывает.
- в разбор входящих сообщений дополнительный байт длины при его наличии
- чтение ошибок - короткое нажатие на кнопку (подключена пин 4)
- удаление ошибок - длительное нажатие на кнопку (подключена пин 4)
Логика такая - коротко нажимаем на кнопку - запросы 2101 перестают подаваться, а подаются запросы чтения ошибок, пока не получим ответ с ошибками, если ответ получили - далее опять долбим запросами 2101
длительно нажимаем на кнопку - запросы 2101 перестают подаваться, а подаются запросы удаления ошибок, пока не получим отчёт что DTC удалены , если отчёт получили - далее опять долбим запросами 2101
Ну может быть, спорить не буду :) Часы делал без нее.
В общем, отлично все работает, читает и сбрасывает ошибки. Правда, как отличить присутсвует или просто в памяти? Иногда проскакивают какие-то длинные сообщения, но на работу не влияют, да и редко.
Received message is OK!
Receive DATA
MAP=1.02 Battery=12.10 Air=15 Temp=93 EngLoad=7 Throtle=0 RPM=0 Speed=0 Inj=12.14 IdleAir=39 O2sens=83 O2int=128 FuelRatio=12.60 STFT=0
Otpravil zapros DTC read
85 F1 11 58 1 1 70 22 73
Received message is OK!
DTC is found!
ERROR 1: P0170
B0 F1 11 61 1 1 1 70 22 0 0 0 FA 79 85 4A 62 B1 8A 12 34 0 0 0 0 0 1E 0 0 0 8E 27 0 0 13 80 12 71 0 FF 7E 0 0 0 84 8 27 34 0 0 0 1A
Received message is OK!
Receive DATA
MAP=1.02 Battery=12.10 Air=15 Temp=93 EngLoad=7 Throtle=0 RPM=0 Speed=0 Inj=12.14 IdleAir=39 O2sens=83 O2int=128 FuelRatio=12.60 STFT=0
B0 F1 11 FA 85 B1 8A 12 8E 27 80 12 84 8 B0 F1 11 FA 85 4A B1 8A 8E 27 80 12 84 B0 F1 11 FA 79 85 4A B1 8A 8E 80 84 B0 F1 11 61 1 1 1 70 22 0 0 0 FA 79 84 4A 62 B1 8A 12 34 0 0 0 0 0 1E 0 0 0 8E 27 0 0 13 80 12 71 0 FF 7E 0 0 0 84 8 27 34 0 0 0 19
Received message is OK!
Receive DATA
MAP=1.02 Battery=12.10 Air=15 Temp=93 EngLoad=7 Throtle=0 RPM=0 Speed=0 Inj=12.14 IdleAir=39 O2sens=83 O2int=128 FuelRatio=12.60 STFT=0
.....
Otpravil zapros DTC clear
83 F1 11 54 FF 0 D8
Received message is OK!
DTC CLEARED
B0 F1 11 61 1 0 0 0 0 0 0 0 FA 79 7E 4D 62 B1 8A 12 34 0 0 0 0 0 1E 0 0 0 8D 27 0 0 1A 80 12 71 0 FF 7E 0 0 0 84 8 27 34 0 0 0 88
Received message is OK!
Receive DATA
MAP=1.02 Battery=12.10 Air=18 Temp=93 EngLoad=7 Throtle=0 RPM=0 Speed=0 Inj=12.05 IdleAir=39 O2sens=114 O2int=128 FuelRatio=12.60 STFT=0
......
Received message is OK!
Receive DATA
MAP=1.02 Battery=12.10 Air=18 Temp=93 EngLoad=7 Throtle=0 RPM=0 Speed=0 Inj=12.05 IdleAir=39 O2sens=128 O2int=128 FuelRatio=12.60 STFT=0
B0 F1 11 61 1 0 0 0 0 0 0 0 FA 79 7C 4E 62 B1 8A 12 34 0 0 0 0 0 1E 0 0 0 8D 27 0 0 1D 80 0 0 8 0 8A FF FF FF B0 F1 11 61 1 0 0 0
CRC fail!!!
FA 79 B1 8A 8D 27 80 12 84 8 8A Otpravil zapros DTC read
82 F1 11 58 0 DC
Received message is OK!
NO DTC
B0 F1 11 FA B1 8A 8D 27 80 12 84 8 8A B0 F1 11 FA B1 8A 8D 27 80 12 84 8A B0 F1 11 FA 79 B1 8A 8D 27 80 84 8A FF B0 F1 11 61 1 0 0 0 0 0 0 0 FA 79 7C 4E 62 B1 8A 12 34 0 0 0 0 0 1E 0 0 0 8D 27 0 0 1D 80 12 71 0 FF 7E 0 0 0 84 8 27 34 0 0 0 8A
Received message is OK!
В конечном скече нужно будет делать проверку и fastinit(); повторять если, например, после пяти секунд отправки запроса Init ничего не меняется. Мало ли из-за чего связь прервется. Сейчас, например, если включить Дуню, а потом зажигание, то ничего не добьешья.
Осталось приборку доломать :)
НО! Пушной зверек подкрался незаметно. Попробовал выводить на экран. Скеч компилируется, но изображения нет. Как я понял, библиотека TV-out жестко завязана на прерывания, а у нас их вагон с тележкой. Блин, и ведь убил пару дней пока нашел рабочий вариант библиотеки под последний IDE.... Вот что теперь делать не представляю. Отказываться от аналогово вывода очень не хочется, т.к. потеряю камеру. Да и смысл тогда огород городить - есть стандартный MID. не такой функциональный, но все же.... Ставить вторую Дуню чисто для вывода на экран и слать ей готовые данные? Блин, сразу бы Нано заказал....
Стою на асфальте..... и чет меня прет...
В общем, пошел в машину. Беру скеч из 1250. Заливаю. Побежала инфа. Получил 3 сообщения с ОК, остальные CRC FAIL. Ну ок, думаю, играемся с задержками. И тут начинаются чудеса! Поменял в 87 строке задержку на 15 и получил только успешную инициализацию. Т.е.
Дальше какие бы значения не ставил, все оставалось так же. И даже вернувшись на значение 10 - тоже самое. Более того! Загрузил предыдущий скеч, коим я логи то и получил, из поста 1234. И тут опять такая же ерунда, несмотря на все значения, что ставил раньше, т.е. 150 мс. Опытным путем выяснил, что если Ардуину со скетчем из 1234 раза 4-5 сбросить кнопкой, то получим
А вот если загрузить скетч 1250, то хоть сколько сбрасывай кнопкой, а заветной информации больше не появляется.
Глюки приборки??? Или влияние разряда ноутбука (Ардуина от него питается по шнурку)? Хотя какая там просадка то по USB может быть...
скорее всего гдето беда с задержками . при рестарте ардуины несколько раз одно накладывается на другое с задержкой - в итоге прокатывает. Нужно попробовать еще в #1250 между 048 и 049 delay поставить например 10мс.
накатал эмулятор панели, но так и не смог добиться отображения текущих данных от проги ОПКОМ. Странно программа себя ведёт. Даже страницы и наименование данных можно листать, а в окошках пусто. Нужно попробовать подсунуть этот эмулятор программе ОПКОМ ориг , а также второму вашему сканеру, может заработает.
Помгла задержка 10 им между 48 и 49. Теперь так:
Постоянно первые 3 сообщения Ок, потом Фэил. И постоянно после сброса Ардуино он коннектится со второго раза. Может, мы не шлем запрос на закрытие соединения и в первый сброс приборка его закрывает? В любом случае, только три правильных ответа как-то маловато....
Оп-ком с эмулятором выдает всего лишь так:
Опель-сканер то же выдает.
Почему три правильных мало? Хватит за глаза - километраж и остаток топлива считать. Нужно заснифить какая команда идет на закрытие диагностической сессии. После двух например правильных ответов закрываем сессию и связываемся с PCM.
А как километраж тогда считать? По миллис?
В любой случае, эмулятор пока ниале, а без него где там что не понятно.
Пойду попробую увидеть комманду на закрытие. Блин, плохо что ноут всего час работает. Батарея.... :(
Раз в минуту будет к панели цепляться
Без эмуля можно цепануть ардуину и смотреть. Поехал, смотришь что меняется. Заправляешься - смотришь что меняется и т.д.
Сниф Опель-сканер. Машина не заведена. Показания такие:
02 B2 00 B4 - получается на прекращение передачи?
понятно только что первый байт после нулей 0х78 (120DEC/10) это напряжение акб. и пятый байт 0х32 (в dec 50) это температуа ДВС. Остальное зашифровано както
Возможно второй байт это напряжение датчика уровня топлива. 0x2С в DEC 44 делим на 10 получаем 4,4 В
нужно было сбросить trip пробег и опять засниффить
Кажется только температуру и расшифровали :)
Хотя нет, есть трип. В первом случае 03 03 это и есть 771, т.е. без запятой пробег Во втором случае 74 06 это и есть 1652, только байты местами поменяны. 7C FF 24 так же справа на лево это пробег - 2424700
перейду на ты. Видишь, как полезно статистику собрать, сразу все понятно стало.
осталось купить канистру с бензином.... ))
нет, не облить и поджечь,
а снять сниф, залить и ещё раз снять сниф.
Тут изменилась только температура двигателя. (ну трип и одометр не в счет)
И судя по третьему логу, он где-то в первых трех значащих байтах. Причем, первый байт с наполнением бака уменьшился, что позволяет думать, что это вольты. А второй и третий байт увеличился. Значит это литры. Вот теперь как бы это увязать с формулой. 40,5л =0х51 = 81; 22л = 0х2c = 44
Тьфу млин, да банально на два делить. Дискретность измерения бака 0,5 литра.
Интересный вопрос - где ж он напряжение берет. но в принципе оно нас не интересует, как и скорость.
Уфффф..... Кажись все данные есть. Теперь самое сложное - сам БК написать :)
напряжение зажигания скорее всего 5 байт справа. переводим в DEC один слева приписываем, а среднюю цифру не учитываем
СА = 202 , т.е 1202 , убираем ноль, ставим запятую = 12,2
дак бак , литры пополам просто делим ))
да я тоже увидел про деление на 2))
выложи скетч который с задержками выдает хотя бы три раза параметры панели
Скетч 1250 с добавление задержки 10 мс между 48 и 49, все как ты сказал. Так:
ща скетч проверочный накатаю
вот проверяй. ту задержку в 150 можно попробовать поуменьшать, вдруг будет работать при меньшей.
периодическое обращение к панели
Скетч из 1272 работает хорошо. Цепляет одно сообщение с CRC Fail, думаю не проблема. Задержку уменьшил до 10 мс, работает. Одометр нужно на 10 делить, отсекая сотые метра. Убрал выбор протокола и адреса, уже ведь не нужны. Глянь, ничего не пропустил?
По периодическому обращению (скетч 1273). Если период так и оставить - 1 минута, то ничего вообще не происходит. Думал, он только через минуту обратиться, но нет. А вот если поставить 1/2, то так:
Т.е. не успев закончить получение, опять начинает запрос, ловит пару последних данных с неверным CRC и на этом виснет.
В принципе, я думаю, это периодическое обращение нужно уже в код готового скетча добавлять, чтоб было видно куда и как. Перед этим запросом нужно ж будет закрывать соединение с ЭБУ.
Кстати, нужно проверить как с ЭБУ данные читаться будут.
Пытаюсь что-то накропать сам. К сожалению, и так не программист, а тут чужой код понять нужно. Для начала постарался вырезать все, что касается LCD, чтоб он мне просто пиды в серийник выводил.
Но получил только так:
Где чего крутить?
И каким-то чудом один раз все же мне выдало показания, но часть из них почему-то неверны. Я бы понял, если б все, но тут только часть. Вот этого вообще не могу понять. Например температура двигателя почему -162 ? По формуле она максимум -40 может быть. Из-за неверного типа переменных такое возможно?
с панелью нужно до конца разобраться, почему не работает периодический запрос. А с PCM будет время, попробую упрощённый скетч накидать
да такое возможно
Скобки.... Либо их где-то не хватает, либо они не там, где надо.... Если скобка стоит после GAUGE_SESSION (); , то prevgauge на каждом цикле равен millis :)
Для пробы уменьшил интервал до 10 секунд. Так вот, первый запрос проходит хорошо и данные получает. А вот второй, через десять секунд, получает два сообщения CRC Fail и программа дальше никуда уже не двигается. Кажись, что-то не то шлем на закрытие соединения.....
Чисто мои мысли, исходя из лога:
После инициализации, мы ждем байта 0х80 и шлем 0x7F. Затем ищем 0x78 и сразу шлем запрос пидов. Но ведь IDEN от приборки приходит два раза. Может второй раз нужно подождать ответ...
Потом Опель-сканер отправляет 02 B0 00 B2 и получает дважды ответ (присутствия?) 06 F0 AA 10 32 10 01 F2.... И только потом уже шлет запрос на пиды 02 11 00 13.... Не кроется ли тут причина остальных неверных сообщений?
При прекращении запросов пид он шлет 02 B2 00 B4, но в ответ получает еще один отзыв присутствия. Вот интересно как же он все-таки закрывает соединение? Нет ли в описании протокола каких-то подсказок, типа как с инициализацией на 5 бод?
возможно, действительно нужно реагировать, только получив два раза иденты от приборки . Завтра будет время набросаю скетч.
щас скетч по PCM скину
скетч PCM, формулы корявые конечно, нужно разбираться. UPDATE: почти разобрались
Ок, завтра запроверю че покажет. Пару вопросов, так сказать для общего развития.
Для чего uint16_t? Это ж, если я правильно понимаю, объявление длины переменной в 16 бит.... Просто до этого было вообще MessageRx[16] и усе. И вкладывалось значение в ранее объявленную переменную float MAP = 0; (кстати МАП с точкой, потому с float)
И второй вопросик, я то ориентировался по снифу, где в логе
первые 3 байта - FF, потому вместо 13 байта брал 16. А тут в скейче наоборот, сдвинуто все в лево на один. Ну, хочется понять. Может повтыкаю в код хорошо, да дойдет.... как до жирафа
Почему формулы корявые? Я проверял на эмуляторе, все сошлось отлично.
Для чего uint16_t? Это ж, если я правильно понимаю, объявление длины переменной в 16 бит.... Просто до этого было вообще MessageRx[16] и усе. И вкладывалось значение в ранее объявленную переменную float MAP = 0; (кстати МАП с точкой, потому с float)
когда пишем формулу, то в ней нужно приводить все переменные к одному типу. например MessageRx[16] это тип byte у которого диапазон от 0 до 255. и если его умножить на 100, например, он выйдет за пределы и возможна ошибка в формуле, поэтому я на всякий привел к двухбатовому числу. числовые константы, на сколько знаю, имеют тип int , поэтому их тоже нужно переводить соответвующе.
FF пробегали потому что мы с ТС очень корявый вариант разбора входящих сообщений сделали. delay там используется. По факту на шине FF скорее всего не пробегают. Щас опыта прибавилось немного. Поэтому пробуем по правильному принимать, без лишних байт. все как положено с Checksum. А влево сдвинуто на один, т.к номера байт в программировании с нулевого начинаются. а в описании разбайтовки мы написали, начиная с первого.
Почему формулы корявые? Я проверял на эмуляторе, все сошлось отлично.
не знаю как ты проверял. Например MAР в mbar чтобы получить , нужна такая формула . (подбирал по эмулятору)
MAP = (buf[12]*100/245);
и т.д.
Так и я по эмулятору. 13 байт ставим равным 0, минимальное значение МАП = 0 Бар, ставим равным 255 - максимальное - 1,04 бар. Вот и получается X*1.04/255=Bar
С остальными параметрами так же. Например, обороты двигателя при 0х00 = 0, а при 0хFF = 6375. Вот и получается X*6375/255
Почему у тебя 245?
У меня формулы вида X*100/255 - выдают проценты. Типа нагрузка на двигатель или процент открытия дроссельной заслонки.
Ладно, собственно, чего думать, пойти и проверить :)
в скетче #1282 исправил формулы
Так не показывает данные, только message ok.
Закомментировал что относится к ошибкам, перенёс пару скобок. Стало показывать, но везде по нулям. Т.е. буфер сообщения пуст.
И получаем так:
Хм.... получается, он вместо запроса 21 01 постоянно шлет запрос инит. Тут где-то собака порылась...
постоянно шлёт инит, т.к. после отправки запроса инита не получаем правильного сообщения от PCM. А это, в свою очередь, происходит из-за того, что keyword при разборе входящего сообщения перепутали.
исправил данный косяк в #1282
ну а скобки ты конечно убрал... Это похоже как студенты на лабораторных работах измерения под результат подгоняют....
Скобки.... Либо их где-то не хватает, либо они не там, где надо.... Если скобка стоит после GAUGE_SESSION (); , то prevgauge на каждом цикле равен millis :)
Для пробы уменьшил интервал до 10 секунд. Так вот, первый запрос проходит хорошо и данные получает. А вот второй, через десять секунд, получает два сообщения CRC Fail и программа дальше никуда уже не двигается. Кажись, что-то не то шлем на закрытие соединения.....
Всё там нормально со скобками. prevgauge присваивается значение millis не каждый проход луп, а только когда выполняется условие if a.
вот сделал интервал можно изменять в секундах, добавил двойное ожидание идентов от панели.
Лог РСМ с моей формулой МАП, т.е. Х*1,04/255, а так же поправил формулу для коррекции, не верно ее написал. Вот так надо: int STFT = (((uint16_t)buf[35]-128)*100/128);
Все показывает отлично. Осталось с ошибками разобраться как глядеть/расшифорвывать и стирать. Прикрутить кнопку к Дуне для перехода в режим ошибок и стирания?
А вот с приборкой так происходит:
После включения идет до:
Стоит секунд 30 и дальше:
Т.е. так происходит каждый второй раз.
"Всё там нормально со скобками. prevgauge присваивается значение millis не каждый проход луп, а только когда выполняется условие if a"
А ты в свой глянь, из 1273 строка 39 ;) Там как раз prevgauge был вынесен за условие
да, твоя правда, почему то не заметил сразу. Смотри ка по панели , ведь после первого идента начинает нормально сыпать сообщениями с данными. поправлю позже код может, нормально заработает
добавил в #1282 округление температур, теперь температуры достоверно показывают. И формулу MAP как у тебя сделал. Не понятно почему в твоём логе показывает мап 0.32 когда должно по эмулю 0,31. С моей формулой как положено 0,31 показывает.
Сыпать он начинает, но почему то инициализация только каждый второй раз проходит.
Округление разное, по ходу. Ну для сравнить завтра захвачу Опель-сканер, посмотрим как он покажет.
STFT кстати, должно быть int, т.к. коррекция идет от -100% до +100%.
добавил
- в разбор входящих сообщений дополнительный байт длины при его наличии
- чтение ошибок - короткое нажатие на кнопку (подключена пин 4)
- удаление ошибок - длительное нажатие на кнопку (подключена пин 4)
Логика такая - коротко нажимаем на кнопку - запросы 2101 перестают подаваться, а подаются запросы чтения ошибок, пока не получим ответ с ошибками, если ответ получили - далее опять долбим запросами 2101
длительно нажимаем на кнопку - запросы 2101 перестают подаваться, а подаются запросы удаления ошибок, пока не получим отчёт что DTC удалены , если отчёт получили - далее опять долбим запросами 2101
библиотека взаимодейтсвия с тактовыми кнопками
Чем эта библиотека для работы с кнопками хороша? Вроде Дуня и так у меент ими пользоваться.
Кстати, включена внутренняя подтяжка?
Библиотека огонь. Подтяжка включена
Ну может быть, спорить не буду :) Часы делал без нее.
В общем, отлично все работает, читает и сбрасывает ошибки. Правда, как отличить присутсвует или просто в памяти? Иногда проскакивают какие-то длинные сообщения, но на работу не влияют, да и редко.
В конечном скече нужно будет делать проверку и fastinit(); повторять если, например, после пяти секунд отправки запроса Init ничего не меняется. Мало ли из-за чего связь прервется. Сейчас, например, если включить Дуню, а потом зажигание, то ничего не добьешья.
Осталось приборку доломать :)
НО! Пушной зверек подкрался незаметно. Попробовал выводить на экран. Скеч компилируется, но изображения нет. Как я понял, библиотека TV-out жестко завязана на прерывания, а у нас их вагон с тележкой. Блин, и ведь убил пару дней пока нашел рабочий вариант библиотеки под последний IDE.... Вот что теперь делать не представляю. Отказываться от аналогово вывода очень не хочется, т.к. потеряю камеру. Да и смысл тогда огород городить - есть стандартный MID. не такой функциональный, но все же.... Ставить вторую Дуню чисто для вывода на экран и слать ей готовые данные? Блин, сразу бы Нано заказал....