CAN Bus example for MRMS Thermal Array Sensor, CAN Bus (mrm-therm-b-can)


If not already done so already, install Arduino software and make basic connections, as described in page for MRMS ESP32: Arduino, IMU, eFuse, BT, WiFi, CAN Bus (mrm-esp32). This setup is convenient, but it is not mandatory. Read on and we will describe how to connect some other microcontroller and power supply.

This setup is necessary for the rest of ML-R system. If You want to try just this example, don't copy all the libraries but only directories "mrm-common" and "mrm-can-bus". They provide CAN Bus support, but again just for ESP32 microcontroller, ML-R or any other. If You want to use some other MCU, You will have to start its CAN Bus driver. If You do so, this example will work for that board, too.


We will order the thermal array to start measuring temperature and sending back the results every few milliseconds.


Starting from a basic connection, let's add a MRMS Thermal Array Sensor, CAN Bus (mrm-therm-b-can). Connecting a ML-R CAN Bus device is easy. Only a cable, like MRMS CAN Bus cable 10 cm (mrm-jst-can10), is necessary. The cable will connect 2 CAN Bus lines (low and high) and will also supply 0 V and 5 V through 3. and 4. wire.

However, this bus is not only intended for ML-R devices, but for any other CAN Bus compatible. You can read here how to connect Your boards to ML-R CAN Bus. For this board, Dupont 0.1" connector is located on the left of the board in the picture left.


The program is short, but it hides some of the details in Mrm_can_bus class:

#include <mrm-can-bus.h>


Mrm_can_bus can;

uint8_t data[8];        // Message content: 8 bytes

void setup() {

  data[0] = COMMAND_SENSORS_MEASURE_CONTINUOUS;  // First byte of the content
  for (uint8_t i = 0; i < 8; i++)
    can.messageSend(0x210 + 2 * i, 1, data); //0x210, 0x212, ... , 0x21E.

void loop() {
  // Receive a message
  CANBusMessage* msg = can.messageReceive();
  if (msg != NULL && msg->data[0] ==  COMMAND_SENSORS_MEASURE_SENDING){
    uint16_t deg = (msg->data[2] << 8) | msg->data[1];
    Serial.println(" deg C");

The program uses Mrm_can_bus to access ESP32s CAN Bus hardware. setup() starts serial communication with PC so that Serial.print() can display the results. Array data is payload CAN Bus messages use. First we will use it for an outgoing message and so we set its first byte to COMMAND_SENSORS_MEASURE_CONTINUOUS. That's the command we'd like to execute. It will instruct the sensor to start sending measurement data continually. As You can have more temperature sensors of this kind in Your CAN Bus, each is supposed to listen to just one message id. The whole range is covered by the loop that follows: 0x210, 0x212,..., 0x21E. You can change address the sensor listens to but You may not know how the one You have is set up. So, we start them all.

loop() receives messages. You should be familiar with CAN Bus message structure to understand data sent and received. When a message is received, the program will check first byte of the payload to see if it is a measurement result. If it is, it will convert bytes 2 and 3 into degrees Celsius and will print the result.

You can use an oscilloscope or a logic analyzer to check the signals.

The program uses mrm-can-bus library which can be found in C:\Users\<Your login name>\Documents\Arduino\libraries\mrm-can-bus\src. Open mrm-can-bus.cpp in an editor. Notepad++ is a good choice. If You want to change bus speed from the default 250 kbps, find line with "CAN_TIMING_CONFIG_250KBITS" and change the constant. If You like to have messages' content displayed, change "#define VERBOSE 0" into "#define VERBOSE 1". This library is based on Espressif's native driver so Espressif original documentation will give You all the information.

If You use ML-R CAN Bus devices, by far the easiest option for CAN Bus usage will be to stick to the ML-R framework which takes care about messaging so CAN Bus layer is not exposed at all. When You demand MRMS Thermal Array Sensor, CAN Bus (mrm-therm-b-can) to return a measured temperature, You just call a function. The framework takes care that the reasonably fresh result is supplied. The details of this work are not so easy to replicate.

This thermal sensor can supply raw data, all the 8x8 measurement points, not just the maximum of them, as in our example. If You need all the data, contact support and we will enhance firmware's functionality.

Here is the complete CAN Bus interface:
CommandMCU -> sensorSensor -> MCUComment
Firmware0x190x1A LowByte HighByteFirmware version = (HighByte << 8) & LowByte.
FPS0x300x31 LowByte HighByteFrames Per Second (sensor's local loop frequency) = (HighByte << 8) & LowByte.
Id change0x40 NewIdChanges message's id the sensor listens to. It is close to its address. Valid NewId values are 0 - 7. Each value chooses addresses in the range: 0x210, 0x214,..., 0x21E. 0 chooses 0x210, 1 0x212, etc.
Alive0xFF id0xFFIf the sensor with address "id" is present, it will return the message.
Measure once0x110x13 LowByte HighByteMeasures just once and returns the result. Result in deg C = (HighByte << 8) & LowByte
Measure continuous0x100x13 LowByte HighByteInitiates measuring and returning of the measured distance each few ms, if the distance changes. Result in deg C = (HighByte << 8) & LowByte.
Stop measuring0x12

CAN Bus limitations

For 1 node You will have no problems. If You plan to have many of them, check this page.