Вопрос по ISO-14230-4

Aku
Offline
Зарегистрирован: 04.12.2018

Скажу честно, не пробовал. Авто на улице в снегу)). Бегаю с ноутом для отладки. Не очень удобно. Может быть в выходной попробую.

Aku
Offline
Зарегистрирован: 04.12.2018

Заметил, что протокол очень чувствителен к временным интервалам.

MaksVV
Offline
Зарегистрирован: 06.08.2015

В моем скетче если что регулируйте задержки строка 62 и 66 . Одна из низ это между отправкой байт на эбу. У меня там стоит 1мс , в ваших скетчах 5мс. Но может и 1 будет работать.

MaksVV
Offline
Зарегистрирован: 06.08.2015

Плюсы моего скетча это: отсутствие delay. Переподключение при обрыве связи, проверка КС , а значит если будет мусор , то на индикацию не пройдут некорректные данные. Также легко добавлять новые пиды.

Aku
Offline
Зарегистрирован: 04.12.2018

Предлагаю свой вариант бортового МК. Добавил немного функционал.

1. Выбор параметра кнопкой.

2. Если температура двигателя меньше 40 градусов, 3 параметра перебираются автоматически.

3. При срабатывании какого-нибудь порога,  моргает индикатор и пикает зуммер.

#define F_CPU 16000000UL

#include "din_ind.h"
//#include "ds18b20.h"

#define TX 1
#define SPEAKER 2
#define BUTTON 3
#define MODEDISPMAX 6 // количество режимов 

//#define TIMEDISP 300000UL // время отображения параметра 5 минут
#define TIMEDISP 60000UL // время отображения параметра 1 минут
//#define TIMEDISP 5000UL // время отображения параметра 5сек

#define TIMEKLINE 200 // время между опросами Kline //100

#define BEEPON 70 // длительность включения BEEP
#define BEEPOFF 50 // длительность выключения BEEP
#define BEEPPAUSE 10000 // длительность между пачками BEEP

#define TIME_DS18B20 1000 //время чтения и отображения DS18B20 (температуры АЦП)
#define TIMEADC 500 //время чтения и отображения напряжения АЦП

#define ADC_AVERAGE 10 // кол-во замеров ADC (max 255)
#define ADC_REF 1022 // опорное напряжение ADC //1035

#define COUNTTOOGLELED 500 // кол-во прерываний для отключения индикации
#define REFRESHMODE 5000 // время смены показаний

char NotInit = false; // флаг инициализации

unsigned int Iso = 0; // стандарт по ISO

unsigned char ModeDisp = 0; // текущий режим

unsigned long ForceBeepCount = 0; // команда на включение бипера на заданное количество Beep

unsigned long PrevButtMillis = 0;  

unsigned char  RxBuffer[11] = {0};

signed char    Temperature = 0;
unsigned int   Cel = 0;
unsigned char  Speed = 0;
unsigned short Rpm = 0;

unsigned short Volt = 0;
signed short mVoltTemp = 0;

char ForceDisplayVoltage = false;  // флаг принудительного отображения напряжения
char ForceDisplayTemper = false;   // флаг принудительного отображения температуры
char ForceDisplayCel = false;      // флаг принудительного отображения нагрузки
char ForceDisplaySpeed = false;    // флаг принудительного отображения скорости
char ForceDisplayRPM = false;      // флаг принудительного отображения оборотов

char ForceToogleLed = false; // флаг принудительного моргания индикатора

char ModeToogle = false; // флаг моргания при достижении 40 градусов

void setup() {
  InitPorts(); 
  InitTimer2(); 
  InitDinInd(); 
  InitKL_5baud();
  ReadTrouble();
  PrevButtMillis = millis();   // запоминаем первое нажатие кнопки 
}

void loop() {
  InitKL_5baud(); 
  ProcessKLine();
  ProcessDisplay();
  //Temperature++; 
  //if (Temperature>=70) Temperature = 70;
  //Speed++;
  //if (Speed>=100) Speed = 100;
  delay(1000);
  //ForceToogleLed = 1;
}

///////////////////////////////
//Функция инициализации Портов
///////////////////////////////
void InitPorts() {
  pinMode(TX,OUTPUT);
  digitalWrite(TX,HIGH);   
  pinMode(BUTTON, INPUT_PULLUP);   
  pinMode(SPEAKER, OUTPUT);
  digitalWrite(SPEAKER,LOW);
  ACSR |= (1 << ACD); // Analog Comparator: Off
  //pinMode(13,OUTPUT);
  //PORTB &= ~(1<<5);
  //PORTB ^= (1<<5); 
}

////////////////////////
//функция опроса кнопки
////////////////////////
void ProcessButton() { 
  static char PrevButtonState = false; // предыдущее состояние кнопки
  static char ButtonState = false;     // текущее состояние кнопки по отжатию
  ButtonState = (!digitalRead(BUTTON)); // читаем текущие состояние кнопки по нажатию
  // ButtonState = digitalRead(BUTTON); // читаем текущие состояние кнопки по отжатию  
  if (!PrevButtonState && ButtonState && (millis() - PrevButtMillis > 200)) { // была не нажата, стала нажата и с прошлого нажатия прошло 200ms
    PrevButtMillis = millis(); // Запоминаем время первого срабатывания
    ButtonState = true; // Запоминаем состояние кнопки по нажатию
    // ButtonState = false; // Запоминаем состояние кнопки по отжатию
    if (++ModeDisp >= MODEDISPMAX) ModeDisp = 0; 
  } else PrevButtonState = ButtonState; // не нажата   
}

////////////////////////////
// Функция обработки данных
////////////////////////////
void ProcessData() {    
  if ((Temperature >= 110)&&(Temperature <= 115)) {ForceBeepCount = 5; ForceDisplayTemper = true; ForceToogleLed = true;} // моргаем инд. и переходим на 0 режим
  //if ((Temperature >= 39)&&(Temperature <= 40)) {ForceBeepCount = 4; ForceDisplayTemper = true; ForceToogleLed = true;}  // моргаем инд. и переходим на 0 режим
  if (Temperature == 40) {ForceBeepCount = 4; ForceDisplayTemper = true; ForceToogleLed = true;}  // моргаем инд. и переходим на 0 режим
  //if ((Temperature >= 38)&&(Temperature <= 39)) {ModeToogle = true;} // перестаем перебирать режим
  if (Temperature == 39) {ModeToogle = true;} // перестаем перебирать режим
  
  if ((Volt >= 55)&&(Volt <= 110)||(Volt >= 150)) {ForceBeepCount = 2; ForceToogleLed = true;} // если напряжение меньше 5,5В и 11В или больше 15В то не пикаем  
  if ((Speed >= 75)&&(Speed <= 76)) {ForceBeepCount = 3; ForceDisplaySpeed = true; ForceToogleLed = true;} // моргаем инд. и переходим на 0 режим
  if ((Rpm >= 4000)&&(Rpm >= 4500)){ForceBeepCount = 1; ForceDisplayRPM = true; ForceToogleLed = true;} // моргаем инд. и переходим на 0 режим
}

