Помогите разобраться почему не работает код

Подскажите пожалуйста по такому вопросу. Нашел код из этой темы Данные из K-line Эбу | Аппаратная платформа Arduino и переделал немного под свои нужды.

#include <Adafruit_ST7735.h>
#include <SPI.h>
#include <SoftwareSerial.h>
#include <utf8rus2.h>

SoftwareSerial K_LINE(2, 3);  // RX, TX

#define TIMER_DELAY \
  Delay = 0; \
  timerdelay = curmillis  // включение этого таймера
#define TFT_CS     10
#define TFT_RST    8
#define TFT_DC     9
#define SERIAL_BAUDRATE 10400

const byte PCMaddress = 0x7A;  // адрес эбу

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); // Инициализация объекта для работы с дисплеем

byte header = 0;        // состояние заголовка
byte message_size = 0;  // размер тела принимаемого сообщения, кол-во байт

byte j = 2;  // инкремент
byte n = 2;
const byte bufsize = 60;   // размер буфера принятого сообщения
byte buf[bufsize] = { 0 };  // буфер принятого сообщения
byte checksum = 0;          // контрольная сумма входящего сообщения
uint32_t curmillis = 0;     // снимок системного времени
byte delaybyte_TX = 0;      // задержка между байтами отправляемого сообщения
byte waitbyte_RX = 1;       // задержка, мс для успевания заполнения буфера RX (подрегулировать в зависимости от уровня жизнидеятельности на Марсе)
uint32_t timerdelay = 0;    // таймер ожидания байт (для успевания заполнения буфера УАРТ)
bool Delay = 0;             // таймер ожидания байт (для успевания заполнения буфера УАРТ)
#define TIMER_DELAY \
  Delay = 0; \
  timerdelay = curmillis  // включение этого таймера

uint32_t prevRESETheader = 0;  // таймер сброса заголовка если в момент приёма сообщения данные оборвались
bool RESETheader_timer = 0;    // таймер сброса заголовка если в момент приёма сообщения данные оборвались


uint32_t prevtimeRequest = 0;
uint16_t periodRequest = 1000;  // периодичность запроса параметров ЭБУ, мс
bool Init = 0;
uint32_t prevInit = 0;

int Temperature;


//**************************** команды, посылаемые на ЭБУ

byte StartSession[] = { 0x81 };       // команда на старт диагностики (может также быть 82)
byte StopSession[] = { 0x82 };        // команда на стоп диагностики
//byte DataRequest[] = { 0x21, 0x80 };  // команда на запрос параметров
byte DataRequest[] = { 0x21, 0xAA };  // команда на запрос параметров
//byte DataRequest[] = { 0x21, 0x01 };  // команда на запрос параметров

//****************************

void lcdPrint(int x, int y, int c1, int c2, String s, int width = 0, int f = 0){
  String ss;
  tft.setCursor(x,y);
  if (width == 0) {
    width = s.length();
  }
  while (ss.length() < width-s.length()) ss += " ";
  ss += s;
  if (c2 == 0){
    tft.setTextColor(c1);
  }
  else{
    tft.setTextColor(c1, c2);
  }
  tft.print(ss);
}

void setup() {
  Serial.begin(SERIAL_BAUDRATE);   // настойки монитора порта отладки
  K_LINE.begin(SERIAL_BAUDRATE);  // настройки шины к-лайн
  delay(2000);
  tft.initR(INITR_BLACKTAB);     // Инициализация дисплея
  tft.fillScreen(ST7735_BLACK); // Очистка экрана перед выводом новых данных
  tft.setTextColor(ST7735_WHITE); // Установка цвета текста
  tft.setRotation(3);
  tft.setTextSize(2);
  lcdPrint(0, 0, ST7735_WHITE, ST77XX_RED, utf8rus2("Связь с ЭБУ"));
  lcdPrint(50, 20, ST7735_BLACK, ST77XX_GREEN, utf8rus2("НЕТ"));
  lcdPrint(0, 50, ST7735_WHITE, ST77XX_RED, utf8rus2("Обороты"));
  lcdPrint(0, 70, ST7735_BLACK, ST77XX_GREEN, String(0), 6);
  lcdPrint(85, 70, ST7735_BLACK, ST77XX_GREEN, utf8rus2("об/мин"));
  lcdPrint(0, 90, ST7735_WHITE, ST77XX_RED, utf8rus2("Скорость"));
  lcdPrint(0, 110, ST7735_BLACK, ST77XX_GREEN, String(0), 6);
  lcdPrint(85, 110, ST7735_BLACK, ST77XX_GREEN, utf8rus2("км/ч"));
  Serial.println(sizeof(buf));
}

