guardar arrays en SD

Buenas,
estoy con un proyecto con un acelerometro triaxial. Quiero recoger 390 datos de cada eje del acelerometro, guardarlos en un array y luego guardarlos en una tarjeta SD. Mi duda es, ¿se puede guardar el array completo en la SD o tengo que guardarlo dato a dato?
Gracias de antemano.

Si buscas Arduino SD y vas a la referencia del playground hubieras encontrado esto : Arduino - SD

Edito toda mi respuesta porque acabo de descubrir que si es posible y no lo sabía.

byte testArray[390];
// llegan los datos de testArray con el acelerómetro
SD.write(testArray,390);

Si la memoria de tu arduino te lo permite.. bien.
Usa un MEGA o DUE para estar cómmodo.

Necesito un dato cada 6 milisegundos. Si leo el valor del acelerometro y guardo en la SD no me da tiempo, por o que he pensado en coger 300 y luego guardarlos. he estado probando con el for pero no consigo hacerlo. estoy probando con el monitor serial, os pongo el trozo :

void loop() {

 int valx=mma.x;
 
 int x[300];
   for(int i=0; i<300; i++){ 
     mma.read();
     int valx=mma.x;
     x[i]=valx;
     
  }

  
for(int i=0; i<300; i++){ 
int xx=x[i];
 Serial.println(xx);
  
}

La idea es una vez logrado imprimirlo al monitor serial cambiarlo a la SD.

Por favor edita tu post y usa tags para postear el código.
Lee las normas del foro.

Y probaste o mediste que tiempo te va a llevar guardarlo en la SD? Las cosas no son gratis!!

Y la otra, es que la función write solo admite arrays de byte. Para escribir un array de cualquier otro tipo, hay que hacer lo siguiente:

archivo.write((byte*)x, sizeof(x))

serggio:
Necesito un dato cada 6 milisegundos. Si leo el valor del acelerometro y guardo en la SD no me da tiempo

Por eso es mejor que guardes los datos en forma binaria.
Las funciones print en la clase File, son computacionalmente más complejas que write; además que hace un llamado implícito a flush, lo que lo hace todavía más lento.

Respecto al tiempo, hace mucho había creado este hilo, y en la respuesta #9, comprobé que la velocidad promedio de escritura, es de 57 KB/s si se hace con arrays y write, aprox. 58368 bytes por segundo se escriben a la tarjeta SD (utilizando ATmega328P a 16 MHz de velocidad).

Si lo convertimos a milisegundos, serían 58 B/ms (bytes por milisegundo), y con 6 ms de tiempo, solo se lograrían escribir 350 bytes.
No cantes victoria todavía, escribir 300 int implica escribir 600 bytes; por lo tanto, se requieren de 10 u 11 milisegundos para escribir 300 int a una tarjeta SD.

Mi prueba involucraba un ciclo for, así que posiblemente la velocidad de escritura puede ser todavía más alta; PERO AÚN ASÍ INSUFICIENTE PARA ESCRIBIR 300 int EN 6 ms.

PD: si los valores no sobrepasan el número 255 (o el rango -128 127), entonces guárdalos en un array de byte, así podrías escribir 300 valores en menos de 6 milisegundos.

Me parece, Lucario, que no necesita 300 ints en 6 milisegundos, sino un int cada 6 milisegundos, lo que a priori parece perfectamente factible si se evitan flush reiterados.
¿Qué te parece, serggio, si partimos de tu método inicial de escritura en SD y vemos qué se puede hacer para mejorarlo? Creo incluso que no sería necesario un array para lo que quieres, y que podrías ir enviando directamente a la SD.

Ante todo muchisimas gracias por vuestras respuestas.
lo datos que recibo del acelerometro los meto en una variable tipo int ya que un byte se me queda corto. Como dice noter seria guardar un dato cada 6ms, aunque en realidad deberia de guardar 3 datos cada 6 ms, un dato para cada eje del acelerometro.
En cuanto a la funcionarchivo.write((byte*)x, sizeof(x)) no la entiendo muy bien, podrias ponerme algun ejemplo?.
El no enviarlo directamente es por no perder tiempo cada vez que recibo un dato, por lo que decidi guardarlo en un array luego guardarlo todo directamente. Creo que es lo mas eficiente.

Y esta tampoco la comprendes?

byte testArray[390];
// llegan los datos de testArray con el acelerómetro
SD.write(testArray,390);

Es lo mismo solo que el usa un puntero y una función que apunta al puntero que te dice la dimensión.
Si tu puntero *x tuviera 390 elementos, sizeof(x) te daría 390 como resultado.
Yo hice un array de bytes de 390 elementos.
Esta es una definición estática y la de Lucario es dinámica.

serggio:
aunque en realidad deberia de guardar 3 datos cada 6 ms, un dato para cada eje del acelerometro.

3 int = 6 bytes.
Uuuuuuuuuu, sobrado iría. No te dije antes que hasta 350 bytes se pueden escribir en 6 milisegundos?

serggio:
En cuanto a la funcion

archivo.write((byte*)x, sizeof(x))

no la entiendo muy bien, podrias ponerme algun ejemplo?.

Como bien dijo surbyte, esta es una definición más "genérica" de lo que hay que escribir a la tarjeta SD.

Eso quiere decir que x puede ser un array de int, long, float; o incluso un struct. No estoy seguro si también aplica para objetos y funciones.

Introducir una referencia de un array de int, en la función write; puede provocar error de compilación. De ahí el casting a byte* (interpretar como un array de este tipo).

Gracias, intentare hacerlo y ya os comento

Ya he conseguido guardar datos en la sd con la rapidez que queria, ahora el problema esta en interpretar lo que he guardado. El acelerometro tiene una resolucion de 14 bits por lo que cada 2 bytes es un dato del acelerometro. Viendo los caracteres guardados en la sd no se interpretarlo para saber su verdadero valor decimal.

Leer un dato binario para saber su valor decimal:

int n = 0;
archivo.readBytes((byte*)&n, 2);
Serial.println(n);

Así para una sola variable.

Para leer un array de int, se hace similar al escribir:

archivo.readBytes((byte*)x, sizeof(x));

serggio:
Viendo los caracteres guardados en la sd no se interpretarlo para saber su verdadero valor decimal.

Así es como funciona un archivo binario; cada par de caracteres (bytes) representan un valor entre 0 a 65536 (unsigned int), o entre -32768 y 32767 (int).

Gracias

Buenas he intentado esto pero no sale, he probado distntas cosas y nada

// Abrimos el archivo.
  File dataFile = SD.open("datay.txt");
  // Si lo hemos podido abrir correctamente:

  if (dataFile) {
    // Mostramos un aviso de comienzo del txt
    Serial.println("* A continuacion se muestra el contenido de leeme.txt:");
    
    while (dataFile.available()) {
      int lec=dataFile.readBytes((byte*)x, sizeof(x));
      Serial.println(lec);
      
    }
    // Cerramos el archivo.
    dataFile.close();
  // Si no hemos conseguido abrir el archivo mandamos un error.
  }else {
    Serial.println("Error al abrir leeme.txt");
  }

Sabe alguien donde puede estar el problema?

Porque no subes un archivo (adjúntalo) tal como te queda almacenado en tu SD y a continuación sube usando tags el código con el que estas trabajando hasta ahora aunque no funcione.

Para mostrar el contenido de un archivo, se hace de la siguiente manera:

while (dataFile.available()) {
    Serial.write(dataFile.read());
 }

En tu código solo se iban a imprimir la cantidad de bytes leídos en cada ciclo.

Gracias Lucario448, ahora si me aparece o que hay en a sd, pero lo necesito en decimal. este es el programa que utilizo para leer:

#include <SD.h>
// Guardamos en que entrada de arduino esta conectado el pin CS del modulo.
const int chipSelect = 4;
  
void setup(){
  // Configuramos el puerto serie para informar de fallos a traves de el.
  Serial.begin(115200);
  
  // El pin CS por defecto de la placa arduino debe ser configurado como salida
  // aunque no se use (10 en la mayoria de las placas, 53 en Arduino Mega).
  pinMode(10, OUTPUT);
  
  // Si ha habido error al leer la tarjeta informamos por el puerto serie.
  if (!SD.begin(chipSelect)){
    Serial.println("Error al leer la tarjeta.");
    return;
  }
    File dataFile = SD.open("datap.txt");
  // Si lo hemos podido abrir correctamente:

  if (dataFile) {
    // Mostramos un aviso de comienzo del txt
    Serial.println("* A continuacion se muestra el contenido de leeme.txt:");
    // Mandamos sus datos por el puerto serie.
   while (dataFile.available()) {
    Serial.write(dataFile.read());
 }
    // Cerramos el archivo.
    dataFile.close();
  // Si no hemos conseguido abrir el archivo mandamos un error.
  }else {
    Serial.println("Error al abrir leeme.txt");
  }
  
}
 

void loop(){
  
   
 
}

Adjunto el archivo de la SD

DATAP.TXT (663 Bytes)

El archivo que adjuntas en realidad es binario.
Creo que el tipo de dato que quieres imprimir es unsigned int; aunque me preocupa que el tamaño del archivo sea número impar (y no múltiplo de 4).

Por lo tanto, esto es lo que querías hacer (supongo):

unsigned int n = 0;
while (dataFile.available() > 1) {
  dataFile.readBytes((byte*)&n, 2);
  Serial.println(n);
 }

no, necesito los datos con signo ya que el acelerometro tambien da valores negativos. el txt esta en binario, por eso mi problema esta en saber el verdadero valor decimal positivo o negativo.