//////////////////////////////////
// Функция отображения параметров
//////////////////////////////////
void ProcessDisplay() {
unsigned long CurrentStateMillis = millis();
static char StateModeStart = false;

static unsigned long PrevModeDispMillis;
  if (!ModeToogle) { // если достигли 40 градусов то больше не перебираем
    ModeToogle = false;   // обнуляем чтоб больше не заходить, если не выбрали  
    if ((millis() - PrevModeDispMillis >= REFRESHMODE)) { // меняем показания через 5 секунд
      if (++ModeDisp >= 3) ModeDisp = 0;         
      PrevButtMillis = millis(); // запоминаем время первого срабатывания чтоб не переходить на 0 режим через время    
      PrevModeDispMillis = millis();
    }
  } 

  if (!(StateModeStart && (CurrentStateMillis - PrevButtMillis) < TIMEDISP))//если не 0 режим и после нажатия прошло время отображения параметра
    ModeDisp = 0; //0 //переходим на 0 режим, температура салона

  if (ForceDisplayVoltage) {    //принудительно отображаем напряжение
    ForceDisplayVoltage = false; // обнуляем чтоб больше не заходить, если не выбрали 
    ModeDisp = 1;
    PrevButtMillis = millis(); // запоминаем время первого срабатывания 
    StateModeStart = false; // после моргания переходим на 0 режим
  }
      
  if (ForceDisplayTemper) {    //принудительно отображаем температуру
    ForceDisplayTemper = false; // обнуляем чтоб больше не заходить, если не выбрали 
    ModeDisp = 2;
    PrevButtMillis = millis(); // запоминаем время первого срабатывания
    StateModeStart = false; // после моргания переходим на 0 режим
  }

  if (ForceDisplayCel) {    //принудительно отображаем нагрузку
    ForceDisplayCel = false; // обнуляем чтоб больше не заходить, если не выбрали 
    ModeDisp = 3;
    PrevButtMillis = millis(); // запоминаем время первого срабатывания
    StateModeStart = false; // после моргания переходим на 0 режим
  }

  if (ForceDisplaySpeed) {    //принудительно отображаем скорость
    ForceDisplaySpeed = false; // обнуляем чтоб больше не заходить, если не выбрали 
    ModeDisp = 4;
    PrevButtMillis = millis(); // запоминаем время первого срабатывания
    StateModeStart = false; // после моргания переходим на 0 режим
  } 

  if (ForceDisplayRPM) {       //принудительно отображаем обороты
    ForceDisplayRPM = false;  // обнуляем чтоб больше не заходить, если не выбрали 
    ModeDisp = 5;
    PrevButtMillis = millis(); // запоминаем время первого срабатывания
    StateModeStart = false; // после моргания переходим на 0 режим
  }
  
  switch (ModeDisp) {
//температура DS18B20
    case 0:
      StateModeStart = true; // обнуляем чтоб больше не заходить, если не выбрали 
      static unsigned long PrevReadDS18B20Millis;
      if ((millis() - PrevReadDS18B20Millis >= TIME_DS18B20)) { // читаем и выводим через некоторое время   
        Digit[0] = 16;          
        //ReadTemperDs18B20();
        mVoltTemp = (Read_ADC_Temp()*ADC_REF/1024UL/10)-60;
        ADC_Temp_Ind();      
        PrevReadDS18B20Millis = millis();       
      } 
      break;  

//напряжение борт. сети
    case 1:
      static unsigned long PrevADCMillis;   
      if ((millis() - PrevADCMillis >= TIMEADC)) {  // выводим через некоторое время  
        //Volt = Read_ADC()*20*ADC_REF/1024UL/100; //99 чуть больше         
        ADC_Volt_Ind();
        PrevADCMillis = millis();      
      }
      break; 
    
//температура K-Line
    case 2:   
      unsigned char temper_module;     
      if (Temperature >=0) temper_module = Temperature;
      else temper_module = - Temperature;
             
      if (Temperature < 0) Digit[0] = 18;       // "прочерк" 
      else {
        if ((temper_module%1000/100) == 0) Digit[0] = 16; // если 0 то пусто
        else Digit[0] = temper_module%1000/100; // Сотни 
      }        
      Digit[1] = temper_module%100/10; // Десятки 
      Digit[2] = temper_module%10;     // Единицы 
      Digit[3] = 19;                   // "Градус" 
      Dp0 = 0; 
      Dp1 = 0; 
      Dp2 = 0;
      Dp3 = 1; 
      break;  
    
//нагрузка K-Line
    case 3:      
      if ((Cel%1000/100) == 0) Digit[0] = 16; // если 0 то пусто
      else Digit[0] = Cel%1000/100;  // Сотни           
      Digit[1] = Cel%100/10;         // Десятки 
      Digit[2] = Cel%10;             // Единицы 
      Digit[3] = 24;                 // "L" 
      Dp0 = 0; 
      Dp1 = 0; 
      Dp2 = 0; 
      Dp3 = 0; 
      break; 
      
// скорость K-Line
    case 4:       
      if (((Speed)%1000/100) == 0) Digit[0] = 16; // если 0 то пусто
      else Digit[0] = Speed%1000/100;  // Сотни           
      Digit[1] = Speed%100/10;         // Десятки 
      Digit[2] = Speed%10;             // Единицы 
      Digit[3] = 31;                   // "c" 
      Dp0 = 0; 
      Dp1 = 0; 
      Dp2 = 0; 
      Dp3 = 0; 
      break;    
       
//обороты K-Line
    case 5:      
      if (Rpm % 10000/1000 == 0) Digit[0] = 16; // если 0 то пусто 
      else Digit[0] = Rpm%10000/1000;         // Тысячи
      Digit[1] = Rpm%1000/100;                // Сотни 
      Digit[2] = Rpm%100/10;                  // Десятки 
      Digit[3] = Rpm%10/1;                    // Единицы 
      Dp0 = 0; 
      Dp1 = 0; 
      Dp2 = 0; 
      Dp3 = 0; 
      break;
  }
}

