R4 Renesas/Arduino_CAN library DOCUMENTATION

I read everything available here on Arduino.cc

When a human readable documentation will be available on the subject?

It's about 4 months I bought an R4 Wifi and I'm not getting real answers on the request for support I posted in this community.

What is my issue? Where the hell to find 2 pages written in human English with an explanation of the methods implemented by the library, how the message body can be sent and transferred with some actionable examples covering both strings and numeric values.

So far the only place is Github https://github.com/arduino/ArduinoCore-renesas/tree/main/libraries/Arduino_CAN where the bare list is available in the keywords.txt file.

Seriously?

Hope someone out there could share something actionable, not the tutorial which is completely useless if you only need to do something real.

By the way, as already explained in last 3 months messagges, I'm running a can bus that connects Arduino Nano Every + MCP2515 and Arduino MKR Wifi 1010Ă  MKR canShield and that perfectly works.

In case, as I'm guessing, nothing is available, will be glad someone from Arduino Team to set up up and confirm that you think the two tutorials and the gihub material are state of the art documentation for a CAN library.

I think all CAN libraries uses the same protocol so all the libraries are similar. If you successfully used CAN on Every and Mkr, there isn't a big deal to figure out, how to work with library on R4. All the functions can be found in the github source code.

You should refer to the CAN API documentation, not to the README in the core trunk

from here

you get here

and you find the API

Also very useful are the examples appearing once you select the correct board

1 Like

Hi ubidefeo nice to see you here again :slight_smile: and thanks for swing answer.

I'm aware of that library documentation, and the Library sandeepmistry/arduino-CAN is what I'm actually using to run the MCP2515 shield. It perfectly works.

I might be mistaken, but on Arduino R4 the library is a different one, arduino/ArduinoCore-renesas. My search for documentation is related to this one.

Then, as suggested here by b707, I did tons of trials and reverse engineering by inferring how it should work from the code I'm already successfully running, and I came out with an "invented solution" as following:

void loop() {
  if (CAN.available())
  {
    CanMsg const msg = CAN.read();
    unsigned char buf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
    idmessaggio= msg.getStandardId();
    Serial.print("IDMessaggio= ");
    Serial.println(idmessaggio);
    for (int i = 0; i < 6; i++) { //6 is number of bytes transmitted that must be received here     
      buf[i]=msg.data[i]; // stores buf[0....5] with received bytes 
    }
    Serial.println("*+*+*+");
    for (int i=0; i<6; i++){
      Serial.print(buf[i]);
      Serial.print("++");
    }
  }

}

which by the way works! :slight_smile:

Anyway thanks again for your promt answer and for providing documentation which is for sure useful (it has indeed been in the past ) but that in the tutorial * Get an overview of the built-in CAN library isn't mentioned anywhere and the only reference is to the "The library used is built into the core". Surely will give a second look also for the R4 can bus case.

Thanks again for prompt and insightful answer. Andrea

And just for a bit of fun, in the context :slight_smile: it's 11 pm here in Milan after all... here a picture of the new Arduino R4 joining the other Arduinos brothers on the canbus workbench :slight_smile:

the comet star in the picture is also suggesting that the idea is to use canbus as the "nervous system" of the upcoming Christmas nativity scene smart blocks :slight_smile: :slight_smile:

2 Likes

hey @apagliari

I'm happy to give some directions.
I have never used CAN in a real project, so I did not have real-life pointers, but good to hear you got it working.

I'll submit this post to our documentation/content team in order for documentation to be amended where possible.

Nice xmas project, maybe we'll see it on our Project Hub for others to learn from? :wink:

Thank you for the valuable feedback, hope this post will help others too
u.

Hi,
I am searching for API:s for the Renesas CAN used in UNO R4.
(Arduino_CAN).
Such as: CAN Id, datalenght (dlc), Standard or Extended CAN 2.0...
Have you found out where to look ?
/Christer

Hi Christer,

sorry to say I didn't find any additional documentation BUT I was able to put together a working code snippet for Arduino R4 Wifi that uses CANBUS as a SENDER.
If you want I can share the code here, but is just something that works for my use case :slight_smile: , and the code is full of debugging lines I hadn't the time to polish out yet. Anyway, let me know. Andrea

Good morning.
Yes please that would be great!
I have had unexpected problems with the UNO R4 wifi.
First the receive pin is 13 and not 5 as it is for the Minima. The pins are not correct in the documentation.
Then I had problems with the 3.3V transeiver.
The levels are to low for my R4 ! When si changed to MCP2551 with 5V level all is fine with the ”standard” code for receiving.
However I need to have API so that : canId, dlc, and the Data 1-8 are ”visible”.
The same goes for sendning CAN msg.

Hi Christer,

here below canbus logical model architecture:

As you can see, with Arduino R4 Wifi I'm using SN65HVD230 as CAN Board which is powered @ 3.3 volt and therefore I'm not facing level shifter issues. In my past experience switching for canbus board from 3,3 to 5 volt has always been a nightmare and therefore I got rid of this problem by selecting a board that can be powered @3.3 without issues

