Go Down

Topic: [SOLUCIONADO] millis() para varios motores servo y stepper (Read 1 time) previous topic - next topic

IgnoranteAbsoluto

Me alegra, Armando, tu "ascenso de división". La programación orientada a objeto tiene más cosas de las que he empleado en el programa, cosas como la herencia, pero sólo con el encapsulamiento y el empleo de los constructores ya son herramientas muy valiosas para la programación.

Para que funcione con un solo botón basta con poner el mismo número del pin para pinRecta y pinDesvio.

Otra forma es cambiar los inicializadores pinRecta y pinDesvio en constructor de la clase Aguja. Para que si se le pasa un -1 en uno de los pines, tome como valor el del otro pin. Es lo mismo, pero "más elegante". Para ello el cambio que hay que hacer es que en:

Code: [Select]
// Implementación de las funciones de la clase Aguja
Aguja::Aguja(Servo &servo, unsigned long duracionCambio, uint8_t pinRecta, uint8_t pinDesvio, uint8_t pinLuzVerde, uint8_t pinLuzAzul)
    : servo(servo),
    duracionCambio(duracionCambio),
    pinRecta(pinRecta),
    pinDesvio(pinDesvio),


Cambiamos las dos últimas líneas para que queden así:

Code: [Select]
// Implementación de las funciones de la clase Aguja
Aguja::Aguja(Servo &servo, unsigned long duracionCambio, uint8_t pinRecta, uint8_t pinDesvio, uint8_t pinLuzVerde, uint8_t pinLuzAzul)
    : servo(servo),
    duracionCambio(duracionCambio),
    pinRecta((pinRecta != 0xFF) ? pinRecta : pinDesvio),     // Si se pasa un -1 en pinRecta, tendrá como valor el mismo que pinDesvio
    pinDesvio((pinDesvio != 0xFF) ? pinDesvio : pinRecta),   // Si se pasa un -1 en pinDesvio, tendrá como valor el mismo que pinRecta


También se podría quitar el uso de uno de los dos pines en la clase, y así ahorrarnos un byte de memoria por cada servo. Pero el ahorro no es significativo y, además, siempre podemos cambiar de opinión a última hora y volver a usar dos pulsadores en lugar de uno, sin tener que volver a modificar la clase. O incluso tener unos con un pulsador y otros con dos.

Voy a ver si hago el montaje con un Arduino MEGA y pruebo a juntar todo el código. Con los cuatro servos y los dos motores paso a paso. Para que no tengas que estar modificando las constantes del código; no estaría de más, si lo tienes ya más o menos definido, que me dijeras los pines del Arduino MEGA a los que vas a conectar cada cosa.

Me he fijado en que parece que ajustas el inicio y fin de la posición del servo usando el segundo y tercer parámetro de servo.attach(). Creo que es mejor y más fácil no usar esos parámetros, sino configurar el ángulo de "recto" y "desvío" de cada servo. No tiene por qué se 0º y 45º, sino cualquier valor arbitrario entre 0 y 180 grados. Además, esto facilita el configurar desvíos en que "recto" ha de tener un ángulo mayor que "desvío". Es decir, en lugar de 0º ser vía recta y 45º ser desviada, podría ser 50º vía recta y 10º desviada.

Además de poner lo de la luz parpadeando mientras se realiza el cambio de aguja. Tal vez, añadiendo dos pulsadores más, se podría tener la posibilidad de memorizar en la EEPROM las dos posiciones de cada servo y configurarlos con el propio programa. Por ejemplo: el programa arranca y funciona normal. Si se mantienen pulsado esos dos botones a la vez durante tres segundos, pasa al modo "configuración". Todos las luces de los cambios de aguja parpadean. Si se pulsa el botón de uno de los cambios de agujas, la luz de la posición en que está parpadea más rápido y la otra se apaga. Ahora se puede ajustar la posición de la aguja grado a grado aumentando o disminuyendo un grado pulsando uno de los dos botones de configuración. Así no hay que estar modificando, recomplilando y cargando el código del Arduino para probar y ajustar los servos.

Cierto es que cada cambio/mejora lleva su tiempo y no se lo dedico muy a menudo. Pero, si no llevas prisa, creo que vale la pena.

apacher

Muchas gracias, analizaré lo que escribiste y definiré los pines del Mega.

Configuré con cero grados para que el servo quede quieto en el default de vía recta, independientemente de donde haya quedado cuando se apagó el Arduino, pensando que el movimiento de la vía es de pocos milímetros y que hay que evitar que el servo trate de ir más allá de los límites físicos que tiene el desvío. No alcanzo a entender lo que me propones, lo que hice fue determinar el cero (equivalente al "recto") de cada servo y que corresponda a la vía sin el desvío.

