Design, Build, Test, Iterate

A better Serial.print() for Arduino — making it work

Finding solutions is not always a trivial process, and once found, it is often the case that the solution Just Doesn’t Work.

(In fact, just as I typed the above, my laptop decided to freeze up and die. I was going to refer back to my terminal outputs while writing the rest of this post, but they’re now gone. Sigh.)

Anyway, Serial.print(“some string”); prints things on the Arduino. A major inconvenience is that I have to use a separate print command every time I switch types. For example, the code to print something like (x, y) (where x and y are variables) is:

Serial.print("(");
Serial.print(x);
Serial.print(", ");
Serial.print(y);
Serial.print(")");

I thought it’d be nice to be able to use something like C’s printf:

Serial.print("(%f, %f)", x, y);

A few Google searches later, I found someone who had already done this, so I defined serPrint() in globals.h.

Naturally, that didn’t work on my system…

error: variable '__c' must be const in order to be put into read-only section by means of '__attribute__((progmem))'

…because my Linux-infested MacBook no longer Just Works.

I was using gcc-avr 4.6.1 and avr-libc 1.7.0 at that point. Google told me that this was a known bug in pre-1.7.0 versions of avr-libc. I downloaded 1.7.2 source from avr-libc’s release page and installed.

More errors!

error: initializer fails to determine size of '__c'

This happened wherever I tried to print a non-string, so I changed things from serPrint(someFloat) to serPrint(“%f”, someFloat). A simple enough workaround. (Actually, serPrint(someFloat) works now.)

More errors!

mathcalls.h:310:error: expected identifier or '(' before 'double'

From a hint I got somewhere, I tried reverting to an older version of gcc-avr. The newest I had in my /var/cache/pacman/pkg prior to 4.6.1 was 4.5.1, so I installed that (but 4.6.0 should work, as well). Finally, success!

One thing that slightly bothers me is that I changed some code in the Arduino libraries per this post, but again, I’ve forgotten exactly why and when I did. It doesn’t seem to make a difference, however, so I’ve let it be.

Unfortunately, I can’t test it right now because I let the battery discharge to a total of 4.7 V.

UPDATE 11/6/11: a combination of avr-libc 1.7.0 and avr-gcc 4.6.2 works out-of-the-box. However, I couldn’t print floats using serPrint(“%f”, someFloat), and I couldn’t use serPrint and Serial.print at the same time, so I switched back to using Serial.print. Sigh.

UPDATE 4/9/12: This forum post discusses the mathcalls.h error and how to fix it.



Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>