// 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;
const int puls_sentido = 15;
const int seta_emergencia=33;
const int LED_horario = 35;
const int LED_antihorario = 34;
const int potenciometro = 26;
const int cable_sent = 32;
int estado_emergencia = 0;
int t_delay = 0;
volatile int sentido = 0;
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
int frecuencia_led=500;
unsigned long tic, tac;
void espera_millis(unsigned long tiempo_espera){
tic=millis();
do{
tac=millis();
}
while(tac-tic<tiempo_espera);
return;
}
hw_timer_t * timer1 = NULL;
void IRAM_ATTR ISR_puls(){ //Interrupción que cuenta los flancos de bajada de la señal (FALLING)
sentido=digitalRead(cable_sent);
float valor = analogRead(potenciometro); //capturamos valor adc delpoteciometro
float valorMapeado = map(valor, 0, 4095, 20, 3); //lo mapeamos para que el valor minimo sea 3 y el maximo 20
t_delay = valorMapeado*1000;
/*
if(sentido=0){
Serial.printf("Sentido: Horario Periodo: %f ms", valorMapeado);
} else {
Serial.printf("Sentido: Antihorario Periodo: %f ms", valorMapeado);
}
*/
// timerAlarmWrite(timer1, t_delay, true);
}
void IRAM_ATTR ISR_seta(){
estado_emergencia=1;
timerAlarmDisable(timer1);
}
hw_timer_t * timer2 = NULL;
void IRAM_ATTR imprtimer() {
//Serial.printf("Vueltas externas %d internas %d npasos: %d \n", nvueltas_internas, nvueltas_externas, npasos);
}
void IRAM_ATTR fintimer() { //interrupcion para controlar el sentido de giro
if (sentido==0){
sgte_paso_horario();
digitalWrite(LED_horario, HIGH);
digitalWrite(LED_antihorario, LOW);
} else {
sgte_paso_antihorario();
digitalWrite(LED_horario, LOW);
digitalWrite(LED_antihorario, HIGH);;
}
}
#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}
};
void sgte_paso_horario(){
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]);
//delay(t_delay);
//if( (++idsec)==NUMSEC) idsec=0;
return;
}
void sgte_paso_antihorario(){
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][3]);
digitalWrite(motor_B, tabla_pasos[idsec][2]);
digitalWrite(motor_C, tabla_pasos[idsec][1]);
digitalWrite(motor_D, tabla_pasos[idsec][0]);
//delay(t_delay);
//if( (++idsec)==NUMSEC) idsec=0;
return;
}
#define NPASOS_VUELTA_INTERNA 32 // 32 paso completo, 64 semipaso
#define RELACION_VUELTAS_ENGRANAJE 64 // VUELTAS INTERNAS PARA HACER 1 VUELTA EXTERNA
void setup()
{
// pines de salida del motor
pinMode(motor_A, OUTPUT);
pinMode(motor_B, OUTPUT);
pinMode(motor_C, OUTPUT);
pinMode(motor_D, OUTPUT);
attachInterrupt(digitalPinToInterrupt(puls_sentido), ISR_puls, FALLING);
attachInterrupt(digitalPinToInterrupt(seta_emergencia), ISR_seta, FALLING);
t_delay = 10;
/*
timer1 = timerBegin(0, 80, true); //timer que configura la velocidad del motor
timerAttachInterrupt(timer1, fintimer, true);
timerAlarmWrite(timer1, t_delay*1000, true);
timerAlarmEnable(timer1);
*/
/* timer2 = timerBegin(1, 80, true); //timer que imprime cada 2s el estado del motor
timerAttachInterrupt(timer2, imprtimer, true);
timerAlarmWrite(timer2, 500000, true);
timerAlarmEnable(timer2);
*/
// 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;
unsigned long t_emerg=0;
void loop(){
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
}
}
if(estado_emergencia==1){
if(millis()>t_emerg+3000){
estado_emergencia=0;
t_emerg=millis();
}
}
while(estado_emergencia=1){
digitalWrite(LED_horario, HIGH);
digitalWrite(LED_antihorario, HIGH);
espera_millis(frecuencia_led);
digitalWrite(LED_horario, LOW);
digitalWrite(LED_antihorario, LOW);
espera_millis(frecuencia_led);
}
// cada segundo imprime mensaje de información
//if(millis()>t1+2000){ // 1*32 en paso completo para una vuelta, 2*32=64 si se va de medio paso
// t1=millis();
// Serial.printf("Vueltas externas %d internas %d npasos: %d \n", nvueltas_internas, nvueltas_externas, npasos);
//}
}