M5Dial & CAN using PlatformIO



  • Has anyone got the m5Stack dial to work with the CAN (Controller Area Network) Unit SKU: U085 using PlatformIO?

    I have got all the examples to compile OK but now I want to connect to the CAN unit I get errors.

    Yours Simon M.



  • Hello @samarkh

    which examples have you tried? Maybe this example code can help?

    Thanks
    Felix



  • The solutions I found worked are
    For the M5Dial
    Platform.ini :-

    ; PlatformIO Project Configuration File
    ;
    ; Build options: build flags, source filter
    ; Upload options: custom upload port, speed and extra flags
    ; Library options: dependencies, extra library storages
    ; Advanced options: extra scripting
    ;
    ; Please visit documentation for the other options and examples
    ; https://docs.platformio.org/page/projectconf.html

    [env:m5stack-stamps3]
    platform = espressif32
    board = m5stack-stamps3
    framework = arduino
    lib_deps =
    m5stack/M5Dial@^1.0.2
    m5stack/M5Unified@^0.1.11
    m5stack/M5GFX@^0.1.11
    platform_packages = framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/archive/refs/tags/2.0.14.zip
    upload_speed = 1500000
    monitor_speed = 115200

    Start of code:

    /**

    #include "M5Dial.h"

    void setup()
    {
    auto cfg = M5.config();
    M5Dial.begin(cfg, true, false);
    ......
    .....
    .....
    etc

    and for the M5 Core2
    Platformio.ini =
    ; PlatformIO Project Configuration File
    ;
    ; Build options: build flags, source filter
    ; Upload options: custom upload port, speed and extra flags
    ; Library options: dependencies, extra library storages
    ; Advanced options: extra scripting
    ;
    ; Please visit documentation for the other options and examples
    ; https://docs.platformio.org/page/projectconf.html

    [env:m5stack-core2]
    platform = espressif32
    board = m5stack-core2
    framework = arduino
    platform_packages =
    framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/archive/refs/tags/2.0.14.zip
    lib_deps =
    m5stack/M5Unified@^0.1.11

    upload_speed = 1500000
    monitor_speed = 115200

    and start of code:

    /*

    • Minimum code to get a display on the
    • M5Stack Core2
    • Using PlatformIO and Arduino

    */
    #include <Arduino.h>
    #include <M5Unified.h>
    #include <M5GFX.h>

    void setup()
    {
    M5.begin();
    ....
    etc

    and for the M5Stack Core3S

    Platformio.ini
    ; PlatformIO Project Configuration File
    ;
    ; Build options: build flags, source filter
    ; Upload options: custom upload port, speed and extra flags
    ; Library options: dependencies, extra library storages
    ; Advanced options: extra scripting
    ;
    ; Please visit documentation for the other options and examples
    ; https://docs.platformio.org/page/projectconf.html

    [env:m5stack-cores3]
    platform = espressif32
    board = m5stack-cores3
    framework = arduino
    lib_deps =
    tinyu-zhao/BMI270_Sensor@^0.0.1
    m5stack/M5CoreS3@^0.0.4
    m5stack/M5Unified@^0.1.11
    platform_packages =
    framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/archive/refs/tags/2.0.14.zip

    build_flags =
    -DESP32S3
    -DBOARD_HAS_PSRAM
    upload_speed = 1500000
    monitor_speed = 115200

    and code start
    /*



    */

    #include <Arduino.h>
    #include <M5CoreS3.h>

    void setup()
    {
    M5.begin(true, true, false); // Init M5CoreS3.
    ...
    etc

    Yours Simon M



  • As yet I have only got the M5Stack ATOMIC CANBus Base and CANBus Unit to work with the following code using Atom Lite & Atom Matrix :-

    #include "M5Atom.h"
    #include <ESP32CAN.h>
    #include <CAN_config.h>

    #define CAN_BASE // Remove to use external CAN bus via Grove cable
    //#define CAN_RECIEVER // Remove to make sender

    #define CAN_MSG_ID 0x001

    CAN_device_t CAN_cfg; // CAN Config.
    unsigned long previousMillis = 0; // will store last time a CAN Message was sent // send. 将存储上次发送CAN消息的时间。
    const int interval = 80; // interval at which send CAN Messages (milliseconds).

    const int rx_queue_size = 10; // Receive Queue size.
    int LedNumberCount = 0;
    int waitCANData = 0;

    uint8_t msgcnt = 0;

    void setup()
    {
    M5.begin(true, true, true);
    Serial.println("Atom Install OK....");
    M5.dis.fillpix(CRGB(100, 0, 0)); //Fill the LED Matrix RED
    delay(2000);

    #ifdef CAN_BASE // CAN base is used
    //default
    CAN_cfg.tx_pin_id = GPIO_NUM_22;
    CAN_cfg.rx_pin_id = GPIO_NUM_19;

    #else
    // Grove
    CAN_cfg.tx_pin_id = GPIO_NUM_26;
    CAN_cfg.rx_pin_id = GPIO_NUM_32;
    #endif

    CAN_cfg.speed = CAN_SPEED_500KBPS;
    
    CAN_cfg.rx_queue  = xQueueCreate(rx_queue_size, sizeof(CAN_frame_t));
    
    ESP32Can.CANInit();
    Serial.println("CAN Install");
    M5.dis.fillpix(CRGB(0, 100, 0));  //Fill the LED Matrix GREEN
    

    M5.dis.fillpix(CRGB(HUE_GREEN)); //Fill the LED Matrix GREEN
    #ifdef CAN_RECIEVER
    Serial.println("Set as RECIEVER");
    #else
    Serial.println("Set as SENDER");
    #endif
    }

    void loop()
    {
    unsigned long currentMillis = millis();

    #ifdef CAN_RECIEVER
    // recieve CAN Message
    CAN_frame_t rx_frame;

    if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame, 3 * portTICK_PERIOD_MS) ==  pdTRUE) 
    {
        if (rx_frame.FIR.B.FF == CAN_frame_std) 
        {
            Serial.printf("New standard frame");
        } 
        else
        {
            Serial.printf("New extended frame");
        }
    
        if (rx_frame.FIR.B.RTR == CAN_RTR) 
        {
            Serial.printf(" RTR from 0x%08X, DLC %d\r\n", rx_frame.MsgID, rx_frame.FIR.B.DLC);
        }
        else
        {
            Serial.printf(" from 0x%08X, DLC %d, Data ", rx_frame.MsgID, rx_frame.FIR.B.DLC);
            for (int i = 0; i < rx_frame.FIR.B.DLC; i++) 
            {
                Serial.printf("0x%02X ", rx_frame.data.u8[i]);
            }
            Serial.printf("\n");
            if (rx_frame.data.u8[0] == 0x01) 
            {
                CAN_frame_t tx_frame;
                tx_frame.FIR.B.FF   = CAN_frame_std;
                tx_frame.MsgID      = CAN_MSG_ID;
                tx_frame.FIR.B.DLC  = 8;
                tx_frame.data.u8[0] = 0x02;
                tx_frame.data.u8[1] = rx_frame.data.u8[1];
                tx_frame.data.u8[2] = 0x00;
                tx_frame.data.u8[3] = 0x00;
                tx_frame.data.u8[4] = 0x00;
                tx_frame.data.u8[5] = 0x00;
                tx_frame.data.u8[6] = 0x00;
                tx_frame.data.u8[7] = 0x00;
                ESP32Can.CANWriteFrame(&tx_frame);
            }
        }
    }
    

    #else
    // Send CAN Message
    if (currentMillis - previousMillis >= interval)
    {
    // ESP32Can.CANInit();
    previousMillis = currentMillis;
    CAN_frame_t tx_frame;
    tx_frame.FIR.B.FF = CAN_frame_std;
    tx_frame.MsgID = CAN_MSG_ID;
    tx_frame.FIR.B.DLC = 8;
    tx_frame.data.u8[0] = 0x01;
    tx_frame.data.u8[1] = msgcnt;
    tx_frame.data.u8[2] = 0x00;
    tx_frame.data.u8[3] = 0x00;
    tx_frame.data.u8[4] = 0x00;
    tx_frame.data.u8[5] = 0x00;
    tx_frame.data.u8[6] = 0x00;
    tx_frame.data.u8[7] = 0x00;

        ESP32Can.CANWriteFrame(&tx_frame);
        // ESP32Can.CANStop();
        msgcnt++;
        if (msgcnt > 29) 
        {
            msgcnt = 0;
        }
    }
    
    CAN_frame_t rx_frame;
    
    if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame, 3 * portTICK_PERIOD_MS) == pdTRUE) 
    {
        if (rx_frame.FIR.B.FF == CAN_frame_std) 
        {
            Serial.printf("New standard frame");
        } 
        else 
        {
            Serial.printf("New extended frame");
        }
    
        if (rx_frame.FIR.B.RTR == CAN_RTR) 
        {
            Serial.printf(" RTR from 0x%08X, DLC %d\r\n", rx_frame.MsgID,
            rx_frame.FIR.B.DLC);
        } 
        else 
        {
            Serial.printf(" from 0x%08X, DLC %d, Data ", rx_frame.MsgID,
            rx_frame.FIR.B.DLC);
            for (int i = 0; i < rx_frame.FIR.B.DLC; i++) 
            {
                Serial.printf("0x%02X ", rx_frame.data.u8[i]);
            }
            Serial.printf("\n");
    
            if (rx_frame.data.u8[0] == 0x02) 
            {
                    if (rx_frame.data.u8[1] < 25)
                {
                    M5.dis.drawpix(rx_frame.data.u8[1], CRGB(100, 0, 0));
                } 
                else if (rx_frame.data.u8[1] > 27) 
                {
                    M5.dis.fillpix(CRGB(0, 0, 20));
                }
                waitCANData = 0;
            }
        }
    }
    

    #endif
    // waitCANData
    M5.update();
    if (M5.Btn.isPressed())
    {
    M5.dis.clear();
    M5.dis.fillpix(CRGB(0, 100, 0));
    esp_restart();
    }
    delay(10);
    }

    when I modify it to work with the Core2, it compiles OK but no echo back. what am I missing?



  • Hello @samarkh

    I assume you've adapted the TX and RX GPIOs for M5Core2 accordingly, yes?

    Thanks
    Felix



  • @felmue
    I used
    /* set CAN pins */
    // GROVE connector GPIO pins
    CAN_cfg.tx_pin_id = GPIO_NUM_32; // Use this order only
    CAN_cfg.rx_pin_id = GPIO_NUM_33;

    and I'm able to see activity on the CAN bus using an oscilloscope.



  • Hello @samarkh

    these GPIOs look ok to me. Hmm, not sure why it doesn't work on M5Core2 though. Sorry.

    Thanks
    Felix



  • I did get this to work. I'm using this library for the CAN part:

    https://github.com/aaknitt/esp32_can/tree/master

    Put this code in lib and change the pin designations in esp32_can.cpp:
    ESP32CAN attribute((weak)) CAN0(GPIO_NUM_1, GPIO_NUM_2) ;

    platformio.ini looks like this:

    [env:m5stack-stamps3]
    platform = espressif32
    board = m5stack-stamps3
    framework = arduino

    lib_deps =
    https://github.com/collin80/can_common
    https://github.com/plapointe6/EspMQTTClient
    m5stack/M5Dial
    m5stack/M5Unified

    upload_speed = 1500000
    monitor_speed = 115200

    Plug it into Port B

    Setup code is like:
    CAN0.setCANPins(GPIO_NUM_1, GPIO_NUM_2);
    USBSerial.println("Set CAN pins...");
    CAN0.begin(500000);
    USBSerial.println("CAN has started...");
    CAN0.watchFor();
    CAN0.setCallback(0, theCanDecoder);

    If you want full code I can probably clean this all up and publish on Git.