Leer datos de un sensor y guardalos en una SD

Hola! Soy nueva utilizando arduino y estoy haciendo un proyecto sencillo, trata de tomar datos de un sensor de corriente y un sensor de voltaje y guardarlos en una microSD, el problema es que quiero guardar los datos cada 3mseg y hasta ahora he logrado que se guarden cada 5seg (lo cual es demasiado tiempo para lo que necesito). Estuve leyendo que con la libreria SD.h se pueden guardar datos hasta cada 20mseg pero creo que mi problema es con los sensores, creo que los sensores están tomando datos cada 5seg y no me sirve, ¿cómo podria tomar datos del sensor en menos tiempo?

Nota: para la programación de los sensores estoy usando la libreria EmonLib y estoy simulando en Proteus

Nota2: intenté utilizar las interrupciones con un timer pero ponía demasiado lenta la comunicación SPI y lo descarté

Gracias de antemano

Su publicacion se MUEVE a su ubicacion actual ya que es mas adecuada.

¿Qué placa usas (Uno, Mega, etc.)?
¿Qué sensores?

Adjunta esquema de conexiones (puedes hacerlo mano y subir una foto, lo importante es que se entienda).
Adjunta el código que estás utilizando de acuerdo a las Normas del Foro en Español, punto 7.

1 Like

Ok gracias por aclarar las normas. Por ahora estoy simulando en Proteus y estoy usando Arduino Uno, el sensor de corriente que estoy usando es el ACS712 y para el sensor de voltaje estoy usando un transformador, pero para el montaje físico pienso usar el sensor de voltaje Zmpt101b.

Adjunto código:

#include <EmonLib.h>
#include <SD.h>
#include <SPI.h>

File archivo; // objeto tipo archivo
float current, voltage; //vriable flotante para el sensor
  const int cs =10;
EnergyMonitor emon1;

void setup() {
  Serial.begin(9600);

  emon1.voltage(A1, 244.26, 1.7);  // Voltage: input pin, calibration, phase_shift
  emon1.current(A0, 2.13); 

  pinMode(cs,OUTPUT); 
  Serial.println("Inicializando tarjeta...");
  if(!SD.begin(cs)) {
    Serial.println("Fallo en inicialización"); //si no está la SD insertada
  }
  else{
    Serial.println("Inicializacion coreccta");
}
}

void loop() {
  emon1.calcVI(20,2000);         // Calculate all. No.of half wavelengths (crossings), time-out. 

  float current = emon1.Irms;
  float voltage = emon1.Vrms;
  float FP = emon1.powerFactor;

  archivo = SD.open("Datos2.txt", FILE_WRITE);
  if (archivo) {
    float current2 = float (current);
    float voltage2 = float (voltage);
    archivo.print(voltage2);
    archivo.print("V");
    archivo.print(", ");
    archivo.print(current2);
    archivo.println("A");
    Serial.println("guardado en sd");
    archivo.close(); //hay que ir cerrándolo para que no se pierdan los datos
  } 
else {
    Serial.println("Error en apertura de archivo"); //si no está insertadala tarjeta
 
  }
}

y adjunto esquema de conexiones en proteus

¿Has revisado la librería EmonLib para ver como influye en los tiempos de lectura?

Mira

emon1.calcVI(20, 2000);         // Calculate all. No.of half wavelengths (crossings), time-out. 

El primer parámetro es el ancho de la ventana de medición medido en cruces por cero (o sea, número de medias ondas).
Supongamos que tu red eléctrica trabaja a 50Hz, entonces 20 cruces por cero equivalen a 200 mseg.
O sea que lo mínimo que puede demorarse la lectura son 200 mseg pero...
El segundo parámetro es el timeout en mseg, y la función devuelve el valor leído cuando se han hecho las 20 lecturas Y se cumple el timeout.
Ahora como mínimo demora 2200 mseg en devolver los valores calculados pero... (otra vez)
Puede demorar lo mismo en encontrar los cruces por cero, así que en total puede demorar hasta 4200 mseg en devolver los resultados.

Puedes disminuir esos tiempos reduciendo el ancho de la ventana y disminuyendo el timeout.

También puedes mejorar los tiempos evitando abrir y cerrar el archivo de salida en cada pasada de loop(), ya que son operaciones que demandan bastantes mseg.

Almacena los valores en un array y guárdalos cada X lecturas.
En el peor caso pierdes los últimos valores que no se hayan llegado a guardar pero ganas en velocidad.
Evalúa lo que te resulte más importante.

Agrego:

Haciendo una simulación en wokwi, solo abrir y cerrar un archivo toma 4,48 mseg.
Si puedes darte el lujo de (con mala suerte) perder por ej. 10 lecturas, accediendo al archivo cada 10 valores ganas 40 mseg.

1 Like

Muchas gracias, eso era el problema que tenía. Redactando mi duda me equivoqué y puse que quería datos cada 3mseg pero quise decir 300mseg y ajustando esos valores lo pude obtener. Mil gracias!

1 Like

Tienes una solución posible pero dependerá de la memoria disponible. Es crear un buffer ring o sea circular donde almacenas los datos, cuando se llena, llamas a un procedimiento que lo vuelca a la SD y al volcar muchos datos, tienes solo un acceso y minimizas entonces el problema de acceso. Logras con eso guardar N muestras consumiendo solo los 5mseg.
Existe un ejemplo en SDFast que se llama AvrAdcLogger

Solo guarda 60 valores de 8 bits o 30 de 10 bits (recuerda que ocupan 2 bytes)
El sample rate puede cambiarse

const float SAMPLE_RATE = 5000;  // Must be 0.25 or greater.

o sea cada 5000 muestras x segundo que ya luce como una barbaridad
En estas condiciones el intervalo de muestreo es de

const float SAMPLE_INTERVAL = 1.0 / SAMPLE_RATE;

o sea 200 useg 5 veces mejor que el 1mseg

Bueno pruebalo a ver si satisface tu necesidad. Usa buens tarjetas SD.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.