2024-01-18 05:47 AM
I'm attempting to interface an STM32G473 with a VESC motor controller using CAN.
I am successfully receiving status frames from the VESC controller, but when I transmit a frame to command it, the ID my scope reads in the frame is not always the same as what I set in my code. It appears to always set bit 0.
For example, if I set an extended ID of 0, my scope reads an ID of 1. Setting the ID to 1 in code results in the same waveform. I've attached waveforms for IDs 0 and 1. The problem persists for other IDs, so 88 becomes 89 etc.
I've used CubeMX to configure FDCAN1 for 500kbps, which gave me this at 150MHz clock:
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1;
hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan1.Init.AutoRetransmission = DISABLE;
hfdcan1.Init.TransmitPause = DISABLE;
hfdcan1.Init.ProtocolException = DISABLE;
hfdcan1.Init.NominalPrescaler = 20;
hfdcan1.Init.NominalSyncJumpWidth = 1;
hfdcan1.Init.NominalTimeSeg1 = 12;
hfdcan1.Init.NominalTimeSeg2 = 2;
hfdcan1.Init.DataPrescaler = 1;
hfdcan1.Init.DataSyncJumpWidth = 1;
hfdcan1.Init.DataTimeSeg1 = 1;
hfdcan1.Init.DataTimeSeg2 = 1;
hfdcan1.Init.StdFiltersNbr = 0;
hfdcan1.Init.ExtFiltersNbr = 0;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
I start it with:
HAL_FDCAN_Start(&hfdcan1);
HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
Once started, receiving works as expected.
I then have this for transmitting, with a temporary test assignment for the ID:
FDCAN_TxHeaderTypeDef header; header.Identifier = id; header.IdType = FDCAN_EXTENDED_ID; header.TxFrameType = FDCAN_DATA_FRAME; header.DataLength = FDCAN_DLC_BYTES_8; header.FDFormat = FDCAN_CLASSIC_CAN; header.MessageMarker = 0; const uint32_t tmp_id = 0; header.Identifier = tmp_id; std::array<uint8_t, 8> buffer = {0}; if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &header, buffer.data()) != HAL_OK) { const auto can_errno = HAL_FDCAN_GetError(&hfdcan1); LOG_ERROR("Failed to add message to FDCAN1 TX FIFO, error={}", can_errno); }
I'm not sure what I'm missing or have misunderstood.
Solved! Go to Solution.
2024-01-19 07:58 AM - edited 2024-01-19 07:59 AM
Hello,
Could you please attach a simple C project in LoopBack mode where you send two frames with IDs 0x0 and 0x1 and the filtering is done only on 0x1? please remove all the stuff not related to the tested FDCAN.
So I will look at and test it next week (when I have time).
2024-01-18 08:11 AM
Hello,
This behavior is strange.
Did you already test it with filters. I mean for example do a test in loopback mode and try to filter on one ID and see if the two IDs are accepted or not.
2024-01-18 08:52 AM
Are you sure the scope is decoding the way you expect?
Is this showing the IDE bit?
What if you send Standard ID forms? Examples from other devices / transmitters?
2024-01-19 02:12 AM
My bus will only ever have the two devices and I'm interested in all messages, so initially I did not filter anything.
Running in internal loopback mode with this filtering, and with nothing else connected:
HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_REJECT_REMOTE, FDCAN_REJECT_REMOTE);
FDCAN_FilterTypeDef sfilter;
sfilter.IdType = FDCAN_EXTENDED_ID;
sfilter.FilterIndex = 0;
sfilter.FilterType = FDCAN_FILTER_RANGE;
sfilter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sfilter.FilterID1 = 0x00000001;
sfilter.FilterID2 = 0x00000001;
if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sfilter) != HAL_OK) {
Error_Handler();
}
The filtering works as I would expect here. The messages I receive all have an ID of 1.
But the frame I transmit with an ID set to 0 is still accepted, and the incoming frame reports an ID of 1.
From my logging I get these lines printed, where I simply log the IDs of outgoing and incoming frame while incrementing the ID.
Sending CAN frame: ID=0x00000000
Received CAN frame: ID=0x00000001
Sending CAN frame: ID=0x00000001
Received CAN frame: ID=0x00000001
Sending CAN frame: ID=0x00000002
Sending CAN frame: ID=0x00000003
Sending CAN frame: ID=0x00000004
Sending CAN frame: ID=0x00000005
Opening the range a bit with ID2 = 0x00000003 gives me this:
Sending CAN frame: ID=0x00000000
Received CAN frame: ID=0x00000001
Sending CAN frame: ID=0x00000001
Received CAN frame: ID=0x00000001
Sending CAN frame: ID=0x00000002
Received CAN frame: ID=0x00000003
Sending CAN frame: ID=0x00000003
Received CAN frame: ID=0x00000003
Sending CAN frame: ID=0x00000004
Sending CAN frame: ID=0x00000005
Sending CAN frame: ID=0x00000006
2024-01-19 02:24 AM
When it decodes the frames sent by the VESC drive it looks as I would expect. It also matches what is logged when I receive it on my STM32.
Changing the ID type to FDCAN_STANDARD_ID removes this odd behaviour. Then the ID's I transmit match the exact ID I receive.
If I change the VESC driver ID to 0 and switch back to normal mode, I do receive the ID I would expect. It ORs a command and an ID together for a status message, 0x900 for command ID and 0x00 for device ID. My received ID is 0x900, so that's good.
It seems that this is only a problem when I try to transmit odd IDs from the STM32 using extended frames then.
2024-01-19 07:58 AM - edited 2024-01-19 07:59 AM
Hello,
Could you please attach a simple C project in LoopBack mode where you send two frames with IDs 0x0 and 0x1 and the filtering is done only on 0x1? please remove all the stuff not related to the tested FDCAN.
So I will look at and test it next week (when I have time).
2024-01-22 02:47 AM