У меня есть следующий код для эскиза Arduino:
#include 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» (знак вопроса вместо фактического значения поплавка). Если я попытаюсь форматировать целое число, это отлично работает.
Поэтому в основном, если я заменю строку printf следующим образом, она будет работать правильно:
printf("%d Volts", 2); //prints correctly "2 Volts"
Любая идея, в чем проблема?
Инструментальная привязка GNU для AVR (которая входит в состав Arduino IDE) по умолчанию использует «минированную» версию стандартной библиотеки C, в которой, например, поддержка с плавающей запятой уменьшается / отбирается от форматированных функций ввода / вывода (только для того, чтобы printf()
вписывался в несколько kBytes долгое время хранения чипа.)
Если вы хотите, чтобы это сработало, вам нужно связать еще одну библиотеку, содержащую обычную версию printf()
, с помощью -Wl,-u,vfprintf -lprintf_flt
.
Из документации avr-libc
:
Если требуется полная функциональность, включая конверсии с плавающей запятой, следует использовать следующие параметры:
-Wl,-u,vfprintf -lprintf_flt -l
Обратите внимание, что если ваш MCU не поддерживает поддержку с плавающей запятой, вы должны полностью отказаться от операций с плавающей запятой. Операции с плавающей запятой будут выполняться в программном обеспечении, которое очень неэффективно и требует много флэш-памяти.
Я сделал это:
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(); }
и теперь я получаю символ ascii, когда я посылаю значение от 0 до 255 через USB. Я должен найти способ преобразования ascii char в int.
например, тип 65, и он печатает A
У меня есть старый код, который может помочь, если вы хотите полностью отказаться от printf и просто нужно печатать с заданным числом цифр до и после десятичного числа. Этот код компилируется на C и отлично работает в среде Arduino. Это почти наверняка можно было сделать в меньшем количестве строк на C ++. Pow10 можно было сделать программно, но полномочия не поддерживались в версии CI, которая работала с:
#include
в/* 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 =0) { c = pow10[k]; c = a/c; if(c>0) { break; } k--; } // number of digits in whole number are k+1 if (0 10) { //overflow decimal = 'e'; } /* extracting most significant digit ie 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 #include
/* 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 =0) { c = pow10[k]; c = a/c; if(c>0) { break; } k--; } // number of digits in whole number are k+1 if (0 10) { //overflow decimal = 'e'; } /* extracting most significant digit ie 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
Вы можете играть с ним и посмотреть, как он работает здесь: http://ideone.com/AtYxPQ