#define, ahorra memoria, ¿Tiene alguna pega? [solucionado, sin pegas]

Hola
Acabo de descubrir que emplear #define me ahorra memoria de programa, cosa que no sabia, pero tengo una duda:

¿Esto tiene alguna pega que se me pase por alto?

Porque he sustituido las instrucciones de este tipo:
int entrada_local = 24; // Pin para lectura de entrada de local

Por este otro:
#define entrada_local 24 // Pin para lectura de entrada de local

Y el compilador me decia antes:
Binary sketch size: 29872 bytes (of a 126976 byte maximum)

Y ahora me dice:
Binary sketch size: 29462 bytes (of a 126976 byte maximum)

Eso son mas de 400 de ahorro.

La duda: ¿Tiene alguna contraindicacion?

Un saludo

El define es una sentencia del preprocesador. Lo que hace es allí donde utilizas entrada_local, lo cambia a 24 cuando se está compilando tu programa.
De esta forma, no estás usando memoria RAM del micro con la variable entrada_local. Ésto tiene sentido, si no vas a cambiar en tiempo de ejecución el pin entrada_local, cosa que la mayoría de las veces ocurre...
Utilizandolo de esta forma, te da flexibilidad a tu código, porque no tienes que cambiar en todas las instrucciones donde escribirías 24 cuando quieras utilizar otra entrada, pero hay que tener en cuenta que no podrás cambiarlo en tiempo de ejecución.

También te permite hacer macros y muchas cosas más. Es bastante potente => Top (The C Preprocessor)

Por ejemplo, algo bastante utilizado, el operador _BV(bit), está generado con un macro => #define _BV( bit ) ( 1<<(bit) ) ,es decir, cuando haces por ejemplo, mialarma=_BV(5) para poner el bit 5 de la variable mialarma a 1, el compilador lo que hace es cambiar el código a mialarma= 1<<5

Por ejemplo, algunas de las instrucciones de Arduino generadas con macros son:
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define constrain(amt,low,high) ((amt)<(low) ? (low): ((amt)>(high)?(high):(amt)))
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
#define radians(deg) ((deg)*DEG_TO_RAD)
#define degrees(rad) ((rad)RAD_TO_DEG)
#define sq(x) ((x)
(x))
#define interrupts() sei()
#define noInterrupts() cli()

y constantes como por ejemplo:

#define HIGH 0x1
#define LOW 0x0

#define INPUT 0x0
#define OUTPUT 0x1

#define true 0x1
#define false 0x0

#define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398
#define TWO_PI 6.283185307179586476925286766559
#define DEG_TO_RAD 0.017453292519943295769236907684886
#define RAD_TO_DEG 57.295779513082320876798154814105

Cuando haces un digitalWrite(13,HIGH), precisamente se transforma ese HIGH por un UNO (1).

Salu2

Yo te voy a dar una constestación de andar por casa que Igor ha metido mucho nivel.

"define" es una constante por lo que una vez que se le da un valor no se puede cambiar. El clasico ejemplo es con pi

#define PI 3.1416

"int entrada_local" es una variable de tipo integer que durante el programa se le puede dar otro valor.

Cuidadín con confundir memoria de programa (es la info que te da Arduino cuando ha compilado), con la memoria RAM utilizada...
He metido un poco de "caña" para que se vea lo potente que puede llegar a ser... :wink:

Cierto que me había colado. Corregido. :*

Pues como siempre: Muchas gracias compañeros.

He descubierto estos cambios que tambien ahorran:
char* cabecera2 = ("8/2011 Rev: 2");
por este otro:
#define cabecera2 "8/2011 Rev: 2"

Obviamente, no tocare nada que en tiempo de ejecucion tenga que cambiar, pero para valores fijos veo que es interesante.

Respecto a una memoria y otra, ¿como saber cuanta consumes?

Pues la del programa esta clara, te lo dice el ide del arduino, pero ¿la otra?

Yo tengo este fragmento en el programa:

  mensaje1("Test de Sistema");    // Empezamos
  delay(1000);
  mensaje1("RAM Libre: ");       // Cantidad de Ram libre
  mensaje2("Bytes ");
  lcd.print(FreeRam());
  delay(1000);
  lcd.clear();

que me dice:
4188 de ram libre
¿es correcto?

AH!! segun el ide estoy consumiendo 29450 bytes de programa, estoy usando un mega pero si usara un arduino 328 que me parece esta en 32000, estaria a punto de llenarlo verdad?

Para las cadenas, si utilizaras progmem, para guardarlas en memoria de programa, aún mejor!!

:wink:

Pues me pongo a ello...

Hago una pausa y luego continuo.

Gracias.

Coño no sabía que los datos los guardaba en la sram a no ser que digesemos que lo guardara en la flash. Pues no hay casi diferencia de espacio entre la sram y la flash. Tengo que mirarlo más a fondo porque creo que tiene miga. Por cierto cuando creamos variables y apartir de cierto punto no las usamos, arduino libera ese espacio en la ram o continua ocupado?

He sustituido las llamadas a las dos cadenas de texto fijo que tengo y no me ha variado la memoria de compilacion (la que muestra el ide) que se ha quedado en 29450.

Pero en la llamada dentro del programa a la funcion FreeRam() si que ha cambiado y antes de usar progmem, me indicaba: 4188 y ahora al usar progmem, me indica 4222, es decir, si que me ha liberado memoria de ram.

Solo tengo un problema y es que en el lcd me muestra "marcianitos" que debe ser por la conversion de tipos, pero es interesante esto del progmem, con los ejemplos no me he aclarado mucho, aunque he conseguido hacerlo funcionar.

Me uno a la pregunta de Ionhs:

cuando creamos variables y apartir de cierto punto no las usamos, arduino libera ese espacio en la ram o continua ocupado?

Excelente informacion amigos, tengo un proyecto con un panel de de leds de SureElectronics y consume una barbaridad de memoria, con deciros que tengo un mando de Radiofrecuecia que cuando lo pruebo solo sin ningun otro codigo me coje la señal a 40m. pero cuado le incorporo el codigo del panel de leds unos cuandos IFs, switch case,etc el mando apenas me responde a 0.5 m.

Probare vuestras sugerencias, y si alguno de vosotros tiene experiencia con estos leds chupadores de ram por favor hacedme saber algun truquillo o libreria que no consuma, estoy utilizando la libreria ht1632c.

S2

cuando creamos variables y apartir de cierto punto no las usamos, arduino libera ese espacio en la ram o continua ocupado?

Os dejo el camino, para que investigueis:

Lo del mando de memoria es un poco más sospechoso... Cuando pruebas el mando solo tiene el resto de la parafernalia conectada? Si no hay nada conectado, es posible que estés teniendo otros problemas que no tienen nada que ver con el programa, vamos a nivel eléctrico.

@fmalpartida Gracias por la respuesta.

El tema es que tengo mi prototipo conectado con todo Arduino+ Panel de leds+ receptor rf
Sin tocar nada de conexiones cargo el sketch simple es decir arduino lee pulsador y hace var++ e imprime en el serial, con esto puedo llegar a 40 m espacio abierto.
Sin embargo cuando cargo el sketch completo 4 pulsadores leen se hacen unos if's, switch cases, itoas y se imprime en el panel de leds, en este caso el rango del mando rf es minimo como dije antes 0.5 m a lo mucho.

Muy raro raro

Cuando se hacen cosas con radio, no hay nada raro... Lo que me resulta curioso es que si te has quedado sin memoria no veas un comportamiento errático.

Me explico, cuando te quedas sin memoria, lo que suele suceder es que machacas la pila, con lo que verías como tus funciones se ejecutan de aquella manera y devuelven el control a lugares donde no debería o incluso resetear el micro. De todas formas, haz la prueba es muy sencillo, si no usas muchas variables de pila (variables locales a funciones), estas no son muy grandes y no tienes muchas llamadas anidadas, con que te sobren unos cientos de bytes debería ser más que suficiente.

Si eso no es el caso, te aconsejo que añadas unos buenos desacoplos (entre 10uF y 100uF en la alimentación de la parte analógica - RF), minimices los cables que conmutan corriente hacia los leds (esto suele ser una buena fuente de ruidos), que no haya puentes colgantes e intenta alejar el receptor todo lo que puedas de la parte de conmutación y digital. También se te puede estar colando algo de ruido por la interfaz que uses entre el receptor y el micro. Sin ver el montaje es un poco complicado...
¿cómo de grande es el panel de LEDs? ¿Cúantos LEDs tiene? ¿Qué fuente estás usando? ¿cómo alimentas la radio? ...
Un saludo

Gracias fmalpartida, lo que hare sera pasar el prototipo de la breadboard a un placa.

Creo que efectivamente quizas sea ruido y no la memoria ya que le he añadido unos calculos extra (como prueba) para que me los imprima en el serial y no hay ningun problema.

El panel de leds que tengo es de 32*16 intentare ponerle en la parte de atras una de esas barreras antiestaticas.

Arduino alimentado por 9v y tanto el panel de leds como el modulo RF cogen los 5v de arduino.

Lo dicho realizare lo descrito arriba y vere si hay algun cambio.

yOPERO:
Creo que efectivamente quizas sea ruido y no la memoria ya que le he añadido unos calculos extra (como prueba) para que me los imprima en el serial y no hay ningun problema.

+1 estoy con vosotros el tema tiene toda la pinta de ser ruido en la alimentacion por las conmutaciones.

Puedes usarl el ULN2803 un chip que veras por miles en las tragaperras para las luces, y de paso separas la alimentacion de los leds de la del arduino:

De todas formas, no es la primera vez que vemos post con problemas de interferencias en la alimentacion del arduino, igual debiamos de ponerle algun filtro o algo.

Aunque en el dibujo ponga puerto de impresora, cambialo por puerto del arduino y el zener te olvidas de el, que el esquema es para bobinas de rele pero te da lo mismo que para leds, eso si, no olvides las resistencias para limitar corriente.

Un saludo.

Gracias Igor R, parece ser que hay que usar el "malloc" para realojar la memoria dinamicamente, sino, te ves que el arduino carga todo en la flash y tira "p'alante" segun el ultimo enlace.

Los miro mas tranquilo que me cuesta bastante en ingles...

Pero gracias a las indicaciones vuestras he podido ahorrar memoria en las variables fijas. Pongo el post como solucionado.

Un saludo.

He estado mirando el link Arduino Playground - Memory donde pone como es la estructura de la memoria de arduino (ya se que algo parecido sale en el datasheet) me ha parecido tan interesante (pensando en mis alumnos) que lo he traducido (añadiendo algunas palabras) Os lo dejo por si a alguno le sirve (hay que estar registrado para ver el link). Me queda pendiente mirar los links de Igor.R pero con el comienzo de las clases...Salu2

Memoria.doc (33 KB)

Lo he descargado Ionhs.

Gracias.