Open discoroveryx opened 4 years ago
@discoroveryx добрый день. Функция чтения потока OBD1 я не писал с нуля. Взял готовую. Собственно ChangeState() это оно и есть. Как она работает не копал глубоко. Главное работает и ладно. Я писал только надстройку к этой функции. Работает она вроде как корректно, поэтому не вижу смысла что то там менять.
Доброе время суток Можете подсказать (помочь) в скетче работал он на меге 2560 про мини одно время скетч работал на 2 дисплея но потом умер ,переключил на один все работало но не долго. По мере возможного добавил стрелочный показатель (но не синхронный запуск для режима тест стрелок) кое как с опозданием пытался что то показывать тахометр(спидометр не запустил. Так же информер ТТ не работал Позже и вовсе отказало чтение OBD хотя пин диода указывал морганием ,но на дисплее так и не выводиться информация. Что ни так сделал в скетче ` // ToyotaOBD1_Reader // In order to read the data from the OBD connector, short E1 + TE2. then to read the data connect to VF1. // Note the data line output is 12V - connecting it directly to one of the arduino pins might damage (proabably) the board // This is made for diaply with an OLED display using the U8glib - which allow wide range of display types with minor adjusments. // Many thanks to GadgetFreak for the greate base code for the reasding of the data. // If you want to use invert line - note the comments on the MY_HIGH and the INPUT_PULLUP in the SETUP void. //////////////////////////////////////////////////////////////////////////////////////////// // Modified version to support two displays using a TCA 9548. // 30 June 2022 by jkl // Warning!!! I have no way to test this code. Once it is tested and verified, this // warning can be removed. -jkl ** // 1 July 2022 Rev.1 adds include of Wire.h -jkl // Adds support for a4988 driver for VID2905 stepper motor. Provides Tachometer reading. // 12 November 2022 by jkl ////////////////////////////////////////////////////////////////////////////////////////////
//#include "SdFat.h"
// Include the AccelStepper Library
// выбрать один вариант логирования
//#define LOGGING_FULL // Запись на SD всех данных //#define LOGGING_DEBUG // Запись на SD всех данных + статистику расхода и пробега //#define SECOND_O2SENS // Включение 2го сенсора кислорода для V движков
//DEFINE пинов под входы-выходы
//DEFINE констант расходомера
//DEFINE модуля записи на SD карту //#define FILE_BASE_NAME "Data" //шаблон имени файла //#define error(msg) sd.errorHalt(&Serial,F(msg)) //ошибки при работе с SD
//DEFINE OBD READER
// I2C address of the TCA 9548
// display channels on TCA 9548
// For each display, create a separate instance.
U8GLIB_SSD1306_128X64 u8g_0(U8G_I2C_OPT_NONE); // Display #0 U8GLIB_SSD1306_128X64 u8g_1(U8G_I2C_OPT_NONE); // Display #1
// Установка выводов const int dirPin = 28; const int stepPin = 26; const int en = 30; // this connection is not needed. const int stepsperevolution = 300; const int dirPin1 = 50; const int stepPin1 = 48; const int en1 = 47; // this connection is not needed. const int stepsperevolution1 = 300;
// modified for tach stepper and controller модифицировано для шагового двигателя и контроллера тахометра
AccelStepper tachStepper(AccelStepper::DRIVER, stepPin, dirPin); // works for a4988 (Bipolar, constant current, step/direction driver)
const long STEPS_PER_REVOLUTION = 315; // for the VID2905 stepper
AccelStepper spdStepper1(AccelStepper::DRIVER, stepPin1, dirPin1);
const long STEPS_PER_REVOLUTION1 = 315;
// Set this value based on a4988 configuration.
// 1 = full step, 2 = 1/2 step, 4 = 1/4 step, 8 = 1/8 step
const int uSteps = 2; // micro step rate
const int MAX_RPM_RANGE = 7000; // Maximum RPM range to display for your car
//SdFat sd; //SdFile file;
MD_KeySwitch S(TOGGLE_BTN_PIN, HIGH); byte CurrentDisplayIDX = 1, TT_last = 0, TT_curr = 0; float total_fuel_consumption = 0, trip_fuel_consumption = 0; float trip_avg_fuel_consumption; float cycle_obd_inj_dur = 0; float cycle_trip = 0; float trip_inj_dur = 0; float total_inj_dur_ee = 0; float current_trip = 0; float total_trip = 0; float all_trip_b = 0; float all_fuel_b = 0; float total_avg_consumption; float total_avg_speed; float trip_avg_speed;
unsigned long current_time = 0; unsigned long total_time = 0; unsigned long t; unsigned long last_log_time = 0; unsigned long odometer; bool flagNulSpeed = true; unsigned int OX, TT;
volatile uint8_t ToyotaNumBytes, ToyotaID, ToyotaData[TOYOTA_MAX_BYTES]; volatile uint16_t ToyotaFailBit = 0; boolean LoggingOn = false; // dfeine connection flag and last success packet - for lost connection function.
void setup() { // char fileName[13] = FILE_BASE_NAME "00.csv"; // const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1; // noInterrupts(); Serial.begin(115200); delay(100);
//EEPROM.put(200, odometer); запись значения одометра EEPROM.get(104, total_trip); EEPROM.get(108, total_time); EEPROM.get(200, odometer); EEPROM.get(204, total_inj_dur_ee); EEPROM.get(50, all_trip_b); EEPROM.get(58, all_fuel_b); analogReference(EXTERNAL);
// NOTE!!! VERY IMPORTANT!!! // Must call this once manually before first call to TCAselect() Wire.begin();
// Call TCAselect to set the channel. TCAselect(DISPLAY_0); // TCA channel for display 0 u8g_0.begin(); // use the default values u8g_0.setFont(u8g_font_profont15r); // I am guessing about this initialization????!!!!!
TCAselect(DISPLAY_1); // TCA channel for display 1 u8g_1.begin(); // use the default values u8g_1.setFont(u8g_font_profont15r); // I am guessing about this initialization????!!!!!
S.begin(); S.enableDoublePress(true); S.enableLongPress(true); S.enableRepeat(false); S.enableRepeatResult(false); S.setDoublePressTime(300); S.setLongPressTime(2000); //u8g.setFont(u8g_font_profont15r); if (DEBUG_OUTPUT) { Serial.println("system Started"); Serial.println("Read float from EEPROM: "); Serial.print("total_trip "); Serial.println(total_trip, 3); Serial.print("total_time "); Serial.println(total_time, 3); Serial.print("odometer "); Serial.println(odometer, 1); Serial.print("total_inj_dur_ee "); Serial.println(total_inj_dur_ee, 3); Serial.print("all_fuel_b "); Serial.println(all_fuel_b, 3); Serial.print("all_trip_b "); Serial.println(all_trip_b, 3); }
/* if (!sd.begin(SS, SPI_FULL_SPEED )) { sd.initErrorHalt(&Serial); } if (BASE_NAME_SIZE > 6) { error("FILE_BASE_NAME too long"); } if (sd.exists("Data99.csv")) //очистка SD карты если логов более 99 штук { u8g.setFont(u8g_font_profont15r); u8g.firstPage(); do { u8g.drawStr( 0, 17, "WIPE DATA!" ); } while ( u8g.nextPage() );
if (!sd.wipe()) {
sd.errorHalt("Wipe failed.");
}
if (!sd.begin(SS, SPI_FULL_SPEED )) {
sd.initErrorHalt();
}
}
while (sd.exists(fileName)) { if (fileName[BASE_NAME_SIZE + 1] != '9') { fileName[BASE_NAME_SIZE + 1]++; } else if (fileName[BASE_NAME_SIZE] != '9') { fileName[BASE_NAME_SIZE + 1] = '0'; fileName[BASE_NAME_SIZE]++; } else { error("Can't create file name"); } }
if (!file.open(fileName, O_CREAT | O_WRITE | O_EXCL)) { error("file.open"); } writeHeader(); / tachStepper.setMaxSpeed(250 uSteps); // these valuses seem to work for VID2905 tachStepper.setAcceleration(250 uSteps); tachStepper.runToNewPosition(-300 uSteps); // move to zero position //tachStepper.setCurrentPosition(0); // set as 0 rpm reference //tachStepper.runToNewPosition(300 uSteps); // move needle full scale tachStepper.runToNewPosition(10 uSteps); // now move needle almost to zero -- tach is ready to use. delay(1000);
spdStepper1.setMaxSpeed(250 uSteps); // these valuses seem to work for VID2905 spdStepper1.setAcceleration(250 uSteps); spdStepper1.runToNewPosition(-300 uSteps); // move to zero position //spdStepper.setCurrentPosition(0); // set as 0 rpm reference //spdStepper.runToNewPosition(300 uSteps); // move needle full scale spdStepper1.runToNewPosition(10 * uSteps); // now move needle almost to zero -- tach is ready to use. delay(1000);
pinMode(ENGINE_DATA_PIN, INPUT); // VF1 PIN pinMode(LED_PIN, OUTPUT); attachInterrupt(digitalPinToInterrupt(ENGINE_DATA_PIN), ChangeState, CHANGE); //setup Interrupt for data line Настройка прерывания для линии передачи данных pinMode(TOGGLE_BTN_PIN, INPUT); // кнопка СЛЕД. ЭКРАН CurrentDisplayIDX = 1; // set to display 1 drawScreenSelector(); //Расходомер t = millis(); last_log_time = millis(); interrupts(); delay(1000); } // END VOID SETUP
void loop(void) { unsigned long new_t; unsigned int diff_t; switch (S.read()) { case MD_KeySwitch::KS_NULL: break; case MD_KeySwitch::KS_PRESS: ent(); break; case MD_KeySwitch::KS_DPRESS:break; //{ // if (LoggingOn == false) LoggingOn = true; else LoggingOn = false; // } break; case MD_KeySwitch::KS_LONGPRESS: { if (CurrentDisplayIDX == 5) cleardataB(); else cleardata(); } break;
case MD_KeySwitch::KS_RPTPRESS: break;
}
if (ToyotaNumBytes > 0) { // if found bytes new_t = millis(); tachStepper.moveTo((long)(map(getOBDdata(OBD_RPM), 0, MAX_RPM_RANGE, 1, STEPS_PER_REVOLUTION uSteps 2))); if (new_t > t && getOBDdata(OBD_RPM) > 100 ) {// выполняем только когда на работающем двигателе diff_t = new_t - t; cycle_obd_inj_dur = getOBDdata(OBD_RPM) / 60000 Ncyl (float)diff_t * getOBDdata(OBD_INJ); //Время открытых форсунок за 1 такт данных. В МС //ОБ/М ОБ/С //форсунка срабатывает раз в 2 оборота КВ //6форсунок в с //время цикла мс в с. Получаем кол-во срабатываний за время цикла. Умножаем на время открытия форсунки, получаем время открытия 6 форсунок В МИЛЛИСЕКУНДАХ
trip_inj_dur += cycle_obd_inj_dur; //Время открытых форсунок за поездку В МС
total_inj_dur_ee += cycle_obd_inj_dur; //Время открытых форсунок за все время. EEPROM В МС
trip_fuel_consumption = trip_inj_dur / 1000 * Ls; //потребление топлива за поездку в литрах
total_fuel_consumption = total_inj_dur_ee / 1000 * Ls; //потребление топлива за все время. Из ЕЕПРОМ в литрах
cycle_trip = (float)diff_t / 3600000 * getOBDdata(OBD_SPD); //расстояние пройденное за такт обд данных
current_trip += cycle_trip; //Пройденное расстояние с момента включения. В КМ
total_trip += cycle_trip; //Полное пройденное расстояние. EEPROM. В КМ
odometer += cycle_trip; //электронный одометр. Хранится в еепром и не стирается кнопкой
current_time += diff_t; //Время в пути в миллисекундах с момента включения
total_time += diff_t; //полное пройденное время в миллисекундах лимит ~49 суток. EEPROM
trip_avg_speed = current_trip / (float)current_time * 3600000 ; //средняя скорость за поездку
total_avg_speed = total_trip / (float)total_time * 3600000; // средняя скорость за все время. км\ч
trip_avg_fuel_consumption = 100 * trip_fuel_consumption / current_trip; //средний расход за поездку
total_avg_consumption = 100 * total_fuel_consumption / total_trip; //среднее потребление за все время - Л на 100км
all_trip_b += cycle_trip ; //Полное пройденное расстояние. EEPROM. В КМ
all_fuel_b += cycle_obd_inj_dur; //Время открытых форсунок за все время. EEPROM В МС
t = new_t;//тест
// if (LoggingOn == true) logData(); //запись в лог данных по двоному нажатию на кнопку
updateEepromData(); //запись данных при остановке
if (millis() - last_log_time > 180000) { //Запись данных в EEPROM каждые 3 минуты. Чтобы не потерять данные при движении на трассе
EEPROM.put(104, total_trip);
EEPROM.put(108, total_time);
EEPROM.put(200, odometer);
EEPROM.put(204, total_inj_dur_ee);
EEPROM.put(50, all_trip_b);
EEPROM.put(58, all_fuel_b);
last_log_time = millis();
}
}
drawScreenSelector(); // draw screen
ToyotaNumBytes = 0; // reset the counter.
} // end if (ToyotaNumBytes > 0) tachStepper.run(); spdStepper1.run();
/ if (millis() % 50 == 0 && LoggingOn == true && CurrentDisplayIDX == 6) { //каждые 50мс, когда включено логирование и выбран экран с флагами(!) OX = analogRead(OX_PIN); if (OX < 400) { //исключаю ложные показание > ~1.3В file.write(';'); file.print(((float)OX VREF_MEASURED) / 1024, 3 ); file.println(); } } if (millis() % 500 == 0) { //каждые пол секунды читаем состояние АКПП TT = analogRead(TT_PIN); TT_curr = (int)(TT VREF_MEASURED / 1024 3.13 + 0.5); if (TT_last != TT_curr) { drawScreenSelector(); TT_last = TT_curr; } // Serial.println((float)TT VREF_MEASURED / 1024 3.13, 3); // Serial.println((int)(TT VREF_MEASURED / 1024 3.13+0.5)); } */ //if (millis() % 5000 < 50) autoscreenchange(); // ротация экранов }
void updateEepromData() { if (getOBDdata(OBD_SPD) == 0 && flagNulSpeed == false) { //Запись данных в еепром когда остановка авто EEPROM.put(104, total_trip); EEPROM.put(108, total_time); EEPROM.put(200, odometer); EEPROM.put(204, total_inj_dur_ee); EEPROM.put(50, all_trip_b); EEPROM.put(58, all_fuel_b); flagNulSpeed = true; //запрет повторной записи last_log_time = millis(); //чтобы не писать лишний раз } if (getOBDdata(OBD_SPD) != 0) flagNulSpeed = false; //начали двигаться - разрешаем запись }
void cleardata() { int i; for (i = 104; i <= 112; i++) { EEPROM.update(i, 0); } for (i = 200; i <= 208; i++) { EEPROM.update(i, 0); } EEPROM.get(104, total_trip); EEPROM.get(108, total_time); EEPROM.get(204, total_inj_dur_ee);
}
void cleardataB () { int i; for (i = 50; i <= 62; i++) { EEPROM.update(i, 0); }
EEPROM.get(50, all_trip_b); EEPROM.get(58, all_fuel_b);
}
/*void writeHeader() {
file.print(F(";OX_RAW;INJ TIME;IGN;IAC;RPM;MAP;ECT;TPS;SPD;VF1;OX;ASE;COLD;KNOCK;OPEN LOOP;Acceleration Enrichment;STARTER;IDLE;A/C;NEUTRAL;AVG SPD;LPK_OBD;LPH_OBD;TOTAL_OBD;AVG_OBD;CURR_OBD;CURR_RUN;total_trip"));
file.print(F(";OX_RAW;INJ TIME;IGN;IAC;RPM;MAP;ECT;TPS;SPD;VF1;OX;AVG SPD;LPK_OBD;LPH_OBD;TOTAL_OBD;AVG_OBD;CURR_OBD;CURR_RUN;total_trip"));
file.print(F(";OX_RAW;INJ TIME;IGN;IAC;RPM;MAP;ECT;TPS;SPD;VF1;OX;LPH_OBD"));
file.println(); file.sync(); } */ //обнуление данных
/*void logData() { file.print(float(millis()) / 60000, 3); file.write(';') ; file.write(';'); file.print(getOBDdata(OBD_INJ)); file.write(';'); file.print(getOBDdata(OBD_IGN)); file.write(';'); file.print(getOBDdata(OBD_IAC)); file.write(';'); file.print(getOBDdata(OBD_RPM)); file.write(';'); file.print(getOBDdata(OBD_MAP)); file.write(';'); file.print(getOBDdata(OBD_ECT)); file.write(';'); file.print(getOBDdata(OBD_TPS)); file.write(';'); file.print(getOBDdata(OBD_SPD)); file.write(';'); file.print(getOBDdata(OBD_OXSENS)); file.write(';'); file.print(getOBDdata(20)); file.write(';');
file.print(getOBDdata(11)); file.write(';'); file.print(getOBDdata(12)); file.write(';'); file.print(getOBDdata(13)); file.write(';'); file.print(getOBDdata(14)); file.write(';'); file.print(getOBDdata(15)); file.write(';'); file.print(getOBDdata(16)); file.write(';'); file.print(getOBDdata(17)); file.write(';'); file.print(getOBDdata(18)); file.write(';'); file.print(getOBDdata(19)); file.write(';');
// file.print(total_avg_speed); file.write(';'); //AVG_SPD ok // file.print(100 / getOBDdata(OBD_SPD) (getOBDdata(OBD_INJ) getOBDdata(OBD_RPM)Ls 0.18)); file.write(';'); //LPK_OBD ok
file.print(getOBDdata(OBD_INJ) getOBDdata(OBD_RPM)Ls * 0.18); file.write(';'); //LPH_OBD ok
//file.print(total_fuel_consumption); file.write(';'); //TOTAL_OBD ok //file.print(trip_avg_fuel_consumption); file.write(';'); //!AVG_OBD //file.print(trip_fuel_consumption); file.write(';'); //!CURR_OBD //file.print(current_trip); file.write(';'); //CURR_RUN ok //file.print(total_trip); file.write(';');//RUN_TOTAL ok
file.println(); file.sync(); } */ void drawScreenSelector(void) { if (CurrentDisplayIDX == 1) DrawCurrentFuelConsuption(); else if (CurrentDisplayIDX == 2) drawTripTimeDistance(); else if (CurrentDisplayIDX == 3) drawTimeDistance(); else if (CurrentDisplayIDX == 4) DrawTotalFuelConsuption(); else if (CurrentDisplayIDX == 5) drawTotalFuelDistanceB(); else if (CurrentDisplayIDX == 6) drawAllData(); else if (CurrentDisplayIDX == 7) drawExtraData(); } // end drawScreenSelector()
void DrawCurrentFuelConsuption(void) { TCAselect(DISPLAY_0); // this will be displayed on display 0 u8g_0.setFont(u8g_font_profont15r); u8g_0.firstPage(); do { u8g_0.setFont(u8g_font_profont15r); u8g_0.drawStr( 0, 15, "TRIP" ); u8g_0.drawStr( 74, 15, "L" ); u8g_0.setPrintPos(35, 15) ; u8g_0.print(trip_fuel_consumption, 1); if (LoggingOn == true) u8g_0.drawHLine(20, 24, 88); // u8g.setPrintPos(90, 20) ; // u8g.print((float)TT VREF_MEASURED / 1024 3.13, 2); / u8g.setFont(u8g_font_profont22r); switch (TT_curr) { //для делителя 10k + 4.7k case 0: u8g.drawStr( 95, 20, "1" ); break; case 2: u8g.drawStr( 95, 20, "2" ); break; case 4: u8g.drawStr( 95, 20, "3" ); break; case 5: u8g.drawStr( 95, 20, "3L" ); break; case 6: u8g.drawStr( 95, 20, "4" ); break; case 7: u8g.drawStr( 95, 20, "4L" ); break; }/ if (getOBDdata(OBD_SPD) > 1) { u8g_0.setFont(u8g_font_profont15r); u8g_0.drawStr( 0, 42, "L/100Km" ); u8g_0.setFont(u8g_font_profont22r); u8g_0.setPrintPos(0, 60) ; // u8g.print( 100 / getOBDdata(OBD_SPD) (getOBDdata(OBD_INJ) getOBDdata(OBD_RPM)Ls 0.18), 1); u8g_0.print( 100 / getOBDdata(OBD_SPD) (getOBDdata(OBD_INJ)/1000 Ls4 getOBDdata(OBD_RPM)60), 1); } else { u8g_0.setFont(u8g_font_profont15r); u8g_0.drawStr( 0, 42, "L/Hour" ); u8g_0.setFont(u8g_font_profont22r); u8g_0.setPrintPos(0, 60) ; // u8g.print(getOBDdata(OBD_INJ) getOBDdata(OBD_RPM)Ls 0.18, 1); u8g_0.print(getOBDdata(OBD_INJ)/1000 Ls4 getOBDdata(OBD_RPM)60, 1); } u8g_0.setFont(u8g_font_profont15r); u8g_0.drawStr( 60, 42, "Average" ); u8g_0.setFont(u8g_font_profont22r); u8g_0.setPrintPos(60, 60) ; if (trip_avg_fuel_consumption < 100) u8g_0.print( trip_avg_fuel_consumption, 1); else u8g_0.drawStr( 60, 60, "---" ); } while ( u8g_0.nextPage() ); }
void DrawTotalFuelConsuption(void) { TCAselect(DISPLAY_1); // this will be displayed on display 1 u8g_1.setFont(u8g_font_profont15r); u8g_1.firstPage(); do { u8g_1.setFont(u8g_font_profont15r); u8g_1.drawStr( 0, 15, "TOTAL" ); // u8g.drawStr( 74, 15, "L" ); u8g_1.drawStr( 42, 15, "Liters" );
// u8g.setPrintPos(42, 15) ; // u8g.print(total_fuel_consumption, 1); if (LoggingOn == true) u8g_1.drawHLine(20, 24, 88); // u8g.setFont(u8g_font_profont22r); // switch (TT_curr) { //для делителя 10k + 4.7k // case 0: u8g.drawStr( 95, 20, "1" ); break; // case 2: u8g.drawStr( 95, 20, "2" ); break; // case 4: u8g.drawStr( 95, 20, "3" ); break; // case 5: u8g.drawStr( 95, 20, "3L" ); break; // case 6: u8g.drawStr( 95, 20, "4" ); break; // case 7: u8g.drawStr( 95, 20, "4L" ); break; // }
// if (getOBDdata(OBD_SPD) > 1) // { u8g_1.setFont(u8g_font_profont15r); // u8g.drawStr( 0, 42, "L/100Km" ); u8g_1.drawStr( 0, 42, "All" ); u8g_1.setFont(u8g_font_profont22r); u8g_1.setPrintPos(0, 60) ; u8g_1.print(total_fuel_consumption, 1); // u8g.print( 100 / getOBDdata(OBD_SPD) (getOBDdata(OBD_INJ) getOBDdata(OBD_RPM)Ls 0.18), 1); // u8g.print( 100 / getOBDdata(OBD_SPD) (getOBDdata(OBD_INJ) Ls4 getOBDdata(OBD_RPM)60), 1); // } else { // u8g.setFont(u8g_font_profont15r); // u8g.drawStr( 0, 42, "L/Hour" ); // u8g.setFont(u8g_font_profont22r); // u8g.setPrintPos(0, 60) ; // u8g.print(getOBDdata(OBD_INJ) getOBDdata(OBD_RPM)Ls 0.18, 1); // u8g.print(getOBDdata(OBD_INJ) Ls4 getOBDdata(OBD_RPM)60, 1); // }
u8g_1.setFont(u8g_font_profont15r);
u8g_1.drawStr( 60, 42, "Average" );
u8g_1.setFont(u8g_font_profont22r);
u8g_1.setPrintPos(60, 60) ;
if (total_avg_consumption < 100)
u8g_1.print( total_avg_consumption, 1);
else u8g_1.drawStr( 60, 60, "---" );
} while ( u8g_1.nextPage() ); }
void drawTimeDistance(void) { TCAselect(DISPLAY_0); // this will be displayed on display 0 u8g_0.setFont(u8g_font_profont15r); u8g_0.firstPage(); do { u8g_0.setFont(u8g_font_profont15r); u8g_0.drawStr( 0, 15, "TOTAL" ); u8g_0.drawStr( 90, 15, "KM" ); u8g_0.setPrintPos(44, 15) ; u8g_0.print(total_trip, 1); if (LoggingOn == true) u8g_0.drawHLine(20, 24, 88); u8g_0.setFont(u8g_font_profont22r); // switch (TT_curr) { //для делителя 10k + 4.7k // case 0: u8g.drawStr( 95, 20, "1" ); break; // case 2: u8g.drawStr( 95, 20, "2" ); break; // case 4: u8g.drawStr( 95, 20, "3" ); break; // case 5: u8g.drawStr( 95, 20, "3L" ); break; // case 6: u8g.drawStr( 95, 20, "4" ); break; // case 7: u8g.drawStr( 95, 20, "4L" ); break; // } u8g_0.setFont(u8g_font_profont15r); u8g_0.drawStr( 0, 42, "Avg SPD" ); u8g_0.setFont(u8g_font_profont22r); u8g_0.setPrintPos(0, 60) ; u8g_0.print(total_avg_speed, 1); u8g_0.setFont(u8g_font_profont15r); u8g_0.drawStr( 60, 42, "Time (M)" ); u8g_0.setFont(u8g_font_profont22r); u8g_0.setPrintPos(60, 60) ; u8g_0.print( float(total_time) / 60000, 1); } while ( u8g_0.nextPage() ); }
void drawTripTimeDistance(void) { TCAselect(DISPLAY_0); // this will be displayed on display 0 u8g_0.setFont(u8g_font_profont15r); u8g_0.firstPage(); do { u8g_0.setFont(u8g_font_profont15r); u8g_0.drawStr( 0, 15, "TRIP" ); u8g_0.drawStr( 90, 15, "KM" ); u8g_0.setPrintPos(44, 15) ; u8g_0.print(current_trip, 1); if (LoggingOn == true) u8g_0.drawHLine(20, 24, 88); u8g_0.setFont(u8g_font_profont22r); // switch (TT_curr) { //для делителя 10k + 4.7k // case 0: u8g.drawStr( 95, 20, "1" ); break; // case 2: u8g.drawStr( 95, 20, "2" ); break; // case 4: u8g.drawStr( 95, 20, "3" ); break; // case 5: u8g.drawStr( 95, 20, "3L" ); break; // case 6: u8g.drawStr( 95, 20, "4" ); break; // case 7: u8g.drawStr( 95, 20, "4L" ); break; // } u8g_0.setFont(u8g_font_profont15r); u8g_0.drawStr( 0, 42, "Avg SPD" ); u8g_0.setFont(u8g_font_profont22r); u8g_0.setPrintPos(0, 60) ; u8g_0.print(trip_avg_speed, 1); u8g_0.setFont(u8g_font_profont15r); u8g_0.drawStr( 60, 42, "Time (M)" ); u8g_0.setFont(u8g_font_profont22r); u8g_0.setPrintPos(60, 60) ; u8g_0.print( float(current_time) / 60000, 1); } while ( u8g_0.nextPage() ); }
void drawTotalFuelDistanceB(void) //-----------TRIP B { TCAselect(DISPLAY_0); // this will be displayed on display 0 u8g_0.setFont(u8g_font_profont15r); u8g_0.firstPage(); do { u8g_0.setFont(u8g_font_profont15r); //u8g.drawStr( 0, 6, "TOTAL" ); //u8g.drawStr( 74, 15, "L" ); //u8g.drawStr( 20, 15, "All Trip B" );
if (LoggingOn == true) u8g_0.drawHLine(20, 24, 88);
u8g_0.setFont(u8g_font_profont15r);
u8g_0.drawStr( 0, 47, "Km" );
u8g_0.setFont(u8g_font_profont15r);
u8g_0.setPrintPos(40, 47) ;
u8g_0.print(all_trip_b, 1);
u8g_0.setFont(u8g_font_profont15r);
u8g_0.drawStr( 0, 63, "Lit" );
u8g_0.setFont(u8g_font_profont15r);
u8g_0.setPrintPos(40, 63) ;
u8g_0.print( all_fuel_b/ 1000 * Ls, 1);
u8g_0.setFont(u8g_font_profont15r);
u8g_0.drawStr( 0, 30, "L/100" );
u8g_0.setFont(u8g_font_profont15r);
u8g_0.setPrintPos(40, 30) ;
u8g_0.print( all_fuel_b / 1000 * Ls * 100 / all_trip_b , 1);
} while ( u8g_0.nextPage() ); } //}
void drawAllData(void) { // graphic commands to redraw the complete screen should be placed here TCAselect(DISPLAY_0); // this will be displayed on display 0 u8g_0.setFont(u8g_font_profont15r); u8g_0.firstPage(); do { u8g_0.drawStr( 0, 17, "INJ" ); u8g_0.setPrintPos(25, 17) ; u8g_0.print(getOBDdata(OBD_INJ));
u8g_0.drawStr( 0, 32, "IGN");
u8g_0.setPrintPos(25, 32) ;
u8g_0.print( int(getOBDdata(OBD_IGN)));
u8g_0.drawStr( 0, 47, "IAC");
u8g_0.setPrintPos(25, 47) ;
u8g_0.print( int(getOBDdata(OBD_IAC)));
u8g_0.drawStr( 0, 62, "RPM");
u8g_0.setPrintPos(25, 62) ;
u8g_0.print( int(getOBDdata(OBD_RPM)));
u8g_0.drawStr( 65, 17, "MAP" );
u8g_0.setPrintPos(92, 17) ;
u8g_0.print( int(getOBDdata(OBD_MAP)));
u8g_0.drawStr( 65, 32, "ECT");
u8g_0.setPrintPos(92, 32) ;
u8g_0.print( int(getOBDdata(OBD_ECT)));
u8g_0.drawStr( 65, 47, "TPS");
u8g_0.setPrintPos(92, 47) ;
u8g_0.print( int(getOBDdata(OBD_TPS)));
u8g_0.drawStr( 65, 62, "SPD");
u8g_0.setPrintPos(92, 62) ;
u8g_0.print( int(getOBDdata(OBD_SPD)));
u8g_0.drawVLine(63, 0, 64);
} while ( u8g_0.nextPage() ); // end picture loop } // end void drawalldata
void autoscreenchange() { CurrentDisplayIDX++; if (CurrentDisplayIDX > 3) CurrentDisplayIDX = 1; drawScreenSelector(); } void ent() {//ПЕРЕКЛЮЧЕНИЕ ЭКРАНОВ CurrentDisplayIDX++; if (CurrentDisplayIDX > 7) CurrentDisplayIDX = 1; drawScreenSelector(); }
float getOBDdata(byte OBDdataIDX) { float returnValue; switch (OBDdataIDX) { case 0:// UNKNOWN returnValue = ToyotaData[0]; break; case OBD_INJ: // Время впрыска форсунок =X0.125 (мс) (x / 8) returnValue = ToyotaData[OBD_INJ] / 8 ; // 0.125; //Время впрыска форсунок x/10 break; case OBD_IGN: // Угол опережения зажигания X0.47-30 (град) returnValue = ToyotaData[OBD_IGN] 0.47 - 30; break; case OBD_IAC: // Состояние клапана ХХ Для разных типов КХХ разные формулы: X/255100 (%) // X (шаг) returnValue = ToyotaData[OBD_IAC] 0.39215; ///optimize divide break; case OBD_RPM: //Частота вращения коленвала X25(об/мин) returnValue = ToyotaData[OBD_RPM] 25; break; case OBD_MAP: //Расходомер воздуха (MAP/MAF) // X0.6515 (кПа) // X4.886 (мм.ртут.столба) // X0.97 (кПа) (для турбомоторов) // X7.732 (мм.рт.ст) (для турбомоторов) // x2(гр/сек) (данная формула для MAF так и не найдена) // X/2555 (Вольт) (напряжение на расходомере) returnValue = ToyotaData[OBD_MAP] 4.886; //MAF break; case OBD_ECT: // Температура двигателя (ECT) // В зависимости от величины Х разные формулы: // 0..14: =(Х-5)2-60 // 15..38: =(Х-15)0.83-40 // 39..81: =(Х-39)0.47-20 // 82..134: =(Х-82)0.38 // 135..179: =(Х-135)0.44+20 // 180..209: =(Х-180)0.67+40 // 210..227: =(Х-210)1.11+60 // 228..236: =(Х-228)2.11+80 // 237..242: =(Х-237)3.83+99 // 243..255: =(Х-243)9.8+122 // Температура в градусах цельсия. if (ToyotaData[OBD_ECT] >= 243) returnValue = ((float)(ToyotaData[OBD_ECT] - 243) 9.8) + 122; else if (ToyotaData[OBD_ECT] >= 237) returnValue = ((float)(ToyotaData[OBD_ECT] - 237) 3.83) + 99; else if (ToyotaData[OBD_ECT] >= 228) returnValue = ((float)(ToyotaData[OBD_ECT] - 228) 2.11) + 80.0; else if (ToyotaData[OBD_ECT] >= 210) returnValue = ((float)(ToyotaData[OBD_ECT] - 210) 1.11) + 60.0; else if (ToyotaData[OBD_ECT] >= 180) returnValue = ((float)(ToyotaData[OBD_ECT] - 180) 0.67) + 40.0; else if (ToyotaData[OBD_ECT] >= 135) returnValue = ((float)(ToyotaData[OBD_ECT] - 135) 0.44) + 20.0; else if (ToyotaData[OBD_ECT] >= 82) returnValue = ((float)(ToyotaData[OBD_ECT] - 82) 0.38); else if (ToyotaData[OBD_ECT] >= 39) returnValue = ((float)(ToyotaData[OBD_ECT] - 39) 0.47) - 20.0; else if (ToyotaData[OBD_ECT] >= 15) returnValue = ((float)(ToyotaData[OBD_ECT] - 15) 0.83) - 40.0; else returnValue = ((float)(ToyotaData[OBD_ECT] - 15) 2.0) - 60.0; break; case OBD_TPS: // Положение дроссельной заслонки // X/2(градусы) // X/1.8(%) returnValue = ToyotaData[OBD_TPS] / 1.8; break; case OBD_SPD: // Скорость автомобиля (км/час) returnValue = ToyotaData[OBD_SPD]; break; // Коррекция для рядных/ коррекция первой половины case OBD_OXSENS: returnValue = (float)ToyotaData[OBD_OXSENS] 0.01953125; break;
case OBD_OXSENS2:// Lambda2 tst
returnValue = (float)ToyotaData[OBD_OXSENS2] * 0.01953125;
break;
// читаем Байты флагов побитно
case 11:
returnValue = bitRead(ToyotaData[11], 0); //Переобогащение после запуска 1-Вкл
break;
case 12:
returnValue = bitRead(ToyotaData[11], 1); //Холодный двигатель 1-Да
break;
case 13:
returnValue = bitRead(ToyotaData[11], 4); //Детонация 1-Да
break;
case 14:
returnValue = bitRead(ToyotaData[11], 5); //Обратная связь по лямбда зонду 1-Да
break;
case 15:
returnValue = bitRead(ToyotaData[11], 6); //Дополнительное обогащение 1-Да
break;
case 16:
returnValue = bitRead(ToyotaData[12], 0); //Стартер 1-Да
break;
case 17:
returnValue = bitRead(ToyotaData[12], 1); //Признак ХХ (Дроссельная заслонка) 1-Да(Закрыта)
break;
case 18:
returnValue = bitRead(ToyotaData[12], 2); //Кондиционер 1-Да
break;
case 19:
returnValue = bitRead(ToyotaData[12], 3); //Нейтраль 1-Да
break;
case 20:
returnValue = bitRead(ToyotaData[12], 4); //Смесь первой половины 1-Богатая, 0-Бедная
break;
case 21:
returnValue = bitRead(ToyotaData[12], 5); //Смесь второй половины 1-Богатая, 0-Бедная
break;
default: // DEFAULT CASE (in no match to number)
// send "error" value returnValue = 9999.99; } // end switch // send value back return returnValue; } // end void getOBDdata
void ChangeState() { static uint8_t ID, EData[TOYOTA_MAX_BYTES]; static boolean InPacket = false; static unsigned long StartMS; static uint16_t BitCount; int state = digitalRead(ENGINE_DATA_PIN); digitalWrite(LED_PIN, state); if (InPacket == false) { if (state == MY_HIGH) { StartMS = millis(); } else { // else if (state == MY_HIGH) if ((millis() - StartMS) > (15 8)) { StartMS = millis(); InPacket = true; BitCount = 0; } // end if ((millis() - StartMS) > (15 8)) } // end if (state == MY_HIGH) } else { // else if (InPacket == false) uint16_t bits = ((millis() - StartMS) + 1 ) / 8; // The +1 is to cope with slight time errors StartMS = millis(); // process bits while (bits > 0) { if (BitCount < 4) { if (BitCount == 0) ID = 0; ID >>= 1; if (state == MY_LOW) // inverse state as we are detecting the change! ID |= 0x08; } else { // else if (BitCount < 4) uint16_t bitpos = (BitCount - 4) % 11; uint16_t bytepos = (BitCount - 4) / 11; if (bitpos == 0) { // Start bit, should be LOW if ((BitCount > 4) && (state != MY_HIGH)) { // inverse state as we are detecting the change! ToyotaFailBit = BitCount; InPacket = false; break; } // end if ((BitCount > 4) && (state != MY_HIGH)) } else if (bitpos < 9) { //else TO if (bitpos == 0) EData[bytepos] >>= 1; if (state == MY_LOW) // inverse state as we are detecting the change! EData[bytepos] |= 0x80; } else { // else if (bitpos == 0) // Stop bits, should be HIGH if (state != MY_LOW) { // inverse state as we are detecting the change! ToyotaFailBit = BitCount; InPacket = false; break; } // end if (state != MY_LOW) if ( (bitpos == 10) && ((bits > 1) || (bytepos == (TOYOTA_MAX_BYTES - 1))) ) { ToyotaNumBytes = 0; ToyotaID = ID; for (uint16_t i = 0; i <= bytepos; i++) ToyotaData[i] = EData[i]; ToyotaNumBytes = bytepos + 1; if (bits >= 16) // Stop bits of last byte were 1's so detect preamble for next packet BitCount = 0; else { ToyotaFailBit = BitCount; InPacket = false; } break; } } } ++BitCount; --bits; } // end while } // end (InPacket == false) } // end void change
void drawExtraData(void) { TCAselect(DISPLAY_0); // this will be displayed on display 0 u8g_0.setFont(u8g_font_profont15r); u8g_0.firstPage(); do { u8g_0.drawStr( 0, 15, "VF" ); u8g_0.setPrintPos(25, 15) ; u8g_0.print(getOBDdata(OBD_OXSENS), 1); if (int(getOBDdata(11)) == 1) { u8g_0.drawStr( 0, 30, "ASE"); } if (int(getOBDdata(12)) == 1) { u8g_0.drawStr( 0, 45, "CLD"); } if (int(getOBDdata(13)) == 1) { u8g_0.drawStr( 0, 60, "KNK"); } if (int(getOBDdata(14)) == 1) { u8g_0.drawStr( 40, 30, "OL"); } if (int(getOBDdata(15)) == 1) { u8g_0.drawStr( 40, 45, "AE"); } if (int(getOBDdata(16)) == 1) { u8g_0.drawStr( 40, 60, "STA"); } if (int(getOBDdata(17)) == 1) { u8g_0.drawStr( 70, 30, "IDL"); } if (int(getOBDdata(18)) == 1) { u8g_0.drawStr( 70, 45, "A/C"); } if (int(getOBDdata(19)) == 1) { u8g_0.drawStr( 70, 60, "NSW"); } if (int(getOBDdata(20)) == 0) { u8g_0.drawStr(70, 15, "LEAN"); } else { u8g_0.drawStr(70, 15, "RICH"); } } while ( u8g_0.nextPage() ); }
// Helper function for changing TCA output channel
// Call this function whenever changing displays.
void TCAselect(uint8_t channel) {
if (channel > 7) return;
Wire.beginTransmission(TCAADDR);
Wire.write(1 << channel);
Wire.endTransmission();
} `
Здравствуйте, собираюсь прочитать при помощи raspberry pi + языка программирования python обороты двигателя моей toyota caldina 1993 года, нашел вот такую расшифровку алгоритма http://toyota.kgbconsulting.ca/wiki/Improved_decoding_of_signals_from_PC_COM_port это на данный момент самое актуальная расшифровка алгоритма или есть уже другие методы? конкретно не понятен момент с делением на 8.3, то есть произошла смена состояния с 0 на 1 начинаем отсчет, затем когда состояние меняться с 1 на 0 вычисляем, сколько по времени линия находилась в состоянии 1, а потом это время делим на 8.3 ? и забиваем массив?