////////////////////////////////////
// Функция чтения параметров K-Line
////////////////////////////////////
void ProcessKLine() {
  static unsigned char index;            
  static unsigned long PrevKlineMillis;
  if ((millis() - PrevKlineMillis >= TIMEKLINE)) {
             
    switch (index) {     
//температура
      case 0:     
        if (Iso == 9141) {         
          static unsigned char EngCoolTemp[6] = {0x68, 0x6A, 0xF1, 0x01, 0x05, 0xC9};
          TxBuf(EngCoolTemp,sizeof(EngCoolTemp)); 
        }
        
        if (Iso == 14230) {         
          static unsigned char EngCoolTemp[6] = {0xC2, 0x33, 0xF1, 0x01, 0x05, 0xEC};
          TxBuf(EngCoolTemp,sizeof(EngCoolTemp)); 
        }                 
        delay(50);                      
        RxBuf(); //записываем в RxBuffer         
        if (RxBuffer[4]==0x05) {
          Temperature = RxBuffer[5];
          Temperature = Temperature - 40;  
        } else {
          NotInit = false; // инициализируем снова
          Serial.end();
          digitalWrite(TX,HIGH);
        }
        break;   

//Нагрузка
      case 1:
        if (Iso == 9141) { 
          static unsigned char CalcEngLoad[6] = {0x68, 0x6A, 0xF1, 0x01, 0x04, 0xC8};
          TxBuf(CalcEngLoad,sizeof(CalcEngLoad)); 
        }
        
        if (Iso == 14230) { 
          static unsigned char CalcEngLoad[6] = {0xC2, 0x33, 0xF1, 0x01, 0x04, 0xEB};  
          TxBuf(CalcEngLoad,sizeof(CalcEngLoad));   
        }
        
        delay(50);  
        RxBuf(); //записываем в RxBuffer             
        if (RxBuffer[4]==0x04) {
          Cel = RxBuffer[5] * 100;   
          Cel = Cel / 255;
        } else {
          NotInit = false; // инициализируем снова
          Serial.end(); 
          digitalWrite(TX,HIGH); 
        }
        break;
            
//скорость 
      case 2:
        if (Iso == 9141) { 
          static unsigned char VehicleSpeed[6] = {0x68, 0x6A, 0xF1, 0x01, 0x0D, 0xD1};
          TxBuf(VehicleSpeed,sizeof(VehicleSpeed));
        }
         
        if (Iso == 14230) { 
          static unsigned char VehicleSpeed[6] = {0xC2, 0x33, 0xF1, 0x01, 0x0D, 0xF4};
          TxBuf(VehicleSpeed,sizeof(VehicleSpeed));
        } 
        
        delay(50);  
        RxBuf(); //записываем в RxBuffer             
        if (RxBuffer[4]==0x0D) {  
          Speed = RxBuffer[5];
        } else { 
          NotInit = false; // инициализируем снова
          Serial.end();
          digitalWrite(TX,HIGH); 
        }
        break;
        
//обороты  
      case 3:
       if (Iso == 9141) { 
         static unsigned char EngineRPM[6] = {0x68, 0x6A, 0xF1, 0x01, 0x0C, 0xD0};
         TxBuf(EngineRPM,sizeof(EngineRPM));  
       }

       if (Iso == 14230) { 
         static unsigned char EngineRPM[6] = {0xC2, 0x33, 0xF1, 0x01, 0x0C, 0xF3};
         TxBuf(EngineRPM,sizeof(EngineRPM)); 
       }
          
        delay(50);                
        RxBuf(); //записываем в RxBuffer            
        if (RxBuffer[4]==0x0C) {        
          Rpm = (256*RxBuffer[5]) + RxBuffer[6]; 
          Rpm = Rpm/4;      
        } else {
            NotInit = false; // инициализируем снова
            Serial.end();
            digitalWrite(TX,HIGH);
        }
        break;

//Напряжение ADC  
      case 4:
       Volt = Read_ADC()*20*ADC_REF/1024UL/100; //99 чуть больше          
       break;
       
//Напряжение термодатчика  
      //case 5:
       //mVoltTemp = (Read_ADC_Temp()*ADC_REF/1024UL/10)-60;
       //break;
    } 
  if (++index>=5) index = 0; //4 + ADC 
  PrevKlineMillis = millis();
  }
}