Un cordial saludo

Armando

IgnoranteAbsoluto

Me refiero a quitar los valores 750 y 1800 de estas líneas de código:

Code: [Select]
    servoUno.attach(PIN_SERVO_UNO, 750, 1800);    //Configura el Servo, 750 ms = 0° y 1800 ms = 180°
    servoDos.attach(PIN_SERVO_DOS, 750, 1800);    //Configura el Servo, 750 ms = 0° y 1800 ms = 180°


Y que no tiene por qué ser 0º y 45º los ángulos en que se ha de posicionar el servo para que queden bien posicionados. ¿Ya tienes los servos montados físicamente en los cambios de aguja?

La verdad es que tardo menos en hacer los cambios que en escribir las explicaciones en el post. Junto con lo de poder definir con -1 si se utiliza un único pulsador para el cambio de aguja (que lo he definido así para los dos servos), he realizado las modificaciones para que parpadee durante el cambio de aguja. El tiempo del parpadeo se define con la constante TIEMPO_PARPADEO. Para ver los cambios del parpadeo basta con buscar esa constante y las variables instanteParpadeo y estadoParpadeo.

Las pruebas del código las he hecho con el Arduino UNO.

El código es demasiado grande como para postearlo directamente (más por los comentarios que por el código en sí). Así que lo adjunto.

apacher

Aún no están instalados los servos en los desvíos, ¿necesitas que lo haga para determinar los grados entre uno y otro estado?

Estoy ahora distribuyendo las conexiones en el Arduino Mega, ¿puedo cambiar los diferentes pines o los traslado tal cual están?

Indicame por favor si las líneas 11 y 12 y 58 y 59 deben quedar como en este último código si dejamos un solo botón para cada servo (que me parece la mejor decisión).

Olvidé responderte este punto del mensaje anterior a éste: no hay prisa! Hagamos por favor todas las mejoras posibles.

Un cordial saludo.

Armando

apacher

#34
May 11, 2020, 08:25 pm Last Edit: May 11, 2020, 08:27 pm by apacher
Te envío una propuesta de distribución de pines en el Arduino Mega:

- pines 1 al 21:   Motores paso a paso - steppers, switches y LEDs respectivos

- pines 22 al 53: Servos, botones y LEDs respectivos

- una vez conectados, accesorios como speakers y otros a distribuir entre los pines libres.

Espero por favor tu confirmación o correcciones para realizar las reconexiones.

Un cordial saludo

Armando

IgnoranteAbsoluto

En principio he configurado los pines del Arduino MEGA para cuatro cambios de aguja con un solo pulsador y sus dos luces. Estos son los pines:

Code: [Select]
const uint8_t PIN_SERVO_UNO     = 5;
const uint8_t PIN_SERVO_DOS     = 6;
const uint8_t PIN_SERVO_TRES    = 7;
const uint8_t PIN_SERVO_CUATRO  = 8;

//Botones
const uint8_t PIN_DESVIO_UNO    = 22;   // Botón para desvío, mueve a izquierda
const uint8_t PIN_DESVIO_DOS    = 23;   // Botón para desvío, mueve a izquierda
const uint8_t PIN_DESVIO_TRES   = 24;   // Botón para desvío, mueve a izquierda
const uint8_t PIN_DESVIO_CUATRO = 25;   // Botón para desvío, mueve a izquierda

const uint8_t VALOR_BOTON_DETECTADO = LOW;  //Valor que deberá tener el pin cuando se detecta el botón

//LEDs
const uint8_t VERDE_RECTA_UNO       = 26;   // Led de vía recta
const uint8_t AZUL_DESVIO_UNO       = 27;   // LED de desvío
const uint8_t VERDE_RECTA_DOS       = 28;   // Led de vía recta
const uint8_t AZUL_DESVIO_DOS       = 29;   // LED de desvío
const uint8_t VERDE_RECTA_TRES      = 30;   // Led de vía recta
const uint8_t AZUL_DESVIO_TRES      = 31;   // LED de desvío
const uint8_t VERDE_RECTA_CUATRO    = 32;   // Led de vía recta
const uint8_t AZUL_DESVIO_CUATRO    = 33;   // LED de desvío



Faltaría definir los pines de los motores paso a paso, sus finales de carrera y sus luces.

Por ahora, para las pruebas, creo que es mejor que no ubiques aún los servos en los cambios de aguja. Así no "sufren" los servos durante las pruebas.

Otra cosa. Los servos, si se ven forzados, cuando tratan de mantener la posición hacen ruido y consumen corriente. Así que voy a hacer que el programa los "desactive" cuando no se han de mover. Pero aún no está implementado.

