cancel
Showing results for 
Search instead for 
Did you mean: 

OBD2 request frames rejection issues

MR17
Associate II
I tried doing an OBD2 request via Car's OBD2 port.

I am able to see the CAN BUS traffic using an oscilloscope , just my request frames are rejected by car. I am using STM32h735G-DK development board to send OBD2 requests. It consists of an inbuilt FDCAN transceiver.

Settings are fine (removed termination resistor as car already has two), baudrate is 500kbps  with 87.5% sample point. I am using the following code to send OBD2 request frames:

I am able to receive CAN frames and able to log CAN frame frames it is just that frames sent are rejected. What am i doing wrong here?

FDCAN Code excerpt:
 
/* ============ 500 kbit/s Bit Timing Derivation ============
   *
   * Step 1: FDCAN Kernel Clock
   *   fCAN = 80 MHz (from Clock Configuration)
   *
   * Step 2: Prescaler
   *   Prescaler = 10
   *
   * Step 3: Time Quantum (tq)
   *   tq = Prescaler / fCAN
   *   tq = 10 / 80,000,000 Hz = 0.125 µs = 125 ns
   *
   * Step 4: Bit Segments (in TQ)
   *   Sync Segment   = 1 TQ  (fixed, always 1)
   *   Time Segment 1 = 12 TQ (Prop_Seg + Phase_Seg1)
   *   Time Segment 2 = 3 TQ  (Phase_Seg2)
   *
   * Step 5: Total Time Quanta per Bit
   *   Total TQ = Sync + TS1 + TS2 = 1 + 12 + 3 = 16 TQ
   *
   * Step 6: Bit Time
   *   Bit Time = Total TQ × tq = 16 × 125 ns = 2000 ns = 2 µs
   *
   * Step 7: Nominal Bit Rate
   *   Bit Rate = 1 / Bit Time = 1 / 2 µs = 500 kbit/s
   *
   * Step 8: Sample Point
   *   Sample Point = (Sync + TS1) / Total TQ = (1 + 13) / 16 = 87.5%
   *
   */ 
  ----------------
  MX_FDCAN2_Init();

  -----------------
  FDCAN_FilterTypeDef sFilterConfig;
  sFilterConfig.IdType = FDCAN_STANDARD_ID;
  sFilterConfig.FilterIndex = 0;
  sFilterConfig.FilterType = FDCAN_FILTER_MASK;         /* Classic ID + mask mode          */
  sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; /* Matching frames → RX FIFO 0     */
  sFilterConfig.FilterID1 = 0x7E8;                      /* Expected ECU response base ID   */
  sFilterConfig.FilterID2 = 0x7F8;                      /* Mask: match 0x7E8 – 0x7EF       */
  if (HAL_FDCAN_ConfigFilter(&hfdcan2, &sFilterConfig) != HAL_OK) {
    Error_Handler();
  }
  /* Reject all non-matching frames (no global accept) */
  if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan2, FDCAN_REJECT, FDCAN_REJECT, FDCAN_REJECT_REMOTE, FDCAN_REJECT_REMOTE) != HAL_OK) {
    Error_Handler();
  }

  if (HAL_FDCAN_Start(&hfdcan2) != HAL_OK) {
    Error_Handler();
  }

  -----------------
  static void MX_FDCAN2_Init(void) {

  /* USER CODE BEGIN FDCAN2_Init 0 */

  /* USER CODE END FDCAN2_Init 0 */

  /* USER CODE BEGIN FDCAN2_Init 1 */

  /* USER CODE END FDCAN2_Init 1 */
  hfdcan2.Instance = FDCAN2;
  hfdcan2.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
  hfdcan2.Init.Mode = FDCAN_MODE_NORMAL;
  hfdcan2.Init.AutoRetransmission = ENABLE;
  hfdcan2.Init.TransmitPause = DISABLE;
  hfdcan2.Init.ProtocolException = DISABLE;
  hfdcan2.Init.NominalPrescaler = 10;
  hfdcan2.Init.NominalSyncJumpWidth = 1;
  hfdcan2.Init.NominalTimeSeg1 = 13;
  hfdcan2.Init.NominalTimeSeg2 = 2;
  hfdcan2.Init.DataPrescaler = 1;
  hfdcan2.Init.DataSyncJumpWidth = 1;
  hfdcan2.Init.DataTimeSeg1 = 1;
  hfdcan2.Init.DataTimeSeg2 = 1;
  hfdcan2.Init.MessageRAMOffset = 0x000;
  hfdcan2.Init.StdFiltersNbr = 1;
  hfdcan2.Init.ExtFiltersNbr = 0;
  hfdcan2.Init.RxFifo0ElmtsNbr = 32;
  hfdcan2.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
  hfdcan2.Init.RxFifo1ElmtsNbr = 0;
  hfdcan2.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
  hfdcan2.Init.RxBuffersNbr = 0;
  hfdcan2.Init.RxBufferSize = FDCAN_DATA_BYTES_8;
  hfdcan2.Init.TxEventsNbr = 0;
  hfdcan2.Init.TxBuffersNbr = 0;
  hfdcan2.Init.TxFifoQueueElmtsNbr = 32;
  hfdcan2.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
  hfdcan2.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
  if (HAL_FDCAN_Init(&hfdcan2) != HAL_OK) {
    Error_Handler();
  }
  /* USER CODE BEGIN FDCAN2_Init 2 */

  /* USER CODE END FDCAN2_Init 2 */
}

