Hola buenas tardes, soy Xavi y este es mi primer mensaje, me he iniciado hace muy poco con arduino, es muy apasionante pero difícil cuando no he programado nunca, trabajo en mantenimiento eléctrico por lo que la lógica de conexión ya la tengo superada.
En un futuro, espero no muy lejano, quiero fabricarme un carril para microfotografía controlado por bluetooth a través de la app RemoteXY.
Ahora estoy encallado con pequeñas funciones que voy probando con la ayuda de videotutoriales. Puedo hacer que el motor avance unos pasos adelante, pare, invierta el sentido y se mueva con exactamente los mismos pasos, y así consecutivamente de forma automática. La intención es mover el motor con dos pulsadores (izquierda y derecha), mientras pulso el botón el motor debe funcionar, y no es así, me podéis ayudar? disculpar por el rollo y sobre todo por mi ignorancia.
Os muestro el programa, saludos!
#define STEP 4
#define DIR 5
evoid setup () {
pinMode(STEP, OUTPUT);
pinMode(DIR, OUTPUT);
pinMode(2, INPUT);
pinMode(3, INPUT);
}
void loop() {
if (digitalRead(2) == HIGH);{
digitalWrite(DIR, HIGH);
for(int i = 0; i < 2000; i++)
digitalWrite(STEP, HIGH);
delay(1);
digitalWrite(STEP, LOW);
delay(1);
}
if (digitalRead(3) == HIGH);{
digitalWrite(DIR, LOW);
for(int i = 0; i < 2000; i++)
digitalWrite(STEP, HIGH);
delay(1);
digitalWrite(STEP, LOW);
delay(1);
}
}
quita ese ; y lo demas funcionará.
Hay mas observaciones.
Lo primero que debes entender es que tu código se pone a mover el motor en una dirección y no presta atención a nada mas x 4 segundos porque mira
En cada for() tienes un loop de 2000 y dos delay(1) de 1 mseg , o sea 2 mseg x 2000 = 4000 mseg = 2 segundos.
Presionas ejectura y no responde por 4 segundos.
Si de casualidad presionas, espera a que termine un ciclo y reacciona, se queda bloqueado por 4 segundos y de nuevo.
Que opciones hay?
Primero existen librerías que hacen mejor las cosas de lo que uno puede hacer.
Asi que esa es la primer salida elegante.
La otra opcion es que haga lo mismo pero que devuelva el control antes y cumpla lo que quieres de otro modo.
Si te quedas con lo básico que es
Demoras 2 mseg y no 4 segundos porque lo he quitado.
#define STEP 4
#define DIR 5
void motor(bool dirValor, int tmp) {
static int contador = 0;
if (contador == 0)
digitalWrite(DIR, dirValor);
digitalWrite(STEP, HIGH);
delay(1);
digitalWrite(STEP, LOW);
delay(1);
if (contador++ > tmp)
contador = 0;
}
void setup () {
pinMode(STEP, OUTPUT);
pinMode(DIR, OUTPUT);
pinMode(2, INPUT);
pinMode(3, INPUT);
}
void loop() {
if (digitalRead(2) == HIGH){
motor(HIGH, 2000);
}
if (digitalRead(3) == HIGH){
motor(LOW, 2000);
}
}
Bueno he creado una simple rutina que tiene dos parámetros, direccion y cantidad de pasos.
La rutina preguna si estamos en le paso 0 y entonces le da la dirección que corresponde, de ese modo lo hago solo 1 vez.
Luego ejecuta lo que tu ya tenias consumiendo solo 2 mseg mas extras por cada instrucción.
Al final pregunto si la variable contador llego a la cantidad de pasos que tu quieres y si es asi la pone a 0, hasta ahi es igual a tu caso salvo que no bloquea mas que 2 mseg.
Lo único raro en todo esto es el uso de
static int contador = 0;
Agregar static a una variable hace que la variable permanezca con el último valor que se le asignó hasta que se vuelva a ingresar a la misma rutina.
De ese modo no empieza en 0 cada vez que la rutina es llamada como ocurriría si no le pones static.
Mil grandísimas gracias, sinceramente, me cuesta entenderlo pero no lo dejare hasta entender el ultimo detalle, static no la conocía, así que ahora toca probar y estudiar.
El cambio mas importante esta en no bloquear el funcionamiento. Para hacerlo no hago un loop tal que deba esperar a que termine.
Entonces el enfoque es que si yo presiono la tecla por ejemplo en el botón del pin 2 y esta en LOW me encuentro con
motor(HIGH, 2000);
Okay hasta ahi. Ahora tal como te dije, esta rutina sigue haciendo lo que hacía la tuya solo que ejecuta y libera.
Mira el código de motor()
Esto es lo mismo que tenias antes. Ejecuto eso para un paso del motor.
Pero cómo hago para que se cumpla todo lo demás? Como le doy el sentido de giro.
Bueno lo primero es que le puedo pasar un parámetro
void motor(bool dirValor, int tmp)
Como verás ahi dice bool o sea una variable del tipo HIGH o LOW nada mas.
Y solo cuando contador este en 0 le daré la direccion que necesita el controlador de motor para decidir la dirección.
El otro elemento que tu usabas en el for() era que repetías 2000 ciclos en este caso.
Bueno el siguiente parametro que llamo con la variable entera tmp es con la que le paso cuantos ciclos hacer.
Eso se ejecuta una vez nada mas, pero en cada paso que la rutina motor se ejecute la variable estática contador (que conserva el valor cada vez que la rutina es llamada) determinará cuando terminamos.
contador++ es lo mismo que poner
contador = contador +1;
y la condición
if (contador++ > tmp)
contador = 0;
sirve para que cuando contador supere los 2000 y acabo de ver un pequeño error
Debería ser
if (contador++ >= tmp)
contador = 0;
se pone a 0 para prepararse para el proximo evento.
Claro que si el boton sigue pulsado volverá a funcionar la rutina y de nuevo si eso paso aparece un nuevo error y es que puedes presionar el otro pulsador y tener ciclos ejecutados del primero y no dará los pasos que esperas.
Buenos días, bien, me cuesta entenderlo, existen muchos conceptos que no conozco, te explico, en un primer intento, el motor solo avanzaba en una dirección, indistintamente de que pulsador presionara, he cambiado el valor 2000 por un 20, no se muy bien que valor he cambiado pero ahora funciona perfectamente, también he añadido una salida para habilitar o deshabilitar el motor, ya que siempre estaba energizado, después de entender todo esto, intentare simplificarlo y trabajar con librerías, otro desafío para mi... de nuevo, gracias.
Te muestro el programa:
#define STEP 4
#define DIR 5
#define ENABLE 6
void motor(bool dirValor, int tmp) {
static int contador = 0;
if (contador == 0)
digitalWrite(DIR, dirValor);
digitalWrite(STEP, HIGH);
delay(1);
digitalWrite(STEP, LOW);
delay(1);
if (contador++ >= tmp)
contador = 0;
}
void setup () {
pinMode(STEP, OUTPUT);
pinMode(DIR, OUTPUT);
pinMode(2, INPUT);
pinMode(3, INPUT);
pinMode(6,OUTPUT);
}
void loop() {
digitalWrite(ENABLE, HIGH);
if (digitalRead(2) == HIGH){
digitalWrite(6, LOW);
motor(HIGH, 20);
}
if (digitalRead(3) == HIGH){
digitalWrite(6, LOW);
motor(LOW, 20);
}
}escribe o pega el código aquí
Hola Surbyte y nuevamente gracias, veo que aportas mucho al foro y eso es de agradecer. Quiero comentarte que tanto de una forma como de otra funciona exactamente igual, solo que con el valor motor(HIGH, 2000) o motor(LOW, 2000) no alterna bien el sentido, solo se dirige hacia un sentido tanto si presiono un botón como el otro, cambiándolo 2000 por 20, funciona perfectamente. Ahora solo queda continuar con el proyecto... una montaña para mi, pero con insistencia espero resolverlo.
Gracias, saludos y muy buen recibimiento del año nuevo!