Micro SD y LED's

Buenas tardes compañeros, estoy trabajando en un sistema con Arduino que me permita almacenar los datos de diversos sensores en una microSD con ayuda de un módulo, así mismo estoy usando una tira de luces led para que se enciendan según el porcentaje de luz. El código funciona bien hasta que añado la sección de las luces, en ese caso en el puerto serial solo me muestra el mensaje de "Acceso correcto a la memoria", pero no almacena los datos. Estoy usando Adafruit NeoPixel.

Esta es la clase que utilizo para almacenar los datos en la SD:

#include <SD.h>

void guardarEnSD(DateTime now, float humidityPromedio, float temperaturePromedio, float porcentaje_luz) {

  if (!SD.begin(10)) {
    Serial.println("Tarjeta SD no detectada.");
    return;
  }

  // Intenta abrir o crear el archivo en modo de escritura
  ArchivoCSV = SD.open("registro.txt", FILE_WRITE);
  
  // Verifica si el archivo se abrió o se creó correctamente
  if (!ArchivoCSV) {
    // Si no se pudo abrir o crear el archivo, muestra un mensaje de error y sale de la función
    Serial.println("Error: No se pudo abrir ni crear el archivo.");
    return;
  }
  
  // Escribe los datos en el archivo
  ArchivoCSV.print(now.year(), DEC);
  ArchivoCSV.print('/');
  ArchivoCSV.print(now.month(), DEC);
  ArchivoCSV.print('/');
  ArchivoCSV.print(now.day(), DEC);
  ArchivoCSV.print(' ');
  ArchivoCSV.print(now.hour(), DEC);
  ArchivoCSV.print(':');
  ArchivoCSV.print(now.minute(), DEC);
  ArchivoCSV.print(',');
  ArchivoCSV.print("Hum: ");
  ArchivoCSV.print(humidityPromedio);
  ArchivoCSV.print("%, Temp: ");
  ArchivoCSV.print(temperaturePromedio);
  ArchivoCSV.print("C, Luz: ");
  ArchivoCSV.print(porcentaje_luz);
  ArchivoCSV.println("%");
  
  // Verificar si el archivo sigue abierto antes de intentar cerrarlo
  if (ArchivoCSV) {
    // Cierra el archivo después de escribir los datos
    ArchivoCSV.close();
    Serial.println("Datos guardados en la tarjeta SD.");
  } else {
    Serial.println("Error: El archivo se cerró inesperadamente.");
  }
}

Y esta es la sección de código de las luces LED's

#include <Adafruit_NeoPixel.h> // Librería NeoPixel
 #define LED_PIN     5       // Pin al que está conectada la tira de LED NeoPixel
#define NUM_LEDS    20       // Número de LEDs en la tira

Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800); // Declaración del objeto NeoPixel

void setup() {

  strip.begin();           // Inicializar la tira de LED NeoPixel
  strip.show();            // Actualizar la tira de LED para mostrar los cambios
  strip.setBrightness(50); // Ajustar el brillo de la tira de LED (de 0 a 255)
}


void loop() {

// Enciende o apaga todos los LEDs según el porcentaje de luz
  if (porcentaje_luz < 51) { // Enciende si el porcentaje de luz es menor a 51
    strip.fill(strip.Color(brillo_led, brillo_led, brillo_led)); // Configura todos los LEDs en la tira al mismo color
  } else { // Apaga si el porcentaje de luz es mayor o igual a 51
    strip.fill(strip.Color(0, 0, 0)); // Apaga todos los LEDs en la tira
  }
  strip.show(); // Actualizar la tira de LED para mostrar los cambios
}

Ambos códigos funcionan bien de forma independiente, pero al momento de integrarlos al código surgen los problemas antes mencionados. He omitido fragmentos de código para que sea más fácil analizar el problema, les agradecería mucho su ayuda.

A petición les dejo el codigo completo

#include <Wire.h>
#include "RTClib.h"
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include <SD.h>
#include <Adafruit_NeoPixel.h> 

#define DHTPIN1 3  
#define DHTPIN2 4  
#define DHTTYPE DHT11  
#define LDR_SENSOR_1 A2 
#define JOYSTICK_X A0       
#define JOYSTICK_Y A1       
#define JOYSTICK_SWITCH 2   
#define JOYSTICK_THRESHOLD 20    
#define VENTILADOR_PIN_1 8  // Primer pin para controlar el ventilador
#define VENTILADOR_PIN_2 9  // Primer pin para controlar el ventilador  
#define LED_PIN     5       // Pin al que está conectada la tira de LED NeoPixel
#define NUM_LEDS    20       // Número de LEDs en la tira

Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800); // Declaración del objeto NeoPixel

File ArchivoCSV;

LiquidCrystal_I2C lcd(0x27, 16, 2);
RTC_DS1307 RTC;

DHT dht1(DHTPIN1, DHTTYPE);
DHT dht2(DHTPIN2, DHTTYPE);

int joystickX = 0;       
int joystickY = 0;       
int joystickSwitchState = HIGH;   
int joystickThreshold = 20;       
int ldrSensor1 = 0;
float porcentaje_luz = 0; // Variable para almacenar el porcentaje de luz
int ventilador = 10; 

