El objetivo de la plataforma Arduino es que los programas sean pequeños, ya que tienen que caber en pocos Kbs. Un pequeño problema que tenemos con eso es que muchas bibliotecas no están implementadas completamente, sino que las encontramos en su versión light, en las que implementan sólo las funcionalidades más normales.
Un ejemplo de ello son los comandos printf() y scanf() cuya funcionalidad no cubre los valores de punto flotante (float, double), y que si hacemos el siguiente programa:
1 2 3 4 5 6 7 8 9 10 11 12 | void setup() { Serial.begin(9600); } void loop() { char buffer[30]; sprintf (buffer, "Valor: %f\n", 25.4); Serial.println(buffer); delay(1000); } |
Veremos constantemente:
…
Valor: ?
Valor: ?
Valor: ?
…
Y no muestra el valor deseado. Eso sí, ocupa 4.29Kb
Tabla de contenidos
La clave para la solución
El tema está en que el compilador no enlaza con las bibliotecas buenas, sino que enlaza con las ligeras. Por lo que tenemos que hacer que éste enlace con las bibliotecas correctas añadiendo el siguiente parámetro al compilador avr-gcc:
-Wl,-u,vfprintf -lprintf_flt
Haciendo el cambio para SConstruct
Si para compilar tus proyectos de Arduino utilizas este método, tienes que modificar una línea en el archivo SConstruct… pongo parte del contexto, cerca de la línea 170, donde pone:
1 2 3 4 5 6 | envArduino.Append(BUILDERS = {'Processing':Builder(action = fnProcessing, suffix = '.cpp', src_suffix = '.pde')}) envArduino.Append(BUILDERS={'Elf':Builder(action=AVR_BIN_PREFIX+'gcc '+ '-mmcu=%s -Os -Wl,--gc-sections -o $TARGET $SOURCES -lm'%MCU)}) envArduino.Append(BUILDERS={'Hex':Builder(action=AVR_BIN_PREFIX+'objcopy '+ '-O ihex -R .eeprom $SOURCES $TARGET')}) |
Debemos escribir:
1 2 3 4 5 6 | envArduino.Append(BUILDERS = {'Processing':Builder(action = fnProcessing, suffix = '.cpp', src_suffix = '.pde')}) envArduino.Append(BUILDERS={'Elf':Builder(action=AVR_BIN_PREFIX+'gcc '+ '-mmcu=%s -Os -Wl,--gc-sections -o $TARGET $SOURCES-Wl, -u,vfprintf -lprintf_flt -lm'%MCU)}) envArduino.Append(BUILDERS={'Hex':Builder(action=AVR_BIN_PREFIX+'objcopy '+ '-O ihex -R .eeprom $SOURCES $TARGET')}) |
Con esta modificación, el programa en Arduino (el binario ocupa 5.8Kb) debe dar:
Valor: 25.400000
Valor: 25.400000
Valor: 25.400000
Más información
La IDE de Arduino hace las llamadas al compilador desde su código fuente en lugar de utilizar un Makefile, por ejemplo, por lo que para compilar incluyendo las instrucciones del linkador en el código fuente del IDE. El problema de esto es que no hay una forma fácil de conmutar el linkado con printf_flt y printf_min (que es como se llama la versión light).
Con scanf() también se puede
scanf() también permite la inclusión de la biblioteca que es capaz de leer floats. La instrucción que hay que escribir es:
-Wl,-u,vfscanf -lscanf_flt
Foto: Eric Lim Photography (Flickr) compartido con CC-by a 30/11/2011
Pingback: Bitacoras.com /
Pingback: BlogESfera.com /
hola amigo , me pregunto si no habra una forma de solucionarlo en windows ?
grasias de ante mano.
scons funciona también bajo Windows , además, hay tutoriales por Internet para configurar Eclipse como IDE para Arduino, por lo que en el compilador podríamos introducir los modificadores que vemos en el post para compilar.
Pingback: Controlando un display de 7 segmentos con Arduino y un botón por interrupción. – Poesía Binaria /
nice blog! its interesting. thank you for sharing.
how to play baccarat online