void loop() {
  curmillis = millis();  // снимок системного времени

  K_LINEread();  // читаем шину к-лайн

  if (curmillis - prevtimeRequest > periodRequest) {  // периодически делаем запрос параметров

    if (Init) {
      lcdPrint(50, 20, ST7735_BLACK, ST77XX_GREEN, utf8rus2("ДА"), 3);
      SendMessage(DataRequest, sizeof(DataRequest));
    }else SendMessage(StartSession, sizeof(StartSession));
    prevtimeRequest = curmillis;
  }

  if (curmillis - prevInit > 10000) {
    lcdPrint(50, 20, ST7735_BLACK, ST77XX_GREEN, utf8rus2("НЕТ"));
    Init = 0;
    prevInit = curmillis;
  }  // периодически делаем сброс инита, если ЭБУ не отвечает
}




void SendMessage(const byte *command, const size_t size) {
  const byte siZe = size + 4;
  byte Mes[siZe];
  byte Checksum = 0;
  for (byte i = 0; i < siZe; i++) {
    if (i == 0) {
      Mes[i] = size;
      bitWrite(Mes[i], 7, 1);
    }
    if (i == 1) Mes[i] = PCMaddress;
    if (i == 2) Mes[i] = 0xF1;
    if (i == 3) {
      for (byte t = 0; t < size; t++) {
        Mes[i] = command[t];
        Checksum += Mes[i];
        K_LINE.write(Mes[i]);
        i++;
      }
    }
    if (i != siZe - 1) Checksum += Mes[i];
    else Mes[i] = Checksum;
    K_LINE.write(Mes[i]);
  }
}