unsigned long lastSDSaveTime = 0;
const unsigned long SDWriteInterval = 120000; // 2 minutos en milisegundos

unsigned long lastLDRDisplayTime = 0;
const unsigned long LDRDisplayDelay = 1000;

enum DisplayMode {
  PANTALLA_HORA_FECHA,
  PANTALLA_DHT11,
  PANTALLA_LDR
};

DisplayMode currentMode = PANTALLA_HORA_FECHA;

void setup() {

  Wire.begin();            
  RTC.begin();             
  Serial.begin(9600);      
  lcd.init();
  lcd.backlight();
  lcd.clear();
  dht1.begin();
  dht2.begin();
  pinMode(JOYSTICK_SWITCH, INPUT_PULLUP);  
  pinMode(ventilador, OUTPUT);
  pinMode(VENTILADOR_PIN_1, OUTPUT);
  pinMode(VENTILADOR_PIN_2, OUTPUT);

  //RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));

  if (!SD.begin(10)) {
    Serial.println("Error al acceder a la tarjeta SD.");
    return;
  }

  Serial.println("Acceso correcto a tarjeta SD.");

  lastSDSaveTime = millis(); // Inicializar el tiempo de guardado en la SD

  strip.begin();           // Inicializar la tira de LED NeoPixel
  strip.show();            // Actualizar la tira de LED para mostrar los cambios
  strip.setBrightness(50); // Ajustar el brillo de la tira de LED (de 0 a 255)

}

void loop() {  
  porcentaje_luz = map(ldrSensor1, 50, 850, 100, 0); // Corregimos el mapeo
  porcentaje_luz = constrain(porcentaje_luz, 0, 100); // Asegura que el porcentaje esté en el rango de 0 a 100

  int brillo_led = map(porcentaje_luz, 0, 100, 255, 0);

  DateTime now = RTC.now();
  float humidity1 = dht1.readHumidity();
  float temperature1 = dht1.readTemperature();
  float humidity2 = dht2.readHumidity();
  float temperature2 = dht2.readTemperature();
  float humidityPromedio = (humidity1 + humidity2) / 2.0;
  float temperaturePromedio = (temperature1 + temperature2) / 2.0;

  ldrSensor1 = analogRead(LDR_SENSOR_1); // Actualizamos la lectura del sensor de luz
  delay(100);


  if (temperaturePromedio >= 26) {
    digitalWrite(VENTILADOR_PIN_1, HIGH); // Encender el primer pin del ventilador
    digitalWrite(VENTILADOR_PIN_2, HIGH); // Encender el segundo pin del ventilador
    Serial.print("Ventilador activado. Temperatura promedio: ");
    Serial.print(temperaturePromedio);
    Serial.println("°C");
  } else {
    digitalWrite(VENTILADOR_PIN_1, LOW); // Apagar el primer pin del ventilador
    digitalWrite(VENTILADOR_PIN_2, LOW); // Apagar el segundo pin del ventilador
  }

  // Enciende o apaga todos los LEDs según el porcentaje de luz
  if (porcentaje_luz < 51) { // Enciende si el porcentaje de luz es menor a 51
    strip.fill(strip.Color(brillo_led, brillo_led, brillo_led)); // Configura todos los LEDs en la tira al mismo color
  } else { // Apaga si el porcentaje de luz es mayor o igual a 51
    strip.fill(strip.Color(0, 0, 0)); // Apaga todos los LEDs en la tira
  }
  strip.show(); // Actualizar la tira de LED para mostrar los cambios

  if (currentMode == PANTALLA_LDR || currentMode == PANTALLA_HORA_FECHA || currentMode == PANTALLA_DHT11) {
    if (millis() - lastSDSaveTime >= SDWriteInterval) {
      guardarEnSD(now, humidityPromedio, temperaturePromedio, porcentaje_luz);
      lastSDSaveTime = millis(); // Actualizar el tiempo de guardado en la SD
    }
  }

  lcd.setCursor(0, 0);
  if (currentMode == PANTALLA_HORA_FECHA) {
    displayPantallaHoraFecha(now);
  } else if (currentMode == PANTALLA_DHT11) {
    displayPantallaDHT11(humidityPromedio, temperaturePromedio);
  } else if (currentMode == PANTALLA_LDR) {
    displayPantallaLDR(porcentaje_luz);
  }

  joystickX = analogRead(JOYSTICK_X);
  joystickY = analogRead(JOYSTICK_Y);
  joystickSwitchState = digitalRead(JOYSTICK_SWITCH);

  if (abs(joystickX - joystickY) > joystickThreshold && joystickSwitchState == HIGH) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Cargando...");
    lcd.setCursor(0, 1);
    lcd.print("Por favor espera");
    delay(3000);  

    lcd.clear();
    currentMode = (currentMode == PANTALLA_HORA_FECHA) ? PANTALLA_DHT11 : (currentMode == PANTALLA_DHT11) ? PANTALLA_LDR : PANTALLA_HORA_FECHA;
  }

  delay(100);
}

