Go Down

Topic: lcd.print and sprintf compatiblity?? (Read 369 times) previous topic - next topic

highflier

Hi All,

I have a bug that occurs in sprintf, but it only started after I added lcd.print to my code what makes it even stranger is that. it is just the 3rd char of the sprint that is somewhat random.

I.E.

  char buffer[40]; // sprintf buffer

setup
{
  lcd.setCursor(0,0);
  lcd.print(55.1);                                                          //deleting this line solves problem and I get right result
}

loop
{
  sprintf(buffer,"%dXXX%04d",55, 1234);
}


buffer has the following in it 55?XX1234



Note this is what I narrowed it down to,  But other lcd.prints sometimes do and sometime do not effect the result,
Also left other required code out of this post, LCD and other initializer stuff.

Any idea's or am I the only one with this compatibility issue?

Highflier

PS. The "XXX" really is supposed to be  a "."
sprintf is being used to convert a double to a string in the actual application



groundfungus

You don't say which library you are using, but most I have seen do not allow the printing of floats with sprintf.  You need to use lcd.print() instead.  The lcd will show ? where the float is to be displayed.

highflier

I am using the windows ide 1.0.5 version of the compiler

#include <EEPROM.h>
#include <Wire.h>
#include <Adafruit_BMP085_U.h>
#include <Adafruit_Sensor.h>

#include <LiquidCrystal_I2C.h>
#include <hc05.h>   
#include <MsTimer2.h>


sprintf is printing int values,  That is why I am manually putting the decimal in the code

//code before I started chasing the bug.
String float_to_string(double val)
{
  double val2 = val-(int)val;
  val2=val2*10000;
  sprintf(buffer,"%d.%04d",(int)val,(int)val2);
  return buffer;
}

polyglot

I think you'll find that one of the calls you make is importing (linking) an incompatible or broken dtostrf  which is then breaking the other call you make.  The fact that you are only calling sprintf with %d doesn't matter; if the sprintf you import has support for %f then it may bring in a dtostrf or similar.  Similarly, the LiquidCrystal::put(float) method will import a dtostrf and other conversion which might break your sprintf.

sprintf is an abomination that shouldn't really be used in microcontroller.  It's expensive in both time (it has to parse the format string on every call!) and space (lots of code to support all the format options you'll never use), and it's very error-prone which is not something you want in an embedded application.

You're better off manually calling dtostrf yourself if you want to print out floats.  Here's an unrelated snippet of code that I use to fill in some fairly complex numbers on an LCD; you can see it manually inserts a sign, uses dtostrf twice and keeps track of the total length (used) of string so generated in order to fit it into the LCD and overwrite any old content with spaces.

Code: [Select]

void Program::Exposure::displayTime(LiquidCrystal &disp, bool lin)
{
    disp.setCursor(0,1);

    // print stops
    char used=0;
    if(stops >= 0){
        disp.print("+");
        ++used;
    }
    dtostrf(0.01f*stops, 0, 2, dispbuf);
    used+=strlen(dispbuf);
    disp.print(dispbuf);

    // print compiled seconds
    if(lin){
        disp.print("=");
        dtostrf(0.001f*ms, 0, 3, dispbuf);
        used+=strlen(dispbuf)+2;
        disp.print(dispbuf);
        disp.print("s");
     
        // fill out to 15 chars with spaces
        // keep the 16th for 'D' drydown-indicator
        for(int i=0;i<15-used;++i)
            dispbuf[i]=' ';
        dispbuf[15-used]='\0';
        disp.print(dispbuf);
    } 
}

bperrybap

How about showing all the code that replicates the issue?
All we have seen so far is fragments of code.
My guess is that it is due to something in the code we are not seeing.


Post all the sketch code that creates the issue
so we can build and see what you are seeing.


--- bill

Go Up