//////////////////////////
// Функция обработки Beep
//////////////////////////
void ProcessBeeper() {
  static unsigned char index;
  static unsigned long BeepMillis;
  static unsigned long PrevBeepMillis; 
  static char count;
    
  switch (index) {
    case 0: 
      if (!((millis()-PrevBeepMillis) >= BeepMillis)) break; 
        if (ForceBeepCount) {
          count = ForceBeepCount;
          //ForceBeepCount = 0;    
          BeepMillis = 0;       
          index = 1;
          PrevBeepMillis = millis(); 
        }    
      break;    
   
    case 1:
      if (!((millis()-PrevBeepMillis) >= BeepMillis)) break;
        Beeper_ON();       
        BeepMillis = BEEPON;      
        index = 2;
        PrevBeepMillis = millis();
      break;
    
    case 2: 
      if (!((millis()-PrevBeepMillis) >= BeepMillis)) break; 
      Beeper_OFF();  
        if (--count>0) {       
          BeepMillis = BEEPOFF; 
          index = 1; 
          PrevBeepMillis = millis();   
        }
        else {        
          BeepMillis = BEEPPAUSE; 
          index = 0; 
          PrevBeepMillis = millis();                    
        }
      break;
   }
  ForceBeepCount = 0;   
}

///////////////////////////////////////////////
//Функция инициализации Таймера2 для Дин. Инд.
///////////////////////////////////////////////
void InitTimer2() {
  cli();// Глобально запрещаю прерывания
  TCCR2A = 0;
  TCCR2B = 0;
  TIMSK2 = 0; 
  TCCR2A |= (1<<COM2A0); // Toggle OC2A,No CTC
  TCCR2B |= (1<<CS21)|(1<<CS20);              // Presc. = 32
  //TCCR2B |= (1<<CS22);                      // Presc. = 64
  TIMSK2 |= (1<<TOIE2); // enable timer overflow interrupt
  sei(); // Глобально разрешаю прерывания 
}

//////////////////////////////////
// Обработчик прерывания дин. инд.
//////////////////////////////////
ISR (TIMER2_OVF_vect) {
  static short  i = 0;
  i++; 
  if (ForceToogleLed) {
    ForceToogleLed = false;  // обнуляем чтоб больше не заходить, если не выбрали 
    if (i>=COUNTTOOGLELED) {     
      i = 0;
      if (OnLed) OnLed = false; 
      else OnLed = true; 
    }    
  } else {
    OnLed = true;
    i = 0;  
  }

/*
static short  z = 0;
static char On = 0;
  z++;    
  if (z>=700) {
    z = 0;
    if (On) {
    On = false; 
    PORTB &= ~(1<<5);
    } else {
      On = true;
      PORTB |= (1<<5);
    }
  }      
*/   
  RefreshDinInd();  
  ProcessButton(); 
  ProcessData();
  ProcessBeeper(); 
}

///////////////////////////////////////////////
// Функция чтения байта с выходом по тайм ауту
///////////////////////////////////////////////
char getSerial(unsigned char &retVal, unsigned long timeout) {
  unsigned long start = millis();
  while (!Serial.available()) { // ждем байт
    if ((millis() - start) > timeout) {
      return true; // не дождались, вышли по тайм ауту
    }
  }
  retVal = Serial.read();
  return false; // дождались байт
}

/////////////////////////////////
//Функция чтения данных по KLine
/////////////////////////////////
void RxBuf() {
  char bByteTimeout = false; 
  unsigned char byteNum = 0;   
  while (!bByteTimeout) {   
      bByteTimeout = getSerial(RxBuffer[byteNum],20); // сохранить ответ
      if (bByteTimeout) {        
        RxBuffer[byteNum] = 0; // текущий байт в 0, если тайм-аут произошел до того, как он мог быть записан
      }        
   byteNum++;
  }
 
  for (unsigned char i = byteNum; byteNum < 11; byteNum++) { // заполнение остатка текущего сообщения нулями
    RxBuffer[byteNum] = 0;
  } 
}

///////////////////////////////////
//Функция отправки данных по KLine
///////////////////////////////////
void TxBuf(unsigned char *array, unsigned char bufSizeTx) {
  for (unsigned char i = 0; i < bufSizeTx; i++) {
    Serial.write(array[i]);
    unsigned char Clear;
    getSerial(Clear,5);
    delay(5); // 5ms <= P4 <= 20ms
  }
}