Adjunto código para el MEGA con los pines definidos y para ya "manejar" los cuatro servos.


apacher

Muchas gracias, bajé el código y pasaré los componentes de los servos al Mega.

¿Defino ahora los pines de los motores paso a paso, sus finales de carrera y sus luces y paso los componentes al Mega o espero tus indicaciones?

Un cordial saludo

Armando

apacher

#37
May 12, 2020, 01:52 pm Last Edit: May 12, 2020, 01:54 pm by apacher
Buenos días.

Pasé dos servos al A Mega 2650 con sus respectivos botones y luces y funcionan perfecto! Excelente el comportamiento de las luces, parpadeando mientras gira e indicando luego la "vía" habilitada.

Para poder practicar los grados del moviento de los servos estoy armando un pequeño "banquito de pruebas" con un sector de vía con desvío y un montaje para el servo.

Nuevamente muchas gracias!

Cordialmente.

Armando

apacher

Estuve regulando la extensión del movimiento con el servo montado en el "banquito de pruebas". La conclusión es que con "anguloDestino" fijado en 20 grados hace perfecto el cambio en estas vías de escala HO (1:87).

Comencé las pruebas sin fijar el servo en el montaje, con lo que se logró evitar que "sufra", como me indicaste.

Vamos muy bien!

Un cordial saludo.

Armando

IgnoranteAbsoluto

Memorizar la última posición de las agujas para recuperarla al encender el Arduino

Aprovechando que vamos a guardar los ángulos de los servos en la EEPROM, guardo en la EEPROM la posición de las agujas cada vez que cambia. De esta manera, cuando se enciende el Arduino, recupera la posición en que estaban las agujas cuando se apagó.

Los cambios son pocos. Añadido de la lectura y escritura de la EEPROM para recuperar las posiciones que teńian las agujas cuando se apagó o reseteó el Arduino. Se le ha añadido la función setup() a la clase Aguja para indicarle en tiempo de ejecución dónde se ha de guardar sus datos en la EEPROM. En lugar de tener cuatro objetos Aguja se tiene ahora un array de cuatro objetos Aguja que nos permite tratarlos a todos con un bucle, en lugar de escribiendo tantas líneas de código como objetos tenemos. La máquina de estado se ha cambiado para que permanezca en el estado ESTADO_INICIAL hasta que se llame a la función setup() del objeto.

Normalmente hay que tener cuidado de no grabar muchísimas veces en una misma dirección de la EEPROM, porque termina degradándose. En este caso se graba siempre que se cambia de posición la aguja; pero no creo que se llegue, ni de lejos, a la vida útil de la EEPROM.

Si se ha cambiado alguna constante del código anterior, para adaptarlas según necesidad, basta con pasar esas modificaciones a este nuevo código.

Adjunto nuevo código.

El siguiente paso que quiero dar, es añadir dos pulsadores para configurar las posiciones de los servos y ajustarlas sin tener que definirlas en el código del programa. Se guardan en la EEPROM y se leen, junto con la última posición de la aguja, al arrancar el Arduino. Se podrá entonces hacer los ajustes de los ángulos de los servos con el sistema funcionando. Sin necesidad de cambiar, compilar y subir el programa al Arduino una y otra vez.

apacher

Ya bajé el código, muchas gracias.

Interpreto que para ejecutarlo debo esperar que configures el siguiente paso ya que anguloDestino aún no tiene los grados y los tendrá una vez que estén incluidos los dos pulsadores, ¿es así?

Un cordial saludo

Armando

apacher

Buen día.

Consulto por una duda que apareció durante las pruebas de determinación de los grados del movimiento del servo en los desvíos de vías. Puede ser que en el futuro agregue algún otro desvío de otro fabricante, que tenga una diferencia en grados con los actuales. ¿Debería configurar otra clase "Aguja" para este desvío?

Un cordial saludo.

Armando

apacher

Disculpame por la pregunta anterior, ahora veo que desde la línea 32 a la 39 diferenciaste cada servo y se pueden modificar en forma individual los grados de movimiento de cada uno.

Un Cordial saludo

Armando

IgnoranteAbsoluto

Configuración de los ángulos de los servos y memorización en la EEPROM.

Me ha costado un poco más de lo que pensaba, pero al fin le he metido la configuración de los ángulos diréctamente con el Arduino. Para ello se necesita añadir dos pulsadores al montaje. Uno incrementa el ángulo y otro lo decrementa., del servo seleccionado y la posición que tiene. El pin en que se conecta cada pulsador se define con las constantes PIN_CONFIGURACION_INCREMENTA y PIN_CONFIGURACION_DECREMENTA. Los pines actualmente configurados son el 34 y 35, respectivamente.


El funcionamiento de la configuración es:

- Se accede al "modo configuración" manteniendo pulsado los dos botones a la vez durante 2 segundos. Este tiempo se puede cambiar con la constante TIEMPO_ENTRAR_CONFIGURACION.

- Cuando se entra en modo configuración, todas las luces de los cruces se apagan salvo la del servo que se está configurando. Esta parpadea rápidamente para indicar que es ella la que se está configurando. El seleccionado es el último que se hubiera accionada, o el servo "UNO" si no se ha accionado ninguno desde que arrancó el programa.

- Para seleccionar el servo que se quiere configurar, basta con pulsar su botón de cambio de desvío. Una vez seleccionado, parpadea sólo su luz correspondiente.

- Se configura la posición que indica la luz que parpadea. Se supone que si parpadea la verde es para configurar el ángulo del servo en la posición de vía recta. Si parpadea la azul es para configurar la posición del servo en la posición de desvío.

- Para cambiar qué ángulo se quiere configurar, basta con pulsar el botón de cambio de desvío. Si ya estaba seleccionado ese desvío, cambiará de posición y se podrá configurar esa nueva posición.

- Para aumentar o disminuir el ángulo del servo seleccionado en su posición actual: se pulsa el botón de configuración de incremento o decremento, según se necesite, las veces que se necesite. Cada pulsación incrementa o decrementa un grado.

- Según se va modificando el ángulo de la posición del servo, este nuevo valor se guarda en la EEPROM. No hay que hacer nada especial para que se guarde.

- Transcurrido 30 segundos desde la última vez que se pulsara uno de los botones de configuración, se saldrá solo del "modo configuración". Dejará de parpadear rápidamente la luz del que se estuviera configurando, y las luces del resto de desvíos se encenderán y volverá todo a funcionar de manera normal.

- Si se reinicia o se apaga el Arduino, al arrancar el programa recupera los valores configurados.

- La primera vez, como en la EEPROM no hay "valores buenos", se configuran con los ángulos indicados al definir cada aguja en el programa. Esos mismos valores son los que se utilizaban hasta la versión anterior del programa para definir los ángulos con que trabajaba cada servo.

- En principio el ángulo no puede ser mayor a 180 ni menor que 0. Si se trata de ir más allá de estos límites, no se hace caso de las pulsaciones de incremento o decremento y el servo no se moverá.


Respondiendo:

... Interpreto que para ejecutarlo debo esperar que configures el siguiente paso ya que anguloDestino aún no tiene los grados y los tendrá una vez que estén incluidos los dos pulsadores, ¿es así?
Por si no ha quedado claro ya. A partir de esta versión del programa, los ángulos que se definen en el código se usan únicamente si en la EEPROM no se han guardado nunca ángulos configurados con el Arduino, mediante los dos pulsadores de configuración.


... Puede ser que en el futuro agregue algún otro desvío de otro fabricante, que tenga una diferencia en grados con los actuales. ¿Debería configurar otra clase "Aguja" para este desvío?
Disculpame por la pregunta anterior, ahora veo que desde la línea 32 a la 39 diferenciaste cada servo y se pueden modificar en forma individual los grados de movimiento de cada uno.
Efectivamente, se podría cambiar los ángulos en el código, pero esos ángulos se pueden modificar directamente con el Arduino y los dos pulsadores de configuración.

Si en un futuro se quieren controlar más servos, bastaría con agregar más elementos al final del array Aguja agujas[ ]


Modificaciones del programa:

- Añadido el soporte para gestionar las configuración de los ángulos.

- Se usa la librería anti-rebote Bounce2. Importante: hay que tenerla instalada para que el programa se pueda compilar. Se entuentra en https://github.com/thomasfredericks/Bounce2
 

Queda pendiente añadir el soporte para el control de los dos motores paso a paso.

Adjunto código.

apacher

Excelente y complejo avance! Muchas gracias una vez más por el esfuerzo!

Hice un prototipo en Fritzing donde incluí dos servos dos steppers, dos L298N, cuatro switches, dos botones y los LEDs correspondientes. Si te parece puedo adjuntarte mañana una imagen en formato JPG del prototipo. Cambié los attach de ambos servos a los pines 34 y 35 del Mega, para liberar lugar para los steppers. Utilizo Fritzing pues me ayuda al armado físico de los circuitos.

Muy claras las respuestas a mis preguntas, disculpame por el error, espero no perder el "ascenso de división", me esforzaré más para seguir navegando en estas aguas profundas.

Un cordial saludo

Armando

Go Up