PROGMEM con array bidimensional

Hola a todos estoy intentando guardar un array de 10*18 elementos en la memoria de programa de arduino, alguien tiene idea de como hacer esto desde una libreria? o minimo desde el IDE? he intentado poner el PROGMEM antes y despues de tipo de dato, y antes del igual. el codigo es:

#include <avr/pgmspace.h>
const  uint16_t  nums [10][18] PROGMEM={
            {0,0,248,508,476,910,910,910,910,910,910,910,910,910,476,508,248,0},
            {0,0,112,240,1008,1008,112,112,112,112,112,112,112,112,112,112,112,0},
            {0,0,248,508,990,910,14,14,28,28,56,56,112,224,448,1022,1022,0},
            {0,0,248,508,990,910,14,28,120,124,30,14,14,910,990,508,248,0},
            {0,0,28,28,60,124,124,252,252,476,924,924,1022,1022,28,28,28,0},
            {0,0,508,508,448,448,896,1016,1020,926,14,14,14,910,990,508,248,0},
            {0,0,248,508,462,960,896,1016,1020,990,910,910,910,910,478,508,248,0},
            {0,0,1022,1022,14,28,28,28,56,56,56,56,112,112,112,240,224,0},
            {0,0,248,508,910,910,910,476,248,508,990,910,910,910,990,508,248,0},
            {0,0,248,508,988,910,910,910,910,990,510,254,14,14,924,508,248,0}
            };

e intento accesar a la informacion de esta forma

    uint16_t fila=nums[num][fil];

He incluido la libreria en el archivo de cabecera, en el de código y hasta dentro del skecth. nada me ha funcionado, si se reduce la memoria flash pero no contiene la información que necesito, es decir la información que me regresa no es la que yo guarde, mas bien es como datos aleatorios de memoria.
No es la unica matriz que me hace esto(tengo otras 3), alguien tiene alguna idea de como hacer y por que no es válido como lo hago?
utilizo la version 1.8.5 de Arduino, con el Arduino mega Original

No hagas un array bidimensional, hazlo unidimensional, con todos los datos unos detrás de otro. Y utiliza la función pgm_read_word_near() para obtener el dato que necesitas.

A modo de ejemplo aquí tienes un bucle que recorre todos los elementos del array y te los muestra:

#include <avr/pgmspace.h>
const size_t NUMS_FIL = 10; // Definimos cuantas filas se supone que tiene el array bidimensional
const size_t NUMS_COL = 18; // Definimos cuantas columnas se supone que tiene el array bidimensional
const PROGMEM uint16_t nums[NUMS_FIL * NUMS_COL] = { // Definimos un array unidimensional con todos los datos, con el tamaño necesario (NUMS_FIL * NUMS_COL)
    0,0,248,508,476,910,910,910,910,910,910,910,910,910,476,508,248,0,
    0,0,112,240,1008,1008,112,112,112,112,112,112,112,112,112,112,112,0,
    0,0,248,508,990,910,14,14,28,28,56,56,112,224,448,1022,1022,0,
    0,0,248,508,990,910,14,28,120,124,30,14,14,910,990,508,248,0,
    0,0,28,28,60,124,124,252,252,476,924,924,1022,1022,28,28,28,0,
    0,0,508,508,448,448,896,1016,1020,926,14,14,14,910,990,508,248,0,
    0,0,248,508,462,960,896,1016,1020,990,910,910,910,910,478,508,248,0,
    0,0,1022,1022,14,28,28,28,56,56,56,56,112,112,112,240,224,0,
    0,0,248,508,910,910,910,476,248,508,990,910,910,910,990,508,248,0,
    0,0,248,508,988,910,910,910,910,990,510,254,14,14,924,508,248,0
};

void setup() {
    Serial.begin(9600);
    for (size_t fila = 0; fila < NUMS_FIL; fila++) { // Recorremos todas las filas
        for (size_t columna = 0; columna < NUMS_COL; columna++) { // Recorremos todas las columnas
            uint16_t valor = pgm_read_word_near(nums + (fila * NUMS_COL) + columna); // Recuperamos el valor de «nums» correspondiente a la fila y columna deseada
            if (columna > 0) { // Ponemos la coma si no estamos mostrando el valor de la primera columna
                Serial.print(F(","));
            }
            Serial.print(valor); // Mostramos el valor
        }
        Serial.println(); // Completada cada fila, pasamos a la siguiente línea
    }
}

void loop() {
    // No ponemos nada aquí porque para el ejemplo no queremos que se repita nada.
}

Espero que te esto te valga.

Perdona, tal vez te maree un poco, pero cuando ya había publicado la respuesta anterior, me di cuenta de que se podría hacer de otra forma que tal vez te guste más.

Volvemos a la idea original de usar un array bidimensional y definirlo tal cual lo habías definido. A partir del array obtenemos mediante ciertos cálculos (que se hacen en tiempo de compilación) las constantes NUMS_FIL y NUMS_COL. Aunque también se pueden definir primero esas constantes y luego usarlas para indicar el tamaño del array.