void K_LINEread() {

  if (K_LINE.available()) {

    // первый старт байт
    if (header == 0 && Delay) {
      TIMER_DELAY;
      buf[0] = K_LINE.read();
      if (!bitRead(buf[0], 6) && bitRead(buf[0], 7)) {
        header = 1;
        RESETheader_timer = 1;
        prevRESETheader = curmillis;
      }
    }

    // второй старт байт
    if (header == 1 && Delay) {
      TIMER_DELAY;
      buf[1] = K_LINE.read();
      if (buf[1] == 0xF1) {
        header = 2;
      } else {
        header = 0;
        RESETheader_timer = 0;
      }
    }

    // третий старт байт
    if (header == 2 && Delay) {
      TIMER_DELAY;
      buf[2] = K_LINE.read();
      if (buf[2] == PCMaddress) {
        message_size = buf[0];
        if (buf[0] != 0x80) {
          header = 4;
          message_size &= ~0x80;
          j = 3;
          n = 3;
        } else {
          header = 3;
          j = 4;
          n = 4;
        }
        if (message_size > bufsize) message_size = bufsize;
        checksum = 0;
      } else {
        header = 0;
        RESETheader_timer = 0;
      }
    }
    // если размер сообщения указан в дополнительном байте (нулевой байт 0x80) читаем этот дополнительный байт:
    if (header == 3 && Delay) {
      TIMER_DELAY;
      buf[3] = K_LINE.read();
      message_size = buf[3];
      Serial.print("message_size:");
      Serial.println(message_size);
      if (message_size > bufsize) message_size = bufsize;
      checksum = 0;
      header = 4;
    }
    
    // пишем тело сообщения
    if (header == 4 && Delay && j < message_size + n + 1) {
      buf[j] = K_LINE.read();
      if (j < message_size + n) checksum += buf[j];  // подсчёт КС
      if (j == message_size + n) {
        Serial.println("header 5");
        header = 5;
      }
      TIMER_DELAY;
      j++;
    }
  }  // end of K_LINE.available()

  // сообщение приняли, действуем
  if (header == 5) {
    TIMER_DELAY;
      
    for (byte i = 0; i < n; i++) checksum += buf[i];  // прибавляем к контрольной сумме старт байты
    
    Serial.print(F("Receive from PCM:     "));
    for (byte i = 0; i < message_size + n + 1; i++) {
      if (buf[i] <= 0x0F) Serial.print(F("0"));
      Serial.print(buf[i], HEX);
      Serial.print(" ");
    }  // Отладка в монитор порта
    Serial.println();

    // если контрольная сумма верна:
    if (buf[message_size + n] == checksum) {
      prevInit = curmillis;  // сбрасываем таймер сброса инита, если получили хоть какое-то сообщение от ЭБУ

      if (buf[n] == 0xC1) Init = 1;  // если пришёл ответ на запрос инита, делаем инит прошёл успешно

      // ниже если получили длинный ответ от ЭБУ с параметрами парсим его, я взял только температуру   ДВС
      else if (buf[n] == 0x61 && buf[n + 1] == DataRequest[1]) {
        Temperature = buf[n + 10] - 40;
        Serial.print(F("TempEngine: "));
        Serial.println(Temperature);
      }

      // ТУТ ЧТО НИБУДЬ ДЕЛАЕМ КОГДА ПОЛУЧИЛИ СООБЩЕНИЕ ОТ ЭБУ
    }

    // если контрольная сумма не совпала:
    //else Serial.println("CRC fail!!!" );
    message_size = 0;
    header = 0;
    RESETheader_timer = 0;
    j = 3;
    checksum = 0;
  }



  // таймер ожидания байт (для успевания появления данных в буфере UART)
  if (!Delay && curmillis - timerdelay > waitbyte_RX) Delay = 1;

  // таймер сброса заголовка если данные оборвались во время приёма заголовка
  if (RESETheader_timer && curmillis - prevRESETheader > 500) {
    RESETheader_timer = 0;
    header = 0;
  }
}

если отправлять 81 7a f1 81 6d 83 f1 7a c1 d0 8f 0e на ответ 81 7a f1 81 6d все нормально
а вот на 82 7a f1 21 aa b8 если отправить 82 7a f1 21 aa b8 9a f1 7a 61 AA 00 94 00 00 00 4A 00 00 00 00 03 20 03 22 01 00 00 04 00 00 03 FF 00 00 , то в ответ ничего не приходит. И при просмотре через Serial Port Monitor наблюдается обрыв чтения ответа вроде как

Покажите мне в коде, где вы такое отправляете? - я никаких отправок, кроме

в коде не вижу.

я подключил ардуино к программатору CH341 через спаянные микросхемы соединённые между собой и через запущенные 2 Serial Port Monitor смотрю 2 порта. Через ардуино отправляется 81 7a f1 81 6d в порт программатора автоматически постоянно, пока в ответ не придет 81 7a f1 81 6d 83 f1 7a c1 d0 8f 0e (этот ответ я отправляю через ch341 порт). После получения идет отправка 82 7a f1 21 aa b8 и в ответ я отсылаю 82 7a f1 21 aa b8 9a f1 7a 61 AA 00 94 00 00 00 4A 00 00 00 00 03 20 03 22 01 00 00 04 00 00 03 FF 00 00. Когда я отсылаю 81 7a f1 81 6d 83 f1 7a c1 d0 8f 0e все нормально приходит и на Serial Port Monitor открытый порт ардуино печатается Receive from PCM: 83 f1 7a c1 d0 8f 0e
А вот на 82 7a f1 21 aa b8 не проходит, пробовал для отслеживания в if (header == 4 && Delay && j < message_size + n + 1) добавлять Serial.println для отслеживания, но как бы идет обрыв или потеря данных.

