2
\$\begingroup\$

I need help in sending float-type values over CANBUS.

I'm working on data acquisition of an fsae car. I'm using Teensy 4.1 and Teensy 3.5 using MCP2562 and MCP2551 CAN transceivers (respectively) to send and receive an Array sensor data for Wheel temperature (MLX90460) and I need to send and receive the data down to its decimal point and might need to send and receive the data up to 150 celsius / 302 Fahrenheit. (I'm using Arduino IDE and Platform IO to code)

  1. Is it possible?
  2. If Q1 is yes, then how?
  3. Is it commonly used to send and receive float value over CANBUS?
\$\endgroup\$

3 Answers 3

3
\$\begingroup\$

Canbus is a pipe where you dump messages. The interpretation of the payload of the messages is up to each node. In a custom system, where all nodes run code you control, you're the boss as to what bits go into any message.

Is it commonly used to send and receive float value over CANBUS?

Sure! It's rather convenient, because most sensible MCU platforms use IEEE-754 float representation, and if you're using them in one project then likely they have same endianness too. So you can send C float fields as raw data by memcpy-ing them from a float field into the send buffer on the transmit side, and then memcpy-ing them back from the send buffer into a float field. Modern compilers (e.g. gcc used for ARM) optimize small memcpy into small inline assembly code. memcpy is then not a literal function call, but telling the compiler "hey, I want to move some bytes of data from here to there, figure it out". memcpy's semantics are important in this respect. There are other ways of "moving data around" using pointer arithmetic and whatnot, and they often are undefined behavior if the type of the data changes. So memcpy is a good choice, at least for a beginner not deep into the semantics of C or C++ (they differ a lot too!).

The classic CAN frame has room for up to 8 bytes of payload. So you can stick one 64-bit double or two 32-bit floats in a CAN frame.

Note: Some C platforms have same size for float and double datatypes - this is allowed by the standard. But all IEEE-754 platforms have float being exactly 4 bytes long, and that should be plenty of resolution for temperature measurements in typical automotive environments.

And you can always make sure - by adding a static assert in the code, so that the compiler will complain if assertions are false:

#include <assert.h>

static_assert(sizeof(float) == 4, "This program needs a 32-bit float type to work");

Static assertions can be inside functions our outside of them in global scope. They'll work the same, since they have no runtime effect. They just help avoid mistakes/problems that the compiler is able to statically detect. Compile-time errors are much easier to figure out than runtime errors :)

\$\endgroup\$
2
\$\begingroup\$

CAN messages are just bits of data.

Float numbers are just bits of data.

  1. Yes, sending floats is possible

  2. Just send the float number in any way you want, there are different representations for different float types and standards. You can even convert it to text string and send the digits. Or you can use the same format you read the data from somewhere and send it as is to somewhere else and let it handle the conversion or interpretation.

  3. Hard to say, as the bits can represent anything you want them to represent.

\$\endgroup\$
1
  • \$\begingroup\$ #3 It is actually easy to say. Most of the higher-level protocols based on CAN support floating point data, e.g. CANOpen, DeviceNet etc. So, yes, it is pretty common. \$\endgroup\$
    – Maple
    Aug 31 at 19:01
1
\$\begingroup\$

Is it possible?

Certainly. With 8 byte data payload of classic CAN, you can fit one 64 bit or two 32 bit numbers in a single frame. Larger numbers would be possible to transmit across several frames, ideally though some higher layer protocol.

If Q1 is yes, then how?

You may have to write a document stating the floating point format and network endianess, since both of these are fundamental to getting anything understood by multiple CPUs.

Is it commonly used to send and receive float value over CANBUS?

It is not common. CAN bus most often exists in deterministic, real-time systems where:

  1. floating point is often not used at all. Low to mid-range MCUs won't even have a FPU.
  2. exposing floating point outside an encapsulated part of the design probably doesn't make any sense.
  3. floating point still doesn't mean "I need decimals" like the would-be embedded programmers coming from the PC world always believe, see this.

A more common format is to use pure raw data (CANopen is one example). For example take a 32 bit unsigned number, then state something like "0 means 0mA, 4294967295 means 20mA". Each node can then re-scale these as needed. Notably this format has higher precision than a 32 bit float and no inaccuracy problematic other than rounding errors.

Most sensors and (SAC) ADC out there will use a resolution between 2^8 to 2^16, meaning using numbers much larger than 65535 (16 bits) is just false accuracy in many cases anyway.

\$\endgroup\$
1
  • \$\begingroup\$ I probably wouldn't map the nominal range to the whole U32 range (0..0xFFFFFFFF). I'd leave some wiggle room for out-of-nominal-range values. But on the whole I agree with both answers. \$\endgroup\$
    – Velvet
    Sep 7 at 9:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.