/* COMMANDS SUPPORTED BY THE SERIAL MONITOR:
1. horario, Horario, h.
2. Antihorario, Antihorario, antihorario, a.
3. Stop, stop, s.
4. Any float type value.
*/
String comando = ""; // Variable para almacenar el comando
bool start=0; //Variable indicadora de incio de giro
//Orden de los pine: Punte H1(11 y 10), puente H2(9 y 8). Nota: la direccion de giro del puente h1 en su pin 11 debe coinsidir con la del puente H2 en su pin 9
// Por ejemplo, si el pin 11 hace que el motor gire a la izquierda, el pin 9 tambien debe hacer que el motor gire a la izquierda
int coil[4] = {11,10,9,8}; //Definir pines utilizados en el arduino para controlar el motor
int timer=10; //Definir tiempo de delay para la activacion de las bobinas (ms)
//Definir matriz de posiciones para el giro en sentido horario
int states[8][4] = {{1,0,0,0},
{1,0,1,0},
{0,0,1,0},
{0,1,1,0},
{0,1,0,0},
{0,1,0,1},
{0,0,0,1},
{1,0,0,1}};
int state=0; //Variable contadora para seleccionar la fila de posiciones de la matriz de estados
long int turn_counter = 0; //Variable cantidad de iteraciones introducida por el usuario
long int turns = 0; //Variable contadora de cantidad de iteraciones
bool turn_direction = 0; //Variable indicadora de seleccion de direccion de giro
int rotation=0; //Selector de direccion de rotacion
void setup() {
Serial.begin(9600); //iniciar el monitor serial a 9600 bps
//Definir los pines del arduino como salidas
for (int i=0; i<4;i++){
pinMode(coil[i],OUTPUT);
digitalWrite(coil[i],LOW);
Serial.print("Coil: ");
Serial.print(coil[i]);
Serial.println(" activated as output");
delay(125);
}
Serial.println();
Serial.println("Select rotation direction: *Horario* *Antihorario* \n");
pinMode(13,OUTPUT);
digitalWrite(13,LOW);
}
void loop() {
//Leer comandos del monitor serial
recepcionComandos();
//Rotar el stepper la cantidad de vueltas deseada
if(start==1 && turns<=turn_counter){
digitalWrite(coil[0],states[state][0]); //Escribir en el primer estado del puente H1
digitalWrite(coil[1],states[state][1]); //Escribir en el segundo estado del puente H1
digitalWrite(coil[2],states[state][2]); //Escribir en el primer estado del puente H2
digitalWrite(coil[3],states[state][3]); // Escribir en el segundo estado del puente H2
delay(timer); //Aplicar tiempo de retardo en el cambio de activacion de bobina
if(rotation==1){ //Rotacion horaria
state+=1; //Aumentar la variable contadora que varia la fila de la matriz "states"
if(state>=8){state=0;} //Reiniciar la variable contadora de la matriz
}
else if(rotation==2){ //Rotacion antihoraria
state-=1; //Reducir la variable contadora que varia la fila de la matriz "states"
if(state<0){state=7;} //Reiniciar la variable contadora de la matriz
}
turns+=1; //Aumentar la variable contadora de la cantidad de vueltas que ha dado el stepper
}
else if(turns>turn_counter && start==1){
Serial.println("Done. \n");
start=0; //Indicar al sistema que se ha finalizado la rotacion
turn_direction=0; //Reiniciar la variable que indica la seleccion de la direccion de giro
rotation=0; //Reiniciar variable que selecciona la direccion de giro
Serial.println("Select rotation direction: *Horario* *Antihorario*");
Serial.print("\n");
}
}
//Funcion para leer comandos del monitor serial
void recepcionComandos() {
if (Serial.available() > 0) {
char caracter = Serial.read();
// Verifica si se ha recibido un carácter de nueva línea ('\n')
if (caracter == '\n') {
// Procesa el comando
procesarComando(comando);
// Limpia la variable del comando para el siguiente
comando = "";
} else {
// Concatena el carácter al comando
comando += caracter;
}
}
}
//Funcion para actuar segun el comando recibido
void procesarComando(String cmd) {
//Condicional para la ejecucion en sentido horario o antihorario
if((cmd=="Horario" || cmd=="horario" || cmd=="h"||cmd=="H")&& start==0){
rotation=1; //Caso horario para el Switch-Case
Serial.println("Turn direction: Clockwise. \n"); //Imprimir en pantalla la direccion de giro seleccionada
}
else if((cmd=="Antihorario" || cmd=="AntiHorario" || cmd=="antihorario" || cmd=="a" || cmd=="A") && start==0){
rotation=2; //Caso antihorario para el Switch-Case
Serial.println("Turn direction: Counterclockwise. \n"); //Imprimir en pantalla la direccion de giro seleccionada
}
else{
if(start==1){
Serial.println("Error. Must send *Stop* command before change rotation direction. \n");
}
}
switch (rotation) {
case 1:
if(start==0){
turn_direction=1; //Activar la bandera de seleccion de giro
Serial.println("Specify number of turns: ");
Serial.print("\n");
} else{
Serial.println("Error. Must send *Stop* command before change rotation direction.");
Serial.print("\n");
}
break;
case 2:
if(start==0){
turn_direction=1; //Activar la bandera de seleccion de giro
Serial.println("Specify number of turns: ");
Serial.print("\n");
} else{
Serial.println("Error. Must send *Stop* command before change rotation direction.");
Serial.print("\n");
}
break;
}
//Detener el motor
if(cmd=="stop" || cmd=="Stop" || cmd=="STOP" || cmd=="s" || cmd=="S"){
for(int i=0; i<=3; i++){//Desactivar todas las salidas
digitalWrite(coil[i],0);
}
start=0; //indicar al programa que se ha detenido el motor
turns = 0; //Reiniciar la variable contadora de vueltas
turn_direction=0; //Reiniciar la bandera de seleccion de giro
rotation=0; //Reiniciar variable que selecciona la direccion de giro
Serial.println("Stopping...");
Serial.print("\n");
Serial.println("Select rotation direction: *Horario* *Antihorario*");
Serial.print("\n");
}
//Detectar la entrada de caracteres numerico en el monitor serial
if(cmd[0]>='0' && cmd[0]<='9'){
float Input_vueltas = cmd.toFloat(); //Convertir comando de String a Float
float received = Input_vueltas/0.05; //Determinar si el valor numerico esta dentro del nivel de precision
String string_value = String(received); //Convertir el resultado de la operacion a String
if(start==0 && string_value.indexOf(".00") != -1 && turn_direction==1){//Determinar si el valor es divisible entre 0.05
turn_counter = (Input_vueltas*360)/0.9; //Calcular el numero de iteraciones necesarias para alcanzar la cantidad de vueltas especificada
Serial.println("Starting... \n");
start = 1;
turns = 0;
}
else if(string_value.indexOf(".00") == -1 && turn_direction==1){
Serial.println("Error. Stepper motor isn't capable of rotating the specified number of turns."); //Mostrar mensaje de error si el stepper no puede realizar la cantidad de vueltas introducida
Serial.println("Use presicion level of 0.05 \n");
}
else if(start==1){
Serial.println("Error. Must send *Stop* command before change turns quantity.");
Serial.print("\n");
}
else if(turn_direction==0){
Serial.println("Error. Must select turn direction before change turns quantity.");
Serial.print("\n");
Serial.println("Select rotation direction: *Horario* *Antihorario*");
Serial.print("\n");
}
}
}