Todo lo demás queda tal cual puse en el primer ejemplo, salvo que hay que convertir el puntero nums de "puntero a un array de arrays de enteros" a un simple puntero de "array de enteros" mediante el "cast" reinterpret_cast<const uint16_t *>(nums) y luego sumar lo mismo que antes. Bueno, a decir verdad también valdría con un simple (uint16_t *)nums y sumar, pero en C++ es preferible la primera opción.

En ambos casos todo se reduce a tratar nums como si fuera un array unidimensional (o vector) porque la función pgm_read_word_near no puede trabajar directamente con arrays multidimensionales.

El código quedaría así:

#include <avr/pgmspace.h>
const PROGMEM uint16_t nums[10][18] = { // Definimos el array bidimensional con los datos deseados
    {0,0,248,508,476,910,910,910,910,910,910,910,910,910,476,508,248,0},
    {0,0,112,240,1008,1008,112,112,112,112,112,112,112,112,112,112,112,0},
    {0,0,248,508,990,910,14,14,28,28,56,56,112,224,448,1022,1022,0},
    {0,0,248,508,990,910,14,28,120,124,30,14,14,910,990,508,248,0},
    {0,0,28,28,60,124,124,252,252,476,924,924,1022,1022,28,28,28,0},
    {0,0,508,508,448,448,896,1016,1020,926,14,14,14,910,990,508,248,0},
    {0,0,248,508,462,960,896,1016,1020,990,910,910,910,910,478,508,248,0},
    {0,0,1022,1022,14,28,28,28,56,56,56,56,112,112,112,240,224,0},
    {0,0,248,508,910,910,910,476,248,508,990,910,910,910,990,508,248,0},
    {0,0,248,508,988,910,910,910,910,990,510,254,14,14,924,508,248,0}
};
const size_t NUMS_FIL = sizeof(nums) / sizeof(nums[0]); // Calculamos el valor de la constante con el número de filas del arrray
const size_t NUMS_COL = sizeof(nums[0]) / sizeof(nums[0][0]); // Calculamos el valor de la constante con el número de columnas del array

void setup() {
    Serial.begin(9600);
    for (size_t fila = 0; fila < NUMS_FIL; fila++) { // Recorremos todas las filas
        for (size_t columna = 0; columna < NUMS_COL; columna++) { // Recorremos todas las columnas
            uint16_t valor = pgm_read_word_near(reinterpret_cast<const uint16_t *>(nums) + (fila * NUMS_COL) + columna); // Recuperamos el valor de «nums» correspondiente a la fila y columna deseada
            if (columna > 0) { // Ponemos la coma si no estamos mostrando el valor de la primera columna
                Serial.print(F(","));
            }
            Serial.print(valor); // Mostramos el valor
        }
        Serial.println(); // Completada cada fila, pasamos a la siguiente línea
    }
}

void loop() {
    // No ponemos nada aquí porque para el ejemplo no queremos que se repita nada.
}

Y lo más simpático de todo es que ambos ejemplos, el anterior y este, una vez compilados generan exactamente el mismo ejecutable. No hay diferencias para el Arduino.

Muchas gracias, es exactamente lo que buscaba, solo que para accesar a la informacion creo que seria mas sencillo de la siguiente forma:

uint16_t valor = pgm_read_word_near(num*18+fil);

no cres?

Eduardosanchez:
Muchas gracias, es exactamente lo que buscaba, solo que para accesar a la informacion creo que seria mas sencillo de la siguiente forma:

uint16_t valor = pgm_read_word_near(num*18+fil);

no cres?

No. Lo que tienes es un array bidimensional (el mismo que en mi segunda respuesta). Y en este caso, como ya de dicho, has de convertir el "puntero a un array de arrays de enteros" en un "puntero a un array de enteros". Y a partir de ahí calcular en qué "lugar" está el dato que deseas. Suponiendo que en tu ejemplo la primera dimensión (que yo llamo fila) sea num y la segunda dimensión (que yo llamo columna) sea fil, para ello has de poner, al estilo C++:

uint16_t valor = pgm_read_word_near(reinterpret_cast<const uint16_t *>(nums) + num * 18 + fil);

Aunque también es igual de válido ponerlo al estilo C:

uint16_t valor = pgm_read_word_near((uint16_t *)nums + num * 18 + fil);

En lo que tú propones te ha faltado poner "en algún lado" la referencia al array nums. Si hubieras puesto:

uint16_t valor = pgm_read_word_near(nums + num*18+fil);

Te valdría en el caso de ser un array unidimensional, como el ejemplo que puse en mi primera respuesta. Fíjate que en esa propuesta quité todas las llaves "internas" del array y que sólo tiene una dimensión.

De todas formas, si no me crees, no tienes más que probar y ver si te funciona o no.

tienes toda la razón, no lo probé como me comentaste pero si me faltaba poner de donde sacar esa información, pero igual la forma que te decía era en un array unidimensional que fue lo que hice, y hasta ahora ha funcionado de maravilla logre reducir del 42% de memoria flash a 7% de flash y solo 7% de Programa, una chulada la verdad.
Saludos.