Libcanard: Examples, Starters, Tutorials

Good day :slight_smile:

This topic is dedicated to collect and provide links supplied by the community. What you will find here are:

  • Examples: Gists, posts links to other forum like Stack Overflow which present a whole solution or partial solution.
  • Starters: for example a Github template project to get you started.
  • Tutorials: Full explanations like those found in Instructables or Medium and/or videos in YouTube.
  • Open Source Libraries: what better examples than a whole open source library or implementation?
  • Example Hardware Setups: There are plenty of affordable and some open source hardware to start exploring UAVCAN.

This topic prime goal is to be informational. We strongly advise and suggest that lengthy discussion or debate of any of the links presented here be carried out at the respective forum dedicated to that link please.

Happy Coding

2 Likes

107-Arduino-UAVCAN is a Arduino library providing a convenient C++ interface for accessing UAVCAN (v1.0-beta) via libcanard. This library works for

  • ArduinoCore-samd: Arduino Zero, MKR 1000, MKR WiFi 1010, Nano 33 IoT, MKR GSM 1400, MKR NB 1500, MKR WAN 1300/1310 :heavy_check_mark:
  • ArduinoCore-mbed: Portenta H7, Nano 33 BLE, Nano RP2040 Connect, Edge Control :heavy_check_mark:
  • arduino-esp32: ESP32 Dev Module, ESP32 Wrover Module, … :heavy_check_mark:

There’s a dedicated thread on this forum for discussing anything related to the library, of course the default GitHub mechanisms of issues and pull requests can also be employed (choose the right medium :wink:).

Here’s a short example of a node publishing a heartbeat using the 107-Arduino-UAVCAN:

/**************************************************************************************
 * INCLUDE
 **************************************************************************************/

#include <SPI.h>

#include <ArduinoUAVCAN.h>
#include <ArduinoMCP2515.h>

/**************************************************************************************
 * CONSTANTS
 **************************************************************************************/

static int const MKRCAN_MCP2515_CS_PIN  = 3;
static int const MKRCAN_MCP2515_INT_PIN = 7;

/**************************************************************************************
 * FUNCTION DECLARATION
 **************************************************************************************/

void spi_select()
{
  digitalWrite(MKRCAN_MCP2515_CS_PIN, LOW);
}

void spi_deselect()
{
  digitalWrite(MKRCAN_MCP2515_CS_PIN, HIGH);
}

uint8_t spi_transfer(uint8_t const data)
{
  return SPI.transfer(data);
}

void onExternalEvent()
{
  mcp2515.onExternalEventHandler();
}

bool transmitCanFrame(uint32_t const id, uint8_t const * data, uint8_t const len)
{
  return mcp2515.transmit(id, data, len);
}

/**************************************************************************************
 * GLOBAL VARIABLES
 **************************************************************************************/

ArduinoMCP2515 mcp2515(spi_select,
                       spi_deselect,
                       spi_transfer,
                       nullptr,
                       nullptr);

ArduinoUAVCAN uavcan(13, micros, transmitCanFrame);

Heartbeat_1_0 hb(0, Heartbeat_1_0::Health::NOMINAL, Heartbeat_1_0::Mode::INITIALIZATION, 0);

/**************************************************************************************
 * SETUP/LOOP
 **************************************************************************************/

void setup()
{
  Serial.begin(9600);
  while(!Serial) { }

  /* Setup SPI access */
  SPI.begin();
  pinMode(MKRCAN_MCP2515_CS_PIN, OUTPUT);
  digitalWrite(MKRCAN_MCP2515_CS_PIN, HIGH);

  /* Attach interrupt handler to register MCP2515 signaled by taking INT low */
  pinMode(MKRCAN_MCP2515_INT_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(MKRCAN_MCP2515_INT_PIN), onExternalEvent, FALLING);

  /* Initialize MCP2515 */
  mcp2515.begin();
  mcp2515.setBitRate(CanBitRate::BR_250kBPS);
  mcp2515.setNormalMode();
}

void loop()
{
  /* Update the heartbeat object */
  hb.uptime(millis() / 1000);
  hb.mode(Heartbeat_1_0::Mode::OPERATIONAL);

  /* Publish the heartbeat once/second */
  static unsigned long prev = 0;
  unsigned long const now = millis();
  if(now - prev > 1000) {
    uavcan.publish(hb);
    prev = now;
  }

  /* Transmit all enqeued CAN frames */
  while(uavcan.transmitCanFrame()) { }
}
2 Likes

Starter Template C Project with CMake for Visual Studio Code

https://github.com/bluecorn/uavcan-template-c is a Visual Studio Code specific starter temple. The code is meant to get you started quickly in building your own libcanard C node. It is meant executed withing a Linux system. Since it used CMake to build then it might work with other IDE’s.

Cheers.

2 Likes

Raspberry Pi with ultrasound example in C

The code is meant to be run using two Raspberry Pi. Each Pi is connected to a MCP2515 module. One Pi is connected to a HC-SR04 ultrasound sensor. The sensor calculated distance to an obstacle is transmitted as a 32bit float. The float is serialized using canard_dsdl.h. At the reciving end the float is deserialized and the distance is printed to the console.

The code can be found at:

raspberry-can-HC-SR04

raspberry-can-master-ultrasound

1 Like

Hi @hugo
I just want to let you know that I rebuilt your raspberry pi example and it just worked out of the box. Thanks for it.

I also managed to receive the data using Yakut. The right command is:

yakut -i='CAN(can.media.socketcan.SocketCANMedia("can0",8),59)' sub 1610:uavcan.primitive.scalar.Real32.1.0

The output should be like:

1610:
  _metadata_:
    timestamp:
      system: 1609230618.943262
      monotonic: 976.584537
    priority: nominal
    transfer_id: 13
    source_node_id: 42
  value: 18.762100219726562
1 Like

Libcanard example for the NXP S32K1 automotive-grade microcontroller.

This demo transmits the uavcan/node/heartbeat message between a pair of UCANS32K146 development boards, in a interrupt-driven approach both for Tx and Rx.

1 Like

We have recently made our official demos public; at the time of writing this, they are all libcanard-based:

This presentation from Landon Haugh deserves a place here:

1 Like