One of the most effective ways of debugging your software without having to add additional hardware is to be able to print information from your source code.
In a normal C/C++ program you might use printf
or std::cout
, these can be set up to work on the Daisy to print over JTAG, but without any extra hardware we can log information out through the built-in USB port on the Daisy.
Your first question might be, "How can I see where it's printing on my computer?" And there are a ton of answers to this question.
The offerings for Serial Monitors vary from OS to OS, but there are a few options that are cross platform, and just work:
(If you're using the Serial Port Helper extension you'll have to the "view" option from "hex" to "string" the first time you connect to the COM port.)
There are a number of other options out there, and if you've already used a different tool with success, feel free to keep using it!
A simple "Hello World", might look a little something like:
Chances are, if you tried to run this code, you might have missed the "Hello World" since it happens almost instantly after the program starts. It probably happened before you could connect to the Serial Port.
There are are a few ways to address this issue, and we'll look at both:
First, you could add a large delay between the Start Log, and the first thing you want to print:
This works, but you still only have 5 seconds to connect to the port before you might end up missing the message.
Another solution would be to move the PrintLine into the infinite while loop.
This works, but if you only want to print something once, or you're debugging something in your initialziation code, then it's not very useful to continuously print it over and over again.
So what's the best solution? Well, there's an optional argument for the Logger that will wait for connection to the COM port before resuming code execution.
By calling:
The program will wait indefinitely until you connect before moving on.
So, for our best Hello World, where it's impossible to miss the message on the Serial Monitor:
Now, there are times where this is exactly what we want, and there's times where we want our board to run with, or without the USB connected. In the latter case, we will instead choose one of the other potential solutions, or create special cases for DEBUG builds vs RELEASE builds.
For those of you used to format specifiers from C or C++, you will feel right at home as the Print
and PrintLine
functions both use the same syntax.
For those unfamiliar, you can find information on the specifiers in the cpp language documentation.
For example, consider counting something:
This example will output:
and so on all the way up to 100 before repeating itself.
Due to the small memory footprint of an embedded platform like daisy, floating point numbers are handled slightly differently by default, and won't work with the f
format specifier.
Each of the following options has its own benefits:
LDFLAG
for f
support: For ease-of-use, when memory limits are not an issue.FLT_FMT
, FLT_VAR
specifiers: For minimal cost, drop in for printing the ocassional float.That said, if you really want to be able to use the f
, and your application isn't nearing the maximum size, you can add the following to your project's application Makefile:
This does add a few kilobytes to the flash usage of any program, and is why it's not included by default.
With that flag added you can print floats as you would expect:
Without the extra memory cost of adding that linker flag, there are a few other ways to output floating point numbers:
One is to use special macros provided with the Logger class:
To specify more or less decimal places you can use the more generic macros
Another way is to use the FixedCapStr
class, and the appendFloat
function:
You'll notice that the default for the AppendFloat
function is to round to the nearest two decimal places. You can adjust this to print more decimal places by adding a second argument:
This last option has a lot of flexibility for other types, and works well when building complex user interfaces with Displays, and the Ui
class. You do have to be mindful that the template argument is large enough for the final string you want to make.
Topics without links are coming soon: