Go Down

Topic: abrir sd y asignar variable a cada dato (Read 2963 times) previous topic - next topic

mamumo

Hola! a ver si alguien me puede echar una mano.
Dispongo de un archivo de texto (gps.txt) en una SD, en el cual tengo una lista de datos.En cada línea tengo una cadena de caracteres diferente.    El programa siguiente es el que empleo para abrir la carpeta:

#include <SD.h>

const int chipSelect = 10;
void setup()
{
  Serial.begin(9600);
  Serial.print("Initializing SD card...");
  pinMode(10, OUTPUT);
 
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    return;
  }
  Serial.println("card initialized.");
  File dataFile = SD.open("gps.txt");
  if (dataFile) {
    while (dataFile.available()) {
      Serial.write(dataFile.read());
    }
    dataFile.close();
  } 
  else {
    Serial.println("error opening gps.txt");
  }
}
void loop()
{
}


Lo que quiero hacer ahora es asignar una variable a cada dato (numerarlos desde el primero hasta el último), para cuando necesite alguno de ellos poder llamarlo directamente sin tener que pasar por todos.

Creo que con un contador que lea todo y asigne a cada dato su posición ya estaría. Si me parece algo fácil de hacer pero no lo consigo....

Un saludo.

eried

Podrias intentar al menos y luego postear el código si es que no te funciona en vez de pedir que alguien te lo haga.
My website: http://ried.cl

mamumo

amigo @eried en ningún momento he pedido que me lo hagan. Como en otros post que he escribo pido ayuda,orientación, ideas.... Hace poco que he empezado en el mundo de arduino y todavía hay miles de instrucciones y trucos que desconozco.
En este caso en concreto no se como leer línea a línea y saber cual es el final, si existe algún instrucción que lo haga o no,si es sencillo o díficil...

Vuelvo a repetir que en ningún momento he dicho que me lo hagan!!
Muy agradable tu comentario...

giltesa

Seria interesante que pusieras una muestra de lo que contiene el fichero de texto.

En C trabajando con ficheros puedes sacar letras, números enteros o con decimales con una única lectura. En Arduino has de ir carácter a carácter para todo.

Lo principal es saber que quieres leer, si por ejemplo el fichero gps.txt contiene información sobre unas coordenadas, imagino que cada linea sera una lectura realizada, y que la siguiente linea sera otra, y la siguiente otra, etc.
Entonces, si es el caso ya que como no lo sé lo estoy dando por supuesto, sabemos que cada linea contiene el mismo tipo de datos que el resto y es independiente al resto de lineas, pongamos por ejemplo que la linea es: (sin comillas)

"315 152 1 253"

Cada número separado con un espacio o con cualquier otro carácter ASCII no numérico.

Tienes que hacer una funcion, que lea carácter a carácter, si tuvieras...

"    315 152      1 253"

varios espacios al principio o entre medio de los números tendrás que hacer que la funcion que lee caracteres se salte los que no sirven, y en que encuentre un numero que lo guarde y los vaya concatenando, no como cadena si no ya como entero, en una variable.

De este modo podrías hacer que cada vez que se llamara a la funcion esta te sacara un número... pero claro, tendrás que hacer algo para que la funcion sepa donde se quedo para saber en que posicion ha de comenzar después...

Te dejo un trozo de código de la funcion:

Code: [Select]

/*
*  FUNCIÓN QUE, A PARTIR DE UNA CADENA, DEVUELVE EL PRIMER NUMERO ENTERO POSITIVO QUE ENCUENTRE.
*
*  Para ello se ha de recibir como parámetros un vector de caracteres y la posición en la que empezar
*  a buscar el numero, esa posición, que es por referencia, será modificada por la posición en la que
*  se dejo de leer una vez obtenido el numero.
*
*/
unsigned short getFirstIntTheString( char *str, byte *i )
{
   unsigned short num = 0;

   // Se avanza hasta encontrar el primer número:
   while( (str[*i] < '0' || str[*i] > '9')  &&  str[*i] != '\0' )
      (*i)++;


   // Se concatenan todos los números seguidos que se encuentren:
   while( str[*i] >= '0' && str[*i] <= '9'  &&  str[*i] != '\0' )
   {
      num *= 10;
      num += (str[*i] - 48);
      (*i)++;
   }
   delay(5);

  // Se devuelve el numero obtenido.
   return num;
}


Eso solo te devuelve el primer numero que encuentre en el vector de caracteres a partir de la posicion de inicio que le indiques.
Antes has de haber metido todos los caracteres de una sola linea en un vector.

Cuando tengas esa linea llamas a la funcion tantas veces como números tengas, y te devolverá los números, que tendrás que guardar cada uno en una variable y hacer con ellos lo que quieras.. para después repetir toda la operación con la siguiente linea.

Saludos!
giltesa.com Mi blog personal sobre informática, electrónica, Arduino, bricolaje, etc.

mamumo

Giltesa, muchas gracias por contestar. Te voy a explicar un poco más mi proyecto, para que lo entiendas mejor.
En mi archivo gps.txt tengo datos como estos:(latitud,longitud,cantidad)

,42.46099,2.41741,23,
,42.46099,2.41741,99,
,42.46099,2.41741,12,
,42.46098,2.41741,45,
,42.46098,2.41741,75,
,42.46098,2.41740,33,
,42.46098,2.41740,63,
,42.46098,2.41739,145,
,42.46088,2.42161,35,
,42.46081,2.42151,85,
,42.46075,2.42159,109,
,42.46071,2.42177,67,

El tamaño del archivo variará, en ocasiones tendré 20 filas y en otras 200 por ejemplo.
La idea que yo tengo es leer cada fila tratando los datos como cadena de caracteres, y en el momento que tenga un espacio saltar de línea. A su vez tendré que asignar el número 1, por ejemplo, si estuviese en la primera fila. Así continuaría sucesivamente.
El problema es que no se como podría guardar cada variable de fila, si empleo arrays, cuando tenga muchos datos puede que use excesiva memoria no? Es que es la única manera que se me ocurre.
Otra duda que tenía es como saber cuando he llegado a la última fila. Consultando un libro he encontrado la instrucción eof. Creo que con esta intrucción me valdrá, no?

giltesa

Bien, el fichero es mas o menos como me imaginaba.
El problema es que no son números enteros y por lo tanto la funcion que te puse no te sirve.
Tendrás que modificar la funcion para que funcione con números decimales y los concatene correctamente (como números).
O también podrías concatenar los caracteres desde una coma a otra y obtener el número como cadena, y después buscar alguna funcion que te pase de cadena a decimal.

Los datos los puedes guardar en las variables:
float latitud;
float longitud;
int cantidad;

Cada vez que leas una fila actualizas los datos de las variables con los de la nueva fila, haces con ellos lo que quieras y lees los siguientes cuando termines.

Una linea no termina cuando encuentras un espacio, la linea termina cuando encuentras el carácter de salto de linea que es:   \n   , al no ser representable no es visible en los ficheros pero esta ahí. (en el Notepad ++ mostrando los caracteres ocultos si que te lo muestran).
En el caso de los vectores de caracteres, el fin de vector o de cadena es siempre con el carácter   \0

La funcion eof() es la que se usa en C, pero para la librería SD de Arduino tienes que usar las que te proporcionan, en este caso file.available() con eso sabes si siguen quedando caracteres por leer en el fichero o no.

Saludos!
giltesa.com Mi blog personal sobre informática, electrónica, Arduino, bricolaje, etc.

mamumo

Si lo estaba haciendo de la forma que dices, distingo cada secuencia entre comas, en mi caso se llama campo. Y lo convierto en real con la función atof. Y así tengo ya el dato listo para luego operar con el.

Lo que no entiendo muy bien es lo de \n, he mirado y puede tener dos significados: de caracter nulo o nueva línea. A cual te refieres? como se usa?

Muchíiisimas gracias, estoy muy agradecida de verdad!

giltesa

De nada!

A lo del carácter \n me refiero a que es el del fin de linea.

Puedes hacer una prueba:
Con el primer código que pusiste modifica la funcion de leer datos de la sd e imprimirlos por el monitor serial para que en caso de que encuentre un carácter '\n' encienda el led 13 durante 1 segundo, veras como después de imprimir cada linea el led se enciende también.

Así:

Code: [Select]

while( dataFile.available() )
{
  if( dataFile.peek() == '\n' )
  {
    digitalWrite( led, HIHG);
delay(1000);
digitalWrite( led, LOW);
  }

  Serial.write( dataFile.read() );
}


Saludos  :)
giltesa.com Mi blog personal sobre informática, electrónica, Arduino, bricolaje, etc.

mamumo

Por hoy ya vale, mañana continuo!!
Ya te iré contando como va la cosa, espero no volver a dar guerra!! jaja

Muchas gracias otra vez
Ciao

Go Up