UAVCAN for Teensy 4.0

Have been attempting to start a UAVCAN model for use with a Teensy 4.0, so far without success. The Teensy allows me to use the Arduino programming environment, with an added library. (Well, several, actually.) None of the models will compile, for a variety of reasons.
One that I am currently working on is libuavcan-Teensy-3.x from Github -

I have attempted to compile the uavcan-Teensy-gnsFix-publish module. It won’t compile, throwing the error message

"C:\\Program Files (x86)\\arduino-1.8.16\\hardware\\teensy/../tools/arm/bin/arm-none-eabi-g++" -E -CC -x c++ -w -g -Wall -ffunction-sections -fdata-sections -nostdlib 
	+ -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -
	+ mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=155 -DARDUINO=10816 -DARDUINO_TEENSY40 -DF_CPU=600000000 -DUSB_SERIAL 
	+ -DLAYOUT_US_ENGLISH "-IC:\\Program Files (x86)\\arduino-1.8.16\\hardware\\teensy\\avr\\cores\\teensy4" 
	+ "-IC:\\Users\\hayes\\Documents\\Arduino\\libraries\\libuavcan_teensy\\src" 
	+ "C:\\Users\\hayes\\Documents\\Arduino\\libraries\\libuavcan_teensy\\src\\uavcan\\uavcan_teensy\\IFCT.cpp" -o nul

Alternatives for kinetis.h: []

ResolveLibrary(kinetis.h)Arduino\libraries\libuavcan_teensy\src\uavcan\uavcan_teensy\IFCT.cpp:31:21: fatal error: kinetis.h: No such file or directory
 -> candidates: []

compilation terminated.

I have searched for the #include <kinetis.h> statement, and it is in the ifct.cpp file, which is itself referenced in another file. The compiler won’t accept changes to the text of ifct.cpp - I have attempted to comment out the #include <kinetis.h> statement, and the compiler throws the same error.
Does anyone have any suggestions for fixing this? This library is created by a developer on the forum.pjrc.com site. I would like to ask a question on that site, but so far haven’t been granted permission to post comments.

Hi John,

As you stated correctly, you should indeed seek help from the maintainers of that library, if there still are any – the last commit was made over three years ago. Even if you can make it work, that code implements the legacy version of the protocol that is not recommended for new designs, as I wrote at Yakut monitor with a Babel - #7 by pavel.kirienko

I would rather suggest considering this modern replacement for Arduino (not sure whether it suits your needs well but it’s modern and well-maintained): https://github.com/107-systems/107-Arduino-UAVCAN. Alternatively, consider going bare bones and integrating raw libcanard directly (this might be a bit more involved though). If you chose the latter, you may benefit from these demo applications we posted here: https://github.com/UAVCAN/demos

OK then. I already have downloaded the code from 107-Arduino-UAVCAN-1.3.1 and 107-Arduino-UAVCAN-master. So I tried UAVCAN-Blink from 1.3.1, assuming that was the latest. It failed to compile, with the following message (edited for brevity) -

Arduino: 1.8.16 (Windows 10), TD: 1.55, Board: "Arduino Uno"

C:\Program Files (x86)\arduino-1.8.16\arduino-builder -dump-prefs -logger=machine -hardware C:\Program Files (x86)\arduino-1.8.16\hardware -hardware 
	+ C:\Users\hayes\AppData\Local\Arduino15\packages -tools C:\Program Files (x86)\arduino-1.8.16\tools-builder -tools 
	+ C:\Program Files (x86)\arduino-1.8.16\hardware\tools\avr -tools C:\Users\hayes\AppData\Local\Arduino15\packages -built-in-libraries 
	+ C:\Program Files (x86)\arduino-1.8.16\libraries -libraries C:\Users\hayes\Documents\Arduino\libraries -fqbn=arduino:avr:uno -ide-version=10816 -build-path 
	+ C:\Users\hayes\AppData\Local\Temp\arduino_build_966456 -warnings=none -build-cache C:\Users\hayes\AppData\Local\Temp\arduino_cache_470180 
	+ -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avrdude.path=C:\Users\hayes\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17 
	+ -prefs=runtime.tools.avrdude-6.3.0-arduino17.path=C:\Users\hayes\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17 
	+ -prefs=runtime.tools.avr-gcc.path=C:\Users\hayes\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7 
	+ -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=C:\Users\hayes\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7 
	+ -prefs=runtime.tools.arduinoOTA.path=C:\Users\hayes\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.3.0 
	+ -prefs=runtime.tools.arduinoOTA-1.3.0.path=C:\Users\hayes\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.3.0 -verbose 
	+ C:\Users\hayes\Documents\CANBus materials\UAVCAN\107-Arduino-UAVCAN-1.3.1\examples\UAVCAN-Blink\UAVCAN-Blink.ino

