// https://wokwi.com/projects/382230750316407809
// nota: el motor paso a paso del simulador es bipolar!!
const int motor_A = 23;
const int motor_B = 22;
const int motor_C = 19;
const int motor_D = 18;
// Pines para el interruptor, potenciómetro, pulsador y relé
const int interruptorPin = 2; // Ejemplo de pin para el interruptor
const int potenciometroPin = 15; // Ejemplo de pin para el potenciómetro
const int pulsadorPin = 12; // Ejemplo de pin para el pulsador
const int relePin = 4; // Ejemplo de pin para el relé
// Pines para los LEDs de dirección
const int ledHorarioPin = 5; // Ejemplo de pin para el LED de sentido horario
const int ledAntihorarioPin = 6; // Ejemplo de pin para el LED de sentido antihorario
// Variables para el control de dirección y velocidad
int direccion = 1; // 1 para horario, -1 para antihorario
int velocidad = 0; // Velocidad inicial
#define NUMSEC 4 // 4 u 8 # lineas de secuencia de movimiento
int tabla_pasos[NUMSEC][4]={ // A B C D
// {HIGH,LOW, LOW, LOW},
{HIGH,HIGH, LOW, LOW},
// {LOW, HIGH, LOW, LOW},
{LOW, HIGH, HIGH,LOW},
// {LOW, LOW, HIGH,LOW},
{LOW, LOW, HIGH,HIGH},
// {LOW, LOW, LOW, HIGH},
{HIGH,LOW, LOW, HIGH}
};
#define NPASOS_VUELTA_INTERNA 32 // 32 paso completo, 64 semipaso
#define RELACION_VUELTAS_ENGRANAJE 64 // VUELTAS INTERNAS PARA HACER 1 VUELTA EXTERNA
int npasos=0; // llega a NPASOS_VUELTA_INTERNA y cuenta vuelta interna ++
int nvueltas_internas=0; // llega a RELACION_VUELTAS_ENGRANAJE y cuenta vuelta externa ++
int nvueltas_externas=0; // lleva la cuenta de vueltas del eje externo
// funcion que proporciona el movimiento del siguiente paso
void sgte_paso(){
static int idsec=0; // va recorriendo la siguiente tabla
// escribimos los valores nuevos de la tabla en los pines ABCD
digitalWrite(motor_A, tabla_pasos[idsec][0]);
digitalWrite(motor_B, tabla_pasos[idsec][1]);
digitalWrite(motor_C, tabla_pasos[idsec][2]);
digitalWrite(motor_D, tabla_pasos[idsec][3]);
if( (++idsec)==NUMSEC) idsec=0;
return;
}
void setup()
{
// pines de salida del motor
pinMode(motor_A, OUTPUT);
pinMode(motor_B, OUTPUT);
pinMode(motor_C, OUTPUT);
pinMode(motor_D, OUTPUT);
// Pines de entrada para interruptor, potenciómetro y pulsador
pinMode(interruptorPin, INPUT);
pinMode(potenciometroPin, INPUT);
pinMode(pulsadorPin, INPUT);
// Pines de salida para LEDs y relé
pinMode(ledHorarioPin, OUTPUT);
pinMode(ledAntihorarioPin, OUTPUT);
pinMode(relePin, OUTPUT);
// Apagar el relé al inicio
digitalWrite(relePin, HIGH);
// initialize the serial port
Serial.begin(115200);
delay(100);
Serial.println("----------------");
Serial.println("Comienzo programa control motor paso a paso");
Serial.printf("Pasos de secuencia de movimiento -> %d\n", NUMSEC);
Serial.printf("Npasos 32 paso completo, 64 semipasode -> %d\n", NPASOS_VUELTA_INTERNA);
Serial.printf("Relacion engranaje - %d vueltas internas para dar 1 vuelta externa \n \n", RELACION_VUELTAS_ENGRANAJE);
delay(1000); // antes de comenzar el bucle del programa
}
unsigned long t1=0;
void loop()
{
delay(10); // retardo en dar el siguiente paso -> no bajar de 2 ms (da una vuelta en T * 32 pasos * 64 engranaje)
npasos++; //si llega a NPASOS_VUELTA_INTERNA -> cuenta nvueltas interna ++
if(npasos == NPASOS_VUELTA_INTERNA){
npasos=0;
nvueltas_internas++;
if(nvueltas_internas==RELACION_VUELTAS_ENGRANAJE){ // llega a RELACION_VUELTAS_ENGRANAJE y cuenta vuelta externa ++
nvueltas_internas=0;
nvueltas_externas++; // lleva la cuenta de vueltas del eje externo
}
}
sgte_paso(); // mueve el motor
// Leer el estado del pulsador
int pulsadorEstado = digitalRead(pulsadorPin);
// Si el pulsador no está presionado, no actualizar la dirección y velocidad
if (pulsadorEstado == LOW) {
// Leer el estado del interruptor
int interruptorEstado = digitalRead(interruptorPin);
// Cambiar la dirección si se presiona el interruptor
if (interruptorEstado == HIGH) {
direccion = -1; // Cambiar a sentido antihorario
} else {
direccion = 1; // Cambiar a sentido horario
}
// Leer el valor del potenciómetro para ajustar la velocidad
int valorPotenciometro = analogRead(potenciometroPin) * (3300.0 / 4095.0);//Convertimos la lectura del ADC a mV
if (valorPotenciometro < 1100) { // Rango para velocidad baja
velocidad = map(valorPotenciometro, 0, 1099, 0, 33);
} else if (valorPotenciometro < 2200) { // Rango para velocidad media
velocidad = map(valorPotenciometro, 1100, 2199, 34, 66);
} else { // Rango para velocidad alta
velocidad = map(valorPotenciometro, 2200, 3300, 67, 100);
}
}
// Actualizar LEDs de dirección
digitalWrite(ledHorarioPin, (direccion == 1) ? HIGH : LOW);
digitalWrite(ledAntihorarioPin, (direccion == -1) ? HIGH : LOW);
// Verificar el estado del botón de emergencia
if (digitalRead(pulsadorPin) == HIGH) {
// Detener el motor y apagar el relé
digitalWrite(relePin, LOW);
// Parpadear LEDs durante la emergencia
digitalWrite(ledHorarioPin, HIGH);
digitalWrite(ledAntihorarioPin, HIGH);
delay(500);
digitalWrite(ledHorarioPin, LOW);
digitalWrite(ledAntihorarioPin, LOW);
delay(500);
} else {
// Encender el relé
digitalWrite(relePin, HIGH);
}
// Informar posición cada 2 segundos
if (millis() > t1 + 2000) {
t1 = millis();
Serial.printf("Vueltas externas %d internas %d npasos: %d \n",
nvueltas_internas, nvueltas_externas, npasos);
}
}