Oct 27, 2015

formatting float printing on Arduino vs Teensyduino

I ran into a bug yesterday that I'd encountered once before. I was running code that was tested and working. This time, I happened to have the right pieces on my desk to figure this out.

Currently, nearly all development I do in this environment is using the Teensyduino 3.x. It's fast, small, and a little bit different. Here's one of the ways.

I like my streams of numbers to line up for readability, especially floats. It's more trouble than it ought to be in most languages.

For the Arduino, there is a function dtostrf() that will print a fixed format float. However, there is a bug that causes it to display wacky numbers, usually when the value of the number is << 0.1, but for other cases as well. Using different boards at different times, I didn't notice the pattern. It turns out that this bug only occurs on the Teensy 3, which uses an ARM processor. In AVR-based boards such as the Arduino Uno and the Teensy 2, it works fine.

The work-around* for the T3 is to use a more standard and powerful printf() or sprintf(). These do not work for floating point numbers when compiled for AVR. (It would be nice if they did.)
*Per these current versions (Arduino 1.6.5, Teensy 1.2.4)

For Arduino and Teensy 2, use dtostrf()

  dtostrf(y, 10, 5, cbuf);     
 Serial.println(cbuf);

  -0.07071
?        
   0.00354
?        
 
 
For Teensy 3, use sprintf()

 sprintf(cbuf, "%10.5f", y);  // correct on T3
 Serial.println(cbuf);
  
 -70711
-0.07071 
 
35355
 0.00354 

 



 test code:

// formatted float printing: Teensy 2 vs 3
char cbuf[20] = "";

void setup() {
  while (!Serial && millis() < 5000) {}  // with timeout
  Serial.begin(9600);    

  float y;
  // -nn.nnnn

  y = -(sin(3.1416 / 4)) / 10;
  dtostrf(y, 10, 5, cbuf);     // incorrect on T3
  Serial.println(cbuf);
  sprintf(cbuf, "%10.5f", double(y));
  Serial.println(cbuf);

  y = +(sin(3.1416 / 4)) / 200;
  dtostrf(y, 10, 5, cbuf);
  Serial.println(cbuf);
  sprintf(cbuf, "%10.5f", y);  //   correct on T3
  Serial.println(cbuf);
}

void loop() {
  ;
}




No comments: