Como optimizar el consumo de memoria en programas de Arduino

Todo cuanto tiene que ver con la obtención, almacenamiento y proceso de la información digital, sus aplicaciones y el software y hardware utilizado.
Responder
Mensaje
Autor
Avatar de Usuario
heli
Mensajes: 1952
Registrado: Mié Sep 06, 2006 7:28 am
País: España
Ciudad: Alcalá de Henares
Ubicación: Alcala de Henares (Madrid, España)
Contactar:

Como optimizar el consumo de memoria en programas de Arduino

#1 Mensaje por heli »

Aunque este tema ya es conocido por los programadores veteranos de arduino es interesante para los mas nuevos...

El compilador de arduino (AVR-GCC), debido a la arquitectura Harvard de los ATMEGA reserva el memoria FLASH y RAM para las constantes, si no se usan determinadas técnicas podemos estar desperdiciando espacio en RAM!
Usando las las directivas PROGMEM y el macro F(), y las funciones pgm_read_byte() y pgm_read_word() es posible evitar esto y ahorrar bastante RAM (de la que andan escasos estos micros).

Aqui lo explico http://heli.xbot.es/?p=519 optimizando el programa del teclado analógico http://heli.xbot.es/?p=501 para ahorrar un 4% de RAM.
¡No es imposible, lo que pasa es que no sabes como hacerlo!
Aka: no es difícil si sabes como.
http://heli.xbot.es

Avatar de Usuario
Anilandro
Mensajes: 4905
Registrado: Dom Feb 11, 2007 10:16 pm
Ubicación: Islas Baleares, España
Contactar:

Re: Como optimizar el consumo de memoria en programas de Ard

#2 Mensaje por Anilandro »

Este método me interesa, Heli. Hasta ahora lo único que hacia era convertir el máximo de datos a constantes y siempre ahorraba algo, pero con la placa Ethernet Shield, al programar una página web y utilizar el mismo método no me fue bien. Todos los textos los pasaba a arrays de constantes, pero el ahorro final de memoria era mínimo. Con los Serial.print() también noté que había que ir con cuidado, porque disparaba la RAM consumida.

Me miraré tu página con calma.

Un detalle que no entiendo es que no existan en C tipos de variables de 1 bit. Existe el "Bool", naturalmente, que sólo contiene 1 bit de información (0-1, False-True), pero de forma incomprensible ocupa 1 Byte en memoria, igual de un Char o un Byte, desperdiciando 7/8 partes de "espacio". También existen la unint32_t, la uint16_t y la uint8_t, pero no la uint4_t y la uint1_t.

Supongo que ello tiene que ver con la estructura física de la memoria, que si se accede por Bytes, debido al tamaño de los registros, tardaría lo mismo en procesar 1 bit que 1 Byte, pero imaginemos que tenemos 1.000 flags de estado de dispositivos, tipo 1-0, utilizando los bits individualmente nos ocuparía solamente 1000/8 = 125 Bytes, pero de la forma actual ocupa 1.000 bytes... En fin, que se me debe escapar algún condicionante, porque lo encuentro ilógico.

Saludos
La VIDA sólo es energía que ha aprendido a defenderse... (Anilandro)

*** La Web de Anilandro *** http://sites.google.com/site/anilandro

Avatar de Usuario
heli
Mensajes: 1952
Registrado: Mié Sep 06, 2006 7:28 am
País: España
Ciudad: Alcalá de Henares
Ubicación: Alcala de Henares (Madrid, España)
Contactar:

Re: Como optimizar el consumo de memoria en programas de Ard

#3 Mensaje por heli »

La gestión de los bool en Arduino es rara... yo también he observado que ocupan un byte completo. En algunos sitios he visto que el AVR-GCC tiene definido bool como uint8_t por lo que es igual a un byte o unsigned char.
Los micros AVR solo pueden manejar bits individuales en los registros, no en la memoria RAM. Eso hace que las variables globales, que suelen estar en RAM, no puedan usarse como bool. O si, pero con un coste computacional alto: leer el dato de RAM, manipular los bits, devolverlo a RAM. Se puede forzar el uso individual de los bits usando este truco:

Código: Seleccionar todo

typedef struct {
byte Bit0 : 1;
byte Bit1 : 1;
byte Bit2 : 1;
byte Bit3 : 1;
byte Bit4 : 1;
byte Bit5 : 1;
byte Bit6 : 1;
byte Bit7 : 1;
} CampoDeBits; 

  // Define una variable tipo CampoDeBits llamada Flags y la nicializa
CampoDeBits Flags = { 0 , 1 , 1 , 0 , 1 , 0 , 1 , 0 };

  // Para distintas pruebas comentar o descomentar esto
// bool FlagP, FlagQ, FlagR;
// byte FlagP, FlagQ, FlagR;

  // Define los flags como elementos de la estructura (bits)
#define FlagP Flags.Bit0
#define FlagQ Flags.Bit1
#define FlagR Flags.Bit2
Haciendo distintas pruebas verás que usando la estructura CampoDeBits los bits solo consumen... 1 bit, 1/8 de byte. Con bool era igual que con byte. Peeeero verás que el código generado crece con este sistema, manejar la estructura CampoDeBits necesita varias microinstrucciones. También será mas lento de procesar.

Consejos para mantener el código lo mas compacto y rápido:
Evitar las variables globales, se almacenan en RAM y el código para gestinarlas es mas largo.
Usar variables locales, incluso arrays (si son de dimensión pequeña, hasta 20 o así). Las variables locales se almacenan en registros, mucho mas sencillos de manejar por el micro, y los AVR tienen 32! (estoy admirado, no 32 factorial). Los bool locales sí ocupan 1 bit solo. Al estar almacenados en registros es posible y facil.
No tener miedo en pasar muchos parámetros a las funciones para evitar variables globales. No sobrecarga casi el código como pasa con otros micros. Yo estaba acostumbrado al i8051 de intel y el manejo dela XRAM era muy complejo y generaba montones de bytes de código. Aqui no pasa.
Para pasar mucha información a las funciones usar punteros a estructuras de datos... puede liar el código y es peligroso si no se usa bien pero es muy óptimo.
¡No es imposible, lo que pasa es que no sabes como hacerlo!
Aka: no es difícil si sabes como.
http://heli.xbot.es

alberttoy
Mensajes: 1090
Registrado: Mar Sep 16, 2014 12:55 am
País: españa
Ciudad: barcelona

Re: Como optimizar el consumo de memoria en programas de Ard

#4 Mensaje por alberttoy »

Muy interesante.
Guárdalo aquí que cualquier día vengo desesperado a buscarlo. Los programas siempre crecen :D

Responder

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 5 invitados