El procedimiento para almacenar un registro de datos o log en una tarjeta de memoria SD con la librería SD de Arduino es similar al que se sigue para trabajar con métodos derivados de la clase Stream, como los de la popular Serial o como ocurre con la librería Ethernet, de la que hable en la guía para hacer consultas HTTP con la librería de comunicaciones Ethernet de Arduino. En líneas generales, los pasos que hay que seguir son:
- Inicializar las comunicaciones y el dispositivo
- Abrir el documento en el que se almacenan los datos
- Escribir los datos (el registro o log)
- Cerrar el documento en el que se han grabado los datos
En el siguiente ejemplo se muestra un sesión de grabación de datos en una tarjeta de memoria SD con la Librería SD estándar de Arduino. Se han resaltado las líneas que son relevantes para ayudar a explicar el proceso que se sigue, aunque revisar los comentarios y los mensajes mostrados con las órdenes Serial.println()
es también ilustrativo del proceso.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
#include <SD.h> // Incluir la librería SD estándar de Arduino #define PIN_CS 4 // Pin usado para activar las comunicaciones SPI de la tarjeta SD #define PIN_CS_CONVENCIONAL 10 // Pin usado normalmente para activar dispositivos SPI File datos; void setup() { pinMode(PIN_CS,OUTPUT); // Es necesario configurar para salida de datos el pin conectado a CS/SS pinMode(PIN_CS_CONVENCIONAL,OUTPUT); // Aunque no se utilice debe establecerse como pin de salida para evitar errores Serial.begin(9600); // Preparar las comunicaciones serie para mostrar mensajes en la consola if(SD.begin(PIN_CS)) // Intentar inicializar las comunicaciones y el dispositivo y no hacer nada si no es posible { Serial.println("Tarjeta SD inicializada (pueden grabarse los datos)"); datos=SD.open("MESTIZO.LRC",FILE_WRITE); if(datos) { Serial.println("Documento creado correctamente"); Serial.println("Guardando datos"); datos.println("[00:42.00]Ese ritmo es tan sencillo"); datos.println("[00:45.00]que yo lo toco tumbao"); //datos.flush(); // Vaciar el buffer es una manera de asegurar que los datos se han grabado datos.close(); Serial.println("Datos guardados"); } else { Serial.println("No se puede crear el documento"); } } else { Serial.println("No se ha podido inicializar la tarjeta SD. No se graban los datos"); } } void loop() { // Disfrutar del nuevo documento creado } |
1. Inicializar las comunicaciones y/o el dispositivo
La librería SD viene con el resto de los recursos de desarrollo de Arduino pero no se carga por defecto: no es seguro que vaya a necesitarse y utiliza recursos a los que se les puede dar otro destino si no se va a trabajar con tarjetas SD. Todo esto quiere decir que es necesario incluirla (cargarla) antes de poder utilizarla, para eso se escribe #include
La función SD.begin(PinCS)
inicializa la librería y el dispositivo, siendo el parámetro número de pin al que está conectada la salida SS/CS del puerto bus SPI. Si no se incluye el parámetro en la llamada a la función se utiliza por defecto el pin que tenga asignado el hardware de la placa (normalmente el 10, como ocurre en un Arduino Uno, o el 54 en una placa Arduino Mega) La función devuelve o en caso de que se inicialice con éxito o no la librería y la tarjeta.
Las comunicaciones entre la tarjeta y la placa Arduino se realizan usando el bus SPI, normalmente valiéndose de que las tarjetas de memoria SD tienen un modo de funcionamiento compatible con SPI, como se explica en el artículo sobre la conexión de una tarjeta SD por SPI a Arduino. Las comunicaciones SPI utilizan la señal CS (por cable select o SS, por slave select) para activar por nivel bajo el dispositivo antes de enviar la información. La librería SD de placa Arduino considera por defecto el pin correspondiente del hardware (normalmente el 10, lo que puede ser un inconveniente en algunas placas como Leonardo) por eso, si se utiliza dicho pin, no es necesario indicarlo al inicializar las comunicaciones y el dispositivo con SD.begin()
pero, en cualquier caso, será necesario declarar como salida con pinMode(10,OUTUPUT)
aunque se utilice otro pin, que también habrá que establecer para salida de datos como puede verse en el código de ejemplo de arriba.
2. Abrir el documento en el que se almacenan los datos
La librería incluye el tipo de datos if()
o while()
.
La función SD.open(nombre_documento,modo)
es el paso previo para poder acceder a un documento (abrirlo) conforme al modo solicitado por el segundo parámetro que puede ser FILE_READ
(leer datos) o FILE_WRITE
(escribir datos) Si el modo de apertura se omite se considera de lectura.
El primero de los parámetros barra o slash (/) También se utiliza la barra o slash para separar carpetas que estuvieran incluidas dentro de otras. Por ejemplo, serviría para acceder a un documento llamado incluido dentro de la carpeta que a su vez estuviera dentro de una carpeta llamada .
no puede omitirse; indica la ruta al documento expresándolo como (1) el nombre de la carpeta en las que se encuentra y (2) su nombre separado por el carácter
El valor de retorno de la función SD.open()
es un puntero al fichero con el que referirse al mismo en posteriores accesos. Como se ha dicho, si no fuera posible abrir el documento en el modo solicitado el valor devuelto es para que sea sencillo verificar si la operación ha tenido éxito o no.
Para el objetivo de este artículo, explicar cómo almacenar un registro de datos en una tarjeta de memoria SD, puede ser un poco pobre acceder a un documento sólo para escribirlo (sobrescribirlo) o leerlo. Por ejemplo, es común crear un nuevo documento si el previsto ya existe (y en ese sentido es frecuente utilizar una numeración como parte del nombre del archivo) o añadir los nuevos datos a un documento que ya existe.
Al objeto de resolver el primer caso, crear un nuevo documento si ya existe otro, la librería SD incluye la función SD.exists(documento)
que permite consultar el sistema de archivos para saber si el parámetro , que puede hacer referencia tanto a un documento (fichero) como a una carpeta (directorio), existe o no devolviendo o respectivamente. Una vez que se sabe que el documento existe, si se quiere conservar, se puede utilizar otro nombre (por ejemplo incrementando una numeración que es parte del mismo, como se ha dicho) para crearlo respetando el que ya está grabado.
Como alternativa, sería posible borrar un documento utilizando el método SD.remove(fichero)
siendo el nombre del documento de la tarjeta de memoria SD que debe borrarse. El nombre del documento se expresa utilizando el formato carpeta/nombre explicado antes.
Las opciones para el segundo caso, añadir datos a un documento, pueden no ser tan evidentes, y seguramente será necesario utilizar alguno de los (no muy documentados) modos de apertura:
- abrir para leer
- abrir de sólo lectura (equivalente a O_READ)
- abrir para escritura de datos
- abrir como sólo escritura (equivalente a O_WRITE)
- abrir como lectura y escritura (equivalente a O_READ|O_WRITE)
- abrir en modo de acceso (equivalente a O_RDWR)
- abrir para añadir (abrir para escritura grabando los datos nuevos al final de los actuales)
- abre para escritura sincronizando a cada grabación
- crea el documento si no existe
- abre el documento sólo si es necesario crearlo
- abre un documento que existe borrando (truncando) previamente su contenido
Considerando los modos de apertura anteriores, puede utilizarse
en la apertura, de manera que se añadirán a un documento que ya existan los nuevos datos, incrementando el registro ya existente, resolviendo así el segundo inconveniente planteado al principio.3. Escribir los datos
Como en otras librerías con métodos basados en la clase Stream, en la librería SD están disponibles, para grabar datos, los métodos print(dato,base)
y println(dato,base)
para almacenar texto y write(buffer,longitud)
para grabación de datos en modo binario.
Las funciones print()
y println()
pueden usarse con un único parámetro de entrada («dato», en la referencia de arriba) que permite escribir un dato como texto o convertirlo a una base si se indica el segundo parámetro opcional («base», en la referencia de arriba) Para expresar la conversión con el segundo parámetro puede usarse alguna de las constantes BIN para convertir a binario (base 2), OCT para convertir a octal (base 8), DEC para decimal (base 10) o HEX para hexadecimal (base 16)
Para los archivos de registro de datos (log) es habitual utilizar formatos de texto porque son muy sencillos de grabar y leer, por lo que, por ejemplo, se podrán consultar o procesar con multitud de aplicaciones. El principal inconveniente a la hora de grabar es su menor rendimiento: normalmente ocupan más en proporción cuando se almacenan datos numéricos; a la hora de leer, el inconveniente es el acceso aleatorio a una parte concreta del documento: con frecuencia es necesario leer toda la información previa hasta encontrar la buscada, lo que hace mucho más lento el proceso. La función de escritura write()
resuelve estos inconvenientes grabando en modo binario. La función necesita un parámetro, «buffer», que es una matriz de byte o char y acepta un segundo parámetro opcional «longitud» con el que especificar la cantidad de bytes que se graban del total del buffer; si se omite este segundo parámetro se almacena la totalidad de la matriz.
4. Cerrar el documento en el que se han grabado los datos
Cuando se ha terminado de grabar todo el registro de datos en el archivo se finaliza su uso (se cierra) con la función close()
del objeto , que además liberará los recursos que estaba utilizando. La llamada se hace con el formato habitual en el que representa el puntero devuelto por SD.open()
.
Por el uso habitual de un dispositivo basado en un microcontrolador de pequeña escala, como es el caso de de un Arduino Uno e incluso de un Arduino Mega, no necesariamente hay un final en la ejecución del programa en el que usar la función close()
, sino que es posible que la aplicación se esté ejecutando hasta apagar el dispositivo. Este comportamiento puede hacer que se pierdan más o menos datos dependiendo del buffer utilizado por el software y por el hardware (por ejemplo por una memoria intermedia en el módulo que soporta la tarjeta SD) Para minimizar este inconveniente se puede utilizar la función flush()
que proporciona el objeto y que vacía el contenido de la memoria intermedia forzando un grabado «real» de los datos en la tarjeta de memoria SD; como es lógico, realizar llamadas intensivas a este método ralentizará el funcionamiento del programa, por lo que debe calcularse con cuidado la necesidad de su uso.
Ejemplo de almacenamiento de datos en una tarjeta SD
En el siguiente ejemplo se muestra cómo sería el proceso de almacenamiento en una tarjeta de memoria SD de un registro de los datos obtenidos por un sensor. El formato elegido es CSV, que compensa el inconveniente de ocupar más de lo necesario (al ser datos numéricos grabados como texto) con la sencillez, tanto en la escritura de la aplicación desarrollada para Arduino como en su posterior interpretación para postprocesar el contenido.
La lectura del sensor del ejemplo corresponde con la monitorización de un circuito de vibración. Los valores monitorizados durante un periodo se acumulan antes de grabarlos para almacenar el número de vibraciones totales detectadas cada cierto tiempo y así estimar la cantidad o frecuencia de movimiento.
Al empezar el programa ya se monitoriza la vibración y puede seguirse en una consola serie. Para iniciar o terminar una sesión de grabación se acciona un pulsador que genera una interrupción. Además de disponer un condensador para evitar rebotes, se bloquea el inicio de una sesión hasta que transcurra cierto tiempo del último cierre.
Como la idea es grabar sesiones de forma consecutiva, el programa grabará un documento con un nombre y un número que se irá incrementando cada vez que se genere.
Como se ha explicado más arriba, especialmente en un dispositivo microcontrolado, es interesante almacenar el contenido del buffer del archivo con cierta frecuencia para evitar (lo más posible) la pérdida de datos. En este ejemplo se consigue utilizando la función flush()
del objeto documento cada cierto intervalo de tiempo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
#include <SD.h> // La librería SD estándar de Arduino #define EN_PRUEBAS true // Para activar y desactivar fácilmente el comportamiento (mensajes, principalmente) de depuración #define PIN_LED_FUNCIONAMIENTO 5 // Para las pruebas es útil saber si se el dispositivo está activo #define PIN_LED_GRABACION 6 // Para las pruebas es útil saber si se están grabando los datos #define PIN_LED_MONITOR 13 // Para las pruebas es útil saber si se están recibiendo datos #define PIN_CS 4 // Pin usado para activar la tarjeta #define PIN_CS_CONVENCIONAL 10 // Pin usado normalmente para activar dispositivos SPI #define INTERRUPCION_SENSOR 0 #define INTERRUPCION_SESION 1 // La interrupción 0 en una placa Leonardo corresponde al pin 3 y al 2 en las otras #if defined(__AVR_ATmega32U4__) #define PIN_SENSOR 3 #define PIN_CONMUTADOR 2 // Se puede utilizar un conmutador para detener manualmente la sesión de grabación (termina a nivel alto) #define ESPERAR_LEONARDO while(!Serial){;} // Esperar a que el puerto serie de la placa Leonardo esté operativo antes de seguir #else #define PIN_SENSOR 2 #define PIN_CONMUTADOR 3 // Se puede utilizar un conmutador para detener manualmente la sesión de grabación (termina a nivel alto) #define ESPERAR_LEONARDO ; // Si no es una placa Leonardo no hay que esperar al puerto serie (el punto y coma es para ver fácilmente que no hace nada) #endif #define INTERVALO_GRABACION 120000 // De vez en cuando hay que grabar para evitar perder datos si se desconecta #define INTERVALO_MONITORIZACION 30000 // Monitorizar cada 30 segundos #define INTERVALO_ENTRE_SESIONES 5000 // No iniciar ni terminar una nueva sesión antes de 5 segundos de la anterior (independiente del uso de un condensador para evitar rebotes en el pulsador de inicio/parada)) #define ESPERA_MOSTRAR_CONSOLA 5000 // En la fase de pruebas esperar 5 segundos para que un ser humano vea la salida por la consola #define PREFIJO_ARCHIVO "MOV" // Los nombres de los documentos tienen el formato MOVn.CSV siendo n el número (correlativo) de archivo #define EXTENSION_ARCHIVO ".CSV" // Se usa el formato CSV, valores expresados como texto y separados por comas (normalmente aunque también puede usarse punto y coma, espacio, tabulador…) #define SEPARADOR_CSV "," // El separador usado para el formato CSV unsigned int cantidad_movimiento; // Un acumulador para la cantidad de movimiento detectada (cambios de estado en el sensor de vibración) unsigned long hora_inicio; // La hora de inicio se va restando de la hora real para almacenar valores de tiempo relativo unsigned long cronometro_sesion; // Un cronómetro para ir almacenando los datos de la sesión periódicamente para evitar pérdidas por desconexión unsigned long cronometro_intervalo_sesion; // Un cronómetro para controlar si se puede iniciar una nueva sesión (si ha pasado el tiempo mínimo) unsigned long cronometro_monitorizacion; // Un cronómetro para almacenar la cantidad acumulada cada cierto periodo de tiempo boolean sd_activa; // Un semáforo para saber si se están almacenando los datos File datos_movimiento; // El puntero al documento en el que se almacenan los datos int numero_archivo; // El signo se utiliza para saber si la apertura de archivo ha tenido éxito String linea_csv; // El contenido de cada línea de datos que se almacena (en formato CSV) unsigned long numero_ultima_linea_grabada; // Contador del último número de línea de datos grabada void setup() { if(EN_PRUEBAS) { Serial.begin(9600); ESPERAR_LEONARDO delay(ESPERA_MOSTRAR_CONSOLA); } pinMode(PIN_SENSOR,INPUT); pinMode(PIN_CONMUTADOR,INPUT); pinMode(PIN_LED_GRABACION,OUTPUT); pinMode(PIN_LED_FUNCIONAMIENTO,OUTPUT); pinMode(PIN_LED_MONITOR,OUTPUT); pinMode(PIN_CS,OUTPUT); pinMode(PIN_CS_CONVENCIONAL,OUTPUT); // Aunque no se utilice debe establecerse como pin de salida para evitar errores numero_archivo=0; cantidad_movimiento=0; hora_inicio=millis(); cronometro_sesion=millis()+INTERVALO_GRABACION; cronometro_intervalo_sesion=0; cronometro_monitorizacion=millis()+INTERVALO_MONITORIZACION; digitalWrite(PIN_LED_FUNCIONAMIENTO,HIGH); attachInterrupt(INTERRUPCION_SENSOR,incrementar_vibracion,CHANGE); // Se usan ambos flancos ya que no se sabe en qué estado quedará el sensor en cada momento attachInterrupt(INTERRUPCION_SESION,conmutar_sesion,RISING); numero_ultima_linea_grabada=0; } void loop() { // Vaciar el buffer periódicamente para minimizar la pérdida de datos if(datos_movimiento) { digitalWrite(PIN_LED_GRABACION,HIGH); if(millis()>cronometro_sesion) { cronometro_sesion=millis()+INTERVALO_GRABACION; datos_movimiento.flush(); if(EN_PRUEBAS) { Serial.print("Vaciado de buffer en "); Serial.println(numero_ultima_linea_grabada,DEC); } } } else { digitalWrite(PIN_LED_GRABACION,LOW); } // Grabar periódicamente los datos almacenados o sólo mostrarlos si la sesión no está activa if(millis()>cronometro_monitorizacion) { if(EN_PRUEBAS) { Serial.print("tiempo "+String(millis()-hora_inicio,DEC)+" ("+String(millis()-hora_inicio,DEC)+") "); Serial.print("cantidad movimiento "+String(cantidad_movimiento,DEC)); } if(datos_movimiento) { if(EN_PRUEBAS) { Serial.println(" (almacenado)"); } linea_csv=String(millis()-hora_inicio,DEC); linea_csv+=String(SEPARADOR_CSV); linea_csv+=String(cantidad_movimiento,DEC); datos_movimiento.println(linea_csv); numero_ultima_linea_grabada++; } else { if(EN_PRUEBAS) { Serial.println(" (no almacenado)"); } } cronometro_monitorizacion=millis()+INTERVALO_MONITORIZACION; cantidad_movimiento=0; digitalWrite(PIN_LED_MONITOR,LOW); } } // Las funciones no devuelven valores ya que todo el programa usa variables globales void activar_sd() { if(EN_PRUEBAS) { Serial.println("Preparando tarjeta SD"); } if(SD.begin(PIN_CS)) { sd_activa=true; if(EN_PRUEBAS) { Serial.println("Tarjeta SD inicializada (pueden grabarse los datos)"); } } else { sd_activa=false; if(EN_PRUEBAS) { Serial.println("Error al inicializar la tarjeta SD (no se graban los datos)"); } } } void incrementar_vibracion() { digitalWrite(PIN_LED_MONITOR,!digitalRead(PIN_SENSOR)); cantidad_movimiento++; } void conmutar_sesion() { // Puede que el tiempo de cambio de sesión sea largo por el acceso a la SD, desactivar mientras las interrupciones por seguridad detachInterrupt(INTERRUPCION_SENSOR); detachInterrupt(INTERRUPCION_SESION); if(datos_movimiento) { terminar_sesion(); } else { iniciar_sesion(); } // Volver a activar las interrupciones al terminar attachInterrupt(INTERRUPCION_SENSOR,incrementar_vibracion,CHANGE); attachInterrupt(INTERRUPCION_SESION,conmutar_sesion,RISING); } void iniciar_sesion() { char nombre_archivo[13]; char buffer_numero_archivo[4]; if(millis()>cronometro_intervalo_sesion) { if(!sd_activa) { activar_sd(); } if(sd_activa) { do { itoa(numero_archivo++,buffer_numero_archivo,10); strcpy(nombre_archivo,PREFIJO_ARCHIVO); strcat(nombre_archivo,buffer_numero_archivo); strcat(nombre_archivo,EXTENSION_ARCHIVO); if(EN_PRUEBAS) { Serial.println("Probando a usar el documento "+String(nombre_archivo)); } } while(SD.exists(nombre_archivo)); datos_movimiento=SD.open(nombre_archivo,FILE_WRITE); if(datos_movimiento) { if(EN_PRUEBAS) { Serial.println("Almacenado datos en "+String(nombre_archivo)); Serial.println("Comienza la sesión de almacenamiento de datos"); } hora_inicio=millis(); cronometro_intervalo_sesion=millis()+INTERVALO_ENTRE_SESIONES; cronometro_sesion=millis()+INTERVALO_GRABACION; numero_ultima_linea_grabada=0; } else { if(EN_PRUEBAS) { Serial.println("No se puede abrir "+String(nombre_archivo)); Serial.println("No se inicia la sesión de almacenamiento de datos"); } } } else { if(EN_PRUEBAS) { Serial.println("La sesión ya está activa, no se vuelve a activar. "); } } } } void terminar_sesion() { if(millis()>cronometro_intervalo_sesion) { cronometro_intervalo_sesion=millis()+INTERVALO_ENTRE_SESIONES; datos_movimiento.flush(); datos_movimiento.close(); //datos_movimiento=false; if(EN_PRUEBAS) { Serial.println("Termina la sesión de almacenamiento de datos"); } } } |
Arturo
Hola buenos dias, estaba leyendo sobre la informacion que subio de como almacenar en la SD, pero en mi caso yo tengo un Arduino YUN, tengo que habiitar los pines como en tu programación? Es que la tarjeta SD ya lo trae en el mismo Arduino YUN, sin necesidad de una shield. me podria ayudar o dar un tutorial
Víctor Ventura
Hola, Arturo.
No lo he probado en un Arduino Yun pero, hasta donde sé, el pin que usan Arduino Mega y Arduino Yun para CS (SS) es el 53.
¿Alguien con un Arduino Yun que lo confirme?
pablo
Lo mejor es bajarte el PINOUT de tu placa…
Humberto
Que tal Victor, estoy implementando el codigo y necesito el O_APPEND, ya que a veces cuando vuelvo a insertar la sd ya no me guarda los datos hasta que reinicio el arduino. Pienso que se podria quitar con dicho codigo ya que su funcion es escribir despues de cada escritura. Solo que me da el error aqui:
File dataFile = SD.open("humedad.txt", FILE_WRITE | FILE_APPEND ) ;
me marca error en
FILE_APPEND
me dice que
was not declared in this scope
Víctor Ventura
Hola, Humberto.
El valor de
O_APPEND
es0x04
Para usar las constantes de los modos de apertura puedes añadir a la cabecera de tu código:
Saludos. Gracias por participar en polaridad.es.
Daniel Aguilar
Buenas tardes. Muy interesante tu post, no obstante, tengo la siguiente duda: ¿CUàl es el tiempo de escritura de arduino si quiero almacenar en una SD datos provenientes de un ADC externo el cuál es bastante rápido?
Víctor Ventura
Hola, Daniel.
No sé decirte exactamente la velocidad. Puede medirse, si es que fuera relevante, pero no creo que todos los accesos, ni aún los del mismo tipo, tarden lo mismo.
Sé que el acceso es bastante lento, así que tendrás que bloquear la recepción de datos desde el dispositivo que hace la ADC, y perder datos, o definir un buffer para grabar lo que no dé tiempo, si es que hay momentos en los que no llegan datos al ADC que se pueden aprovechar para sincronizar los que no fue posible grabar.
Espero que esto te ayude un poco. Gracias por participar en polaridad.es
Luis
Buenas tardes y muchas gracias por este tutorial, que llevo meses buscando algo similar, claro y conciso y hoy lo encontre por fin.
Tengo una pequeña duda: tengo dos archivos, encender.txt y apagar.txt, ambos estan ordenados 22121435 por dd/MM/hh/mm. o asi: 22/12 14:35 este para encender.txt y 22121641 (22/12 16:41 para apagar.txt, la pregunta seria si se podrian tener los dos archivos abiertos a la vez o tendria que ponerle una condicion como por ejemplo si son mas de las 15 horas abre el archivo apagar.txt.
Lo que pretendo es que arduino compare a traves del rtc los archivos contenidos en la SD y si el dia, mes, hora y minutos del dia actual estan en el archivo endender.txt me encienda un led, si no estan lo deje apagado. Nuevamente cuando se aproxime la hora de apagar, lea el archivo apagar.txt y si coincide el dia, mes, hora y minutos actuales con los del archivo me apague el led si esta encendido. un saludo y perdon por als molestias
Víctor Ventura
Hola, Luis.
En efecto, no se pueden mantener abiertos los dos documentos a la vez usando la librería SD. Si los documentos con las fechas los gestionas tú ¿No podrías poner toda la información en uno solo?
Supongo que tienes buenas razones para usar una tarjeta SD en lugar de, por ejemplo, leer los datos de la EEPROM, que me da la impresión de que es más eficiente, salvo que sean miles de veces las que enciendes y apagas los LED. Lógicamente, tú conoces mejor tu proyecto para optar por un método u otro 🙂
Tampoco entiendo muy bien lo de leer todo el documento. Seguramente pensando en un dispositivo con pocos recursos (como un MCU) lo que yo haría, por si te ayuda en algo, sería leer de forma circular un valor, usarlo, y leer el siguiente indexándolo con un puntero (esto sería sencillísimo usando la EEPROM). Como hay fechas para encender y apagar, leería ambas, con el mismo criterio, y así las tendría preparadas. Después de utilizar cada fecha (cuando venzan y se encienda o apague cuando se alcancen) volvería a leer.
¿Te ayudo algo con esto? Gracias por participar en polaridad.es
Luis
Hola, si que me has ayudado, y lo de usar la sd es porque cada 3 meses se cambiaran las horas y dias de encendido y apagado, y habra que volver a escribirlas en la SD.
El proyecto es para el bloqueo de una puerta de seguridad, en lugar del led habra un rele que de paso a 220v que cerrara o abrira segun sean las horas y dias, luego la siguiente parte que si utilizare la EEPROM, habra tarjetas con un codigo alfa-numerico que permitiran desbloquear o bloquear esa puerta a aquellas personas que tengan la clave en la tarjeta a cualquier hora y dia, mas que nada para evitar alguna caída, pero primero tengo que verificar que el codigo no me de muchos problemas. Un saludo y gracias
Víctor Ventura
Gracias a ti por contarnos tu proyecto 🙂 ¡Vuelve pronto por polaridad.es!
Xabat Etxegia
Hola buenos días, estamos haciendo un proyecto en tecnología en 2. de bachillerato y quiero saber como puedo pasar al mismo tiempo datos de diversos sensores de arduino a una SD.
Víctor Ventura
Hola, Xabat.
Si estás creando un documento en formato CSV puedes grabar en cada línea varios datos separándolos por comas (precisamente esa es la finalidad de ese formato de archivo).
Por ejemplo, una línea podría contener una referencia al tiempo (puede ser el tiempo real o el transcurrido desde cierto instante), una coma, la temperatura obtenida de un sensor, otra coma, el consumo eléctrico y un fin de línea. Unas cuantas líneas de ese ejemplo podrían quedar así:
20161219104412,20.5,0.75
20161219104422,21.0,0.8
20161219104442,21.5,0.75
No das muchos datos del problema, así que solo puedo responderte genéricamente pero, usando la imaginación, puedo suponer que el problema sea grabar varios datos (a la librería SD no le gusta trabajar con varios documentos a la vez). La solución se puede intuir en la respuesta pero, por aclararlo, la idea es grabar todos los datos de los diferentes sensores de una vez (en una linea del documento CSV) almacenándolos en el MCU hasta que sea el momento, aunque la frecuencia de muestreo de ellos sea diferente, repitiendo u omitiendo datos si fuera necesario para sincronizarlos.
Espero que esto os ayude un poco.
Sería genial si nos contaras cómo es el proyecto y cómo se va desarrollando para que a todos nos enriquezca vuestra experiencia.
¡Suerte con el proyecto!
Xabat Etxegia
Gracias, nos ha servido de mucho. Queremos hacer un CanSat para el concurso nacional, y para ello tenemos que recopilar información de varios sensores y pasarlos a una tarjeta SD para luego hacer varios gráficos (tiempo-altura, temperatura-altura).
Por otra parte, tenemos que utilizar el sensor NTC 10k pero no conseguimos calcular la temperatura real. Creo que el problema esta en que los valores que recibimos son de la resistencia y no sabemos como traducirlos en temperatura nos podrías ayudar?
Víctor Ventura
Hola, Xabat.
Como la relación entre la resistencia del termistor y la temperatura no es lineal, la trasposición no es inmediata; tendrás que convertir los valores que obtienes, para lo que necesitarás los datos del fabricante y/o valores medidos del componente real.
El cálculo es un poco largo de explicar en la extensión de un comentario (a lo mejor me animo a escribir un artículo al respecto) así que, si no tienes experiencia usando termistores, te recomiendo que uses el método de lectura de un termistor usando una tabla de búsqueda o el método de cálculo de la temperatura de un termistor con una fórmula (función), ambos del playground de Arduino; son muy sencillos de implementar.
¡Suerte con el proyecto y gracias por compartirlo en polaridad.es!
Eñaut
Buenas tardes Víctor! Soy un compañero de grupo de Xabat. Lo primero darte las gracias por la ayuda y en general por invertir una parte de tu tiempo en ayudar a los demas! Por otra parte, te animo a que escribas el artículo del que hablas en tu último comentario, no solo porque nos serviría a nosotros sino para bien de todos los interesados en este tema. Por último, refiriéndome también a tu último comentario, no entiendo a que te refieres cuando dices «método de lectura de un termistor usando una tabla de búsqueda o el método de cálculo de la temperatura de un termistor con una fórmula (función), ambos del playground de Arduino». Si no te importa mucho explicarme un poco de que se trata, te lo agradecería!! Un saludo.
Víctor Ventura
Hola, Eñaut
Básicamente hay dos formas de calcular la temperatura en función de la resistencia del termistor: ① creando un vector que almacena la temperatura correspondiente a la resistencia medida (o que se obtiene a partir de él), recurso que en programación se suele llamar tabla de búsqueda o tabla de consulta (o más frecuentemente LuT) o ② utilizando una función que permite calcular la temperatura conociendo la resistencia en el termistor, para lo que suele utilizarse la ecuación de Steinhart-Hart.
En el comentario a que haces referencia enlazo a los correspondientes recursos del playground de Arduino desde donde puedes descargar código para calcular la temperatura por cada método. Puedes probar ambos y quedarte con el que te vaya mejor a tu proyecto.
Hay muchos artículos sobre el uso de termistores pero si os parece interesante escribiré uno en cuanto tenga un rato libre. Espero que os guste 🙂
Gracias por participar en polaridad.es
Eñaut
He subido el siguiente sketch (que es el del playground de Arduino) y los resultados me salen alrededor de 80.
#include
double Thermistor(int RawADC) {
double Temp;
Temp = log(10000.0*((1024.0/RawADC-1)));
// =log(10000.0/(1024.0/RawADC-1)) // for pull-up configuration
Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp );
Temp = Temp – 273.15; // Convert Kelvin to Celcius
Temp = (Temp * 9.0)/ 5.0 + 32.0; // Convert Celcius to Fahrenheit
return Temp;
}
void setup() {
Serial.begin(115200);
}
void loop() {
Serial.println(int(Thermistor(analogRead(0)))); // display Fahrenheit
delay(100);
}
Víctor Ventura
Hola, Eñaut.
Pues si está en el exterior, con el frío que hace estos días, puede que sea un poco alto (26,7 °C ¿No prefieres usar grados Celsius?) Por cierto, creo que hay algún error en el código, seguramente al pegarlo en el comentario.
Parece que la cosa prospera ¿No? ¡Ánimo con el proyecto!
Eñaut
Hola Víctor. No entiendo cual puede ser el fallo, ya que el sketch lo he «copiado» del Playground de Arduino y las conexiones (son muy simples) las he repasado y estan bien. Acabo de probar otra vez, ahora sí en grados Celsius, y estando en clase (interior) los resultados me salen alrededor de 30. Para que sepas, aparte de este sensor de temperatura utilizamos otro, LM35DZ, y con ese sensor no tenemos ningun problema.
Víctor Ventura
Hola, Eñaut.
Los termistores suelen ser bastante fiables y (en el rango que les corresponda) bastante precisos. Es raro que te dé un valor tan alto… suponiendo que lo sea.
Para buscar el problema, lo que yo haría es:
Los valores que usa tu código son:
A=0.001129148
B=0.000234125
C=8.76741E-08
Si no consigues esos valores del fabricante puedes calcularlos/estimarlos, pero es un poco delicado, a lo peor en tal caso te interesa usar otro componente ¿Ese LM35? 🙁
Creo que ya sé el problema del código que has pegado: contiene los caracteres < y > en
#include <math.h>
que, usados como texto, no aparecen en el comentario porque tienen un significado especial en HTML.¡Ánimo, ya casi lo tienes resuelto!
Gracias por participar en polaridad.es
Eñaut
Buenas noches, la cosa es que nos obligan a utilizar los dos sensores de temperatura, no podemos elegir uno u otro. Bueno, para calcular la temperatura con el sensor NTC, partiendo de la fórmula «deltaV=R*I» consigo medir la resistencia del sensor (Rntc), pero luego como relaciono esa resistencia con la temperatura (aparte de utilizando la tabla que aparece en el «datasheet» del sensor)?
Víctor Ventura
Hola, Eñaut.
Las dos formas de calcular la temperatura con un termistor son ① por medio de la ecuación de Steinhart–Hart, que necesita las constantes correspondientes, que el fabricante debe proporcionar, o ② utilizando una tabla de búsqueda (LuT) que contiene los valores de temperatura en función de la resistencia que, como en el caso anterior, el fabricante proporciona en la correspondiente hoja de datos.
Si no dispones de los datos del fabricante (parece que no es tu caso) tienes que crear tú la LuT midiendo temperaturas y resistencias. Con esos valores también podrías calcular los coeficientes que necesitas para aplicar la ecuación de Steinhart–Hart, aunque es algo delicado que no creo que merezca la pena en este caso (para el proyecto que estás haciendo).
La ecuación de Steinhart–Hart es bastante precisa y los datos que se obtienen al aplicarla suelen ser los correctos siempre que las constantes o coeficientes correspondientes lo sean. Utilizar una LuT puede ser más sencillo (desde el punto de vista del MCU, ya que requiere menos cálculo) pero necesita cierta cantidad de memoria para almacenar los datos y, dependiendo de cantidad disponible y de la precisión que se necesite, puede ser necesario interpolar pero es un método perfectamente aceptable y muy utilizado tanto en electrónica como en programación.
Entiendo que la hoja de datos del fabricante del termistor que estás usando te facilita una tabla de valores ¿Qué inconveniente tienes en utilizarla? Incluso, aunque optaras por usar la ecuación de Steinhart–Hart, me parecería interesante usar también la LuT para tener una doble comprobación en un programa de prueba.
Si ya la has aplicado y el resultado también es incorrecto puede ser que hayas confundido el termistor, la hoja de datos o el circuito no esté bien ¿Lo revisaste como te sugerí en un comentario anterior? Es algo trivial pero, si hay errores, hasta lo más evidente puede haberlos producido.
¡Ánimo con el proyecto y un saludo!
Frank
Hola amigo, hago un proyecto en el que necesito guardar la medición de temperatura de un sensor, pero necesito guardar esta medición según la fecha y a la hora que se realizó ¿es posible? para luego visualizarla en un archivo de lectura.
Víctor Ventura
Hola, Frank.
Claro que puedes grabar la hora junto con la temperatura, pero normalmente necesitarás incorporar un RTC a tu circuito.
En polaridad.es puedes encontrar varios artículos sobre el RTC DS3231 que te pueden dar una idea.
Saludos y suerte con tu proyecto.
Johann
Hola! queria saber como hago para leer un archivo con extension .HTML
hice un servidor web con la ethernet shield y me ocupa mucha memoria de la placa. y quiero almacenar los codigos html en la tarjeta sd. asi que cuando yo le mande el comendo desde la web lo haga desde la tarjeta sd y las acciones del codigo que esta cargada en el microcontrolador atmega328p! tengo un Arduino Uno!
Víctor Ventura
Hola, Johann.
El método para leer de la tarjeta de memoria SD es similar al que se expone para escribir pero en lugar de enviar los datos con
print
owrite
se leen conread
. A grandes rasgos, los pasos que hay que seguir son:#include <SD.h>
File web;
. Seguramente también necesites una variable de tipo texto para almacenar lo que vayas leyendo; podrías definirla con algo comochar letra;
.SD.begin(PIN_CS);
web=SD.open("WEB.HTM",FILE_READ);
para hacerlo.read
hasta que devuelva -1, que es la forma de indicar que se ha llegado al final, o usaravailable
para saber cuánto texto hay disponible. Para leer puedes usar algo comoletra=web.read();
.web.close();
, aunque no sea imprescindible (si no lees más) lo correcto es cerrar el fichero al final de la lectura.Gracias por visitar polaridad.es
Eñaut
Hola Víctor, te he escrito anteriormente sobre como almacenar datos en la tarjeta SD. Como te dijimos, estamos preparando un CanSat para el concurso nacional y decidimos utilizar una cámara monocromática e ir poniéndole diferentes filtros para, durante el vuelo del CanSat, sacar varias fotos con los diferentes filtros y después sacar conclusiones. El problema es que tenemos que buscar una aplicación a la cámara y las fotos, esto es, para que serán las fotos o que conclusiones sacaremos de ellas; al principio pensamos en seguir los pasos de Sarah Parcak (arqueóloga estadounidense, la cual busca restos arqueológicos tomando fotos desde el aire y con diferentes filtros) pero no nos termina de convencer. Se te ocurre algúna otra aplicación?? (no se si sabrás mucho sobre esto, pero por si acaso te lo pregunto)
Víctor Ventura
Hola, Eñaut.
Mis conocimientos sobre arqueología se sitúan entre nada y absolutamente nada 🙁 Eres muy amable al pensar que yo sé de cosas tan variadas 🙂
Con respecto a lo de la cámara, quería hacer una puntualización por si te ayuda. Los filtros lo que hacen es bloquear determinadas longitudes de onda, no añadirlas. Es decir, a una cámara que sea, por ejemplo, capaz de captar la radiación infrarroja (la mayoría) se le puede impedir que las detecte interponiendo en su objetivo un filtro infrarrojo. El filtro «quita» (bloquea) esa parte del espectro, no la aporta cuando la cámara no la «tiene».
Como es fácil conseguir una cámara cuyo sensor detecte infrarrojos (y el filtro de infrarrojos) es un buen ejemplo, lástima que no os guste. También se puede usar (más o menos) para detectar calor y tiene aplicación en varios campos: encontrar incipientes incendios, presencia de animales, fugas de gases, humedad en las edificaciones… y restos arqueológicos, que me acabo de enterar 🙂 Para otros colores, sin usar cámaras multiespectrales específicas, ahora no caigo en ningún ejemplo interesante, pero si se me ocurre te mando un correo electrónico.
¡Qué nivel está alcanzando vuestro proyecto! ¿no os gustaría escribir artículos para polaridad.es? Espero por lo menos que nos contéis qué tal sale 🙂
Hasta pronto.
Eñaut
Buenas tardes Víctor, siento no haber contestado antes a tu mensaje pero hemos estado bastante liados de trabajo… hemos mirado lo que dijiste de que se puede detectar el calor, pero no sabemos como hacerlo, tú sabes?
Por otro lado, en cuanto al módulo SD, a que pines tengo que conectarlo en un Arduino Pro Micro (es el que nos han dado los de la organización de la competición)?(https://forum.arduino.cc/index.phptopic=240815.0) La información de este enlace trata sobre ello, pero he visto que unos dicen que las conexiones son de una manera y otros dicen que de otra. Me puedes ayudar?
Por último, sintiéndolo mucho no tengo/tenemos tiempo para escribir artículos en tu blog (ni en ningún otro, claro), ya que estamos en 2º de bachillerato y es un año duro y difícil.
Un saludo,
Eñaut
Eñaut
Perdona, la gente que ha comentado en dicho enlace dice que las conexiones son de una manera, pero en la librería de la SD he visto que son de otra manera: (cambia el SCSG—–>SS 0 CS)
Pro Micro Pin 10 -> Módulo SD CS
Pro Micro Pin 16 -> Módulo SD MOSI
Pro Micro Pin 14 – > Módulo SD MISO
Pro Micro Pin 15 -> SCK módulo SD
o
uint8_t const SS_PIN = 17;
uint8_t const MOSI_PIN = 16;
uint8_t const MISO_PIN = 14;
uint8_t const SCK_PIN = 15;
Víctor Ventura
Hola, Eñaut.
He revisado el pinout del Pro Micro y ciertamente corresponde con lo que escribes (lo de usar el pin 10 para CS es discutible pero es lo habitual)
No entiendo cuál es el problema ¿Que la numeración no corresponde con la de otras placas? eso es normal, cada placa (por supuesto, cada MCU tiene su propio pinout.
Saludos.
Víctor Ventura
Hola, Eñaut.
Me alegra verte de nuevo por aquí. La forma de comunicación a la que se presta este canal es así, no te preocupes, escribe cuando te venga bien 🙂
Básicamente, para detectar el calor con una cámara sin filtro infrarrojo hay que suponer que donde se detecta más intensidad de luz es donde hay más calor.
Como no es una cámara térmica, la anterior afirmación es mentira: la cámara también detectará la luz en el espectro visible. A determinadas horas y con determinados objetos (¿arqueológicos?) el error es más admisible. A plena luz no sirve.
Para poder ir más allá de simplemente concluir algo como «esto está más caliente que esto otro» (porque se ve más iluminado) tendrás que hacer mediciones en condiciones controladas para calibrar (o algo parecido) las imágenes que obtienes.
La parte más delicada es la obtención de la imagen (imagino que no la tienes que procesar para que tu proyecto esté terminado) porque se trata de una cantidad de datos grande para un dispositivo pequeño (como el MCU de la placa Pro Micro) Lo más seguro es que necesites una cámara que incorpore un buffer (probablemente FIFO) que te permita leer de ahí las imágenes «sin prisas» en lugar de hacerlo desde la cámara.
No he encontrado nada de código (ya listo) que te pueda servir, afortunadamente, estas cámaras suelen comunicar por el puerto serie y no son demasiado difíciles de manejar.
No puedo ver el enlace que me dices 🙁 así que no sé a lo que te refieres.
¡Ánimo con tu bachillerato e intenta también pasártelo bien! Tenéis un centro muy interesante 😉
¡Te sigo esperando por polaridad.es!
Eñaut
De acuerdo, problema solucionado! Ahora, tengo que usar el sensor BMP180 para calcular la presión atmosférica, temperatura y altura, pero me piden utilizar una formula específica para calcular la altura. Para ello he buscado información en internet pero no encuentro ningun «sketch» en el que apliquen dicha fórmula para calcular la altura; entonces, la fórmula estará en la librería que utilizan? Si sabes donde puedo encontrar esa fórmula aplicada a un «sketch» te agradecería me lo comunicaras. Un saludo!
Gracias
Pedro Rubio
Buenas!
¿habría alguna manera de que el programa guarde varios ficheros .txt?
Gracias de antemano. Un Saludo
Víctor Ventura
Hola, Pedro.
¿Varios ficheros a la vez? La respuesta corta es no. La respuesta larga empieza por sí, pero tiene tantos detalles que es mejor resumir que no se puede o no merece la pena, especialmente usando un MCU pequeño.
Supongo que no te refieres a varios ficheros de manera secuencial (primero uno, luego otro… En tal caso, la respuesta sería sí y lo único que hay que hacer es abrirlos, almacenar la información cerrarlos y proceder con el siguiente de la misma forma.
Para resolver con un rodeo lo de grabar varios documentos a la vez puedes establecer tu propio protocolo con en contenido (por ejemplo una línea de texto para cada uno de los documentos) y luego posprocesarlo en otro sistema (en un servidor, PC… depende de lo que vayas a hacer con los ficheros)
Saludos y gracias por participar en polaridad.es
Juan Pedro
Hola se pueden tener dos archivos abiertos a la vez, y escribir en ellos.
Gracias
jose luis
hola amigo victor gracias por el post ..amigo victor pot favor necesito tu ayuda estoy empezando en esto de arduino y quiero hacer una maquinita que imprima en un lcd un usuario una contraseña guardados en una sd seria osea tendrai una lista de ejeplo 1000 usuarios con sus respectivas contraeñas ejemplo user :juan pass:122344 cada vez que ingrese una modena en un monedero amigo regalame un ejemplo por g¿favor gracias te lo agradezco de corazon
salvador
Buenos dias, estoy intentando sacar datos de una SD, consigo hacer un serial.print del fichero pero intento convertir este fichero en una variable para poder trabajar con ella pero no lo consigo. ¿Me puedes orientar sobre la forma de hacerlo?.
Gracias
Víctor Ventura
Hola, Salvador.
No entiendo tu pregunta ¿Te refieres a tomar los valores del fichero para la variable? ¿Cómo se leerían a lo largo del tiempo?
Si nos das más información, a lo mejor algún lector o yo mismo podemos ayudarte.
Saludos.
Adri
Hola buenas, tengo un rfid un rtc y lector sd y quiero guardar el id de cada tarjeta con la hora y fecha en una sd, sabrias como poderlo almacenar? Estoy teniendo algunos problemas.
Gracias
Leyre
Hola!
estoy intentando hacer un proyecto en el que comunico el arduino con 9 sensores mediante CAN Open, e intento guardar los mensajes que estos sensores envían. La velocidad de comunicación es de 250kbps, y cada 50 ms los sensores envían sus datos.
No consigo guardar todos los mensajes, creo que por que arduino no es capaz de guardar todos los mensajes en la SD tan rapidamente.
¿Se te ocurre alguna otra manera de hacerlo?
#include
#include
#include
long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
char msgString[128];
volatile int contador=0;
int guardar=0;
#define CAN0_INT 18 //PIN INT MCP2515
#define TarjetaSD 7 //PIN de la tarjeta SD
MCP_CAN CAN0(4); // Set CS to pin 4
File Archivo; //Genero el archivo donde se guardan los datos capturados
void setup()
{
Serial.begin(250000);
// Initialize MCP2515 running at 16MHz with a baudrate of 250kb/s and the masks and filters disabled.
if(CAN0.begin(MCP_ANY, CAN_250KBPS, MCP_16MHZ) == CAN_OK)
CAN0.setMode(MCP_NORMAL); // Set operation mode to normal so the MCP2515 sends acks to received data.
pinMode(CAN0_INT, INPUT); // Configuring pin for /INT input
pinMode(TarjetaSD, OUTPUT);
attachInterrupt(digitalPinToInterrupt(CAN0_INT),Interrupcion,FALLING);//Si detecta flanco de bajada en la señal del pin CAN0_INT llama a la interrupcion.
if (!SD.begin(TarjetaSD))
{
Serial.println(«Se ha producido un fallo al iniciar la tarjeta»);
return;
}
Serial.println(«Se ha iniciado la comunicación correctamente»);
Archivo = SD.open(«Captura.txt», FILE_WRITE);
}
void loop()
{
int a=5;
//Archivo.close();
}
void Interrupcion()
{
CAN0.readMsgBuf(&rxId, &len, rxBuf); // Read data: len = data length, buf = data byte(s)
Archivo = SD.open(«Captura.txt», FILE_WRITE);
Archivo.print(«COB-ID»);
Archivo.print(rxId);
Archivo.print(rxBuf[0],HEX);
Archivo.print(» «);
Archivo.print(rxBuf[1],HEX);
Archivo.print(» «);
Archivo.print(rxBuf[2],HEX);
Archivo.print(» «);
Archivo.print(rxBuf[3], HEX);
Archivo.print(» «);
Archivo.print(rxBuf[4], HEX);
Archivo.print(» «);
Archivo.print(rxBuf[5], HEX);
Archivo.print(» «);
Archivo.print(rxBuf[6], HEX);
Archivo.print(» «);
Archivo.println(rxBuf[7], HEX);*/
Archivo.close();
//Limpio las variables
for(int i=0;i<=7;i++)
{rxBuf[i]=0;}
}
Andrès
Buenas Colegas!
Estoy intentando almacenar datos de una variable (pulso) que sera enviado
a través de un modulo Wifi de arduino. La interrogativa es si se puede diseñar un sistema
tipo SCADA ya que son diversas variables.
Lautaro benitez
Hola que tal, muy buen posteo. Mi pregunta es como debería hacer para que no me sobrescriba el mismo archivo utilizando la función SD.exists(filename), o sea que analice si existe un archivo con ese nombre que cree uno nuevo con el nombre variado así no me agrega mas datos al mismo archivo. o si no también como nombrar al archivo en base a una variable que pueda llegar a ser nombrar el archivo con la hora, temperatura, etc.
Espero ser claro con mi cuestión. Muchas gracias. Lautaro
LuIS
Hola Victor
Hace rato intento hacer funcionar Shierld Ethrnet, SD Card y Nrf24, los tres en el mismo proyecto
Los tres utilizan Bus spi
Me has ayudado mucho con SDCARD_ss_pin, no sabia de ello
Me está faltando algo y no se que es……me podrás echar un cable….?
MI nombre es Luis…..tresbien65@gmail.com
Muchas gracias
vicente
Buenas tardes Victor.
Ante todo darte las gracias por tus publicaciones. Tengo un pequeño problema. Con Arduino Uno necesito grabar en una micro sd una determinada variable todos los dias a una hora fija. A la vez que la grabo, tengo que recuperar el valor anterior y añadir a la primera la diferencia entre ambas. Pongamos el caso de un depósito de agua y un indicador de nivel. Diariamente recupero el último grabado, establezco la diferencia con el nivel actual y grabo nivelactual + diferencia. Consigo grabar, consigo recuperar, pero no consigo hacer la interpretación correcta. Me podrías echar un cable?
Muchas gracias
Danilo
Estoy muy interesado en este desarrollo pero tengo problemas seria de gran ayuda tu opinion
lo estoy desarrollando con Arduino uno pero lo unico que no hace es guarda en la SD sale (No guardado)