///////////////////////////////
//Функция инициализации K-Line
///////////////////////////////
void InitKL_5baud() {
  if (!NotInit) { // если не было инициализации, то инициализируем 
    delay(2500); 
    digitalWrite(TX, LOW );
    delay(200);              
    digitalWrite(TX, HIGH ); 
    delay(400);
    digitalWrite(TX, LOW ); 
    delay(400);
    digitalWrite(TX, HIGH );
    delay(400);
    digitalWrite(TX, LOW ); 
    delay(400);
    digitalWrite(TX, HIGH );
    delay(200);
    
    Serial.begin(10400);
  
    unsigned char InitError = 0;  // номер ошибки       
    unsigned char Sync = 0;
    unsigned char Key1 = 0;
    unsigned char Key2 = 0;
    unsigned char InvKey2 = 0;
    unsigned char Clear = 0;
    unsigned char InvAddress = 0;
    if (!getSerial(Sync,300)) {
      if (Sync == 0x55) {
        if (!getSerial(Key1,20)) { // если успешно прочитали key1
          if(!getSerial(Key2,20)) { // если успешно прочитали key2
            delay(25);  // 25ms <= W4 <= 50ms 
            InvKey2 = ~Key2;
            Serial.write(InvKey2);   
            getSerial(Clear,5); // читаем эхо invKey2          
            if (!getSerial(InvAddress,50)) { // если успешно прочитали инверсию байта
              if (InvAddress == 0xCC) { // если получили 0xCC                
                if ((Key1 == 0x08) && (Key2 == 0x08)) Iso = 9141;
                if (Key2 == 0x8F) Iso = 14230;              
                //MsbToLed(Key1); // отображаем key1, key2
                //LsbToLed(Key2);  
                NotInit = true; // инит успешно, больше не инициализируем                                                                             
              } else {    
                InitError = 6; // байт не равен 0xCC
              }
            } else {    
              InitError = 5; // не получили инверсию байта 0x33
            }
          } else {    
            InitError = 4; // не получили key2
          }
        } else {    
          InitError = 3; // не получили key1
        }
      } else {    
        InitError = 2; // байт sync не равен 0x55
      }
    } else {    
      InitError = 1; // не получили sync
    }
    
    if (InitError) { // выводим ошибки, если есть
      Digit[0] = 14; // E
      Digit[1] = 22; // r
      Digit[2] = 30; // r.
      Digit[3] = InitError; 
      Dp0 = 0; 
      Dp1 = 0; 
      Dp2 = 0; 
      Dp3 = 0; 
      delay(5000); //5000
    }                    
    delay(TIMEKLINE);  // 55ms <= P3 (wait between messages) <= 5s 
    //delay(2000); // если отображаем key1, key2
  } // NotInit
}

/////////////////////////
//Функция включения BEEP
/////////////////////////
void Beeper_ON() {
  digitalWrite(SPEAKER,HIGH);  
}

//////////////////////////
//Функция выключения BEEP
//////////////////////////
void Beeper_OFF() {
  digitalWrite(SPEAKER,LOW);  
}

////////////////////////
//Функция чтения ошибок
////////////////////////
void ReadTrouble() {

  if (Iso == 9141) { 
    static unsigned char Trouble[5] = {0x68, 0x6A, 0xF1, 0x03, 0xC6};
    TxBuf(Trouble,sizeof(Trouble));
  }

  if (Iso == 14230) { 
    static unsigned char Trouble[5] = {0xC2, 0x33, 0xF1, 0x03, 0xE9};
    TxBuf(Trouble,sizeof(Trouble));
  }
          
  delay(50);    
  RxBuf(); //записываем в RxBuffer
  
  //RxBuffer[5] = 0xFF;
  //RxBuffer[6] = 0x12;
 
  unsigned char dtc1 = (RxBuffer[5] & 0xC0) | (dtc1 >> 6);    
  unsigned char dtc2 = (RxBuffer[5] & 0x30) >> 4;
  unsigned char dtc3 =  RxBuffer[5] & 0x0F;
  unsigned char dtc4 = (RxBuffer[6] & 0xF0) >> 4;
  unsigned char dtc5 =  RxBuffer[6] & 0x0F;
  
  if (dtc1||dtc2||dtc3||dtc4||dtc5) { // если есть ошибки  
    Digit[0] = 14; // E
    Digit[1] = 22; // r
    Digit[2] = 30; // r.
      
    switch (dtc1) {
      case 0x00 :
         Digit[3] = 26;
        break;
      case 0x40 :
         Digit[3] = 12;
        break;
      case 0x80 :
         Digit[3] = 11;
        break;
      case 0xC0 :
         Digit[3] = 28;
        break;
    }
    Dp0 = 0; 
    Dp1 = 0; 
    Dp2 = 0; 
    Dp3 = 0;   
    delay(2000);      
    Digit[0] = dtc2;
    Digit[1] = dtc3;
    Digit[2] = dtc4;
    Digit[3] = dtc5;     
    delay(2000); 
  }
}

//////////////////////////
//Функция удаления ошибок
//////////////////////////
/*
void CLRTrouble() {
  if (Iso == 9141) { 
    static unsigned char ClearTrouble[5] = {0x68, 0x6A, 0xF1, 0x04, 0xC7};
    TxBuf(ClearTrouble,sizeof(ClearTrouble));  
  }

  if (Iso == 14230) { 
    static unsigned char ClearTrouble[5] = {0xC2, 0x33, 0xF1, 0x04, 0xEA};
    TxBuf(ClearTrouble,sizeof(ClearTrouble));  
  }     
  delay(50);    
}
*/

//////////////////////
// Функция чтения ADC
//////////////////////
unsigned long Read_ADC() {
unsigned long Result = 0;  
// Настраиваю  АЦП
  DIDR0 |= (1 << 7); // отключаем цифровой вход ADC7 напряжение
  ADMUX |= (1 << REFS1)|(1 << REFS0) // Int. 1.1V Ref. with ext. cap. at AREF.   
      |(1 << MUX2)|(1 << MUX1)|(1 << MUX0); // ADC7 volt                        
      //|(1 << MUX3)|(1 << MUX2)|(1 << MUX1); // 1.1V
              
  ADCSRA |= (1 << ADEN) // ADC enable
      |(1 << ADPS2)|(1 << ADPS1)|(1 << ADPS0); // CK/128

  delay(1);
  
  for (unsigned char i=0;i<ADC_AVERAGE;i++) {  
    do {ADCSRA |= (1 << ADSC);} // Старт преобразования
    while ((ADCSRA & (1 << ADIF)) == 0); // ждем флаг ADIF 
    Result = Result + ADCW; // Result + (ADCL|ADCH << 8);     
    ADCSRA |= (1 << ADIF);    // сбрасываем флаг ADIF      
    ADCSRA &= ~(1 << ADSC);   // Стоп преобразования
  }
  Result = Result / ADC_AVERAGE;
  DIDR0 = 0;
  ADMUX = 0;
  ADCSRA = 0;

  return Result;
}

void ADC_Volt_Ind() { 
  if ((Volt%1000/100)==0) Digit[0] = 16;  
  else Digit[0] = Volt%1000/100; // Десятки вольт
  Digit[1] = Volt%100/10;  // Единицы вольт
  Digit[2] = Volt%10;    // 1/10 вольт            
  Digit[3] = 28;  // U
  Dp0 = 0;
  Dp1 = 1;
  Dp2 = 0;
  Dp3 = 0;
}

///////////////////////////
// Функция чтения ADC темп
///////////////////////////
unsigned long Read_ADC_Temp() {
unsigned long Result = 0;  
// Настраиваю  АЦП
  DIDR0 |= (1 << 6); // отключаем цифровой вход ADC6 температура
  ADMUX |= (1 << REFS1)|(1 << REFS0) // Int. 1.1V Ref. with ext. cap. at AREF.  
      |(1 << MUX2)|(1 << MUX1);  // ADC6 temp                        
      //|(1 << MUX3)|(1 << MUX2)|(1 << MUX1); // 1.1V
              
  ADCSRA |= (1 << ADEN) // ADC enable
      |(1 << ADPS2)|(1 << ADPS1)|(1 << ADPS0); // CK/128

  delay(1);
  
  for (unsigned char i=0;i<ADC_AVERAGE;i++) {  
    do {ADCSRA |= (1 << ADSC);} // Старт преобразования
    while ((ADCSRA & (1 << ADIF)) == 0); // ждем флаг ADIF 
    Result = Result + ADCW; // Result + (ADCL|ADCH << 8);     
    ADCSRA |= (1 << ADIF);    // сбрасываем флаг ADIF      
    ADCSRA &= ~(1 << ADSC);   // Стоп преобразования
  }
  Result = Result / ADC_AVERAGE;
  DIDR0 = 0;
  ADMUX = 0;
  ADCSRA = 0;
  return Result;
}

