10

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」(実際の float 値ではなく疑問符) が出力されます。整数をフォーマットしようとすると、うまくいきます。

したがって、基本的に、printf 行を次のように置き換えると、正しく機能します。

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

何が問題なのですか?

4

4 に答える 4

12

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

これを機能させたい場合は、リンカー フラグprintf()を使用して、通常バージョンの を含む別のライブラリを再度リンクする必要があります。-Wl,-u,vfprintf -lprintf_flt

于 2013-01-03T20:43:34.653 に答える
4

avr-libc ドキュメントから:

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

-Wl,-u,vfprintf -lprintf_flt -l

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

于 2013-01-03T20:40:36.913 に答える
0

私はこれをしました:

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 と入力すると、A が出力されます。

于 2014-11-01T13:03:39.677 に答える
0

printf を完全に避けたい場合や、小数点以下の桁数を指定して印刷する必要がある場合に役立つ古いコードがあります。このコードは 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

于 2016-03-19T01:43:11.577 に答える