#include <Arduino.h>
// Pines y constantes
const byte pinAnalogico = A0; // Pin analógico conectado al divisor de tensión
const byte pinPWM = 9; // Pin PWM conectado a la puerta del MOSFET
const byte pinModo1 = 3; // Pin digital para el primer modo del interruptor
const byte pinModo2 = 4; // Pin digital para el segundo modo del interruptor
const byte vModo1 = 16; // Voltaje objetivo Modo1
const byte vModo2 = 24; // Voltaje objetivo Modo2
const float R1 = 46500.0; // Resistencia 1 del divisor de tensión (en ohmios)
const float R2 = 9530.0; // Resistencia 2 del divisor de tensión (en ohmios)
const float Vref = 5.0; // Voltaje de referencia del ADC
const int resolucionADC = 1023; // Resolución del ADC (10 bits, valores de 0 a 1023)
const float factorCalibracion = 1.00; // Factor de calibración para ajustar lecturas de voltaje
// Rango configurable de voltaje para el cálculo del porcentaje de carga
const float voltajeMinimo = 22.4; // Voltaje mínimo de la batería (en V)
const float voltajeMaximo = 29.4; // Voltaje máximo de la batería (en V)
// Rango aceptable de voltaje para la batería
const float rangoVoltajeMinimo = 20.0; // Voltaje inferior aceptable
const float rangoVoltajeMaximo = 30.0; // Voltaje superior aceptable
// Contador y flag para advertencias
int contadorAdvertencias = 0; // Contador de advertencias consecutivas
bool advertenciaActiva = false; // Bandera para indicar si hay una advertencia activa
// Variables para manejo no bloqueante (millis())
unsigned long tiempoAnteriorAdvertencia = 0; // Tiempo de la última advertencia
const unsigned long intervaloAdvertencia = 1000; // Intervalo entre advertencias (en ms)
unsigned long tiempoAnteriorLoop = 0; // Tiempo del último ciclo
const unsigned long intervaloLoop = 1000; // Intervalo del ciclo principal (en ms)
void setup() {
pinMode(pinPWM, OUTPUT); // Configurar el pin PWM como salida
pinMode(pinModo1, INPUT_PULLUP); // Configurar el pin para el modo 1 con resistencia pull-up
pinMode(pinModo2, INPUT_PULLUP); // Configurar el pin para el modo 2 con resistencia pull-up
Serial.begin(9600); // Inicializar comunicación serie
Serial.println("Inicializando programa...");
}
void configurarPWM(float voltajeObjetivo, float Vbateria) {
int pwmValor = 0;
if (Vbateria >= voltajeObjetivo) {
if (Vbateria != 0) {
pwmValor = int((voltajeObjetivo / Vbateria) * 255.0);
} else {
Serial.println("Error: División por cero detectada en cálculo de PWM.");
pwmValor = 0;
}
} else {
pwmValor = 255; // Máximo duty cycle si el voltaje es menor o igual al objetivo
}
// Asegurarse de que pwmValor esté dentro del rango permitido
pwmValor = constrain(pwmValor, 0, 255);
analogWrite(pinPWM, pwmValor);
// Monitorizar los valores de salida
Serial.print("Voltaje objetivo: ");
Serial.println(voltajeObjetivo);
Serial.print("PWM Valor aplicado: ");
Serial.println(pwmValor);
}
void loop() {
unsigned long tiempoActual = millis(); // Obtener el tiempo actual
// Controlar la frecuencia del ciclo principal usando millis()
if (tiempoActual - tiempoAnteriorLoop >= intervaloLoop) {
tiempoAnteriorLoop = tiempoActual; // Actualizar el tiempo del último ciclo
// Leer voltaje de la batería
int lecturaADC = analogRead(pinAnalogico); // Leer el valor del ADC (0 a 1023)
Serial.print("Lectura ADC: ");
Serial.println(lecturaADC);
// Convertir el valor ADC a voltaje medido
float Vmedido = (lecturaADC * Vref) / resolucionADC;
Serial.print("Voltaje medido: ");
Serial.println(Vmedido);
// Calcular el voltaje real de la batería usando el divisor de tensión y calibración
float Vbateria = Vmedido * (R1 + R2) / R2 * factorCalibracion;
Serial.print("Voltaje real de la batería: ");
Serial.println(Vbateria);
// Verificar si el voltaje está dentro de un rango aceptable
if (Vbateria < rangoVoltajeMinimo || Vbateria > rangoVoltajeMaximo) {
// Solo imprimir advertencias en intervalos definidos
if ((!advertenciaActiva || contadorAdvertencias < 3) && (tiempoActual - tiempoAnteriorAdvertencia >= intervaloAdvertencia)) {
Serial.println("Advertencia: Voltaje fuera de rango aceptable (20-30 V). Verifique la conexión.");
contadorAdvertencias++;
advertenciaActiva = true;
tiempoAnteriorAdvertencia = tiempoActual; // Actualizar el tiempo de la última advertencia
}
Serial.println("Saliendo del loop debido a voltaje fuera de rango.");
analogWrite(pinPWM, 0); // Asegurar que el PWM esté apagado
return; // Finalizar el loop si el voltaje está fuera de rango
} else {
// Resetear el estado de advertencia si el voltaje está dentro del rango
advertenciaActiva = false;
contadorAdvertencias = 0;
}
// Determinar el modo según las entradas digitales
if (digitalRead(pinModo1) == LOW && digitalRead(pinModo2) == HIGH) {
configurarPWM(vModo1, Vbateria); // Configurar PWM para 16V si el modo 1 está activo
} else if (digitalRead(pinModo1) == HIGH && digitalRead(pinModo2) == LOW) {
configurarPWM(vModo2, Vbateria); // Configurar PWM para 24V si el modo 2 está activo
} else if (digitalRead(pinModo1) == LOW && digitalRead(pinModo2) == LOW) {
configurarPWM(vModo2, Vbateria); // Configurar PWM para 24V si el modo 1y2 está activo
} else {
analogWrite(pinPWM, 0); // Apagar el motor si no hay modos activos
Serial.println("Motor apagado.");
}
}
}