// ============================================ // XIAO ESP32C3 + A4988 + Sensor de Humedad // Orquideario automático // ============================================ #define STEP_PIN 4 #define DIR_PIN 5 #define SENSOR_PIN 2 // Si tienes ENABLE conectado al A4988 #define EN_PIN 6 // ----------------------------- // UMBRALES DE HUMEDAD // ----------------------------- // En sensor capacitivo normalmente: // valor alto = seco // valor bajo = húmedo int umbralSeco = 3000; // si supera este valor, necesita riego int umbralHumedo = 2300; // cuando baja a este valor, detener riego // ----------------------------- // CONFIGURACIÓN DEL MOTOR // ----------------------------- int delayInicio = 8000; // arranque lento int delayFinal = 3500; // velocidad de trabajo segura // Tiempo de subida y bajada del recipiente int tiempoSubida = 8000; int tiempoBajada = 8000; // Seguridad: tiempo máximo regando arriba unsigned long tiempoMaxRiego = 15000; // 15 segundos bool sistemaOcupado = false; // ============================================ // SETUP // ============================================ void setup() { Serial.begin(115200); delay(500); pinMode(STEP_PIN, OUTPUT); pinMode(DIR_PIN, OUTPUT); pinMode(EN_PIN, OUTPUT); digitalWrite(EN_PIN, LOW); // LOW habilita el A4988 Serial.println("SISTEMA INICIADO"); Serial.println("Orquideario automatico listo"); } // ============================================ // LOOP PRINCIPAL // ============================================ void loop() { if (sistemaOcupado) { delay(10); return; } int humedad = leerHumedadPromedio(); Serial.print("Humedad: "); Serial.println(humedad); // Si el sustrato está seco if (humedad > umbralSeco) { sistemaOcupado = true; Serial.println("SUSTRATO SECO -> SUBIENDO RECIPIENTE"); subir(tiempoSubida); Serial.println("REGANDO HASTA HUMEDAD ADECUADA"); unsigned long inicioRiego = millis(); while (true) { humedad = leerHumedadPromedio(); Serial.print("Humedad durante riego: "); Serial.println(humedad); // Si ya llegó a humedad adecuada if (humedad <= umbralHumedo) { Serial.println("HUMEDAD ADECUADA -> BAJANDO RECIPIENTE"); break; } // Seguridad para no regar demasiado if (millis() - inicioRiego > tiempoMaxRiego) { Serial.println("TIEMPO MAXIMO DE RIEGO ALCANZADO -> BAJANDO"); break; } delay(1000); } bajar(tiempoBajada); Serial.println("CICLO DE RIEGO TERMINADO"); delay(6000); sistemaOcupado = false; } delay(3000); } // ============================================ // LECTURA PROMEDIO DEL SENSOR // ============================================ int leerHumedadPromedio() { long suma = 0; for (int i = 0; i < 10; i++) { suma += analogRead(SENSOR_PIN); delay(20); } return suma / 10; } // ============================================ // SUBIR // ============================================ void subir(int tiempo_ms) { Serial.println("SUBIENDO"); digitalWrite(DIR_PIN, HIGH); delay(100); moverMotorConRampa(tiempo_ms); Serial.println("RECIPIENTE ARRIBA"); } // ============================================ // BAJAR // ============================================ void bajar(int tiempo_ms) { Serial.println("BAJANDO"); digitalWrite(DIR_PIN, LOW); delay(100); moverMotorConRampa(tiempo_ms); Serial.println("RECIPIENTE ABAJO"); } // ============================================ // MOVIMIENTO CON RAMPA // ============================================ void moverMotorConRampa(int tiempo_ms) { unsigned long inicio = millis(); unsigned long duracion = tiempo_ms; while (millis() - inicio < duracion) { unsigned long transcurrido = millis() - inicio; int velocidadActual; if (transcurrido < duracion * 0.30) { velocidadActual = map(transcurrido, 0, duracion * 0.30, delayInicio, delayFinal); } else if (transcurrido > duracion * 0.70) { velocidadActual = map(transcurrido, duracion * 0.70, duracion, delayFinal, delayInicio); } else { velocidadActual = delayFinal; } digitalWrite(STEP_PIN, HIGH); delayMicroseconds(velocidadActual); digitalWrite(STEP_PIN, LOW); delayMicroseconds(velocidadActual); } }