"C:\\Users\\hayes\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive 
	+ -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L 
	+ -DARDUINO=10816 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IC:\\Users\\hayes\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.4\\cores\\arduino" 
	+ "-IC:\\Users\\hayes\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.4\\variants\\standard" 
	+ "-IC:\\Users\\hayes\\Documents\\Arduino\\libraries\\107-Arduino-UAVCAN\\src" 
	+ "C:\\Users\\hayes\\AppData\\Local\\Temp\\arduino_build_966456\\sketch\\UAVCAN-Blink.ino.cpp" -o nul

Alternatives for map: []

ResolveLibrary(map)

  -> candidates: []

In file included from C:\Users\hayes\Documents\CANBus materials\UAVCAN\107-Arduino-UAVCAN-1.3.1\examples\UAVCAN-Blink\UAVCAN-Blink.ino:1:0:

ArduinoUAVCAN.h:19:10: fatal error: map: No such file or directory

 #include <map>

          ^~~~~

compilation terminated.

Using library 107-Arduino-UAVCAN at version 1.4.0 in folder: C:\Users\hayes\Documents\Arduino\libraries\107-Arduino-UAVCAN 

exit status 1

map: No such file or directory

The interesting thing about this error message is that I changed the #include <map> to #include <map.h>, thinking that may aid in compilation, primarily because I got the same error message when the original text was there. It still didn’t compile, with the same error message, when I changed it back to #include <map>. My limited understanding informs me that “map,” “memory” and “functional” are STLs from the C++ libraries. I thought all this code was supposed to be in C.
Am I missing something here? How can I get this example to compile? I chose it because I thought it would be the simplest one.

Generally, you are not supposed to modify the codebase to make it work. Please do restore the original #include <map>, as it was correct. You may have misconfigured your build system; I won’t be able to assit you as I don’t have experience with Arduino, but @aentinger might (perhaps after the holidays? we shall see).

You can use code formatting to avoid issues with lost symbols. I’ve edited your post accordingly.

1 Like

Generally speaking Teensy is not supported by 107-Arduino-UAVCAN. It seems that the Teensy build environment is missing the STL library, but others seem to have made it work. Probably best to ask Paul Stoffregen about it, or to use a supported platform.

I encountered a similar problem with the missing STL library. But it was with another project library - FlexCAN_T4.

This problem has two solutions:

  1. Switching from the Arduino IDE to the PlatformIO
  2. Renaming the .ipp files to extension .h and adjusting the parent header files accordingly.

Hi Aleksandr,

I think it’s better that we stick to English if possible, as I suspect there are very few users who can read Russian. Our little Telegram group is probably a better place for asking questions in Russian.

  1. You don’t need drivers for TJA1051 because this is a physical layer chip. It is basically a level shifter with some basic half-duplex management logic, it works out of the box, no drivers required.

  2. UAVCAN implementation libraries can send/receive UAVCAN transfers automatically, yes. At the moment we only have two implementations: PyUAVCAN and libcanard, in your case only the latter is of relevance. Libcanard provides a simple API for exchanging serialized blobs of data, which you are expected to construct/parse using automatically generated C code transcompiled from DSDL with the help of Nunavut:

git clone https://github.com/UAVCAN/public_regulated_data_types
nnvg --target-language c --target-endianness=little --enable-serialization-asserts public_regulated_data_types/uavcan
nnvg --target-language c --target-endianness=little --enable-serialization-asserts public_regulated_data_types/reg --lookup-dir public_regulated_data_types/uavcan
  1. UAVCAN is one of many implementations of the publish-subscribe pattern, but one of very few that are suitable for mission-critical real-time networks. We did not invent the pub-sub pattern itself but merely constructed a solid implementation of it. The following materials should explain how to define and use custom data types:
  1. libuavcan is not yet ready for use, so that means you can only use libcanard.

  2. There is no documentation in Russian, but there’s this:

Pavel!
Thank you very much for your comprehensive answer. Now everything is more or less falling into place in my head. I will read and study the material. As soon as I run UAVCAN (libcanard) on Teensy 4.0 I will post the link to the project here.

Unfortunately I can’t edit my previous post anymore, so I am going to post the translation of my questions below. Thank you!

Hi everyone!
I have a similar project at Teensy 4.0, is installed as one of the microcontrollers in CAN network. Its controlled some buttons, encoders and joysticks. But its main function is to receive data via UAVCAN and after some simple processing, transfer this data via USB, similarly in the opposite direction: receiving data via USB, processing it and sending data o the network via UAVCAN.

I have some questions about UAVCAN - I use Teensy 4.0 in conjunction with TJA1051 which is connected directly to CTX1 and CRX1 (FlexCAN) port.

  1. Do I need to install drivers for the CAN chip? That is, take the data in CAN bus format in the beginning and somehow pass it to the UAVCAN module? If so, where in the library can I see the code that is responsible for receiving data from the CAN bus?

  2. Then the UAVCAN library will automatically decrypt the data according to the standard protocol and give me the data in human-understandable form?

  3. I understand the principle of the product, that is, someone on the network publishes the data (with a hashtag type label), and someone subscribes to this data and gets only what he needs (genius idea!). And where in the code can I add my custom publications/subscriptions if the standard protocol doesn’t have the options I need?

  4. What’s the better choice for Arduino-like development environments Libcanard or libuavcan? Theoretically all the code for Arduino projects is written in C++, so the question is what is better to integrate into the project? Are there any fundamental differences in these libraries?

And the main question - is there any manual for working with UAVCAN in Russian?

The 107-Arduino-UAVCAN library is missing a file specialized for Teensy 4.0 in the utility folder, namely crit_sec_enter and crit_sec_leave

That too :man_shrugging: As I wrote, Teensy is not supported. And I should know, I wrote the library :stuck_out_tongue_winking_eye:

Edit: Sorry, I did not see your more comprehensive translated questions above :bow: (I just replied to your last statement).

I compiled the project in the PlatformIO for Teensy 4.0 without much trouble. I just needed another file in the utility folder with the following content:

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

#include "CritSec.h"

#if defined(__arm__) && defined(TEENSYDUINO) && (defined(__IMXRT1052__) || defined(__IMXRT1062__))
#include <Arduino.h>

/**************************************************************************************
 * FUNCTION DEFINITION
 **************************************************************************************/

extern "C" void crit_sec_enter()
{
  noInterrupts();
}

extern "C" void crit_sec_leave()
{
  interrupts();
}

#endif /* TEENSY40 */

Now I need to connect CAN1 (FlexCAN_T4 library) to 107-UAVCAN instead of MCP2515 as in the original library.
I’m a bad programmer, I don’t understand a lot of things yet, but I’m growing on myself :wink:
All in all I will try to test it within a week and upload it somewhere on the github. And you as a professional, finalize it, if you have time for that.

Hi all!
I need help.
In order to make UAVCAN work on Teensy 4.x I need to present UAVCAN message as a structure:

typedef struct CAN_message_t {
  uint32_t id = 0;                    // can identifier
  uint16_t timestamp = 0;      // FlexCAN time when message arrived
  uint8_t idhit = 0;                  // filter that id came from
  struct {
    bool extended = 0;           // identifier is extended (29-bit)
    bool remote = 0;              // remote transmission request packet type
    bool overrun = 0;             // message overrun
    bool reserved = 0;
  } flags;
  uint8_t len = 8;                  // length of data
  uint8_t buf[8] = { 0 };         // data
  int8_t mb = 0;                   // used to identify mailbox reception
  uint8_t bus = 0;                // used to identify where the message came from when events() is used.
  bool seq = 0;                    // sequential frames
} CAN_message_t;