An if you want the have a look to the "raw" code I'm using, here we are:

//file name CAN_Bus_Sender_R4Wifi_CodeBrickE
// use of arduino R4 to get button values, send them over canbus and display the value on the led matrix
//https://labs.arduino.cc/en
//https://labs.arduino.cc/en/labs/led-matrix
//https://ledmatrix-editor.arduino.cc/


//Canbus
#include <Arduino_CAN.h>
unsigned long idmessaggio = 0;
unsigned char DataTransmitted[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };  //array for data transmission over canbus
static uint32_t const CAN_ID = 0x02;
static uint32_t const msg = 0;

//***LED MATRIX
#include "Arduino_LED_Matrix.h"
#include "frames.h"
ArduinoLEDMatrix matrix;

// ***KEYPAD
#include "Adafruit_Keypad.h"
// define your specific keypad here via PID
//used this Adafruit Model since is the one with 4x4 matrix
#define KEYPAD_PID3844
// define your pins here
// can ignore ones that don't apply
#define R1 9
#define R2 8
#define R3 7
#define R4 6
#define C1 5
#define C2 4
#define C3 3
#define C4 2
// leave this import after the above configuration
#include "keypad_config.h"
//initialize an instance of class NewKeypad
Adafruit_Keypad customKeypad = Adafruit_Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

char Button;  //define a variable where to store the current value of pressed button

void setup() {
  Serial.begin(9600);
  //while (!Serial) {};  //remember to comment line out  to start even without serial monitor which is really relevant
  matrix.begin();
  customKeypad.begin();
  //**canbus
  if (!CAN.begin(CanBitRate::BR_250k)) {
    Serial.println("CAN.begin(...) failed.");
    for (;;) {}
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  customKeypad.tick();

  while (customKeypad.available()) {
    keypadEvent e = customKeypad.read();
    Button = (char)e.bit.KEY;  //it works and it's key for following logic to be implemented
    Serial.print((char)e.bit.KEY);
    if (e.bit.EVENT == KEY_JUST_PRESSED) Serial.println(" pressed");
    else if (e.bit.EVENT == KEY_JUST_RELEASED) Serial.println(" released");
    switch (Button) {
      case 'A':
        {  //wrapping the case because of msg variable defined inside the case
          Serial.println("E' proprio un AAAA!!");
          DataTransmitted[0] = Button;
          CanMsg const msg(CanStandardId(CAN_ID), sizeof(DataTransmitted), DataTransmitted);  //key
          if (int const rc = CAN.write(msg); rc < 0) {
            Serial.print("CAN.write(...) failed with error code ");
            Serial.println(rc);
            //for (;;) {} //stops the execution but can be not necessary if meanwhile the can receiver starts
          }
          matrix.loadFrame(A);
          delay(500);
        }  // wrapping the case
        break;
      case 'B':
        {  //wrapping the case
          Serial.println("E' proprio un BBB!!");
          DataTransmitted[0] = Button;
          CanMsg const msg(CanStandardId(CAN_ID), sizeof(DataTransmitted), DataTransmitted);  //key
          if (int const rc = CAN.write(msg); rc < 0) {
            Serial.print("CAN.write(...) failed with error code ");
            Serial.println(rc);
            //for (;;) {} //stops the execution but can be not necessary if meanwhile the can receiver starts
          }
          matrix.loadFrame(B);
          delay(500);
        }  // wrapping the case
        break;
      case 'C':
        {  //wrapping the case
          Serial.println("E' proprio un CCC!!");
          DataTransmitted[0] = Button;
          CanMsg const msg(CanStandardId(CAN_ID), sizeof(DataTransmitted), DataTransmitted);  //key
          if (int const rc = CAN.write(msg); rc < 0) {
            Serial.print("CAN.write(...) failed with error code ");
            Serial.println(rc);
            //for (;;) {} //stops the execution but can be not necessary if meanwhile the can receiver starts
          }
          matrix.loadFrame(C);
          delay(500);
        }  // wrapping the case
        break;
      case 'D':
        {  //wrapping the case
          Serial.println("E' proprio un DDD!!");
          DataTransmitted[0] = Button;
          CanMsg const msg(CanStandardId(CAN_ID), sizeof(DataTransmitted), DataTransmitted);  //key
          if (int const rc = CAN.write(msg); rc < 0) {
            Serial.print("CAN.write(...) failed with error code ");
            Serial.println(rc);
            //for (;;) {} //stops the execution but can be not necessary if meanwhile the can receiver starts
          }
          matrix.loadFrame(D);
          delay(500);
        }  // wrapping the case
        break;
    }

    Serial.print("Bottone premuto = ");
    Serial.println(Button);
  }

  delay(10);
}

In this code snippet, apart a overusage "print..." for debugging sake [sorry for that ! :-)] the idea is to read a keypad, send the value over canbus and show on arduino R4 led matrix the value in order to provide a feebdack about the fact that the button pressure has been detected and the value sent over can bus.
As I said, the code can be surely reengineered, but it is working in real life and is much more concrete than the official example. Hope this could be of some value for you, Christer.

