Working with FlatBuffers on Teensy 3.2
14 September 2020 at 12:52 pm
FlatBuffers is a very nice solution for sending data between machines. Data is sent binary and no parsing is required. Since it’s very compact and requires no extra logic, it can be many hundred times faster than parsing and sending JSON.
Getting it to work with Teensy took some time, so here are my notes from getting this working.
Why FlatBuffers
For a customer project, I need to exchange data quickly via Serial. There’s a lot of possibilities, but after looking through what standard solutions are available, FlatBuffers really sticks out. The alternative could be writing your own binary protocol, but with FlatBuffers, you’ll get several features that would be hard to implement yourself. FlatBuffers start from a Schema that forces you to think about data structure quite early in the project. The Schema supports deprecation, so your code can survive changes in data structure. Based on the Schema file, you’ll generate a class that you can use straight in your project (C++, C#, C, Dart, Go, Java, JavaScript, Lobster, Lua, PHP, Python, Rust, TypeScript) to generate objects to send.
The basic usage is that you’ll create a buffer, fill it with data and send it off via whatever transport you want as binary data. Once received, the receiver reads the binary data into a byte array and passes this to a generated class for that platform. The second you’ve fed the data to the object, you can access the data. No deserialisation required - a string is a string, a float is a float. The generated class also comes with a basic validation tool that is useful.
Using in TeensyDuino
The TeensyDuino IDE won’t compile flatbuffers from it’s default location, so you’ll have to copy it to your library folder Documents/Arduino/libraries/flatbuffers This is ok, since we’ll also need to do some minor changes to the files.
The first problem is that FlatBuffers compiled for Linux has some specific output for Arduino. Using FlatBuffers with Arduino devices will require you to install and use the “Arduino STL” library. Teensy (and other ARM platforms) will already have proper STL support and Teensy will have the constant ARDUINO defined, making this go wrong.
By default, there’s a couple things you’ll need to do in base.h to make it work with Teensy. We have to remove what applies to ARDUINO specific things and we’ll have to omit the first part of the path to stl_emulation.h as in this example.
If you don’t do these changes, you’ll get redefinition errors and more.
You’ll also run into an issue with _write not being defined:
writer.c:(.text._write_r+0x12): undefined reference to '_write'
This is solved by adding the “nosys.specs” flag to the output you are using for Teensy31 in “boards.txt”. I use the “Faster” output, so I added it for that one.
teensy31.menu.opt.o2std.build.flags.ldspecs=--specs=nosys.specs
This seems to be a very common problem and I found the solution in this thread.
Transmitting as Binary vs ASCII
When sending the buffers, don’t forget the difference between Serial.print & Serial.write
Serial.write(receivedString[i]); // Sends as Binary
Serial.print(receivedString[i]); // Sends as ASCII