pschichtel/JavaCAN

Unable to send Frame with Extended Frame Format

Dragos-Ioan opened this issue · 8 comments

Hello,

First of all, thank you for your contributions, this is really easy to use and fast to setup.

I am trying to send a Can Frame with extended frame format. After looking in your code i did not see an option to manually set an ID as EFF and in the comments for CanFrame.Create it said it returns the full 32 bits so I assumed there is nothing for me to do there.

I am using the following code to send the frame:
socket.write(CanFrame.create(0x144201AA, FD_NO_FLAGS, messageData));

When I read back this frame it comes back as ID = 1AA and isExtended() returns false.

Could you please help in finding what I'm doing wrong here ?
Much appreciated

Sorry for the late response, turns out I don't get notifications for my own repository :O
I'll look into this probably towards the weekend. I guess you tried this against a vcan adapter, right? I haven't done much testing with EFF.

Also: Would it be possible to share (some of) the code?

Just had a quick look at it: Your ID does not carry the EFF bit (see CanId), that's why only the SFF-part is available.

Okay, I suspected I did not set something right.
From my prior understanding an extended ID is simply an ID length 8. I did look for functions in the code to manually set EFF flag.
Unfortunately, I do not have the freedom to change the ID (i have to send this exact ID since it's the one recognized).
Could you possibly give me an example of an EFF ID that is recognized as EFF ? I can adapt my code from there so you don't have to change anything.

To answer your previous questions, I am not using vcan, I have an extension board that uses 2 mcp2517fd transcievers.
I set them using socketCAN and the "ip link set can0 up type can bitrate 250000 dbitrate 500000 fd on" command.
This part is working as expected and cansend is sending both standard and fd frames.

//Initialization
final RawCanChannel raspiSocket = CanChannels.newRawChannel();
raspiSocket.setOption(FD_FRAMES, true);
raspiSocket.bind(NetworkDevice.lookup("can0"));
//I can leave it as block since it seems to work fine this way and I am able to send standard frames.
//Sending. This is hardcoded to test.
raspiSocket.write(CanFrame.create(0x144201AA, FD_NO_FLAGS, messageData));

Thanks for your support !

Unfortunately, I do not have the freedom to change the ID (i have to send this exact ID since it's the one recognized).

The EFF CAN IDs are only 29 bits long, SocketCAN (ab)uses the 3 most significant bits for certain can flags. I carried that logic over to a) be consistent and b) for performance.

socket.write(CanFrame.create(0x144201AA, FD_NO_FLAGS, messageData));

So you can simply fix this by OR-ing in the CanId.EFF_FLAG:

socket.write(CanFrame.create(0x144201AA | CanId.EFF_FLAG, FD_NO_FLAGS, messageData));

This will not actually change the CAN ID, as the change happens to the most sigificant bit only, which will not actually be transmitted.

Have a look at these *_FLAG and *_MASK fields:
https://github.com/pschichtel/JavaCAN/blob/master/src/main/java/tel/schich/javacan/CanId.java#L30-L58

You are right, OR-ing the flag solved it.
I did not think about OR-ing the EFF flag myself, my bad. I just concluded that, since there is no "setEFF" function, the code verifies the length and sends the ID as EFF. Hence my question.
Thanks a lot for your input and the code example, that really helped.
Please feel free to close this issue since there is nothing to change on your side (as expected).

It would be nice to be able to check for the address length, problem is: socketcan always expects an 32 bit integer. At one point I modelled the SFF/EFF state more explicitly, but dropped it as the overhead of the conversions did not seem worth it for that slight usability advantage. Especially since this is intended more as a low-level framework. Sadly Java does not support opaque type aliases to differentiate the address types purely on the type level.

I will keep this open for the moment, because I'm not fully satisfied with the current state either and your issue confirmed my suspicion once more.

The method CanFrame.create will now enforce SFF ids and the new CanFrame.createExtended will enfore the id to be an EFF id. The original CanFrame.create is now CanFrame.createRaw which still intepretes the full 32bit of the given integer, but that should rarely be necessary.