А какая разница, принцип работы у них одинаковый
А какая разница, принцип работы у них одинаковый
Нужно подключатся к датчику хола
Сигнал оборотов можно снять с низковольтной части катушки зажигания через фильтр-делитель (по-моему на скутере так и сделано). Это может получиться проще, чем параллелиться к датчику коленвала и точно меньше влияния на ЭБУ. Аналогично и можно на выход сигнала с ЭБУ на показометр приборки: по-моему тоже спокойней, чем на датчик да и самый короткий провод выйдет.
Доброго времени суток.Проблема такая:на машине стоит сигнализация с автозапуском magicar 5 scher-khan.В этой сигнализации вход контроля заведённого двигателя подключается к лампе генератора либо по шумам,входа тахометра нет.Зарядка идёт на машине через 1,5 секунды после запуска(стартер будет перекручивать),по шумам не работает.Можно ли подключить оптопару к выходу тахометра приборки?(к катушке не хотелось бы т.к. при каких то проблемах с инжектором будут винить сигнализацию)
Теоретически возможно, но на практике я не проверялМожно ли подключить оптопару к выходу тахометра приборки?
я по твоему коду считал обороты и все нормально, все описано на канале, где выйдет серия видео по автоподсосу https://www.youtube.com/watch?v=uEUfugpbsMo
Все привет
Решил панелку на авто замутить частично механически и через андроид 7" в центре
Есть вопрос по теме скетча под А4988 для спид и тахо
в скейчах не столь силен есть скетч обработан частично нет синхронности режима тест стрелок
Тахо работает с опозданием не в полную силу, spd не прописан в работу. и нет вывода инфо по режиму ТТ
Может кто помочь
Код:// 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 "U8glib.h" //#include "SdFat.h" #include <SPI.h> #include <Wire.h> #include <EEPROM.h> #include <MD_KeySwitch.h> // Include the AccelStepper Library #include <AccelStepper.h> #define VREF_MEASURED 3.32 //Измеренное опорное напряжение с 3.3В стабилизатора // выбрать один вариант логирования #define LOGGING_MINIMAL // Запись минимума данных //#define LOGGING_FULL // Запись на SD всех данных //#define LOGGING_DEBUG // Запись на SD всех данных + статистику расхода и пробега //#define SECOND_O2SENS // Включение 2го сенсора кислорода для V движков #define DEBUG_OUTPUT false // for debug option - swith output to Serial //DEFINE пинов под входы-выходы #define LED_PIN 6 #define OX_PIN 0 // A0 для сенсора кислорода #define TT_PIN 1 // A1 для сенсора ТТ АКПП #define ENGINE_DATA_PIN 2 // D2 VF1 PIN #define TOGGLE_BTN_PIN 7 // D7 batton A PIN #define TOGGLE_BTN_PINb 6 // D6 batton B PIN #define INJECTOR_PIN 3 // D3 Номер ноги для форсунки #define SS 5 // D5 Номер ноги SS SD модуля //DEFINE констант расходомера #define Ls 0.055 // производительсность форсунки литров в секунду // базовый 0.004 или 240cc #define Ncyl 4 // кол-во цилиндров //DEFINE модуля записи на SD карту //#define FILE_BASE_NAME "Data" //шаблон имени файла //#define error(msg) sd.errorHalt(&Serial,F(msg)) //ошибки при работе с SD //DEFINE OBD READER #define MY_HIGH HIGH //LOW //Инвертировать линию Eng с помощью оптосоединителя, если у вас нет, то измените эти определения low & high на противоположные. #define MY_LOW LOW //HIGH #define TOYOTA_MAX_BYTES 24 #define OBD_INJ 1 //Injector pulse width (INJ) Длительность импульса инжектора #define OBD_IGN 2 //Ignition timing angle (IGN) Угол опережения зажигания #define OBD_IAC 3 //Idle Air Control (IAC) Контроль холостого хода Воздуха #define OBD_RPM 4 //Engine speed (RPM) Частота вращения двигателя #define OBD_MAP 5 //Manifold Absolute Pressure (MAP) Абсолютное давление в коллекторе #define OBD_ECT 6 //Engine Coolant Temperature (ECT) Температура охлаждающей жидкости двигателя #define OBD_TPS 7 //Throttle Position Sensor (TPS) Датчик положения дроссельной заслонки #define OBD_SPD 8 //Speed (SPD) Скорость #define OBD_OXSENS 9 // Лямбда 1 #ifdef SECOND_O2SENS #define OBD_OXSENS2 10 // Лямбда 2 на V-образных движка. У меня ее нету. #endif // I2C address of the TCA 9548 #define TCAADDR 0x70 // display channels on TCA 9548 #define DISPLAY_0 2 #define DISPLAY_1 4 // 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() { #ifdef LOGGING_FULL 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")); #endif #ifdef LOGGING_DEBUG 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")); #endif #ifdef LOGGING_MINIMAL file.print(F(";OX_RAW;INJ TIME;IGN;IAC;RPM;MAP;ECT;TPS;SPD;VF1;OX;LPH_OBD")); #endif 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(';'); #ifdef LOGGING_FULL 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(';'); #endif #ifdef LOGGING_DEBUG // 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 #endif file.print(getOBDdata(OBD_INJ) * getOBDdata(OBD_RPM)*Ls * 0.18); file.write(';'); //LPH_OBD ok #ifdef LOGGING_DEBUG //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 #endif 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 *Ls*4* 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 *Ls*4* 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) *Ls*4* 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) *Ls*4* 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: // Время впрыска форсунок =X*0.125 (мс) (x / 8) returnValue = ToyotaData[OBD_INJ] / 8 ; //* 0.125; //Время впрыска форсунок x/10 break; case OBD_IGN: // Угол опережения зажигания X*0.47-30 (град) returnValue = ToyotaData[OBD_IGN] * 0.47 - 30; break; case OBD_IAC: // Состояние клапана ХХ Для разных типов КХХ разные формулы: X/255*100 (%) // X (шаг) returnValue = ToyotaData[OBD_IAC] * 0.39215; ///optimize divide break; case OBD_RPM: //Частота вращения коленвала X*25(об/мин) returnValue = ToyotaData[OBD_RPM] * 25; break; case OBD_MAP: //Расходомер воздуха (MAP/MAF) // X*0.6515 (кПа) // X*4.886 (мм.ртут.столба) // X*0.97 (кПа) (для турбомоторов) // X*7.732 (мм.рт.ст) (для турбомоторов) // x*2(гр/сек) (данная формула для MAF так и не найдена) // X/255*5 (Вольт) (напряжение на расходомере) 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; #ifdef SECOND_O2SENS case OBD_OXSENS2:// Lambda2 tst returnValue = (float)ToyotaData[OBD_OXSENS2] * 0.01953125; break; #endif // читаем Байты флагов побитно 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; #ifdef SECOND_O2SENS //Вторая лябмда для Vобразных движков case 21: returnValue = bitRead(ToyotaData[12], 5); //Смесь второй половины 1-Богатая, 0-Бедная break; #endif 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(); }
Последний раз редактировалось brat4791; 05.04.2023 в 22:37.
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)