Thank You!
I will do some more UNO R4 tests later this week.
My main interest is Nmea2000 marine network that is using extendid canbus at 250 kbps as ”carrier”.
The Nmea2000 spec is not open and on top of this there are some specific protocols for some companies. Garmin , Volvo Penta, …..
Today I have mainly used Teensy 4.0 mcu.
The canbus load is heavy , >90%.

I have used and tried UNOR3, Due, Mega, Esp32, Adafruit feather and Teensy mcu with canbus . All without problems but with different performance.

ons 27 dec. 2023 kl. 21:15 skrev apagliari via Arduino Forum <notifications@arduino.discoursemail.com>:

Hi again…..
I am not shure if I understand you ?
I see that you have Arduino nano with Nires canbus shield. I also have these, and both have 5V logic levels.
The Uno R3 is also a 5V logic board.
The new R4 Wifi and Minima I think ….
are also 5V to be compatible with UNO R3 ?!?

When I tested earlier I had problems receiving on my UNO R4 wifi when the pulses was low ( about 3.3V).
I will try later to find the threshold on Receiving.
As I said earlier, when I shifted to a MCP2551 transeiver with 5V logic levels all is fine.

I am planning to make some boards with CAN bus transeiver for the UNO R4 wifi so I must have this perfect.
I will use the ISO1050 dubr chip for this because it is opto isolated to the bus.

/Christer

ons 27 dec. 2023 kl. 21:01 skrev apagliari via Arduino Forum <notifications@arduino.discoursemail.com>:

| apagliari
December 27 |

  • | - |

Hi Christer,

here below canbus logical model architecture:

Ja

Hi, Now everything works fine receiving CAN msg. I use MCP2551 transceiver and both 3.3 and 5V level to RX pin is fine. There is a big difference in performance with a high CANbus load between UNO R4 vs. R3 !

My raw test code below:

/*
  CAN_read_R4_ver1
   Tested 2023.12.28 with MCP2551 Transeiver with 5V and 3.3V to UNO R4_Rx
   Note: UNO R4 Minima Rx pin 5, UNO R4 wifi Rx pin 13. 
 
  Receive and read CAN Bus messages
  See also the full documentation here:
  https://docs.arduino.cc/tutorials/uno-r4-wifi/can
*/


#include <Arduino_CAN.h>

int msg_data = 0;
bool isStandardId;
bool checkstandardId = 0;
bool checkextendedId = 0;
int canId = 0;
int dlc = 0;

unsigned char buf[8];  //CA
char msgString[128];   //CA

long RXcounter = 0;  // receive counter



void setup() {
  Serial.begin(115200);
  while (!Serial)
    ;
  delay(10);
  Serial.println("CAN_read_R4_ver1");

  if (!CAN.begin(CanBitRate::BR_250k)) {
    Serial.println("CAN.begin(...) failed.");
    for (;;) {}
  }

  Serial.println("Setup. OK");
  delay(2000);
}




void loop() {
  if (CAN.available()) {

    CanMsg const msg = CAN.read();

    RXcounter = RXcounter + 1;

    Serial.println("----------------------------------");
    Serial.print("counter received: ");
    Serial.println(RXcounter);
    // Serial.print("CAN msg: ");  Serial.println(msg);


    checkstandardId = msg.isStandardId();
    if (checkstandardId == 1) {
      Serial.print("Standard CANId,");
      canId = msg.getStandardId();
      Serial.print("  canId (HEX): ");
      Serial.print(canId, HEX);
      dlc = (msg.data_length);
      Serial.print("   dlc: ");
      Serial.println(dlc);

      for (int i = 0; i < dlc; i++) {
        buf[i] = msg.data[i];
      }
      Serial.print("data (HEX): ");
      for (int i = 0; i < dlc; i++) {
        Serial.print(buf[i], HEX);
        Serial.print("  ");
      }
      Serial.println();
    }

    checkstandardId = msg.isStandardId();
    if (checkstandardId == 0) {
      Serial.print("Extended CANId, ");
      canId = msg.getExtendedId();
      Serial.print("  canId (HEX): ");
      Serial.print(canId, HEX);
      dlc = (msg.data_length);
      Serial.print("  dlc: ");
      Serial.println(dlc);

      for (int i = 0; i < dlc; i++) {
        buf[i] = msg.data[i];
      }
      Serial.print("data (HEX): ");
      for (int i = 0; i < dlc; i++) {
        Serial.print(buf[i], HEX);
        Serial.print("  ");
      }
      Serial.println();
    }
  }
}

Have the same question. Did you ever find any decent documentation? Thanks!