-----------------
/* This callback is triggered by TIM1 overflow every 1 second to send an OBD-II RPM request frame */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) { 
  if (htim->Instance == TIM1) {
    FDCAN_TxHeaderTypeDef TxHeader;
    uint8_t TxData[DATA_LEN] = {0};
    TxHeader.Identifier = 0x7E0; // OBD-II request ID for Engine ECU, cycled through 0x7E0-0x7E7 for different ECUs, same rejection issue
    TxHeader.IdType = FDCAN_STANDARD_ID;
    TxHeader.TxFrameType = FDCAN_DATA_FRAME;
    TxHeader.DataLength = FDCAN_DLC_BYTES_8;
    TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
    TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
    TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
    TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
    TxHeader.MessageMarker = 0;
    TxData[0] = 0x02; // SF, 2 data bytes
    TxData[1] = 0x01; // Service 01
    TxData[2] = 0x0C; // PID 0C — RPM

    HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan2, &TxHeader, TxData);
  }
}
20 REPLIES 20
Andrew Neil
Super User

Perhaps this example by @Gretchev can help you: Simple Classic CAN + FreeRTOS Demo simulating OBD and a vehicle ?

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

 


@mƎALLEm wrote:

What clock source are you using for FDCAN? HSI or HSE+Crystal?  if HSI, please use HSE + a crystal or any other external precise source.

 


Please find the Clock configuration in the attached files.

I must confess few days back i saw my request frames on the bus ACKed by some node on the car. Do you perhaps think the clock source is not stable enough?

Indeed you are using HSI. It’s recommended to use HSE and a crystal for CAN communication. I don’t have my PC now (i’m posting with my phone) but the disco board has already a crystal (crystal oscillator XO).
So please use it instead of HSI:

IMG_4830.png

You shoud select HSE in bypass mode and set the crystal value to 25MHz in the clock view.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

@mƎALLEm wrote:

But that doesn’t make sense if his can node is receiving well the frames from the car. That seems to be not a baudrate issue but more related to a jitter or something similar.


That is where I think the problem could be related , as I was seeing frames validated by car few days back but still there was no response from the car(this is secondary problem). Will also attach the file when my frames became valid and ACKed. Filter Columns using 7E.


@mƎALLEm wrote:

Indeed you are using HSI. It’s recommended to use HSE and a crystal fir CAN communication. I don’t have my PC now but the disco board has already a crystal. So please use it instead of HSI.


will definitely try it tomorrow, as per my code , do i have to better handle FreeFiFolevel? as when i changed the ID to a different address i still saw probably queue FiFo appear on the bus which was ODD.

edit: @mƎALLEm Please see if the configs are fine , i was able to get 500kbps bitrate with HSE as BYPASS Clock Source and FDCAN kernel Clock 25 Mhz resulting to 80% sample point. Hope it is valid sample point,

will definitely have a look

LCE
Principal II

Still not clear:

Do you receive the car's messages on the bus in the STM32 ?

MR17
Associate II

@LCE wrote:

Still not clear:

Do you receive the car's messages on the bus in the STM32 ?



yes, i do !
Seems like clock source might be the issue like @mƎALLEm mentioned. As receiving frames are different from sending frames on the CAR's CAN Bus as slight drift cannot be tolerated.

Sample point set at 80% works but the recommended sample point is at 87.5% of the bit time as you mentionned in your first post.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

Because the OP seems to receive CAN packets correctly, and BRS is off (or is it used on the bus?), and at the bit rate of 500kbit, this should not matter too much when transmitting - or does it?

Maybe for getting the ACK correctly?

2000 ns * 80.0% SP -> 1600 ns

2000 ns * 87.5% SP -> 1750 ns

-> delta 150 ns

Hmm, can't imagine that this is the problem, but it's worth a try to reduce TS1 by 1 and increase TS2 by 1.