CAN Bus example for MRMS ESP32: Arduino, IMU, eFuse, BT, WiFi, CAN Bus (mrm-esp32)


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 above 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 send a simple CAN Bus message to a device and listen to its reply.


Starting from a basic connection, let's add a MRMS LIDAR 2m VL53L0X, CAN Bus (mrm-lid-can-b) or any other CAN Bus device, ML-R or some other. 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.


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;
uint32_t ms = 0;

void setup() {

void loop() {

  // Send a message
  if (millis() - ms > 1000){
    uint32_t stdId = 0x180; // Message id
    uint8_t dlc = 1;        // Message byte count
    uint8_t data[8];        // Message content: 8 bytes
    data[0] = 0xFF;         // First byte of the content
    can.messageSend(stdId, dlc, data);
    printf("Message sent\n\r");
    ms = millis();

  // Receive a message
  if (can.messageReceive()){
    printf("Message received\n\r");
The program uses mrm-can-bus library to access ESP32s CAN Bus hardware. setup() just starts serial communication with PC so that printf() can display the results.

loop() sends a message in the first part and receives one in the second. You must be familiar with CAN Bus message structure to understand data sent and received. There must be at least 1 CAN Bus device attached to MRMS ESP32: Arduino, IMU, eFuse, BT, WiFi, CAN Bus (mrm-esp32). The device's filter should pass messages with id 0x180, as it is the case for MRMS LIDAR 2m VL53L0X, CAN Bus (mrm-lid-can-b), when configured as first device of its kind. If Your device responds to a different message id, change 0x180 into appropriate value. You may also be forced to change data transfer rate and the message content. The content is fine for the attached lidar and for all ML-R devices.

Even if no device responds to id 0x180, the program will print "Message sent" every 1 sec. You can use an oscilloscope or a logic analyzer to check the signals. If there is a device that listens to 0x180 (it passes it CAN Bus incoming message filter), and if it sends a message in response, You will get additional message "Message received" after each message sent. This response is expected from every ML-R device because 0xFF forces them to respond with the same content, 0xFF. Its purpose is to find if the device is active.

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 LIDAR 2m VL53L0X, CAN Bus (mrm-lid-can-b) to return a measured distance, 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.

CAN Bus limitations

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