Получение сообщения длиннее 8 байт с CAN шины через MCP 2515

Br1ght
Offline
Зарегистрирован: 30.04.2021

Добрый день. Буду очень благодарен за подсказку с кодом. Я от программирования довольно далек, но в скетче более-менее разобрался, кроме одного момента. 

В целом всё успешно: получаю из КАН-шины ответ на запрос в виде последовательности байт. Затем определенные байты использую для вычисления значений типа RPM, температуры и прочего. Но это работает только с блоками, где ответ на мой запрос не длиннее 8 байт.

Например, я успешно получаю из блока двигателя вот эту строку: 5 62 20 2 B B8. Беру из неё 5 и 6 байты, подставляю в известную мне формулу и всё ок.

float enginePIDs(int parameter) {
  unsigned char PID[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  float retValue = 9999; // возвращаемое значение (если 9999 - ошибка)
  long unsigned int moduleIdRequest = 0x7E0; // id модуля в запросе данных
  long unsigned int moduleIdAnswer = 0x7E8; // id модуля в ответе
  PID[0] = 0x03; // количество байт в запросе   
  PID[1] = 0x22; // префикс PID для запроса
  switch (parameter) {
    case 0:
      // 2002 - PID RPM
      PID[2] = 0x20; PID[3] = 0x02;
      break;
  }
  // посылаем запрос ЭБУ
  CAN1.sendMsgBuf(moduleIdRequest, 0, 8, PID);
  PID[1] = 0x62; // префикс PID для ответа    
  rxId = 0x000; // обнуляем идентификатор
  timeOut = millis() + 500; // крайнее время ожидания ответа
  // ждём нужного ответа
  while ((rxId != moduleIdAnswer || rxBuf[1] != PID[1] || rxBuf[2] != PID[2] || rxBuf[3] != PID[3]) && millis() < timeOut) {
    if (CAN_MSGAVAIL == CAN1.checkReceive()) {
      CAN1.readMsgBuf(&len, rxBuf); // чтение данных: len = data length, buf = data byte(s)
      rxId = CAN1.getCanId(); // получаем ID сообщения
    }
  }
  if (rxId == moduleIdAnswer && rxBuf[1] == PID[1] && rxBuf[2] == PID[2] && rxBuf[3] == PID[3]) {
    // вычисляем параметр, A = rxBuf[4], B = rxBuf[5], C = rxBuf[6], D = rxBuf[7]
    switch (parameter) {
      case 0:
        // RPM
        retValue = (256 * rxBuf[4] + rxBuf[5]) / 4.0;
        break; 
    }
  }
  return retValue;
}

Но другой блок отвечает на запрос сообщением из аж 23 байт. И как нарочно, для вычислений мне нужен 18 байт.

что сделать с CAN1.readMsgBuf(&len, rxBuf) чтобы получить все байты ответа? Как вызвать её три раза так, чтобы 1 раз читались первые 8 байт, потом вторые, потом третьи. Это вообще возможно?

sadman41
Offline
Зарегистрирован: 19.10.2016

Прям так и шлёт, три пакета с одним и тем же ID? В мессейдж мож sequence id засунут?

rkit
Offline
Зарегистрирован: 23.11.2016

В CAN 2.0 пакетов с нагрузкой больше 8 байтов не бывает. Либо у тебя устройство с CAN-FD, и тогда 2515 не пойдет, либо ты что-то путаешь.

Br1ght
Offline
Зарегистрирован: 30.04.2021

вот примеры сообщений:

короткое, из блока двигателя: 7E0;222002;62 20 02 0B D8

длинное, из блока климата, в моем случае: 744;2122;61 22 03 00 00 02 20 00 00 00 34 80 FA 09 00 00 38 02 1B 7E 17 8B 00 00 00 00 00

Br1ght
Offline
Зарегистрирован: 30.04.2021

вот в другом немного формате

двигатель 

22:26:48.611 -> CAN ID: 7E8

22:26:48.644 -> data len = 8
22:26:48.644 -> 5 62 20 02 0B B8   
 
климат 
 
22:31:39.092 -> CAN ID: 764
22:31:39.092 -> data len1 = 8
22:31:39.092 -> 10 1B 61 22 0 0 0 2   ну и дальше в буфер не лезет, собственно)

 

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

Оно не не лезет в буфер, стандарт не даёт в кадрах передавать более 8 байт. Скорее всего от климата несколько фреймов с одним и тем же ID. Вам нужно просто типа склеить несколько кадров по 8 байт

sadman41
Offline
Зарегистрирован: 19.10.2016

Макс, а как там последовательность кадров задается, в этих ваших автомобилях?

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

Не знаю, стандарта нет, это как производителю в голову взбредет. В теле кадра байт на это может быть отведен