void displayPantallaHoraFecha(DateTime now) {
  lcd.print("Fecha y Hora:");
  lcd.setCursor(0, 1);
  lcd.print(now.year(), DEC);
  lcd.print('/');
  lcd.print(now.month(), DEC);
  lcd.print('/');
  lcd.print(now.day(), DEC);
  lcd.print(' ');
  lcd.print(now.hour(), DEC);
  lcd.print(':');
  lcd.print(now.minute(), DEC);
}

void displayPantallaDHT11(float humidityPromedio, float temperaturePromedio) {
  lcd.print("Hum: ");
  lcd.print(humidityPromedio);
  lcd.print("%  ");

  lcd.setCursor(0, 1);
  lcd.print("Tem: ");
  lcd.print(temperaturePromedio);
  lcd.print("C");
}

void displayPantallaLDR(float porcentaje_luz) {
  lcd.setCursor(0, 0);
    lcd.print("Porcentaje luz: ");
    lcd.setCursor(0, 1);
    lcd.print("   ");
    lcd.print(porcentaje_luz);
    lcd.print("%");
}

void guardarEnSD(DateTime now, float humidityPromedio, float temperaturePromedio, float porcentaje_luz) {

  if (!SD.begin(10)) {
    Serial.println("Tarjeta SD no detectada.");
    return;
  }

  // Intenta abrir o crear el archivo en modo de escritura
  ArchivoCSV = SD.open("registro.txt", FILE_WRITE);
  
  // Verifica si el archivo se abrió o se creó correctamente
  if (!ArchivoCSV) {
    // Si no se pudo abrir o crear el archivo, muestra un mensaje de error y sale de la función
    Serial.println("Error: No se pudo abrir ni crear el archivo.");
    return;
  }
  
  // Escribe los datos en el archivo
  ArchivoCSV.print(now.year(), DEC);
  ArchivoCSV.print('/');
  ArchivoCSV.print(now.month(), DEC);
  ArchivoCSV.print('/');
  ArchivoCSV.print(now.day(), DEC);
  ArchivoCSV.print(' ');
  ArchivoCSV.print(now.hour(), DEC);
  ArchivoCSV.print(':');
  ArchivoCSV.print(now.minute(), DEC);
  ArchivoCSV.print(',');
  ArchivoCSV.print("Hum: ");
  ArchivoCSV.print(humidityPromedio);
  ArchivoCSV.print("%, Temp: ");
  ArchivoCSV.print(temperaturePromedio);
  ArchivoCSV.print("C, Luz: ");
  ArchivoCSV.print(porcentaje_luz);
  ArchivoCSV.println("%");
  
  // Verificar si el archivo sigue abierto antes de intentar cerrarlo
  if (ArchivoCSV) {
    // Cierra el archivo después de escribir los datos
    ArchivoCSV.close();
    Serial.println("Datos guardados en la tarjeta SD.");
  } else {
    Serial.println("Error: El archivo se cerró inesperadamente.");
  }
}

Podemos ver como queda el código integrado que te da problemas?

Si, ya lo dejé al final del post, gracias

En un Arduino UNO tengo este mensaje del compilador:

El Sketch usa 20448 bytes (63%) del espacio de almacenamiento de programa. El máximo es 32256 bytes.
Las variables Globales usan 1568 bytes (76%) de la memoria dinámica, dejando 480 bytes para las variables locales. El máximo es 2048 bytes.
Poca memoria disponible, se pueden producir problemas de estabilidad.

Posiblemente sea un problema de escasez de memoria.

¿Qué Arduino usas?

La SD ya fue iniciada en setup() entonces no la vuelvas a iniciar cada vez que vas a guardar datos

void guardarEnSD(DateTime now, float humidityPromedio, float temperaturePromedio, float porcentaje_luz) { 
// if (!SD.begin(10)) { 
//   Serial.println("Tarjeta SD no detectada."); 
//   return; 
// } 

// ... 

Si el programa avanzó hasta el punto en que guarda el porcentaje de luz, el archivo tiene que estar abierto (caso contrario no salvó los datos), entonces no tiene sentido esta verificación.
Directamente cierra el archivo

// Verificar si el archivo sigue abierto antes de intentar cerrarlo 
// if (ArchivoCSV) { 
  // Cierra el archivo después de escribir los datos 
  ArchivoCSV.close(); 
  Serial.println("Datos guardados en la tarjeta SD."); 
// } else { 
//   Serial.println("Error: El archivo se cerró inesperadamente."); 
//}

De otro modo y para que la verificación sea útil, deberías verificar que el archivo esté abierto antes de cada escritura, o sea antes de cada ArchivoCSV.print().

Si encuentro más detalles, sigo. :wink:

1 Like

Gracias, justo estoy con un Arduino UNO, reconsideraré cambiarlo a un MEGA, gracias

Hi,
Aqui tu estas enviendo muchos mensajes y tambien muchos mensajes usando el lcd. Estos mensajes consumen mucha memoria. Otra cosa estas declarando varibles int cuando puedes declararlas como byte. Trata de eliminar los mesajes siempre y cuanod no sean necesarios.

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