#include <Wire.h>
#include <LiquidCrystal_I2C.h> // Librería para manejar el LCD (I2C)
#include <Keypad.h> // Librería para manejar el teclado matricial
// Configuración del LCD (I2C)
LiquidCrystal_I2C lcd(0x27, 20, 4); // Dirección I2C, columnas, filas
// Configuración del teclado matricial
const byte ROWS = 4; // Cuatro filas
const byte COLS = 4; // Cuatro columnas
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {15, 2, 4, 16}; // Pines de las filas
byte colPins[COLS] = {17, 5, 18, 19}; // Pines de las columnas
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// Pines para el motor y puente H
const int pinIN1 = 23; // Sentido de giro 1
const int pinIN2 = 13; // Sentido de giro 2
const int freq = 5000; // Frecuencia del PWM
const int resolution = 8; // Resolución del PWM (8 bits)
// Pines para el encoder, potenciómetro y pulsadores
const int encoderPinA = 34; // Pin A del encoder
const int encoderPinB = 35; // Pin B del encoder
const int potPin = 32; // Pin del potenciómetro
const int startButton = 14; // Pin del botón de inicio
const int stopButton = 27; // Pin del botón de parada
// Variables globales
volatile int pulseCount = 0; // Cuenta los pulsos del encoder
int targetRPM = 0; // RPM objetivo
bool motorRunning = false; // Estado del motor
unsigned long previousMillis = 0; // Tiempo previo para cálculo de RPM
void IRAM_ATTR encoderISR() {
pulseCount++; // Incrementa la cuenta de pulsos cada vez que el pin genera una interrupción
}
void setup() {
Serial.begin(115200);
lcd.init(); // Inicializa el LCD con 20 columnas y 4 filas
lcd.backlight();
delay(1000);
// Inicializa los pines del motor
pinMode(pinIN1, OUTPUT);
pinMode(pinIN2, OUTPUT);
// Inicializa los pines del encoder
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
// Asocia interrupciones al pin del encoder
attachInterrupt(digitalPinToInterrupt(encoderPinA), encoderISR, RISING);
// Configura los botones
pinMode(startButton, INPUT_PULLUP);
pinMode(stopButton, INPUT_PULLUP);
showMenu();
}
void loop() {
char key = keypad.getKey();
if (key) {
switch (key) {
case '5': // Ajustar RPM
adjustRPM();
break;
case '6': // Sentido de giro
adjustDirection();
break;
case '7': // Modo Manual
manualControl();
break;
}
}
if (digitalRead(startButton) == LOW) {
startMotor();
}
if (digitalRead(stopButton) == LOW) {
stopMotor();
}
if (motorRunning) {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= 1000) { // Actualiza cada segundo
int rpm = calculateRPM();
lcd.setCursor(0, 2); // Imprime en la segunda línea del LCD
lcd.print("RPM: ");
lcd.print(rpm);
previousMillis = currentMillis;
pulseCount = 0; // Reinicia el contador de pulsos
}
}
}
int calculateRPM() {
int pulsesPerRevolution = 20; // Ajusta según las especificaciones del encoder
int rpm = (pulseCount / pulsesPerRevolution) * 60; // Calcula las RPM
return rpm;
}
void showMenu() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("5. Ajustar RPM");
lcd.setCursor(0, 1);
lcd.print("6. Sentido giro");
lcd.setCursor(0, 2);
lcd.print("7. Modo Manual");
}
void manualControl() {
lcd.clear();
lcd.print("Modo Manual");
lcd.setCursor(0, 1);
lcd.print("Gire pot. para");
lcd.setCursor(0, 2);
lcd.print("control de velocidad");
while (true) {
int potValue = analogRead(potPin); // Lee el valor del potenciómetro
int pwmValue = map(potValue, 0, 4095, 0, 255); // Mapea el valor a rango de PWM
setMotorSpeed(pwmValue); // Ajusta la velocidad del motor
if (digitalRead(startButton) == LOW) {
break; // Sale del modo manual si se presiona el botón de inicio
}
}
}
void adjustRPM() {
lcd.clear();
lcd.print("Ingrese RPM:");
String rpmInput = "";
while (true) {
char key = keypad.getKey();
if (key) {
if (key == '#') { // Confirmar entrada
targetRPM = rpmInput.toInt();
lcd.clear();
lcd.print("RPM set to: ");
lcd.print(targetRPM);
delay(1000);
showMenu();
break;
} else if (key == '*') { // Borrar
rpmInput = "";
lcd.setCursor(0, 1);
lcd.print(" "); // Borra la línea
} else { // Añadir el dígito al string
rpmInput += key;
lcd.setCursor(0, 1);
lcd.print(rpmInput);
}
}
}
}
void adjustDirection() {
lcd.clear();
lcd.print("5. Adelante");
lcd.setCursor(0, 1);
lcd.print("6. Atras");
while (true) {
char key = keypad.getKey();
if (key) {
if (key == '5') {
setMotorDirection(true); // Adelante
lcd.clear();
lcd.print("Direccion: Adelante");
delay(1000);
showMenu();
break;
} else if (key == '6') {
setMotorDirection(false); // Atrás
lcd.clear();
lcd.print("Direccion: Atras");
delay(1000);
showMenu();
break;
}
}
}
}
void setMotorSpeed(int speed) {
// Usa la nueva función ledcWrite con el pin y el ciclo de trabajo (duty cycle)
bool success = ledcWrite(pinIN1, speed);
if (!success) {
Serial.println("Error al escribir el ciclo de trabajo PWM.");
}
}
void setMotorDirection(bool forward) {
if (forward) {
digitalWrite(pinIN1, HIGH);
digitalWrite(pinIN2, LOW);
} else {
digitalWrite(pinIN1, LOW);
digitalWrite(pinIN2, HIGH);
}
}
void startMotor() {
motorRunning = true;
setMotorSpeed(128); // Velocidad media como ejemplo
lcd.clear();
lcd.print("Motor en marcha");
}
void stopMotor() {
motorRunning = false;
setMotorSpeed(0); // Detener motor
lcd.clear();
lcd.print("Motor detenido");
}