Guardar y obtener datos sd

Hola.

Estoy realizando un proyecto de lectura a distancia.
De momento he conseguido realizar la cuenta a través de un relé y guardar los datos en la eeprom por si hubiera un fallo de corriente.

Quisiera guardar los datos en una Sd, para evitar estropear la eeprom por superar el número maximo de escrituras.

En esta parte estoy estancado porque por más que busco, no encuentro la solución.

He modificado el scketch para que solo me guarde el ultimo dato en un archivo tipo *. txt, borrando el anterior, pero no se obtener el valor que queda registrado en el archivo y pasarlo a una variable del tipo long.
Para que dicho valor quede registrado en la variable contador.

Os dejo el código sobre el que estoy trabajando.

#include <EEPROM.h>
bool dato = LOW;
bool datoAnterior = LOW;
unsigned long contador;
unsigned long ValorActual=10000;
int Direccion=0;


void setup() {
EEPROM.get (Direccion,contador);//Recoge el valor de la variable de la memoria eeprom
pinMode(2,INPUT_PULLUP);
Serial.begin(9600);

}


void loop() {
 if (ValorActual>contador){
  contador=ValorActual;
  }
 
 dato = digitalRead(2);
 if (dato == LOW && datoAnterior == HIGH)
 {
  contador++;
  EEPROM.put (Direccion,contador);
  }
 datoAnterior = dato;
 Serial.println(contador);
  
}

Aquí tengo algo para que te hagas una idea:

#include <SD.h> // Recuerda que la IDE de Arduino tiene su propia librería para uso de tarjetas SD

#define NOMBRE_ARCHIVO "algo.dat" // No lo ejemplifico .txt porque es más fácil trabajar con datos binarios; a menos que sea necesario leer el archivo fuera del Arduino para ver el valor
#define PIN_ENTRADA 2
#define CS_PIN 4 // Define la conexión del CS del módulo de la tarjeta SD

bool sdDetectada;
bool datoAnterior = HIGH;
unsigned long contador;

void setup() {
  Serial.begin(9600);
 
  sdDetectada = SD.begin(CS_PIN); // La tarjeta SD debe pasar por un proceso para que funcione en SPI. Si al final responde, retorna true; caso contrario, está dañada, mal formateada o ausente.
  if (sdDetectada) {
    contador = lecturaSD();
    Serial.print(F("Valor recuperado en la SD: "));
    Serial.println(contador);
 }
  else Serial.println(F("No se detecto la tarjeta SD. El contador iniciara desde cero pero no se almacenara nada."));
 
  pinMode(PIN_ENTRADA, INPUT_PULLUP);
}

void loop() {
  bool dato = digitalRead(PIN_ENTRADA);
 
  if (!dato && datoAnterior) { // Equivale a lo que tenías antes; solo está más abreviado
   escrituraSD();
   Serial.println(contador);
  }
  datoAnterior = dato;
}

unsigned long lecturaSD() {
  unsigned long v = 0;
  File archivo = SD.open(NOMBRE_ARCHIVO);
 
  if (archivo) { // Sé que no es tipo bool, pero es compatible en contexto booleano. true: el archivo se pudo abrir; false: el archivo no se pudo abrir
 
    archivo.readBytes((byte*)&v, sizeof(unsigned long)); // Lectura versión binaria
    // v = archivo.parseInt(); // Lectura versión textualizada
    archivo.close(); // Siempre es buena práctica cerrar un archivo cuando no se necesita
  }
  else Serial.println(F("El archivo no se pudo abrir o no existe; el contador iniciara desde cero"));
 
  return v;
}

void escrituraSD() {
 if (!sdDetectada) return; // No molestarse si la tarjeta SD nunca fue detectada en primer lugar.
 
 File archivo = SD.open(NOMBRE_ARCHIVO, O_WRITE | O_CREAT | O_TRUNC);
 // No usamos FILE_WRITE por dos razones:
 // 1. Aquí es innecesaria la capacidad de lectura.
 // 2. La opción O_TRUNC hace que automáticamente se elimine cualquier contenido previo; es más sencillo que mandar a borrar y recrear el archivo entero.
 
 if (archivo) { // Sé que no es tipo bool, pero es compatible en contexto booleano. true: el archivo se pudo abrir; false: el archivo no se pudo abrir o crear
 
  archivo.seek(0); // Por si acaso, la idea es sobrescribir un dato, no preservar los antiguos y adjuntar el nuevo
  archivo.write((byte*)&contador, sizeof(unsigned long)); // Escritura versión binaria
  // v = archivo.print(contador); // Escritura versión textualizada
  archivo.close(); // Siempre es buena práctica cerrar un archivo cuando no se necesita
  Serial.println(F("Guardado exitoso"));
 }
 else Serial.println(F("El archivo no se pudo abrir; reintentando en la proxima iteracion."));
}

