Pages: [1]   Go Down
Author Topic: Guardar datos complejos en la SD [INFO]  (Read 1396 times)
0 Members and 1 Guest are viewing this topic.
Euskadi
Offline Offline
God Member
*****
Karma: 16
Posts: 721
Arduinotarrak
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hola,
como es un tema bastante recurrente, ahí va un ejemplo de cómo guardar y recuperar datos complejos en una SD, porque casi siempre los ejemplos se suelen reducir a datos en forma de texto.

La mejor opción para ello, a mi modo de ver,  es utilizar una estructura de datos, donde se pueden incluir toda clase de variables (no punteros).

Por ejemplo, si se define una estructura como esta
Code:
struct datos
{
  int id;  
  char nombre[11];
  float temperatura;
  float humedad;
} datos, datos2;

Se puede escribir y leer la estructura como un todo en la SD. Para probar, poner primero contenido en la estructura,

Code:
  datos.id = 33;
  datos.temperatura = 25.3;
  datos.humedad = 77.7;
  strcpy(datos.nombre, "lugar_A");

Para escibir, como la función write pide un buffer del tipo const uint8_t hay que hacer una conversión explícita

Code:

  myFile = SD.open("test.txt", FILE_WRITE);
  if(myFile)
  {
     Serial.println("abierto para escribir 'test.txt'");
     myFile.write((const uint8_t*)(&datos), sizeof(datos));
     myFile.close();
  }

Y para leer, en el ejemplo se utiliza datos2 para comprobar que los datos se cargan desde el fichero, aunque se podría haber usado datos

Code:
   
     myFile = SD.open("test.txt");
     if(myFile)
     {
        Serial.println("abierto para leer 'test.txt'");

        myFile.read(&datos2, sizeof(datos2));

        // y para mostrar por la consola
        Serial.print("id: ");
        Serial.println(datos2.id, DEC);
        Serial.print("nombre: ");
        Serial.println(datos2.nombre);
        
        Serial.print("temperatura: ");
        Serial.println(datos2.temperatura, DEC);  
        Serial.print("humedad: ");
        Serial.println(datos2.humedad, DEC);  
        
        myFile.close();
     }

Tan solo queda un detalle por arreglar: la salida por consola me da
Code:
temperatura: 25.2999992370
humedad: 77.6999969482


Ahí va el sketch entero por si alguien lo quiere probar

Code:


/*
Conexiones para un Arduino Uno:
uint8_t const SS_PIN   = 10;
uint8_t const MOSI_PIN = 11;
uint8_t const MISO_PIN = 12;
uint8_t const SCK_PIN  = 13;

*/

#include <SD.h>

File myFile;

int kont;

struct datos
{
  int id;
  float temperatura;
  float humedad;
  char nombre[11];
} datos, datos2;

void setup()
{
  kont = 0;
  Serial.begin(9600);
  Serial.print("Initializing SD card...");
  pinMode(10, OUTPUT);
 
  if (!SD.begin(10))
  {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  
  datos.id = 33;
  datos.temperatura = 25.3;
  datos.humedad = 77.7;
  strcpy(datos.nombre, "lugar_A");
 
  myFile = SD.open("test.txt", FILE_WRITE);
  if(myFile)
  {
     Serial.println("abierto para escribir 'test.txt'");
     myFile.write((const uint8_t*)(&datos), sizeof(datos));
     myFile.close();
      
     myFile = SD.open("test.txt");
     if(myFile)
     {
        Serial.println("abierto para leer 'test.txt'");

        myFile.read(&datos2, sizeof(datos2));
        Serial.print("id: ");
        Serial.println(datos2.id, DEC);
        Serial.print("nombre: ");
        Serial.println(datos2.nombre);
        
        Serial.print("temperatura: ");
        Serial.println(datos2.temperatura, DEC);  
        Serial.print("humedad: ");
        Serial.println(datos2.humedad, DEC);  
        
        myFile.close();
     }
     else
     {
         Serial.println("error read test.txt");
     }
  }
  else
  {
      // if the file didn't open, print an error:
      Serial.println("error FILE_WRITE test.txt");
  }
}


void loop()
{
  
}



« Last Edit: August 19, 2013, 01:10:51 am by curro92 » Logged

Don Benito
Offline Offline
Jr. Member
**
Karma: 1
Posts: 66
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Como te lo has currado  smiley
+1
Logged

domotica arduino android

0
Offline Offline
Edison Member
*
Karma: 17
Posts: 1413
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

enhorabuena por el post. muy util !

Podrias dar mas detalles de estas lineas=

Code:
myFile.write((const uint8_t*)(&datos), sizeof(datos));

1) datos se supone que es una STRUCTURA, y lo estas convirtiendo (cast) a un "unsigned integer 8 bits" ?
2) El "&" se usa para que el cast se realice sobre los elementos que integran la Structura, en lugar de tener que referirse a cada elemento por separado?
3) Sizeof, simplemente le dice cuantos elementos van a escribirse, es decir, los que hay dentro de la estructura?
por lo que realmente la funcion write, aquí es algo compleja y hace una lectura de todos los elementos de la estructura de uno en uno?