///////////////////////////
// Функция чтения ADC темп
///////////////////////////
void ADC_Temp_Ind() { 
  if (mVoltTemp < 0) {
  // Отрицательная температура
    mVoltTemp =-mVoltTemp;    // Перевожу отрицательное число в положительное
    Digit[1] = 18;       // Символ "-"
    if (mVoltTemp < 10) {
      // -9*...-1*
      Digit[2] = mVoltTemp % 10;  // Единицы градусов
      Digit[3] = 19;    // Символ градуса
    }
    else {
      // -55...-10
      Digit[2] = mVoltTemp % 100 / 10;  // Десятки градусов
      Digit[3] = mVoltTemp % 10;      // Единицы градусов
    }
  }
  else {
  // Положительная температура
    if (mVoltTemp > 99) {
      // 100...125
      Digit[1] = mVoltTemp % 1000 / 100;  // Сотни градусов
      Digit[2] = mVoltTemp % 100 / 10;  // Десятки градусов
      Digit[3] = mVoltTemp % 10;      // Единицы градусов
    }
    else {
      if (mVoltTemp > 9) {
        // 10*...99*
        Digit[1] = mVoltTemp % 100 / 10;  // Десятки градусов
        Digit[2] = mVoltTemp % 10;      // Единицы градусов
        Digit[3] = 19;        // Символ градуса
      }
      else {
        // 0*...9*
        Digit[1] = 16;       // Пустой символ
        Digit[2] = mVoltTemp % 10;    // Единицы градусов
        Digit[3] = 19;      // Символ градуса
      }
    }
  }  
  Dp0 = 0;
  Dp1 = 0; 
  Dp2 = 0;
  Dp3 = 0;              
}


 

MaksVV
Offline
Зарегистрирован: 06.08.2015

а все таки #45 пробовали?

Aku
Offline
Зарегистрирован: 04.12.2018

MaksVV,Спасибо за помощь. Нет. Не дошло до этого. Когда у меня заработало, смысл пропал. Но если очень нужно, то попробую.

MaksVV
Offline
Зарегистрирован: 06.08.2015

в вашем скетче delay-и присутсвтуют и нет проверки корректности полученных от PCM данных, поэтому на экране возможно будут проскакивать нереальные значения и подтормаживания, а также плохое реагирования на кнопку. Так для прикола проверьте мой мой скетч. 

Aku
Offline
Зарегистрирован: 04.12.2018

Если говорить про Delay(1000), которая в в основном цикле, то она там совсем не нужна. Её нужно закомментировать. Я её использовал для отладки. А в остальных случаях я так думаю без задержек не получится. Да и максимум там задержка на 50-100мс.

MaksVV
Offline
Зарегистрирован: 06.08.2015

100 это уже очень прилично я вам скажу. Нормальные программы так не пишут. Например , обороты двс скачками будут отображаться. Мой скетч тоже далеко не идеал. Но delay больших нет. Максимум 5 вроде гдето было. Подобные пару скетчей у меня отлично работают. Посмотрите принцип получения байт от PCM.

lev2606
Offline
Зарегистрирован: 19.06.2019

Привет, MaksVV. А почему в скетче №45 Вы считываете напряжение из одного байта SysVolt = buf[n+2]/10.0 ?

В документации на Pid-ы другая формула 

 

PID
(hex)
PID
(Dec)
Data bytes returned Description Min value Max value Units Formula

 

42 66 2 Control module voltage
0  
65.535 V {\displaystyle {\frac {256A+B}{1000}}}
 

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

Aku пишет:

Добрый день MaksVV. Спасибо за скетч. У меня работает свой сейчас. Читаю параметры температуры, скорости и обороты двигателя. Но с напряжением по адресу 0x42h почему-то не получается. Возвращает 0x83 0xF1 0x10 0x7F 0x01 0x12 0x16.

 

MaksVV пишет:

вот исправленный скетч, в том есть косяки . Видимо такой PID 01 42   ЭБУ не поддерживает.