2013-01-03 5 views
7

のマークを問う:アルドゥイーノ:printfの/ fprintfのプリントは、私はArduinoのスケッチのために、次のコードを持っている代わりに、フロート

#include <LiquidCrystal.h> 

LiquidCrystal lcd(12, 11, 5, 4, 3, 2); 
static FILE lcdout = {0} ; 

static int lcd_putchar(char ch, FILE* stream) 
{ 
    lcd.write(ch) ; 
    return (0) ; 
} 

void setup() { 
    lcd.begin(16, 2); 
    fdev_setup_stream (&lcdout, lcd_putchar, NULL, _FDEV_SETUP_WRITE); 
} 

void loop() 
{ 
    stdout = &lcdout; 
    printf("%.2f Volts", 2.0); 
} 

問題は、コードの最後の行に来ます。これは "2.00 Volts"を出力する代わりに、 "?Volts"(実際の浮動小数点値の代わりに疑問符)を出力します。私が整数をフォーマットしようとすると、これはうまくいきます。

私は、次のとprintfのラインを交換するのであれば基本的には、それが正常に動作します:

printf("%d Volts", 2); //prints correctly "2 Volts" 

問題何任意のアイデアを? avr-libcdocumentationから

+1

易しく書き直さダウンSTDLIB浮動小数点数の変換は処理できませんか? @DanielFischer正確に。 –

+0

。 –

+0

面白いことは、単にlcd.print(2.0)を実行すれば、あなたが望むものを正確に印刷できるということです。 sprintfの必要はありません。また、オプションの第2パラメータを使用して小数点以下の桁数を指定することもできます。例えば。 lcd.print(2,3)はあなたに "2.000"を与えます。 –

答えて

6

AVRのGNUツールチェーン(Arduino IDEに含まれています)は、デフォルトでC標準ライブラリの「縮小版」を使用しています。たとえば、浮動小数点サポートがフォーマットから縮小/削除されていますI/O機能(単にチップの数キロバイト長期保存に収まるようにするためprintf()インチ)

あなたはこれが仕事をしたい場合は、あなたが使用することにより、printf()の正常なバージョンを含む別のライブラリagainsリンクする必要があり-Wl,-u,vfprintf -lprintf_fltリンカーフラグ。

+0

私は自分のコードをリンクするときにこのリンカ引数を提供する必要があります。そうしないと、ライブラリを再度コンパイルして、このリンカ引数を提供する必要がありますか? –

+0

@NicolaeSurduライブラリを再コンパイルする必要はありません。独自のコードをリンクするときにこれらのフラグを指定する必要があります。 –

+0

ご協力いただきありがとうございます! –

3

浮動小数点変換を含むすべての機能が必要な場合は、以下のオプションを使用する必要があります。

-Wl,-u,vfprintf -lprintf_flt -l

なお、あなたのMCU doesnの場合浮動小数点のサポートがある場合、浮動小数点演算を完全に回避するようにしてください。浮動小数点演算は、非常に非効率的で多くのフラッシュメモリが必要なソフトウェアで行われます。

+0

あなたは '-lprintf_min' IIRC(これはAVRで遊んでいたのですが)は必要ありません。' libc.a'にはミニライブラリが含まれています。 –

+0

@ H2CO3回線を削除しました。私はあなたが完全な 'printf_flt'を使わなければ、' printf'で浮動小数点サポートを持っていないと思います。 – ouah

+0

はい、それは私が本質的に言っていることです。あなたはいつも '?'を得るでしょう。 –

0

私はこの1つでした:

unsigned char buffer[32]; 

void setup() { 
    serial.begin(); 
} 

void loop() { 
    if(serial.available()) { 
    int size = serial.read(buffer); 
    if (size!=0) { 
     //serial.write((const uint8_t*)buffer, size); 
     int bright = atoi((char *) buffer); 

     //int final = ((unsigned int)buffer[0]); 

     //int final = bright -'0'; 
     serial.write(bright); 
     serial.write('\n'); 
    } 
    } 
    serial.poll(); 
} 

を、私はUSB経由で0〜255の値を送信する際に、今私は、ASCII文字を取得します。 私はascii charをintに変換する方法を見つけるべきです。

例えば私は65を入力し、それは私はあなたが完全にprintfのを避けたいと単に小数点の前と後桁の与えられた数で印刷する必要がある場合に役立つかもしれないいくつかの古いコードを持っている

0

を印刷します。このコードはC言語でコンパイルされ、Arduino IDEでも正常に動作します。ほとんど確実にC++の行数を減らすことができます。 pow10はで働いていたプログラムで行うことができるが、パワーはCIのバージョンではサポートされませんでした。

#include <stdio.h> 

/* 
Because lcd and serial don't support printf, and its very costly, and all we need 
is simple formating with a certain number of digits and precision, this ftoa is enough. 
If digits is negative, it will pad left. 
*/ 
#define BUF_LEN 20 
char buf[BUF_LEN]; //need a buffer to hold formatted strings to send to LCD 

int ftoa(char * str, float f, char digits, char precision) { 
char i=0,k,l=0; 
long a,c; 
long pow10[10] = {1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000}; 
unsigned char b; 
char decimal='.'; 

    if(digits>=10) {return 0;}; 
    // check for negative float 
    if(f<0.0) { 
    str[i++]='-'; 
    f*=-1; 
    (0<digits?digits--:digits++); 
    } 
    a=(int)f; // extracting whole number 
    f-=a; // extracting decimal part 
    k = digits; 
    // number of digits in whole number 
    while(k>=0) { 
    c = pow10[k]; 
    c = a/c; 
    if(c>0) { break; } 
    k--; 
    } // number of digits in whole number are k+1 
    if (0<k && digits==k && c>10) { //overflow 
    decimal = 'e'; 
    } 
/* 
extracting most significant digit i.e. right most digit , and concatenating to string 
obtained as quotient by dividing number by 10^k where k = (number of digit -1) 
*/ 
    for(l=abs(k);l>=0;l--){ 
    c = pow10[l]; 
    b = a/c; 
    str[i++]=(l&&!b?' ':b+48); //digit or pad 
    a%=c; 
    } 
    if (precision) {str[i++] = decimal;}; 
/* extracting decimal digits till precision */ 
    if (0>precision) {k=0; precision=abs(precision);} 
    for(l=0;l<precision;l++) { 
    f*=10.0; 
    b = (int)f; //math floor 
    str[i++]=b+48; //48 is ASCII 0 
    f-=(float)b; 
    if (!k && 0==f) { break; } //nothing left, save chars. 
    //won't work if there are any floating point errors. 
    } 
    str[i]='\0'; 
    return i; 
    } 

あなたはそれで遊ぶと、それはここで実行見ることができます: http://ideone.com/AtYxPQ

関連する問題