Muchas líneas de código están comentadas con el fin de explicar cómo se trabaja con una tarjeta SD; las partes que no lo están se supone que deben ser autodescriptivas.
Sí todavía hay algo que no entiendes, puedes mirar la documentación o preguntar por aquí.

Moderador: Editado. No repitas lo que se lee arriba

Te agradezco tu tiempo, pero por más vueltas que le doy no consigo hacerlo funcionar.

Me da errores de compilación, utilizas una variable llamada lecturaSD que no aparece en el programa.

¿Podrias echarle un vistazo?, porque tiene buena pinta, pero algo falta y yo no soy capaz de dar con ello.

Gracias

wawrwd:
Me da errores de compilación, utilizas una variable llamada lecturaSD que no aparece en el programa.

Lucario448:

unsigned long lecturaSD() {

unsigned long v = 0;
  File archivo = SD.open(NOMBRE_ARCHIVO);

if (archivo) { // Sé que no es tipo bool, pero es compatible en contexto booleano. true: el archivo se pudo abrir; false: el archivo no se pudo abrir

archivo.readBytes((byte*)&v, sizeof(unsigned long)); // Lectura versión binaria
    // v = archivo.parseInt(); // Lectura versión textualizada
    archivo.close(); // Siempre es buena práctica cerrar un archivo cuando no se necesita
  }
  else Serial.println(F("El archivo no se pudo abrir o no existe; el contador iniciara desde cero"));

return v;
}

¿Seguro que no olvidaste esta parte? No sé tú, pero puedo jurar que a mi me compila sin problemas

Funciona perfectamente, sólo he añadido que le sume 1 a la variable contador.
Dediqué muchas horas en la búsqueda de una solución y no encontraba nada, creo que este sketch podrá servir de ayuda a mucha gente.

Muchísimas gracias porque sin tú ayuda difícilmente, podría haber terminado este proyecto.

#include <SD.h> // Recuerda que la IDE de Arduino tiene su propia librería para uso de tarjetas SD
#include <SoftwareSerial.h> // Para añadir más puertos serie y poder utilizar el módulo GSM
SoftwareSerial SIM900(6, 7); // Configura el puerto serial para el SIM900
#include "RTClib.h"
#define NOMBRE_ARCHIVO "laNucia2.dat" // No lo ejemplifico .txt porque es más fácil trabajar con datos binarios; a menos que sea necesario leer el archivo fuera del Arduino para ver el valor
#define PIN_ENTRADA 2 // pin que se utiliza para conectar el relé para realizar el conteo del caudalímetro
#define CS_PIN 10 // Define la conexión del CS del módulo de la tarjeta SD

bool sdDetectada;
bool datoAnterior = LOW;
unsigned long contador;
unsigned long valorActual=0;

void setup() {
  Serial.begin(9600);
 
  sdDetectada = SD.begin(CS_PIN); // La tarjeta SD debe pasar por un proceso para que funcione en SPI. Si al final responde, retorna true; caso contrario, está dañada, mal formateada o ausente.
  if (sdDetectada) {
    contador = lecturaSD();
    Serial.print(F("Valor recuperado en la SD: "));
    Serial.println(contador);
 }
  else Serial.println(F("No se detecto la tarjeta SD. El contador iniciara desde cero pero no se almacenara nada."));
 
  pinMode(PIN_ENTRADA, INPUT);
    if (valorActual > contador)
  {contador=valorActual;
  escrituraSD();
  }
}

void loop() {
  bool dato = digitalRead(PIN_ENTRADA);
 
  if (!dato && datoAnterior) { // Equivale a lo que tenías antes; solo está más abreviado
      contador++;
      escrituraSD();
      Serial.println(contador);
  }
  datoAnterior = dato;
}

unsigned long lecturaSD() {
  unsigned long v = 0;
  File archivo = SD.open(NOMBRE_ARCHIVO);
 
  if (archivo) { // Sé que no es tipo bool, pero es compatible en contexto booleano. true: el archivo se pudo abrir; false: el archivo no se pudo abrir
 
    archivo.readBytes((byte*)&v, sizeof(unsigned long)); // Lectura versión binaria
    // v = archivo.parseInt(); // Lectura versión textualizada
    archivo.close(); // Siempre es buena práctica cerrar un archivo cuando no se necesita
  }
  else Serial.println(F("El archivo no se pudo abrir o no existe; el contador iniciara desde cero"));
 
  return v;
}