Я не проверял каждый байт, но похоже что в коротком ответе вы добавляете CRC в конце, а в длинном ответе нет… разве что так совпало что CRC у вас 00

проверка проходит в if (header == 5) но оно даже не доходит до при срабатывании if (header == 5) должно выводит Serial.print(F("Receive from PCM: "));
Если вдруг дульный совет будет спасибо. А так сам буду тогда копать дальше в чем проблема

ну так добавьте вывод в Сериал для каждого вашего шага header == 0, 1, 2, 3… и хоть поймете, в каком месте оно затыкается.

попробовал добавить сериал для вывода buf[j] выводить все отправленные данные 61 AA 00 94 00 00 00 4A 00 00 00 00 03 20 03 22 01 00 00 04 00 00 03 FF 00 00 , хотел понять почему не срабатывает

Добавил вывод j, n, message_size для проверки отчего же не срабатывает, а тут приходит неполный ответ 61 AA 00 94 00 00 00 4A 00 00 00 00 03 20 03 22 01 00 00 04 00 00 03, в общем фиг его пойми пока. буду дальше копать

вы не поняли.
У вас сейчас прием каждого байта сообщения - это новое условие. header == 0, 1, 2, 3
Вот в каждое условие и добавьте вывод, чтобы видеть, на каком шаге вы спотыкаетесь.
Что вы в потемках бродите

1 лайк

В общем добавил и вот что видно - что ответ приходит вроде как. Так же добавил в header=4 отображение что приходит. Непонятно почему в в header=5 переключается

81 7a f1 81 6d 83 f1 7a c1 d0 8f 0e 
header 0
header 1
header 0
header 0
header 1
header 0
header 1
header 2
header 4
C1
header 4
D0
header 4
8F
header 4
0E
header 5

Receive from PCM:     83 F1 7A C1 D0 8F 0E 

82 7a f1 21 aa b8 9a f1 7a 61 aa 00 94 00 00 00 4a 00 00 00 00 03 20 03 22 01 00 00 04 00 00 03 ff 00 00 
header 0
header 1
header 0
header 0
header 0
header 1
header 0
header 1
header 2
header 4
61
header 4
AA
header 4
00
header 4
94
header 4
00
header 4
00
header 4
00
header 4
4A
header 4
00
header 4
00
header 4
00
header 4
00
header 4
03
header 4
20
header 4
03
header 4
22
header 4
01
header 4
00
header 4
00
header 4
04
header 4
00
header 4
00
header 4
03
header 4
FF
header 4
00
header 4
00

А если добавить в header=4 вывод message_size, то приходит не полный ответ и сбрасывается на header=0

81 7a f1 81 6d 83 f1 7a c1 d0 8f 0e 
header 0
header 1
header 0
header 0
header 1
header 0
header 1
header 2
header 4
C1
message_size:3
header 4
D0
message_size:3
header 4
8F
message_size:3
header 4
0E
message_size:3
header 5

Receive from PCM:     83 F1 7A C1 D0 8F 0E 

82 7a f1 21 aa b8 9a f1 7a 61 aa 00 94 00 00 00 4a 00 00 00 00 03 20 03 22 01 00 00 04 00 00 03 ff 00 00 
header 0
header 1
header 0
header 0
header 0
header 1
header 0
header 1
header 2
header 4
61
message_size:26
header 4
AA
message_size:26
header 4
00
message_size:26
header 4

94
message_size:26
header 4
00
message_size:26
header 4
00
message_size:26
header 4
00
message_size:26
header 4
4A

message_size:26
header 4
00
message_size:26
header 4
00
message_size:26
header 4
00
message_size:26
header 4
00
message_size:26
header 4
03
message_size:26
header 4
20
message_size:26
header 4
03
message_size:26
header 4
22
message_size:26
header 4
01
message_size:26
header 0
header 0
header 0
header 0
header 0
header 0
header 0
header 0
header 0

в общем перенес j++; перед сравнениями и вроде как заработало. Только с checksum придётся попрощаться потому как не все ответы в конце checksum имеют.