Sending the message will look like this:
Can1.write (frame);

Can you help me to form a message to send via CAN as a structure, similar to the example above?

I am not sure I understand the question. Are you asking how do you convert a CanardFrame to what you specified above or is your question about UAVCAN transfer serialization? Perhaps you could restate your question in terms of the entities defined in libcanard’s API?

Now I can transmit classic CAN or CANFD messages. Everything is fine here.

Then I have to generate a UAVCAN frame and transmit it via CANbus as a standard message - question how to do this?

Use canardTxPush() / canardTxPeek() / canardTxPop() as explained in the libcanard documentation.

Thank you!

Hi all!

I can’t translate UAVCAN frame via CANbus

How do I tell the program that CAN_message_t &msg is CanardFrame const & frame

Or how do I pass CanardFrame const & frame through the Can1.write(msg) function;

See sketch below


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

#include <Arduino.h>

#include "../lib/UAVCAN/src/ArduinoUAVCAN.h"
#include "../lib/FlexCAN_T4/FlexCAN_T4.h"

/**************************************************************************************
 * NAMESPACE
 **************************************************************************************/

using namespace uavcan::node;

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

static int const NODE_ID  = 126;                    // от 1 до 127
static int const LED_BLINK_PIN = 2;                 // UAVCAN Detector
static int const SILENT_CAN_PIN  = 21;              //
static CanardPortID const BIT_PORT_ID  = 1620U;     //

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

//CAN
void    can_normal       ();
void    can_silent       ();

//UAVCAN
bool    transmitCanFrame(CanardFrame const &);

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

FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can1;
CAN_message_t msg;

ArduinoUAVCAN uc(NODE_ID, transmitCanFrame);
Heartbeat_1_0<> hb;

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

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

  /* Setup CAN access */
  can_normal();
  Can1.begin();
  Can1.setClock(CLK_16MHz);
  Can1.setBaudRate(250000);
  //Can1.setMaxMB(16);
  //Can1.enableFIFO();
  //Can1.enableFIFOInterrupt();
  //Can1.onReceive(canSniff);
  //Can1.mailboxStatus();

  /* Configure initial heartbeat */
  hb.data.uptime = 0;
  hb = Heartbeat_1_0<>::Health::NOMINAL;
  hb = Heartbeat_1_0<>::Mode::INITIALIZATION;
  hb.data.vendor_specific_status_code = 0;
}

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

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

  /* Transmit all enqeued CAN frames */
  while(uc.transmitCanFrame()) { }
}

/**************************************************************************************
 * FUNCTION DEFINITION
 **************************************************************************************/

void can_normal()
{
  pinMode (SILENT_CAN_PIN, OUTPUT);
  digitalWrite(SILENT_CAN_PIN, LOW);
}

void can_silent()
{
  pinMode (SILENT_CAN_PIN, OUTPUT);
  digitalWrite(SILENT_CAN_PIN, HIGH);
}

bool transmitCanFrame(CanardFrame const & frame)
{
  /* ???????????????
  How do I tell the program that CAN_message_t &msg is CanardFrame const & frame
  Or how do I pass CanardFrame const & frame through the Can1.write(msg) function;
  */
  
  //return Can1.write(msg);
}

I connected two libraries

https://github.com/107-systems/107-Arduino-UAVCAN

and

https://github.com/tonton81/FlexCAN_T4

You have to construct a new instance of CAN_message_t and populate its fields with the values taken from CanardFrame. The latter can be discarded afterwards.

bool transmitCanFrame(CanardFrame const & frame)
{
  CAN_message_t msg;
  msg.id = frame.extended_can_id;
  msg.buf = reinterpret_cast<uint8_t const *>(frame.payload);
  msg.len = static_cast<uint8_t const>(frame.payload_size);
  return Can1.write(msg);
}

Get error:

incompatible types in assignment of ‘const uint8_t* {aka const unsigned char*}’ to ‘uint8_t [8] {aka unsigned char [8]}’

Please help :slight_smile:

Use std::copy or std::memcpy

1 Like