Jeff Epler's blog2021-10-30T21:12:03ZPhotos, electronics, cnc, and moreJeff Eplerjepler@unpythonic.netUse printf() in Arduino programs2021-10-30T21:12:03Z2021-10-30T21:12:03Zhttps://emergent.unpythonic.net/01635628323
<p>Are you happiest with printf() debugging? Do circumstances lead to you
writing "arduino code" because it's just about the easiest way to set up
an embedded software project that's not to different from C(++)? I have
something for you.
<p>I've only tested it on a sample of 1 board (the <a href="https://www.adafruit.com/product/3857">Adafruit Feather
M4 Express</a>) but I suspect that
it works on a wide variety of <strong>arm-based</strong> (or, actually,
newlib-based) boards.
<p>Long story short, put the following code in your <strong>.ino</strong>
file, call <code>Serial.begin()</code> as usual, then use
<code>printf(...)</code> and <code>fprintf(stderr, ...)</code> just
like you would anywhere. The only caveat I've discovered so far is that
printing floating-point numbers didn't work for me.
<p><pre>
// This bridges from stdio output to Serial.write
#include <errno.h>
#undef errno
extern int errno;
extern "C" int _write(int file, char *ptr, int len);
int _write(int file, char *ptr, int len) {
if (file < 1 || file > 3) {
errno = EBADF;
return -1;
}
if (file == 3) { // File 3 does not do \n -> \r\n transformation
Serial.write(ptr, len);
return len;
}
// color stderr
static bool stderr_flag;
bool is_stderr = (file == 2);
if (is_stderr != stderr_flag) {
if (is_stderr) {
Serial.write("\033[95m");
} else {
Serial.write("\033[0m");
}
stderr_flag = is_stderr;
}
int result = len;
for (; len--; ptr++) {
int c = *ptr;
if (c == '\n')
Serial.write('\r');
Serial.write(c);
}
return result;
}
extern "C" int write(int file, char *ptr, int len);
int write(int file, char *ptr, int len) __attribute__((alias("_write")));
</pre>