He entendido algo bien? puedes corregirme donde me equivoco?
muchas gracias
« Last Edit: August 30, 2013, 03:06:24 pm by Sergegsx » Logged

* Si preguntas, pon el código de tu programa, hace mucho mas fácil ayudarte. Y me ahorro un mensaje pidiendo que lo hagas.
* Si consigues solucionar tu problema, dedica unos minutos a explicar en tu post como lo conseguiste para beneficio de todos.
* Cambia el 'Subject' de tu hilo y añade 'SOLUCIONADO' cuando hayas llegado a una solución al problema que planteaste.
* Utiliza un 'Subject' para tu hilo que explique de que va el hilo.
Si estas empezando:
* Comienza a usar Arduino
* Guías de iniciación a Arduino
* Ejemplos
* Referencia del Lenguaje
* Conceptos básicos
Guia de usuario de arduino
Tutoriales en Ingles
Si necesitas que alguien te escriba el código: http://www.freelancer.com/  o esta  http://www.guru.com/

Palencia, Spain
Offline Offline
God Member
*****
Karma: 25
Posts: 502
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

enhorabuena por el post. muy util !

Podrias dar mas detalles de estas lineas=

Code:
myFile.write((const uint8_t*)(&datos), sizeof(datos));

1) datos se supone que es una STRUCTURA, y lo estas convirtiendo (cast) a un "unsigned integer 8 bits" ?
2) El "&" se usa para que el cast se realice sobre los elementos que integran la Structura, en lugar de tener que referirse a cada elemento por separado?
3) Sizeof, simplemente le dice cuantos elementos van a escribirse, es decir, los que hay dentro de la estructura?
por lo que realmente la funcion write, aquí es algo compleja y hace una lectura de todos los elementos de la estructura de uno en uno?

He entendido algo bien? puedes corregirme donde me equivoco?
muchas gracias
Hola. Efectivamente datos es una estructura que contiene la información que deseamos guardar.
El & es el operador de indirección, y lo que hace es devolvernos un puntero a esa estructura, es decir, la dirección de memoria donde está guardada; osea que &datos es un puntero a nuestra struct de datos.
Como la función write necesita un (puntero a uint8) se realiza el casting a (uint8 *) para evitar un toque de atención del compilador. Así que lo que hace write es escribir (sizeof(datos)) bytes (uint8) a partir de la dirección de memoria donde está la estructura, sin importarle qué tipo de datos contiene.
Como añadido, señalar que este sistema es sencillo y efectivo, pero hay que tener en cuenta que nuestra struct no contenga punteros, porque copiará eso, el puntero y no el contenido (por ejemplo si tenemos un char *cadena dentro de nuestra estructura deberemos ocuparnos de copiar la cadena aparte).
« Last Edit: August 30, 2013, 05:49:21 pm by noter » Logged

Euskadi
Offline Offline
God Member
*****
Karma: 16
Posts: 721
Arduinotarrak
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Hola, Sergegsx
@noter lo ha explicado a la perfección.
Lo que no sé por qué es necesaria esa conversión explícita a uint8 ('unsigned int de 8 bites'), cuando se podría hacer lo mismo con un unsigned char o un byte, porque lo que se transmite cada vez por el puerto serie es eso, una serie de 8 bites.
Logged

0
Offline Offline
Edison Member
*
Karma: 17
Posts: 1413
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

muchisimas gracias noter, me ha quedado clarisimo y creo que por fin he entendido al menos 1 uso practico de los punteros, hasta ahora nunca habia entendido para que usarlo.
mil gracias

curro92 gracias por el post, parece sencillo pero creo que seria buena idea meterlo en el playground si no lo esta ya.
Logged

* Si preguntas, pon el código de tu programa, hace mucho mas fácil ayudarte. Y me ahorro un mensaje pidiendo que lo hagas.
* Si consigues solucionar tu problema, dedica unos minutos a explicar en tu post como lo conseguiste para beneficio de todos.
* Cambia el 'Subject' de tu hilo y añade 'SOLUCIONADO' cuando hayas llegado a una solución al problema que planteaste.
* Utiliza un 'Subject' para tu hilo que explique de que va el hilo.
Si estas empezando:
* Comienza a usar Arduino
* Guías de iniciación a Arduino
* Ejemplos
* Referencia del Lenguaje
* Conceptos básicos
Guia de usuario de arduino
Tutoriales en Ingles
Si necesitas que alguien te escriba el código: http://www.freelancer.com/  o esta  http://www.guru.com/

Palencia, Spain
Offline Offline
God Member
*****
Karma: 25
Posts: 502
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Hola, Sergegsx
@noter lo ha explicado a la perfección.
Lo que no sé por qué es necesaria esa conversión explícita a uint8 ('unsigned int de 8 bites'), cuando se podría hacer lo mismo con un unsigned char o un byte, porque lo que se transmite cada vez por el puerto serie es eso, una serie de 8 bites.

Creo que los tres datos son equivalentes, y de hecho también compila sin errores (byte *)&datos y (unsigned char*)&datos. A mí, personalmente, me gusta usar la notación byte, pero para otros tal vez sea más explícito el uint8 (para gustos los colores smiley).
Logged

Pages: [1]   Go Up
Jump to: